Merge "Add uid to PendingStartActivityUids when activity resumed." into rvc-dev am: c05fd22ce1 am: bb97cab3ce

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11723113

Change-Id: If32fc31a02f37e48c26faa3462f9873edc6eb973
This commit is contained in:
Hui Yu
2020-06-09 05:25:11 +00:00
committed by Automerger Merge Worker
8 changed files with 126 additions and 91 deletions

View File

@@ -429,11 +429,17 @@ public abstract class ActivityManagerInternal {
int userId, int[] appIdWhitelist);
/**
* Add or delete uid from the ActivityManagerService PendingStartActivityUids list.
* Add uid to the ActivityManagerService PendingStartActivityUids list.
* @param uid uid
* @param pending add to the list if true, delete from list if false.
* @param pid pid of the ProcessRecord that is pending top.
*/
public abstract void updatePendingTopUid(int uid, boolean pending);
public abstract void addPendingTopUid(int uid, int pid);
/**
* Delete uid from the ActivityManagerService PendingStartActivityUids list.
* @param uid uid
*/
public abstract void deletePendingTopUid(int uid);
/**
* Is the uid in ActivityManagerService PendingStartActivityUids list?

View File

@@ -28,6 +28,7 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.AppOpsManager.OP_NONE;
@@ -299,7 +300,6 @@ 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;
@@ -421,7 +421,6 @@ public class ActivityManagerService extends IActivityManager.Stub
* Priority we boost main thread and RT of top app to.
*/
public static final int TOP_APP_PRIORITY_BOOST = -10;
private static final String SYSTEM_PROPERTY_DEVICE_PROVISIONED =
"persist.sys.device_provisioned";
@@ -823,45 +822,7 @@ 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;
}
}
private final PendingStartActivityUids mPendingStartActivityUids;
/**
* Puts the process record in the map.
@@ -2585,6 +2546,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mFactoryTest = FACTORY_TEST_OFF;
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
mInternal = new LocalService();
mPendingStartActivityUids = new PendingStartActivityUids(mContext);
}
// Note: This method is invoked on the main thread but may need to attach various
@@ -2742,6 +2704,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mInternal = new LocalService();
mPendingStartActivityUids = new PendingStartActivityUids(mContext);
}
public void setSystemServiceManager(SystemServiceManager mgr) {
@@ -6093,9 +6056,18 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
for (int i = 0; i < pids.length; i++) {
ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
states[i] = (pr == null) ? PROCESS_STATE_NONEXISTENT : pr.getCurProcState();
if (scores != null) {
scores[i] = (pr == null) ? ProcessList.INVALID_ADJ : pr.curAdj;
if (pr != null) {
final boolean isPendingTop =
mPendingStartActivityUids.isPendingTopPid(pr.uid, pids[i]);
states[i] = isPendingTop ? PROCESS_STATE_TOP : pr.getCurProcState();
if (scores != null) {
scores[i] = isPendingTop ? ProcessList.FOREGROUND_APP_ADJ : pr.curAdj;
}
} else {
states[i] = PROCESS_STATE_NONEXISTENT;
if (scores != null) {
scores[i] = ProcessList.INVALID_ADJ;
}
}
}
}
@@ -8839,15 +8811,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return true;
}
}
if (mInternal.isPendingTopUid(uid)) {
Slog.wtf(TAG, "PendingStartActivityUids isUidActive false but"
+ " isPendingTopUid true, uid:" + uid
+ " callingPackage:" + callingPackage);
return true;
} else {
return false;
}
return mInternal.isPendingTopUid(uid);
}
boolean isUidActiveLocked(int uid) {
@@ -19731,22 +19695,18 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
public void updatePendingTopUid(int uid, boolean pending) {
synchronized (mPendingStartActivityUidsLocked) {
if (pending) {
mPendingStartActivityUidsLocked.add(uid);
} else {
mPendingStartActivityUidsLocked.delete(uid);
}
}
public void addPendingTopUid(int uid, int pid) {
mPendingStartActivityUids.add(uid, pid);
}
@Override
public void deletePendingTopUid(int uid) {
mPendingStartActivityUids.delete(uid);
}
@Override
public boolean isPendingTopUid(int uid) {
synchronized (mPendingStartActivityUidsLocked) {
return mPendingStartActivityUidsLocked.isPendingTopUid(uid);
}
return mPendingStartActivityUids.isPendingTopUid(uid);
}
}

View File

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

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import android.content.Context;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
/**
* 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 ActivityManagerService#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 class PendingStartActivityUids {
static final String TAG = ActivityManagerService.TAG;
// Key is uid, value is Pair of pid and SystemClock.elapsedRealtime() when the
// uid is added.
private final SparseArray<Pair<Integer, Long>> mPendingUids = new SparseArray();
private Context mContext;
PendingStartActivityUids(Context context) {
mContext = context;
}
synchronized void add(int uid, int pid) {
if (mPendingUids.get(uid) == null) {
mPendingUids.put(uid, new Pair<>(pid, SystemClock.elapsedRealtime()));
}
}
synchronized void delete(int uid) {
final Pair<Integer, Long> pendingPid = mPendingUids.get(uid);
if (pendingPid != null) {
final long delay = SystemClock.elapsedRealtime() - pendingPid.second;
if (delay >= 1000 /*ms*/) {
Slog.i(TAG,
"PendingStartActivityUids startActivity to updateOomAdj delay:"
+ delay + "ms," + " uid:" + uid + " packageName:"
+ Settings.getPackageNameForUid(mContext, uid));
}
mPendingUids.delete(uid);
}
}
synchronized boolean isPendingTopPid(int uid, int pid) {
final Pair<Integer, Long> pendingPid = mPendingUids.get(uid);
if (pendingPid != null) {
return pendingPid.first == pid;
} else {
return false;
}
}
synchronized boolean isPendingTopUid(int uid) {
return mPendingUids.get(uid) != null;
}
}

