Loading services/core/java/com/android/server/am/ActivityManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; services/core/java/com/android/server/am/UidObserverController.java +43 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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<>(); Loading @@ -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) { Loading @@ -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); } Loading @@ -119,7 +121,7 @@ public class UidObserverController { } } SparseArray<ChangeRecord> getPendingUidChangesForTest() { ArrayList<ChangeRecord> getPendingUidChangesForTest() { return mPendingUidChanges; } Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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++) { Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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(" "); Loading Loading @@ -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); Loading services/core/java/com/android/server/am/UidRecord.java +4 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +6 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } } Loading services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java +41 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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) { Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -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;
services/core/java/com/android/server/am/UidObserverController.java +43 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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<>(); Loading @@ -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) { Loading @@ -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); } Loading @@ -119,7 +121,7 @@ public class UidObserverController { } } SparseArray<ChangeRecord> getPendingUidChangesForTest() { ArrayList<ChangeRecord> getPendingUidChangesForTest() { return mPendingUidChanges; } Loading Loading @@ -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) { Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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++) { Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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(" "); Loading Loading @@ -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); Loading
services/core/java/com/android/server/am/UidRecord.java +4 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading
services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +6 −12 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } } Loading
services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java +41 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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) { Loading