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

Commit 1e32c07e authored by Alex Salo's avatar Alex Salo
Browse files

Don't free resources if service is actually in use

If there were active requests recently - don't expire the connection.
Don't call cancel if the request has succeded.

Test: manually with logging
Bug: 111939367
Change-Id: Ib38d7552a828eb0330419db7ff15666cde8db4f9
parent a0d18b60
Loading
Loading
Loading
Loading
+57 −39
Original line number Diff line number Diff line
@@ -104,8 +104,7 @@ public class AttentionManagerService extends SystemService {

    @Override
    public void onSwitchUser(int userId) {
        cancelAndUnbindLocked(peekUserStateLocked(userId),
                AttentionService.ATTENTION_FAILURE_UNKNOWN);
        cancelAndUnbindLocked(peekUserStateLocked(userId));
    }

    /** Resolves and sets up the attention service if it had not been done yet. */
@@ -152,7 +151,8 @@ public class AttentionManagerService extends SystemService {
        }

        synchronized (mLock) {
            unbindAfterTimeoutLocked();
            final long now = SystemClock.uptimeMillis();
            freeIfInactiveLocked();

            final UserState userState = getOrCreateCurrentUserStateLocked();
            // lazily start the service, which should be very lightweight to start
@@ -172,7 +172,7 @@ public class AttentionManagerService extends SystemService {
                try {
                    // throttle frequent requests
                    final AttentionCheckCache attentionCheckCache = userState.mAttentionCheckCache;
                    if (attentionCheckCache != null && SystemClock.uptimeMillis()
                    if (attentionCheckCache != null && now
                            < attentionCheckCache.mLastComputed + STALE_AFTER_MILLIS) {
                        callback.onSuccess(requestCode, attentionCheckCache.mResult,
                                attentionCheckCache.mTimestamp);
@@ -190,6 +190,7 @@ public class AttentionManagerService extends SystemService {
                                userState.mAttentionCheckCache = new AttentionCheckCache(
                                        SystemClock.uptimeMillis(), result,
                                        timestamp);
                                userState.mCurrentAttentionCheckIsFulfilled = true;
                            }
                            StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
                                    result);
@@ -198,14 +199,10 @@ public class AttentionManagerService extends SystemService {
                        @Override
                        public void onFailure(int requestCode, int error) {
                            callback.onFailure(requestCode, error);
                            userState.mCurrentAttentionCheckIsFulfilled = true;
                            StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
                                    error);
                        }

                        @Override
                        public IBinder asBinder() {
                            return null;
                        }
                    });
                } catch (RemoteException e) {
                    Slog.e(LOG_TAG, "Cannot call into the AttentionService");
@@ -219,7 +216,10 @@ public class AttentionManagerService extends SystemService {
    /** Cancels the specified attention check. */
    public void cancelAttentionCheck(int requestCode) {
        synchronized (mLock) {
            final UserState userState = getOrCreateCurrentUserStateLocked();
            final UserState userState = peekCurrentUserStateLocked();
            if (userState == null) {
                return;
            }
            if (userState.mService == null) {
                if (userState.mPendingAttentionCheck != null
                        && userState.mPendingAttentionCheck.mRequestCode == requestCode) {
@@ -236,8 +236,12 @@ public class AttentionManagerService extends SystemService {
    }

    @GuardedBy("mLock")
    private void unbindAfterTimeoutLocked() {
        mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CONNECTION_EXPIRED,
    private void freeIfInactiveLocked() {
        // If we are called here, it means someone used the API again - reset the timer then.
        mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);

        // Schedule resources cleanup if no one calls the API again.
        mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CHECK_CONNECTION_EXPIRATION,
                CONNECTION_TTL_MILLIS);
    }

@@ -264,12 +268,14 @@ public class AttentionManagerService extends SystemService {
    }

    @GuardedBy("mLock")
    UserState peekCurrentUserStateLocked() {
    @Nullable
    private UserState peekCurrentUserStateLocked() {
        return peekUserStateLocked(ActivityManager.getCurrentUser());
    }

    @GuardedBy("mLock")
    UserState peekUserStateLocked(int userId) {
    @Nullable
    private UserState peekUserStateLocked(int userId) {
        return mUserStates.get(userId);
    }

@@ -406,6 +412,8 @@ public class AttentionManagerService extends SystemService {
        @GuardedBy("mLock")
        int mCurrentAttentionCheckRequestCode;
        @GuardedBy("mLock")
        boolean mCurrentAttentionCheckIsFulfilled;
        @GuardedBy("mLock")
        PendingAttentionCheck mPendingAttentionCheck;

        @GuardedBy("mLock")
@@ -501,7 +509,7 @@ public class AttentionManagerService extends SystemService {
    }

    private class AttentionHandler extends Handler {
        private static final int CONNECTION_EXPIRED = 1;
        private static final int CHECK_CONNECTION_EXPIRATION = 1;
        private static final int ATTENTION_CHECK_TIMEOUT = 2;

        AttentionHandler() {
@@ -511,20 +519,27 @@ public class AttentionManagerService extends SystemService {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                // Do not occupy resources when not in use - unbind proactively.
                case CONNECTION_EXPIRED: {
                case CHECK_CONNECTION_EXPIRATION: {
                    for (int i = 0; i < mUserStates.size(); i++) {
                        cancelAndUnbindLocked(mUserStates.valueAt(i),
                                AttentionService.ATTENTION_FAILURE_UNKNOWN);
                        cancelAndUnbindLocked(mUserStates.valueAt(i));
                    }

                }
                break;

                // Callee is no longer interested in the attention check result - cancel.
                case ATTENTION_CHECK_TIMEOUT: {
                    cancelAndUnbindLocked(peekCurrentUserStateLocked(),
                    synchronized (mLock) {
                        final UserState userState = peekCurrentUserStateLocked();
                        if (userState != null) {
                            // If not called back already.
                            if (!userState.mCurrentAttentionCheckIsFulfilled) {
                                cancel(userState,
                                        AttentionService.ATTENTION_FAILURE_TIMED_OUT);
                            }

                        }
                    }
                }
                break;

                default:
@@ -533,10 +548,7 @@ public class AttentionManagerService extends SystemService {
        }
    }

    @GuardedBy("mLock")
    private void cancelAndUnbindLocked(UserState userState,
            @AttentionFailureCodes int failureCode) {
        synchronized (mLock) {
    private void cancel(UserState userState, @AttentionFailureCodes int failureCode) {
        if (userState != null && userState.mService != null) {
            try {
                userState.mService.cancelAttentionCheck(
@@ -548,12 +560,19 @@ public class AttentionManagerService extends SystemService {
            if (userState.mPendingAttentionCheck != null) {
                userState.mPendingAttentionCheck.cancel(failureCode);
            }
        }
    }

    @GuardedBy("mLock")
    private void cancelAndUnbindLocked(UserState userState) {
        synchronized (mLock) {
            cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN);

            mContext.unbindService(userState.mConnection);
            userState.mConnection.cleanupService();
            mUserStates.remove(userState.mUserId);
        }
    }
    }

    /**
     * Unbinds and stops the service when the screen off intent is received.
@@ -563,8 +582,7 @@ public class AttentionManagerService extends SystemService {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
                cancelAndUnbindLocked(peekCurrentUserStateLocked(),
                        AttentionService.ATTENTION_FAILURE_UNKNOWN);
                cancelAndUnbindLocked(peekCurrentUserStateLocked());
            }
        }
    }