View File

@@ -521,7 +521,6 @@ public class AppOpsService extends IAppOpsService.Stub {
public boolean hasForegroundWatchers;
public long lastTimeShowDebugToast;
public long lastTimePendingTopUid;
public UidState(int uid) {
this.uid = uid;
@@ -545,7 +544,6 @@ public class AppOpsService extends IAppOpsService.Stub {
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.
@@ -611,7 +609,6 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_CAMERA:
if (mActivityManagerInternal != null
&& mActivityManagerInternal.isPendingTopUid(uid)) {
maybeLogPendingTopUid(op, mode);
return MODE_ALLOWED;
} else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
@@ -629,7 +626,6 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_RECORD_AUDIO:
if (mActivityManagerInternal != null
&& mActivityManagerInternal.isPendingTopUid(uid)) {
maybeLogPendingTopUid(op, mode);
return MODE_ALLOWED;
} else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
@@ -709,7 +705,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mode == DEBUG_FGS_ALLOW_WHILE_IN_USE && state != UID_STATE_FOREGROUND_SERVICE) {
return;
}
final long now = System.currentTimeMillis();
final long now = SystemClock.elapsedRealtime();
if (lastTimeShowDebugToast == 0 || now - lastTimeShowDebugToast > 600000) {
lastTimeShowDebugToast = now;
mHandler.sendMessage(PooledLambda.obtainMessage(
@@ -717,19 +713,6 @@ 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

@@ -2842,7 +2842,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// their client may have activities.
// No longer have activities, so update LRU list and oom adj.
app.updateProcessInfo(true /* updateServiceConnectionActivities */,
false /* activityChange */, true /* updateOomAdj */);
false /* activityChange */, true /* updateOomAdj */,
false /* addPendingTopUid */);
}
}

View File

@@ -1682,7 +1682,8 @@ class ActivityStack extends Task {
// happens to be sitting towards the end.
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, false /* updateOomAdj */);
true /* activityChange */, false /* updateOomAdj */,
false /* addPendingTopUid */);
} else if (!next.isProcessRunning()) {
// Since the start-process is asynchronous, if we already know the process of next
// activity isn't running, we can start the process earlier to save the time to wait
@@ -1839,7 +1840,8 @@ class ActivityStack extends Task {
next.setState(RESUMED, "resumeTopActivityInnerLocked");
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */);
true /* activityChange */, true /* updateOomAdj */,
true /* addPendingTopUid */);
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.

View File

@@ -1007,8 +1007,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
boolean updateOomAdj) {
boolean updateOomAdj, boolean addPendingTopUid) {
if (mListener == null) return;
if (addPendingTopUid) {
mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
}
// Posting on handler so WM lock isn't held when we call into AM.
final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
mListener, updateServiceConnectionActivities, activityChange, updateOomAdj);
@@ -1068,7 +1071,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
// update ActivityManagerService.PendingStartActivityUids list.
if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
mAtm.mAmInternal.updatePendingTopUid(mUid, true);
mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
}
// 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