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

Commit dd4ed1b0 authored by Alex Salo's avatar Alex Salo Committed by android-build-merger
Browse files

Merge "Don't call ActivityManagerService on main thread" into qt-dev am: 9a01bb42

am: 545cc778

Change-Id: Ib8e04b3d104791f2913be69b02af3fcc7bd2bd58
parents 47a8e0ec 545cc778
Loading
Loading
Loading
Loading
+32 −27
Original line number Original line Diff line number Diff line
@@ -190,9 +190,7 @@ public class AttentionManagerService extends SystemService {


            final UserState userState = getOrCreateCurrentUserStateLocked();
            final UserState userState = getOrCreateCurrentUserStateLocked();
            // lazily start the service, which should be very lightweight to start
            // lazily start the service, which should be very lightweight to start
            if (!userState.bindLocked()) {
            userState.bindLocked();
                return false;
            }


            // throttle frequent requests
            // throttle frequent requests
            final AttentionCheckCache cache = userState.mAttentionCheckCache;
            final AttentionCheckCache cache = userState.mAttentionCheckCache;
@@ -310,7 +308,7 @@ public class AttentionManagerService extends SystemService {
    protected UserState getOrCreateUserStateLocked(int userId) {
    protected UserState getOrCreateUserStateLocked(int userId) {
        UserState result = mUserStates.get(userId);
        UserState result = mUserStates.get(userId);
        if (result == null) {
        if (result == null) {
            result = new UserState(userId, mContext, mLock, mComponentName);
            result = new UserState(userId, mContext, mLock, mAttentionHandler, mComponentName);
            mUserStates.put(userId, result);
            mUserStates.put(userId, result);
        }
        }
        return result;
        return result;
@@ -456,31 +454,33 @@ public class AttentionManagerService extends SystemService {


    @VisibleForTesting
    @VisibleForTesting
    protected static class UserState {
    protected static class UserState {
        final ComponentName mComponentName;
        private final ComponentName mComponentName;
        final AttentionServiceConnection mConnection = new AttentionServiceConnection();
        private final AttentionServiceConnection mConnection = new AttentionServiceConnection();


        @GuardedBy("mLock")
        @GuardedBy("mLock")
        IAttentionService mService;
        IAttentionService mService;
        @GuardedBy("mLock")
        @GuardedBy("mLock")
        boolean mBinding;
        @GuardedBy("mLock")
        AttentionCheck mCurrentAttentionCheck;
        AttentionCheck mCurrentAttentionCheck;
        @GuardedBy("mLock")
        @GuardedBy("mLock")
        AttentionCheckCache mAttentionCheckCache;
        AttentionCheckCache mAttentionCheckCache;
        @GuardedBy("mLock")
        private boolean mBinding;


        @UserIdInt
        @UserIdInt
        final int mUserId;
        private final int mUserId;
        final Context mContext;
        private final Context mContext;
        final Object mLock;
        private final Object mLock;
        private final Handler mAttentionHandler;


        UserState(int userId, Context context, Object lock, ComponentName componentName) {
        UserState(int userId, Context context, Object lock, Handler handler,
                ComponentName componentName) {
            mUserId = userId;
            mUserId = userId;
            mContext = Preconditions.checkNotNull(context);
            mContext = Preconditions.checkNotNull(context);
            mLock = Preconditions.checkNotNull(lock);
            mLock = Preconditions.checkNotNull(lock);
            mComponentName = Preconditions.checkNotNull(componentName);
            mComponentName = Preconditions.checkNotNull(componentName);
            mAttentionHandler = handler;
        }
        }



        @GuardedBy("mLock")
        @GuardedBy("mLock")
        private void handlePendingCallbackLocked() {
        private void handlePendingCallbackLocked() {
            if (!mCurrentAttentionCheck.mIsDispatched) {
            if (!mCurrentAttentionCheck.mIsDispatched) {
@@ -499,26 +499,25 @@ public class AttentionManagerService extends SystemService {


        /** Binds to the system's AttentionService which provides an actual implementation. */
        /** Binds to the system's AttentionService which provides an actual implementation. */
        @GuardedBy("mLock")
        @GuardedBy("mLock")
        private boolean bindLocked() {
        private void bindLocked() {
            // No need to bind if service is binding or has already been bound.
            // No need to bind if service is binding or has already been bound.
            if (mBinding || mService != null) {
            if (mBinding || mService != null) {
                return true;
                return;
            }
            }


            final boolean willBind;
            mBinding = true;
            final long identity = Binder.clearCallingIdentity();
            // mContext.bindServiceAsUser() calls into ActivityManagerService which it may already

            // hold the lock and had called into PowerManagerService, which holds a lock.
            try {
            // That would create a deadlock. To solve that, putting it on a handler.
                final Intent mServiceIntent = new Intent(
            mAttentionHandler.post(() -> {
                final Intent serviceIntent = new Intent(
                        AttentionService.SERVICE_INTERFACE).setComponent(
                        AttentionService.SERVICE_INTERFACE).setComponent(
                        mComponentName);
                        mComponentName);
                willBind = mContext.bindServiceAsUser(mServiceIntent, mConnection,
                // Note: no reason to clear the calling identity, we won't have one in a handler.
                mContext.bindServiceAsUser(serviceIntent, mConnection,
                        Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
                        Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
                mBinding = willBind;

            } finally {
            });
                Binder.restoreCallingIdentity(identity);
            }
            return willBind;
        }
        }


        private void dump(IndentingPrintWriter pw) {
        private void dump(IndentingPrintWriter pw) {
@@ -587,6 +586,7 @@ public class AttentionManagerService extends SystemService {
            super(Looper.myLooper());
            super(Looper.myLooper());
        }
        }


        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            switch (msg.what) {
                // Do not occupy resources when not in use - unbind proactively.
                // Do not occupy resources when not in use - unbind proactively.
@@ -651,7 +651,12 @@ public class AttentionManagerService extends SystemService {
                return;
                return;
            }
            }


            mContext.unbindService(userState.mConnection);
            mAttentionHandler.post(() -> mContext.unbindService(userState.mConnection));
            // Note: this will set mBinding to false even though it could still be trying to bind
            // (i.e. the runnable was posted in bindLocked but then cancelAndUnbindLocked was
            // called before it's run yet). This is a safe state at the moment,
            // since it will eventually, but feels like a source for confusion down the road and
            // may cause some expensive and unnecessary work to be done.
            userState.mConnection.cleanupService();
            userState.mConnection.cleanupService();
            mUserStates.remove(userState.mUserId);
            mUserStates.remove(userState.mUserId);
        }
        }
+1 −0
Original line number Original line Diff line number Diff line
@@ -86,6 +86,7 @@ public class AttentionManagerServiceTest {
        UserState mUserState = new UserState(0,
        UserState mUserState = new UserState(0,
                mContext,
                mContext,
                mLock,
                mLock,
                mMockHandler,
                componentName);
                componentName);
        mUserState.mService = new MockIAttentionService();
        mUserState.mService = new MockIAttentionService();
        mSpyUserState = spy(mUserState);
        mSpyUserState = spy(mUserState);