Merge "Check PendingStartActivityUids list before updateOomAdj is done." into rvc-dev am: 600ce540ca am: 20710498ee am: 5b95c916c5

Change-Id: Ibc31718f6e0626b6190560cd25f529c512c71339
This commit is contained in:
Hui Yu
2020-05-21 16:39:47 +00:00
committed by Automerger Merge Worker
5 changed files with 119 additions and 3 deletions

View File

@@ -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);
}

View File

@@ -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;
@@ -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
@@ -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;
}
}
@@ -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) {

View File

@@ -938,6 +938,7 @@ public final class OomAdjuster {
mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
}
mService.mInternal.updatePendingTopUid(uidRec.uid, false);
}
if (mLocalPowerManager != null) {
mLocalPowerManager.finishUidChanges();

View File

@@ -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;
@@ -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;
@@ -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) {
@@ -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) {
@@ -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> {

View File

@@ -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;
@@ -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.