Loading core/java/android/app/ActivityManagerInternal.java +13 −0 Original line number Diff line number Diff line Loading @@ -428,4 +428,17 @@ public abstract class ActivityManagerInternal { String[] requiredPermissions, boolean serialized, int userId, int[] appIdWhitelist); /** * Add or delete uid from the ActivityManagerService PendingStartActivityUids list. * @param uid uid * @param pending add to the list if true, delete from list if false. */ public abstract void updatePendingTopUid(int uid, boolean pending); /** * Is the uid in ActivityManagerService PendingStartActivityUids list? * @param uid * @return true if exists, false otherwise. */ public abstract boolean isPendingTopUid(int uid); } services/core/java/com/android/server/am/ActivityManagerService.java +72 −1 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; Loading Loading @@ -821,6 +822,46 @@ public class ActivityManagerService extends IActivityManager.Stub } } /** * While starting activity, WindowManager posts a runnable to DisplayThread to updateOomAdj. * The latency of the thread switch could cause client app failure when the app is checking * {@link #isUidActive} before updateOomAdj is done. * * Use PendingStartActivityUids to save uid after WindowManager start activity and before * updateOomAdj is done. * * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock! */ final PendingStartActivityUids mPendingStartActivityUidsLocked = new PendingStartActivityUids(); final class PendingStartActivityUids { // Key is uid, value is SystemClock.elapsedRealtime() when the key is added. private final SparseLongArray mPendingUids = new SparseLongArray(); void add(int uid) { if (mPendingUids.indexOfKey(uid) < 0) { mPendingUids.put(uid, SystemClock.elapsedRealtime()); } } void delete(int uid) { if (mPendingUids.indexOfKey(uid) >= 0) { long delay = SystemClock.elapsedRealtime() - mPendingUids.get(uid); if (delay >= 1000) { Slog.wtf(TAG, "PendingStartActivityUids startActivity to updateOomAdj delay:" + delay + "ms," + " uid:" + uid + " packageName:" + Settings.getPackageNameForUid(mContext, uid)); } mPendingUids.delete(uid); } } boolean isPendingTopUid(int uid) { return mPendingUids.indexOfKey(uid) >= 0; } } /** * Puts the process record in the map. * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this Loading Loading @@ -8791,7 +8832,18 @@ public class ActivityManagerService extends IActivityManager.Stub "isUidActive"); } synchronized (this) { return isUidActiveLocked(uid); if (isUidActiveLocked(uid)) { return true; } } if (mInternal.isPendingTopUid(uid)) { Slog.wtf(TAG, "PendingStartActivityUids isUidActive false but" + " isPendingTopUid true, uid:" + uid + " callingPackage:" + callingPackage); return true; } else { return false; } } Loading Loading @@ -19682,6 +19734,25 @@ public class ActivityManagerService extends IActivityManager.Stub return uid >= 0 && mDeviceOwnerUid == uid; } } @Override public void updatePendingTopUid(int uid, boolean pending) { synchronized (mPendingStartActivityUidsLocked) { if (pending) { mPendingStartActivityUidsLocked.add(uid); } else { mPendingStartActivityUidsLocked.delete(uid); } } } @Override public boolean isPendingTopUid(int uid) { synchronized (mPendingStartActivityUidsLocked) { return mPendingStartActivityUidsLocked.isPendingTopUid(uid); } } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { services/core/java/com/android/server/am/OomAdjuster.java +1 −0 Original line number Diff line number Diff line Loading @@ -938,6 +938,7 @@ public final class OomAdjuster { mService.mServices.foregroundServiceProcStateChangedLocked(uidRec); } } mService.mInternal.updatePendingTopUid(uidRec.uid, false); } if (mLocalPowerManager != null) { mLocalPowerManager.finishUidChanges(); Loading services/core/java/com/android/server/appop/AppOpsService.java +28 −2 Original line number Diff line number Diff line Loading @@ -521,6 +521,7 @@ public class AppOpsService extends IAppOpsService.Stub { public boolean hasForegroundWatchers; public long lastTimeShowDebugToast; public long lastTimePendingTopUid; public UidState(int uid) { this.uid = uid; Loading @@ -542,6 +543,10 @@ public class AppOpsService extends IAppOpsService.Stub { if (mode == MODE_FOREGROUND) { if (appWidgetVisible) { return MODE_ALLOWED; } else if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if (state <= UID_STATE_TOP) { // process is in TOP. return MODE_ALLOWED; Loading Loading @@ -604,7 +609,11 @@ public class AppOpsService extends IAppOpsService.Stub { } else if (mode == MODE_ALLOWED) { switch (op) { case OP_CAMERA: if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { return MODE_ALLOWED; } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) { Loading @@ -618,7 +627,11 @@ public class AppOpsService extends IAppOpsService.Stub { return MODE_IGNORED; } case OP_RECORD_AUDIO: if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { return MODE_ALLOWED; } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) { Loading Loading @@ -704,6 +717,19 @@ public class AppOpsService extends IAppOpsService.Stub { mActivityManagerInternal, uid, op, mode)); } } void maybeLogPendingTopUid(int op, int mode) { final long now = System.currentTimeMillis(); if (lastTimePendingTopUid == 0 || now - lastTimePendingTopUid > 300000) { lastTimePendingTopUid = now; Slog.wtf(TAG, "PendingStartActivityUids evalMode, isPendingTopUid true, uid:" + uid + " packageName:" + Settings.getPackageNameForUid(mContext, uid) + " op:" + op + " mode:" + mode); } } } final static class Ops extends SparseArray<Op> { Loading services/core/java/com/android/server/wm/WindowProcessController.java +5 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.IApplicationThread; import android.app.ProfilerInfo; Loading Loading @@ -1065,6 +1066,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // to track as a separate apk in the process. packageName = info.packageName; } // update ActivityManagerService.PendingStartActivityUids list. if (topProcessState == ActivityManager.PROCESS_STATE_TOP) { mAtm.mAmInternal.updatePendingTopUid(mUid, true); } // Posting the message at the front of queue so WM lock isn't held when we call into AM, // and the process state of starting activity can be updated quicker which will give it a // higher scheduling group. Loading Loading
core/java/android/app/ActivityManagerInternal.java +13 −0 Original line number Diff line number Diff line Loading @@ -428,4 +428,17 @@ public abstract class ActivityManagerInternal { String[] requiredPermissions, boolean serialized, int userId, int[] appIdWhitelist); /** * Add or delete uid from the ActivityManagerService PendingStartActivityUids list. * @param uid uid * @param pending add to the list if true, delete from list if false. */ public abstract void updatePendingTopUid(int uid, boolean pending); /** * Is the uid in ActivityManagerService PendingStartActivityUids list? * @param uid * @return true if exists, false otherwise. */ public abstract boolean isPendingTopUid(int uid); }
services/core/java/com/android/server/am/ActivityManagerService.java +72 −1 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; Loading Loading @@ -821,6 +822,46 @@ public class ActivityManagerService extends IActivityManager.Stub } } /** * While starting activity, WindowManager posts a runnable to DisplayThread to updateOomAdj. * The latency of the thread switch could cause client app failure when the app is checking * {@link #isUidActive} before updateOomAdj is done. * * Use PendingStartActivityUids to save uid after WindowManager start activity and before * updateOomAdj is done. * * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock! */ final PendingStartActivityUids mPendingStartActivityUidsLocked = new PendingStartActivityUids(); final class PendingStartActivityUids { // Key is uid, value is SystemClock.elapsedRealtime() when the key is added. private final SparseLongArray mPendingUids = new SparseLongArray(); void add(int uid) { if (mPendingUids.indexOfKey(uid) < 0) { mPendingUids.put(uid, SystemClock.elapsedRealtime()); } } void delete(int uid) { if (mPendingUids.indexOfKey(uid) >= 0) { long delay = SystemClock.elapsedRealtime() - mPendingUids.get(uid); if (delay >= 1000) { Slog.wtf(TAG, "PendingStartActivityUids startActivity to updateOomAdj delay:" + delay + "ms," + " uid:" + uid + " packageName:" + Settings.getPackageNameForUid(mContext, uid)); } mPendingUids.delete(uid); } } boolean isPendingTopUid(int uid) { return mPendingUids.indexOfKey(uid) >= 0; } } /** * Puts the process record in the map. * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this Loading Loading @@ -8791,7 +8832,18 @@ public class ActivityManagerService extends IActivityManager.Stub "isUidActive"); } synchronized (this) { return isUidActiveLocked(uid); if (isUidActiveLocked(uid)) { return true; } } if (mInternal.isPendingTopUid(uid)) { Slog.wtf(TAG, "PendingStartActivityUids isUidActive false but" + " isPendingTopUid true, uid:" + uid + " callingPackage:" + callingPackage); return true; } else { return false; } } Loading Loading @@ -19682,6 +19734,25 @@ public class ActivityManagerService extends IActivityManager.Stub return uid >= 0 && mDeviceOwnerUid == uid; } } @Override public void updatePendingTopUid(int uid, boolean pending) { synchronized (mPendingStartActivityUidsLocked) { if (pending) { mPendingStartActivityUidsLocked.add(uid); } else { mPendingStartActivityUidsLocked.delete(uid); } } } @Override public boolean isPendingTopUid(int uid) { synchronized (mPendingStartActivityUidsLocked) { return mPendingStartActivityUidsLocked.isPendingTopUid(uid); } } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
services/core/java/com/android/server/am/OomAdjuster.java +1 −0 Original line number Diff line number Diff line Loading @@ -938,6 +938,7 @@ public final class OomAdjuster { mService.mServices.foregroundServiceProcStateChangedLocked(uidRec); } } mService.mInternal.updatePendingTopUid(uidRec.uid, false); } if (mLocalPowerManager != null) { mLocalPowerManager.finishUidChanges(); Loading
services/core/java/com/android/server/appop/AppOpsService.java +28 −2 Original line number Diff line number Diff line Loading @@ -521,6 +521,7 @@ public class AppOpsService extends IAppOpsService.Stub { public boolean hasForegroundWatchers; public long lastTimeShowDebugToast; public long lastTimePendingTopUid; public UidState(int uid) { this.uid = uid; Loading @@ -542,6 +543,10 @@ public class AppOpsService extends IAppOpsService.Stub { if (mode == MODE_FOREGROUND) { if (appWidgetVisible) { return MODE_ALLOWED; } else if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if (state <= UID_STATE_TOP) { // process is in TOP. return MODE_ALLOWED; Loading Loading @@ -604,7 +609,11 @@ public class AppOpsService extends IAppOpsService.Stub { } else if (mode == MODE_ALLOWED) { switch (op) { case OP_CAMERA: if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) { return MODE_ALLOWED; } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) { Loading @@ -618,7 +627,11 @@ public class AppOpsService extends IAppOpsService.Stub { return MODE_IGNORED; } case OP_RECORD_AUDIO: if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { if (mActivityManagerInternal != null && mActivityManagerInternal.isPendingTopUid(uid)) { maybeLogPendingTopUid(op, mode); return MODE_ALLOWED; } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) { return MODE_ALLOWED; } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) { Loading Loading @@ -704,6 +717,19 @@ public class AppOpsService extends IAppOpsService.Stub { mActivityManagerInternal, uid, op, mode)); } } void maybeLogPendingTopUid(int op, int mode) { final long now = System.currentTimeMillis(); if (lastTimePendingTopUid == 0 || now - lastTimePendingTopUid > 300000) { lastTimePendingTopUid = now; Slog.wtf(TAG, "PendingStartActivityUids evalMode, isPendingTopUid true, uid:" + uid + " packageName:" + Settings.getPackageNameForUid(mContext, uid) + " op:" + op + " mode:" + mode); } } } final static class Ops extends SparseArray<Op> { Loading
services/core/java/com/android/server/wm/WindowProcessController.java +5 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_N import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.IApplicationThread; import android.app.ProfilerInfo; Loading Loading @@ -1065,6 +1066,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // to track as a separate apk in the process. packageName = info.packageName; } // update ActivityManagerService.PendingStartActivityUids list. if (topProcessState == ActivityManager.PROCESS_STATE_TOP) { mAtm.mAmInternal.updatePendingTopUid(mUid, true); } // Posting the message at the front of queue so WM lock isn't held when we call into AM, // and the process state of starting activity can be updated quicker which will give it a // higher scheduling group. Loading