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

Commit c2ad29b1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Invoke uid state change callback for all nonexistent apps" into main

parents 187956c0 f506c367
Loading
Loading
Loading
Loading
+37 −33
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ import static android.app.AppOpsManager.SAMPLING_STRATEGY_RARELY_USED;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
import static android.app.AppOpsManager.UID_STATE_NONEXISTENT;
import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
import static android.app.AppOpsManager._NUM_OP;
import static android.app.AppOpsManager.extractFlagsFromKey;
@@ -464,7 +463,19 @@ public class AppOpsService extends IAppOpsService.Stub {
                    Clock.SYSTEM_CLOCK, mConstants);

            mUidStateTracker.addUidStateChangedCallback(new HandlerExecutor(mHandler),
                    this::onUidStateChanged);
                    new AppOpsUidStateTracker.UidStateChangedCallback() {
                        @Override
                        public void onUidStateChanged(int uid, int uidState,
                                boolean foregroundModeMayChange) {
                            AppOpsService.this
                                    .onUidStateChanged(uid, uidState, foregroundModeMayChange);
                        }

                        @Override
                        public void onUidProcessDeath(int uid) {
                            AppOpsService.this.onUidProcessDeath(uid);
                        }
                    });
        }
        return mUidStateTracker;
    }
@@ -1500,9 +1511,6 @@ public class AppOpsService extends IAppOpsService.Stub {
    // The callback method from AppOpsUidStateTracker
    private void onUidStateChanged(int uid, int state, boolean foregroundModeMayChange) {
        synchronized (this) {
            if (state == UID_STATE_NONEXISTENT) {
                onUidProcessDeathLocked(uid);
            }
            UidState uidState = getUidStateLocked(uid, false);

            boolean hasForegroundWatchers = false;
@@ -1590,11 +1598,6 @@ public class AppOpsService extends IAppOpsService.Stub {
                }
            }

            if (state == UID_STATE_NONEXISTENT) {
                // For UID_STATE_NONEXISTENT, we don't call onUidStateChanged for AttributedOps
                return;
            }

            if (uidState != null) {
                int numPkgs = uidState.pkgOps.size();
                for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
@@ -1619,8 +1622,8 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    @GuardedBy("this")
    private void onUidProcessDeathLocked(int uid) {
    private void onUidProcessDeath(int uid) {
        synchronized (this) {
            if (!mUidStates.contains(uid) || !Flags.finishRunningOpsForKilledPackages()) {
                return;
            }
@@ -1645,6 +1648,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            });
            finishChainsLocked(chainsToFinish);
        }
    }

    @GuardedBy("this")
    private void finishChainsLocked(SparseLongArray chainsToFinish) {
+13 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -27,8 +28,10 @@ import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_NONEXISTENT;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
import static android.permission.flags.Flags.finishRunningOpsForKilledPackages;

import android.annotation.CallbackExecutor;
import android.util.SparseArray;
@@ -68,6 +71,14 @@ interface AppOpsUidStateTracker {
            return UID_STATE_BACKGROUND;
        }

        if (finishRunningOpsForKilledPackages()) {
            if (procState < PROCESS_STATE_NONEXISTENT) {
                return UID_STATE_CACHED;
            }

            return UID_STATE_NONEXISTENT;
        }

        // UID_STATE_NONEXISTENT is deliberately excluded here
        return UID_STATE_CACHED;
    }
@@ -119,6 +130,8 @@ interface AppOpsUidStateTracker {
         *                               evaluated result may have changed.
         */
        void onUidStateChanged(int uid, int uidState, boolean foregroundModeMayChange);

        void onUidProcessDeath(int uid);
    }

    void dumpUidState(PrintWriter pw, int uid, long nowElapsed);
+20 −17
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.ProcessCapability;
import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -32,6 +31,7 @@ import static android.app.AppOpsManager.OP_CONTROL_AUDIO;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_NONEXISTENT;
@@ -75,7 +75,6 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
    private SparseBooleanArray mAppWidgetVisible = new SparseBooleanArray();
    private SparseBooleanArray mPendingAppWidgetVisible = new SparseBooleanArray();
    private SparseLongArray mPendingCommitTime = new SparseLongArray();
    private SparseBooleanArray mPendingGone = new SparseBooleanArray();

    private ArrayMap<UidStateChangedCallback, Executor>
            mUidStateChangedCallbacks = new ArrayMap<>();
@@ -221,11 +220,12 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
    public void updateUidProcState(int uid, int procState, int capability) {
        int uidState = processStateToUidState(procState);

        int prevUidState = mUidStates.get(uid, AppOpsManager.MIN_PRIORITY_UID_STATE);
        int prevUidState = mUidStates.get(uid, AppOpsManager.UID_STATE_NONEXISTENT);
        int prevCapability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
        int pendingUidState = mPendingUidStates.get(uid, MIN_PRIORITY_UID_STATE);
        int pendingUidState = mPendingUidStates.get(uid, UID_STATE_NONEXISTENT);
        int pendingCapability = mPendingCapability.get(uid, PROCESS_CAPABILITY_NONE);
        long pendingStateCommitTime = mPendingCommitTime.get(uid, 0);

        if ((pendingStateCommitTime == 0
                && (uidState != prevUidState || capability != prevCapability))
                || (pendingStateCommitTime != 0
@@ -239,8 +239,7 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {

            boolean hasLostCapability = (prevCapability & ~capability) != 0;

            if (procState == PROCESS_STATE_NONEXISTENT) {
                mPendingGone.put(uid, true);
            if (uidState == UID_STATE_NONEXISTENT) {
                commitUidPendingState(uid);
            } else if (uidState < prevUidState) {
                // We are moving to a more important state, or the new state may be in the
@@ -342,7 +341,7 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {

    private void commitUidPendingState(int uid) {

        int uidState = mUidStates.get(uid, MIN_PRIORITY_UID_STATE);
        int uidState = mUidStates.get(uid, UID_STATE_NONEXISTENT);
        int capability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
        boolean appWidgetVisible = mAppWidgetVisible.get(uid, false);

@@ -350,18 +349,23 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
        int pendingCapability = mPendingCapability.get(uid, capability);
        boolean pendingAppWidgetVisible = mPendingAppWidgetVisible.get(uid, appWidgetVisible);

        boolean foregroundChange = uidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                != pendingUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
        // UID_STATE_NONEXISTENT is a state that isn't used outside of this class, nonexistent
        // processes have always been represented as CACHED
        int externalUidState = Math.min(uidState, UID_STATE_CACHED);
        int externalPendingUidState = Math.min(pendingUidState, UID_STATE_CACHED);

        boolean foregroundChange = externalUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                != externalPendingUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                || capability != pendingCapability
                || appWidgetVisible != pendingAppWidgetVisible;

        if (uidState != pendingUidState
        if (externalUidState != externalPendingUidState
                || capability != pendingCapability
                || appWidgetVisible != pendingAppWidgetVisible) {

            if (foregroundChange) {
                // To save on memory usage, log only interesting changes.
                mEventLog.logCommitUidState(uid, pendingUidState, pendingCapability,
                mEventLog.logCommitUidState(uid, externalPendingUidState, pendingCapability,
                        pendingAppWidgetVisible, appWidgetVisible != pendingAppWidgetVisible);
            }

@@ -370,24 +374,23 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
                Executor executor = mUidStateChangedCallbacks.valueAt(i);

                executor.execute(PooledLambda.obtainRunnable(
                        UidStateChangedCallback::onUidStateChanged, cb, uid, pendingUidState,
                        foregroundChange));
                        UidStateChangedCallback::onUidStateChanged, cb, uid,
                        externalPendingUidState, foregroundChange));
            }
        }

        if (mPendingGone.get(uid, false)) {
        if (pendingUidState == UID_STATE_NONEXISTENT && uidState != pendingUidState) {
            mUidStates.delete(uid);
            mCapability.delete(uid);
            mAppWidgetVisible.delete(uid);
            mPendingGone.delete(uid);
            if (finishRunningOpsForKilledPackages()) {
                for (int i = 0; i < mUidStateChangedCallbacks.size(); i++) {
                    UidStateChangedCallback cb = mUidStateChangedCallbacks.keyAt(i);
                    Executor executor = mUidStateChangedCallbacks.valueAt(i);

                    // If foregroundness changed it should be handled in earlier callback invocation
                    executor.execute(PooledLambda.obtainRunnable(
                            UidStateChangedCallback::onUidStateChanged, cb, uid,
                            UID_STATE_NONEXISTENT, foregroundChange));
                            UidStateChangedCallback::onUidProcessDeath, cb, uid));
                }
            }
        } else {
+0 −247
Original line number Diff line number Diff line
@@ -26,15 +26,12 @@ import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUD
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_TOP;
import static android.permission.flags.Flags.delayUidStateChangesFromCapabilityUpdates;

import static com.android.server.appop.AppOpsUidStateTracker.processStateToUidState;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -42,7 +39,6 @@ import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -64,7 +60,6 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.quality.Strictness;

import java.util.PriorityQueue;

@@ -94,7 +89,6 @@ public class AppOpsUidStateTrackerTest {
    public void setUp() {
        mSession = ExtendedMockito.mockitoSession()
                .initMocks(this)
                .strictness(Strictness.LENIENT)
                .startMocking();
        mConstants.TOP_STATE_SETTLE_TIME = 10 * 1000L;
        mConstants.FG_SERVICE_STATE_SETTLE_TIME = 5 * 1000L;
@@ -590,221 +584,6 @@ public class AppOpsUidStateTrackerTest {
        verify(cb, times(0)).onUidStateChanged(anyInt(), anyInt(), anyBoolean());
    }

    @Test
    public void testUidStateChangedCallbackCachedToBackground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
                ActivityManager.PROCESS_STATE_RECEIVER);
    }

    @Test
    public void testUidStateChangedCallbackCachedToForeground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
                ActivityManager.PROCESS_STATE_BOUND_TOP);
    }

    @Test
    public void testUidStateChangedCallbackCachedToForegroundService() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
    }

    @Test
    public void testUidStateChangedCallbackCachedToTop() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY,
                ActivityManager.PROCESS_STATE_TOP);
    }

    @Test
    public void testUidStateChangedCallbackBackgroundToCached() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_RECEIVER,
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
    }

    @Test
    public void testUidStateChangedCallbackBackgroundToForeground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_RECEIVER,
                ActivityManager.PROCESS_STATE_BOUND_TOP);
    }

    @Test
    public void testUidStateChangedCallbackBackgroundToForegroundService() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_RECEIVER,
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
    }

    @Test
    public void testUidStateChangedCallbackBackgroundToTop() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_RECEIVER,
                ActivityManager.PROCESS_STATE_TOP);
    }

    @Test
    public void testUidStateChangedCallbackForegroundToCached() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_BOUND_TOP,
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
    }

    @Test
    public void testUidStateChangedCallbackForegroundToBackground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_BOUND_TOP,
                ActivityManager.PROCESS_STATE_RECEIVER);
    }

    @Test
    public void testUidStateChangedCallbackForegroundToForegroundService() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_BOUND_TOP,
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
    }

    @Test
    public void testUidStateChangedCallbackForegroundToTop() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_BOUND_TOP,
                ActivityManager.PROCESS_STATE_TOP);
    }

    @Test
    public void testUidStateChangedCallbackForegroundServiceToCached() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
    }

    @Test
    public void testUidStateChangedCallbackForegroundServiceToBackground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_STATE_RECEIVER);
    }

    @Test
    public void testUidStateChangedCallbackForegroundServiceToForeground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_STATE_BOUND_TOP);
    }

    @Test
    public void testUidStateChangedCallbackForegroundServiceToTop() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_STATE_TOP);
    }

    @Test
    public void testUidStateChangedCallbackTopToCached() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
    }

    @Test
    public void testUidStateChangedCallbackTopToBackground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_STATE_RECEIVER);
    }

    @Test
    public void testUidStateChangedCallbackTopToForeground() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_STATE_BOUND_TOP);
    }

    @Test
    public void testUidStateChangedCallbackTopToForegroundService() {
        testUidStateChangedCallback(
                ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
    }

    @Test
    public void testUidStateChangedCallbackCachedToNonexistent() {
        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .cachedState()
                .update();

        procStateBuilder(UID)
                .nonExistentState()
                .update();

        verify(cb, never()).onUidStateChanged(anyInt(), anyInt(), anyBoolean());
    }

    @Test
    public void testUidStateChangedCallbackBackgroundToNonexistent() {
        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .backgroundState()
                .update();

        procStateBuilder(UID)
                .nonExistentState()
                .update();

        verify(cb, atLeastOnce()).onUidStateChanged(eq(UID), eq(UID_STATE_CACHED), eq(false));
    }

    @Test
    public void testUidStateChangedCallbackForegroundToNonexistent() {
        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .foregroundState()
                .update();

        procStateBuilder(UID)
                .nonExistentState()
                .update();

        verify(cb, atLeastOnce()).onUidStateChanged(eq(UID), eq(UID_STATE_CACHED), eq(true));
    }

    @Test
    public void testUidStateChangedCallbackForegroundServiceToNonexistent() {
        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .foregroundServiceState()
                .update();

        procStateBuilder(UID)
                .nonExistentState()
                .update();

        verify(cb, atLeastOnce()).onUidStateChanged(eq(UID), eq(UID_STATE_CACHED), eq(true));
    }

    @Test
    public void testUidStateChangedCallbackTopToNonexistent() {
        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .topState()
                .update();

        procStateBuilder(UID)
                .nonExistentState()
                .update();

        verify(cb, atLeastOnce()).onUidStateChanged(eq(UID), eq(UID_STATE_CACHED), eq(true));
    }

    @Test
    public void testUidStateChangedBackgroundThenForegroundImmediately() {
        procStateBuilder(UID)
@@ -882,32 +661,6 @@ public class AppOpsUidStateTrackerTest {
        assertEquals(UID_STATE_TOP, mIntf.getUidState(UID));
    }

    public void testUidStateChangedCallback(int initialState, int finalState) {
        int initialUidState = processStateToUidState(initialState);
        int finalUidState = processStateToUidState(finalState);
        boolean foregroundChange = initialUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                        != finalUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED;
        boolean finalUidStateIsBackgroundAndLessImportant =
                finalUidState > UID_STATE_MAX_LAST_NON_RESTRICTED
                        && finalUidState > initialUidState;

        UidStateChangedCallback cb = addUidStateChangeCallback();

        procStateBuilder(UID)
                .setState(initialState)
                .update();

        procStateBuilder(UID)
                .setState(finalState)
                .update();

        if (finalUidStateIsBackgroundAndLessImportant) {
            mClock.advanceTime(mConstants.TOP_STATE_SETTLE_TIME + 1);
        }

        verify(cb, atLeastOnce())
                .onUidStateChanged(eq(UID), eq(finalUidState), eq(foregroundChange));
    }

    private UidStateChangedCallback addUidStateChangeCallback() {
        UidStateChangedCallback cb =
+260 −0

File added.

Preview size limit exceeded, changes collapsed.