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

Commit dbcb31f2 authored by Craig Mautner's avatar Craig Mautner
Browse files

Fix potential synch problems.

- Do not schedule GC until all stacks are idle.
- Call sendPendingThumbnail outside of synchronized lock.
- Remove redundant synchronized locks.

Change-Id: I56581ca12a534765132bed405fa4b340c418436f
parent bad82253
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -2782,8 +2782,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    @Override
    public void setRequestedOrientation(IBinder token,
            int requestedOrientation) {
    public void setRequestedOrientation(IBinder token, int requestedOrientation) {
        synchronized (this) {
            ActivityRecord r = ActivityRecord.isInStackLocked(token);
            if (r == null) {
@@ -2792,8 +2791,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            final long origId = Binder.clearCallingIdentity();
            mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
            Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    mConfiguration,
                    r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
                    mConfiguration, r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
            if (config != null) {
                r.frozenBeforeDestroy = true;
                if (!updateConfigurationLocked(config, r, false, false)) {
@@ -3639,6 +3637,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    @Override
    public void forceStopPackage(final String packageName, int userId) {
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                != PackageManager.PERMISSION_GRANTED) {
@@ -3687,6 +3686,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    /*
     * The pkg name and app id have to be specified.
     */
    @Override
    public void killApplicationWithAppId(String pkg, int appid) {
        if (pkg == null) {
            return;
@@ -3711,6 +3711,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    @Override
    public void closeSystemDialogs(String reason) {
        enforceNotIsolatedCaller("closeSystemDialogs");
@@ -3755,8 +3756,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                Process.SYSTEM_UID, UserHandle.USER_ALL);
    }
    public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
            throws RemoteException {
    @Override
    public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) {
        enforceNotIsolatedCaller("getProcessMemoryInfo");
        Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
        for (int i=pids.length-1; i>=0; i--) {
+48 −43
Original line number Diff line number Diff line
@@ -1255,6 +1255,7 @@ final class ActivityStack {
        return resumeTopActivityLocked(prev, null);
    }

    // Checked.
    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        // Find the first activity that is not finishing.
        ActivityRecord next = topRunningActivityLocked(null);
@@ -2881,7 +2882,7 @@ final class ActivityStack {
    }

    // Checked.
    final ActivityRecord activityIdleInternalLocked(IBinder token, boolean fromTimeout,
    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);

@@ -2889,11 +2890,9 @@ final class ActivityStack {

        ArrayList<ActivityRecord> stops = null;
        ArrayList<ActivityRecord> finishes = null;
        ArrayList<ActivityRecord> thumbnails = null;
        ArrayList<UserStartedState> startingUsers = null;
        int NS = 0;
        int NF = 0;
        int NT = 0;
        IApplicationThread sendThumbnail = null;
        boolean booting = false;
        boolean enableScreen = false;
@@ -2931,7 +2930,9 @@ final class ActivityStack {
            // We are now idle.  If someone is waiting for a thumbnail from
            // us, we can now deliver.
            r.idle = true;
            if (mStackSupervisor.allResumedActivitiesIdle()) {
                mService.scheduleAppGcsLocked();
            }
            if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
                sendThumbnail = r.app.thread;
                r.thumbnailNeeded = false;
@@ -2943,12 +2944,10 @@ final class ActivityStack {
            ensureActivitiesVisibleLocked(null, 0);

            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
            if (mStackSupervisor.isMainStack(this)) {
                if (!mService.mBooted) {
            if (!mService.mBooted && mStackSupervisor.isMainStack(this)) {
                mService.mBooted = true;
                enableScreen = true;
            }
            }
        } else if (fromTimeout) {
            reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
        }
@@ -2960,64 +2959,70 @@ final class ActivityStack {
            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
            mFinishingActivities.clear();
        }
        if ((NT=mCancelledThumbnails.size()) > 0) {

        final ArrayList<ActivityRecord> thumbnails;
        final int NT = mCancelledThumbnails.size();
        if (NT > 0) {
            thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
            mCancelledThumbnails.clear();
        } else {
            thumbnails = null;
        }

        if (mStackSupervisor.isMainStack(this)) {
            booting = mService.mBooting;
            mService.mBooting = false;
        }

        if (mStartingUsers.size() > 0) {
            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
            mStartingUsers.clear();
        }

        int i;

        // Send thumbnail if requested.
        if (sendThumbnail != null) {
        // Perform the following actions from unsynchronized state.
        final IApplicationThread thumbnailThread = sendThumbnail;
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (thumbnailThread != null) {
                    try {
                sendThumbnail.requestThumbnail(token);
                        thumbnailThread.requestThumbnail(token);
                    } catch (Exception e) {
                        Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
                        mService.sendPendingThumbnail(null, token, null, null, true);
                    }
                }

                // Report back to any thumbnail receivers.
                for (int i = 0; i < NT; i++) {
                    ActivityRecord r = thumbnails.get(i);
                    mService.sendPendingThumbnail(r, null, null, null, true);
                }
            }
        });

        // Stop any activities that are scheduled to do so but have been
        // waiting for the next one to start.
        for (i=0; i<NS; i++) {
        for (int i = 0; i < NS; i++) {
            r = stops.get(i);
            synchronized (mService) {
            if (r.finishing) {
                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
            } else {
                stopActivityLocked(r);
            }
        }
        }

        // Finish any activities that are scheduled to do so but have been
        // waiting for the next one to start.
        for (i=0; i<NF; i++) {
        for (int i = 0; i < NF; i++) {
            r = finishes.get(i);
            synchronized (mService) {
                activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
            }
        }

        // Report back to any thumbnail receivers.
        for (i=0; i<NT; i++) {
            r = thumbnails.get(i);
            mService.sendPendingThumbnail(r, null, null, null, true);
            activityRemoved |= destroyActivityLocked(r, true, false, "finish-idle");
        }

        if (booting) {
            mService.finishBooting();
        } else if (startingUsers != null) {
            for (i=0; i<startingUsers.size(); i++) {
            for (int i = 0; i < startingUsers.size(); i++) {
                mService.finishUserSwitch(startingUsers.get(i));
            }
        }
+3 −11
Original line number Diff line number Diff line
@@ -187,8 +187,8 @@ public class ActivityStackSupervisor {

    boolean allResumedActivitiesIdle() {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            if (mStacks.get(stackNdx).mResumedActivity == null ||
                    !mStacks.get(stackNdx).mResumedActivity.idle) {
            final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
            if (resumedActivity == null || !resumedActivity.idle) {
                return false;
            }
        }
@@ -727,15 +727,7 @@ public class ActivityStackSupervisor {
    }

    void resumeTopActivityLocked() {
        final int start, end;
        if (isHomeStackMain()) {
            start = 0;
            end = 1;
        } else {
            start = 1;
            end = mStacks.size();
        }
        for (int stackNdx = start; stackNdx < end; ++stackNdx) {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            mStacks.get(stackNdx).resumeTopActivityLocked(null);
        }
    }