Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a95cea04 authored by Philip Cuadra's avatar Philip Cuadra
Browse files

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
parent 0f6c2bfe
Loading
Loading
Loading
Loading
+91 −34
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@ import android.util.EventLog;
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.OsConstants;
import android.system.StructStat;

import com.android.internal.app.ResolverActivity;
import com.android.internal.os.BackgroundThread;

import dalvik.system.VMRuntime;

@@ -64,6 +69,8 @@ public final class PinnerService extends SystemService {

    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 @@ public final class PinnerService extends SystemService {
        mContext = context;
        mShouldPinCamera = context.getResources().getBoolean(
                com.android.internal.R.bool.config_pinnerCameraApp);
        mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());
    }

    @Override
@@ -80,22 +88,8 @@ public final class PinnerService extends SystemService {
        }
        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,7 +100,8 @@ public final class PinnerService extends SystemService {
     */
    @Override
    public void onUnlockUser(int userHandle) {
        handlePin(userHandle);
        mPinnerHandler.sendMessage(
                mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, userHandle, 0));
    }

    /**
@@ -117,11 +112,39 @@ public final class PinnerService extends SystemService {
     */
    @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) {
            synchronized(this) {
                boolean success = pinCamera(userHandle);
                if (!success) {
                    //this is not necessarily an error
@@ -131,6 +154,7 @@ public final class PinnerService extends SystemService {
                }
            }
        }
    }

    /**
     *  determine if the camera app is already pinned by comparing the
@@ -316,6 +340,7 @@ public final class PinnerService extends SystemService {
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
            pw.println("Pinned Files:");
            synchronized(this) {
                for (int i = 0; i < mPinnedFiles.size(); i++) {
                    pw.println(mPinnedFiles.get(i).mFilename);
                }
@@ -324,6 +349,7 @@ public final class PinnerService extends SystemService {
                }
            }
        }
    }

    private static class PinnedFile {
        long mAddress;
@@ -336,4 +362,35 @@ public final class PinnerService extends SystemService {
             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);
            }
        }
    }

}