Make pinning files async in a background thread
Make the actual pinning of files be async in the system server background thread.
There's no need to block system_server from doing useful work on the ui
thread while the files are pinned.
bug 28251566
Change-Id: I905c165533692979ac179e987216378210396e75
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index e63f536..eaf317a 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -28,6 +28,10 @@
import android.util.Slog;
import android.os.Binder;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
@@ -35,6 +39,7 @@
import android.system.StructStat;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.os.BackgroundThread;
import dalvik.system.VMRuntime;
@@ -64,6 +69,8 @@
private final long MAX_CAMERA_PIN_SIZE = 50 * (1 << 20); //50MB max
+ private PinnerHandler mPinnerHandler = null;
+
public PinnerService(Context context) {
super(context);
@@ -71,6 +78,7 @@
mContext = context;
mShouldPinCamera = context.getResources().getBoolean(
com.android.internal.R.bool.config_pinnerCameraApp);
+ mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());
}
@Override
@@ -80,22 +88,8 @@
}
mBinderService = new BinderService();
publishBinderService("pinner", mBinderService);
-
- // Files to pin come from the overlay and can be specified per-device config
- String[] filesToPin = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_defaultPinnerServiceFiles);
- // Continue trying to pin remaining files even if there is a failure
- for (int i = 0; i < filesToPin.length; i++){
- PinnedFile pf = pinFile(filesToPin[i], 0, 0, 0);
- if (pf != null) {
- mPinnedFiles.add(pf);
- if (DEBUG) {
- Slog.i(TAG, "Pinned file = " + pf.mFilename);
- }
- } else {
- Slog.e(TAG, "Failed to pin file = " + filesToPin[i]);
- }
- }
+ mPinnerHandler.sendMessage(
+ mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG));
}
/**
@@ -106,27 +100,57 @@
*/
@Override
public void onUnlockUser(int userHandle) {
- handlePin(userHandle);
+ mPinnerHandler.sendMessage(
+ mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0));
}
/**
- * Pin camera on user switch.
- * If more than one user is using the device
- * each user may set a different preference for the camera app.
- * Make sure that user's preference is pinned into memory.
- */
+ * Pin camera on user switch.
+ * If more than one user is using the device
+ * each user may set a different preference for the camera app.
+ * Make sure that user's preference is pinned into memory.
+ */
@Override
public void onSwitchUser(int userHandle) {
- handlePin(userHandle);
+ mPinnerHandler.sendMessage(
+ mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0));
}
- private void handlePin(int userHandle) {
+ /**
+ * Handler for on start pinning message
+ */
+ private void handlePinOnStart() {
+ // Files to pin come from the overlay and can be specified per-device config
+ String[] filesToPin = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_defaultPinnerServiceFiles);
+ synchronized(this) {
+ // Continue trying to pin remaining files even if there is a failure
+ for (int i = 0; i < filesToPin.length; i++){
+ PinnedFile pf = pinFile(filesToPin[i], 0, 0, 0);
+ if (pf != null) {
+ mPinnedFiles.add(pf);
+ if (DEBUG) {
+ Slog.i(TAG, "Pinned file = " + pf.mFilename);
+ }
+ } else {
+ Slog.e(TAG, "Failed to pin file = " + filesToPin[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for camera pinning message
+ */
+ private void handlePinCamera(int userHandle) {
if (mShouldPinCamera) {
- boolean success = pinCamera(userHandle);
- if (!success) {
- //this is not necessarily an error
- if (DEBUG) {
- Slog.v(TAG, "Failed to pin camera.");
+ synchronized(this) {
+ boolean success = pinCamera(userHandle);
+ if (!success) {
+ //this is not necessarily an error
+ if (DEBUG) {
+ Slog.v(TAG, "Failed to pin camera.");
+ }
}
}
}
@@ -316,11 +340,13 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
pw.println("Pinned Files:");
- for (int i = 0; i < mPinnedFiles.size(); i++) {
- pw.println(mPinnedFiles.get(i).mFilename);
- }
- for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
- pw.println(mPinnedCameraFiles.get(i).mFilename);
+ synchronized(this) {
+ for (int i = 0; i < mPinnedFiles.size(); i++) {
+ pw.println(mPinnedFiles.get(i).mFilename);
+ }
+ for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
+ pw.println(mPinnedCameraFiles.get(i).mFilename);
+ }
}
}
}
@@ -336,4 +362,35 @@
mFilename = filename;
}
}
+
+ final class PinnerHandler extends Handler {
+ static final int PIN_CAMERA_MSG = 4000;
+ static final int PIN_ONSTART_MSG = 4001;
+
+ public PinnerHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+
+ case PIN_CAMERA_MSG:
+ {
+ handlePinCamera(msg.arg1);
+ }
+ break;
+
+ case PIN_ONSTART_MSG:
+ {
+ handlePinOnStart();
+ }
+ break;
+
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
}