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

Commit a3eea61e authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "Don't skip dispatching onUidGone() when a uid dies."

parents b27f59f6 cf4ceb82
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14872,6 +14872,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            change |= UidRecord.CHANGE_IDLE;
        }
        final int enqueuedChange = mUidObserverController.enqueueUidChange(
                uidRec == null ? null : uidRec.pendingChange,
                uid, change, procState, procStateSeq, capability, ephemeral);
        if (uidRec != null) {
            uidRec.lastReportedChange = enqueuedChange;
+43 −25
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerProto;
import android.app.IUidObserver;
@@ -29,7 +31,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
@@ -53,7 +54,7 @@ public class UidObserverController {
    final RemoteCallbackList<IUidObserver> mUidObservers = new RemoteCallbackList<>();

    @GuardedBy("mLock")
    private final SparseArray<ChangeRecord> mPendingUidChanges = new SparseArray<>();
    private final ArrayList<ChangeRecord> mPendingUidChanges = new ArrayList<>();
    @GuardedBy("mLock")
    private final ArrayList<ChangeRecord> mAvailUidChanges = new ArrayList<>();

@@ -71,27 +72,27 @@ public class UidObserverController {
    private static final boolean VALIDATE_UID_STATES = true;
    private final ActiveUids mValidateUids;

    UidObserverController(Handler handler) {
    UidObserverController(@NonNull Handler handler) {
        mHandler = handler;
        mValidateUids = new ActiveUids(null /* service */, false /* postChangesToAtm */);
    }

    void register(IUidObserver observer, int which, int cutpoint, String callingPackage,
            int callingUid) {
    void register(@NonNull IUidObserver observer, int which, int cutpoint,
            @NonNull String callingPackage, int callingUid) {
        synchronized (mLock) {
            mUidObservers.register(observer, new UidObserverRegistration(callingUid,
                    callingPackage, which, cutpoint));
        }
    }

    void unregister(IUidObserver observer) {
    void unregister(@NonNull IUidObserver observer) {
        synchronized (mLock) {
            mUidObservers.unregister(observer);
        }
    }

    int enqueueUidChange(int uid, int change, int procState, long procStateSeq,
            int capability, boolean ephemeral) {
    int enqueueUidChange(@Nullable ChangeRecord currentRecord, int uid, int change, int procState,
            long procStateSeq, int capability, boolean ephemeral) {
        synchronized (mLock) {
            if (mPendingUidChanges.size() == 0) {
                if (DEBUG_UID_OBSERVERS) {
@@ -100,10 +101,11 @@ public class UidObserverController {
                mHandler.post(mDispatchRunnable);
            }

            ChangeRecord changeRecord = mPendingUidChanges.get(uid);
            if (changeRecord == null) {
                changeRecord = getOrCreateChangeRecordLocked();
                mPendingUidChanges.put(uid, changeRecord);
            final ChangeRecord changeRecord = currentRecord != null
                    ? currentRecord : getOrCreateChangeRecordLocked();
            if (!changeRecord.isPending) {
                changeRecord.isPending = true;
                mPendingUidChanges.add(changeRecord);
            } else {
                change = mergeWithPendingChange(change, changeRecord.change);
            }
@@ -119,7 +121,7 @@ public class UidObserverController {
        }
    }

    SparseArray<ChangeRecord> getPendingUidChangesForTest() {
    ArrayList<ChangeRecord> getPendingUidChangesForTest() {
        return mPendingUidChanges;
    }

@@ -175,7 +177,10 @@ public class UidObserverController {
                mActiveUidChanges = new ChangeRecord[numUidChanges];
            }
            for (int i = 0; i < numUidChanges; i++) {
                mActiveUidChanges[i] = mPendingUidChanges.valueAt(i);
                final ChangeRecord changeRecord = mPendingUidChanges.get(i);
                mActiveUidChanges[i] = getOrCreateChangeRecordLocked();
                changeRecord.copyTo(mActiveUidChanges[i]);
                changeRecord.isPending = false;
            }
            mPendingUidChanges.clear();
            if (DEBUG_UID_OBSERVERS) {
@@ -216,13 +221,15 @@ public class UidObserverController {

        synchronized (mLock) {
            for (int j = 0; j < numUidChanges; j++) {
                mAvailUidChanges.add(mActiveUidChanges[j]);
                final ChangeRecord changeRecord = mActiveUidChanges[j];
                changeRecord.isPending = false;
                mAvailUidChanges.add(changeRecord);
            }
        }
    }

    private void dispatchUidsChangedForObserver(IUidObserver observer,
            UidObserverRegistration reg, int changesSize) {
    private void dispatchUidsChangedForObserver(@NonNull IUidObserver observer,
            @NonNull UidObserverRegistration reg, int changesSize) {
        if (observer == null) {
            return;
        }
@@ -318,7 +325,7 @@ public class UidObserverController {
        return mValidateUids.get(uid);
    }

    void dump(PrintWriter pw, String dumpPackage) {
    void dump(@NonNull PrintWriter pw, @Nullable String dumpPackage) {
        synchronized (mLock) {
            final int count = mUidObservers.getRegisteredCallbackCount();
            boolean printed = false;
@@ -353,7 +360,7 @@ public class UidObserverController {
        }
    }

    void dumpDebug(ProtoOutputStream proto, String dumpPackage) {
    void dumpDebug(@NonNull ProtoOutputStream proto, @Nullable String dumpPackage) {
        synchronized (mLock) {
            final int count = mUidObservers.getRegisteredCallbackCount();
            for (int i = 0; i < count; i++) {
@@ -366,23 +373,34 @@ public class UidObserverController {
        }
    }

    boolean dumpValidateUids(PrintWriter pw, String dumpPackage, int dumpAppId,
            String header, boolean needSep) {
    boolean dumpValidateUids(@NonNull PrintWriter pw, @Nullable String dumpPackage, int dumpAppId,
            @NonNull String header, boolean needSep) {
        return mValidateUids.dump(pw, dumpPackage, dumpAppId, header, needSep);
    }

    void dumpValidateUidsProto(ProtoOutputStream proto, String dumpPackage,
    void dumpValidateUidsProto(@NonNull ProtoOutputStream proto, @Nullable String dumpPackage,
            int dumpAppId, long fieldId) {
        mValidateUids.dumpProto(proto, dumpPackage, dumpAppId, fieldId);
    }

    static final class ChangeRecord {
        public boolean isPending;
        public int uid;
        public int change;
        public int procState;
        public int capability;
        public boolean ephemeral;
        public long procStateSeq;

        void copyTo(@NonNull ChangeRecord changeRecord) {
            changeRecord.isPending = isPending;
            changeRecord.uid = uid;
            changeRecord.change = change;
            changeRecord.procState = procState;
            changeRecord.capability = capability;
            changeRecord.ephemeral = ephemeral;
            changeRecord.procStateSeq = procStateSeq;
        }
    }

    private static final class UidObserverRegistration {
@@ -416,7 +434,7 @@ public class UidObserverController {
                ActivityManagerProto.UID_OBSERVER_FLAG_PROCSTATE,
        };

        UidObserverRegistration(int uid, String pkg, int which, int cutpoint) {
        UidObserverRegistration(int uid, @NonNull String pkg, int which, int cutpoint) {
            this.mUid = uid;
            this.mPkg = pkg;
            this.mWhich = which;
@@ -425,7 +443,7 @@ public class UidObserverController {
                    ? new SparseIntArray() : null;
        }

        void dump(PrintWriter pw, IUidObserver observer) {
        void dump(@NonNull PrintWriter pw, @NonNull IUidObserver observer) {
            pw.print("    ");
            UserHandle.formatUid(pw, mUid);
            pw.print(" ");
@@ -460,7 +478,7 @@ public class UidObserverController {
            }
        }

        void dumpDebug(ProtoOutputStream proto, long fieldId) {
        void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
            final long token = proto.start(fieldId);
            proto.write(UidObserverRegistrationProto.UID, mUid);
            proto.write(UidObserverRegistrationProto.PACKAGE, mPkg);
+4 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;

import com.android.internal.annotations.GuardedBy;
import com.android.server.am.UidObserverController.ChangeRecord;

/**
 * Overall information about a uid that has actively running processes.
@@ -107,6 +108,9 @@ public final class UidRecord {
            UidRecordProto.CHANGE_UNCACHED,
    };

    // UidObserverController is the only thing that should modify this.
    final ChangeRecord pendingChange = new ChangeRecord();

    int lastReportedChange;

    public UidRecord(int _uid) {
+6 −12
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.SparseArray;

import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
@@ -834,12 +833,13 @@ public class ActivityManagerServiceTest {
            // Reset the current state
            mHandler.reset();
            clearPendingUidChanges();
            uidRecord.pendingChange.isPending = false;

            mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch);

            // Verify that pendingChange is updated correctly.
            final ChangeRecord pendingChange = getPendingChange(uidRecord.uid);
            assertNotNull(pendingChange);
            final ChangeRecord pendingChange = uidRecord.pendingChange;
            assertTrue(pendingChange.isPending);
            assertEquals(TEST_UID, pendingChange.uid);
            assertEquals(expectedProcState, pendingChange.procState);
            assertEquals(TEST_PROC_STATE_SEQ1, pendingChange.procStateSeq);
@@ -923,22 +923,16 @@ public class ActivityManagerServiceTest {
        mAms.mProcessList.mActiveUids.clear();
    }

    private ChangeRecord getPendingChange(int uid) {
        final SparseArray<ChangeRecord> pendingChanges =
                mAms.mUidObserverController.getPendingUidChangesForTest();
        return pendingChanges.get(uid);
    }

    private void addPendingUidChange(ChangeRecord record) {
        mAms.mUidObserverController.getPendingUidChangesForTest().put(record.uid, record);
        mAms.mUidObserverController.getPendingUidChangesForTest().add(record);
    }

    private void addPendingUidChanges(ArrayList<ChangeRecord> changes) {
        final SparseArray<ChangeRecord> pendingChanges =
        final ArrayList<ChangeRecord> pendingChanges =
                mAms.mUidObserverController.getPendingUidChangesForTest();
        for (int i = 0; i < changes.size(); ++i) {
            final ChangeRecord record = changes.get(i);
            pendingChanges.put(record.uid, record);
            pendingChanges.add(record);
        }
    }

+41 −21
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -51,6 +52,9 @@ import com.android.server.am.UidObserverController.ChangeRecord;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;

@SmallTest
public class UidObserverControllerTest {
@@ -66,36 +70,41 @@ public class UidObserverControllerTest {

    @Before
    public void setUp() {
        mUidObserverController = new UidObserverController(Mockito.mock(Handler.class));
        MockitoAnnotations.initMocks(this);
        mUidObserverController = new UidObserverController(mock(Handler.class));
    }

    @Test
    public void testEnqueueUidChange() {
        int change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_ACTIVE,
                PROCESS_STATE_FOREGROUND_SERVICE, PROCESS_CAPABILITY_ALL, 0, false);
        int change = mUidObserverController.enqueueUidChange(null, TEST_UID1,
                UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
                PROCESS_CAPABILITY_ALL, 0, false);
        assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
                UidRecord.CHANGE_ACTIVE, change);
        assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
                PROCESS_CAPABILITY_ALL, 0, false);
        assertNull(getPendingChange(TEST_UID2));

        change = mUidObserverController.enqueueUidChange(TEST_UID2, UidRecord.CHANGE_CACHED,
                PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE, 99, true);
                PROCESS_CAPABILITY_ALL, 0, false, null);
        final ChangeRecord record1 = getLatestPendingChange(TEST_UID1);
        assertNull(getLatestPendingChange(TEST_UID2));

        final ChangeRecord record2 = new ChangeRecord();
        change = mUidObserverController.enqueueUidChange(record2, TEST_UID2,
                UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE,
                99, true);
        assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
                UidRecord.CHANGE_CACHED, change);
        assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
                PROCESS_CAPABILITY_ALL, 0, false);
                PROCESS_CAPABILITY_ALL, 0, false, null);
        assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT,
                PROCESS_CAPABILITY_NONE, 99, true);
                PROCESS_CAPABILITY_NONE, 99, true, record2);

        change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_UNCACHED,
                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
        change = mUidObserverController.enqueueUidChange(record1, TEST_UID1,
                UidRecord.CHANGE_UNCACHED, PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
        assertEquals("expected=ACTIVE|UNCACHED,actual=" + changeToStr(change),
                UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, change);
        assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED,
                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
                PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false, record1);
        assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT,
                PROCESS_CAPABILITY_NONE, 99, true);
                PROCESS_CAPABILITY_NONE, 99, true, record2);
    }

    @Test
@@ -135,11 +144,11 @@ public class UidObserverControllerTest {
        addPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_PROCSTATE,
                PROCESS_STATE_TOP, 0, PROCESS_CAPABILITY_ALL, false);

        final IUidObserver observer1 = Mockito.mock(IUidObserver.Stub.class);
        final IUidObserver observer1 = mock(IUidObserver.Stub.class);
        registerObserver(observer1,
                ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_ACTIVE,
                PROCESS_STATE_IMPORTANT_FOREGROUND, TEST_PKG2, TEST_UID2);
        final IUidObserver observer2 = Mockito.mock(IUidObserver.Stub.class);
        final IUidObserver observer2 = mock(IUidObserver.Stub.class);
        registerObserver(observer2, ActivityManager.UID_OBSERVER_PROCSTATE,
                PROCESS_STATE_SERVICE, TEST_PKG3, TEST_UID3);

@@ -209,13 +218,16 @@ public class UidObserverControllerTest {
        record.procStateSeq = procStateSeq;
        record.capability = capability;
        record.ephemeral = ephemeral;
        mUidObserverController.getPendingUidChangesForTest().put(uid, record);
        mUidObserverController.getPendingUidChangesForTest().add(record);
    }

    private void assertPendingChange(int uid, int change, int procState, long procStateSeq,
            int capability, boolean ephemeral) {
        final ChangeRecord record = getPendingChange(uid);
            int capability, boolean ephemeral, ChangeRecord expectedRecord) {
        final ChangeRecord record = getLatestPendingChange(uid);
        assertNotNull(record);
        if (expectedRecord != null) {
            assertEquals(expectedRecord, record);
        }
        assertEquals(change, record.change);
        assertEquals(procState, record.procState);
        assertEquals(procStateSeq, record.procStateSeq);
@@ -223,8 +235,16 @@ public class UidObserverControllerTest {
        assertEquals(ephemeral, record.ephemeral);
    }

    private ChangeRecord getPendingChange(int uid) {
        return mUidObserverController.getPendingUidChangesForTest().get(uid);
    private ChangeRecord getLatestPendingChange(int uid) {
        final ArrayList<ChangeRecord> changeRecords = mUidObserverController
                .getPendingUidChangesForTest();
        for (int i = changeRecords.size() - 1; i >= 0; --i) {
            final ChangeRecord record = changeRecords.get(i);
            if (record.uid == uid) {
                return record;
            }
        }
        return null;
    }

    private static String changeToStr(int change) {