Explanationif(mBitmap == null){
mBitmap = Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);;
}
final Canvas c = new Canvas (mBitmap);
c.drawColor(0, PorterDuff.Mode.CLEAR);
commandManager.executeAll(c);
This is the core of the saving part, in order for our drawing to be exported we have to create a canvas with bitmap to draw upon to, See Canvas Class for more info.

canvas.drawBitmap (mBitmap, 0, 0,null);
We put our bitmap to our original canvas (the surfaceView's canvas) so that we can see our drawings

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mBitmap = Bitmap.createBitmap (width, height, Bitmap.Config.ARGB_8888);;
}
We would have to recreate our bitmap when we change the orientation (The drawings will currently be removed)

final Activity currentActivity = this;
Handler saveHandler = new Handler(){ ... }
We cant call the UI tread from another thread so we pass a handler to our AsyncTask, see Using Handler in Android for more information on Handlers

@Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}
In order for us to export the bitmap and not hard the UX of our app, we need to create a background thread for it, for more information on AsyncTask see the AsyncTask Class and Painless Threading

final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/myAwesomeDrawing.png"));
nBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
This is default Java feature, if your now from Java then this just mean that you create a buffer where when we use that in mBitmap.compress the compressed bitmap would be buffered into that FileOutputStream (i hope i was clear in this. haha)

Reference
Most of the stuff here were back in 2009, most of them are in Google Groups.