Merge "Disable ClockOptionsProvider so clocks don't appear in picker app" into qt-dev
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index 82593b5..1fdb1f3 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -458,7 +458,7 @@
}
private String getFuncTypeAsString() {
- if (isRecycled()) throw new IllegalStateException();
+ if (isRecycled()) return "<recycled>";
if (isConstSupplier()) return "supplier";
String name = LambdaType.toString(getFlags(MASK_EXPOSED_AS));
if (name.endsWith("Consumer")) return "consumer";
@@ -466,7 +466,7 @@
if (name.endsWith("Predicate")) return "predicate";
if (name.endsWith("Supplier")) return "supplier";
if (name.endsWith("Runnable")) return "runnable";
- throw new IllegalStateException("Don't know the string representation of " + name);
+ return name;
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b342d37..33d6591 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -272,6 +272,7 @@
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.provider.DeviceConfig.Properties;
import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
@@ -356,6 +357,7 @@
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerService;
@@ -392,6 +394,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
@@ -861,6 +864,51 @@
*/
final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
+ /**
+ * Depth of overlapping activity-start PSS deferral notes
+ */
+ private final AtomicInteger mActivityStartingNesting = new AtomicInteger(0);
+
+ private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
+ new ActivityMetricsLaunchObserver() {
+ @Override
+ public void onActivityLaunched(byte[] activity, int temperature) {
+ // This is safe to force to the head of the queue because it relies only
+ // on refcounting to track begin/end of deferrals, not on actual
+ // message ordering. We don't care *what* activity is being
+ // launched; only that we're doing so.
+ if (mPssDeferralTime > 0) {
+ final Message msg = mBgHandler.obtainMessage(DEFER_PSS_MSG);
+ mBgHandler.sendMessageAtFrontOfQueue(msg);
+ }
+ }
+
+ // The other observer methods are unused
+ @Override
+ public void onIntentStarted(Intent intent) {
+ }
+
+ @Override
+ public void onIntentFailed() {
+ }
+
+ @Override
+ public void onActivityLaunchCancelled(byte[] abortingActivity) {
+ }
+
+ @Override
+ public void onActivityLaunchFinished(byte[] finalActivity) {
+ }
+ };
+
+ /**
+ * How long we defer PSS gathering while activities are starting, in milliseconds.
+ * This is adjustable via DeviceConfig. If it is zero or negative, no PSS deferral
+ * is done.
+ */
+ private volatile long mPssDeferralTime = 0;
+ private static final String ACTIVITY_START_PSS_DEFER_CONFIG = "activity_start_pss_defer";
+
private boolean mBinderTransactionTrackingEnabled = false;
/**
@@ -874,6 +922,20 @@
*/
boolean mFullPssPending = false;
+ /**
+ * Observe DeviceConfig changes to the PSS calculation interval
+ */
+ private final DeviceConfig.OnPropertiesChangedListener mPssDelayConfigListener =
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(Properties properties) {
+ mPssDeferralTime = properties.getLong(ACTIVITY_START_PSS_DEFER_CONFIG, 0);
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Activity-start PSS delay now "
+ + mPssDeferralTime + " ms");
+ }
+ }
+ };
/**
* This is for verifying the UID report flow.
@@ -1838,6 +1900,8 @@
}
static final int COLLECT_PSS_BG_MSG = 1;
+ static final int DEFER_PSS_MSG = 2;
+ static final int STOP_DEFERRING_PSS_MSG = 3;
final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
@Override
@@ -1945,6 +2009,30 @@
}
} while (true);
}
+
+ case DEFER_PSS_MSG: {
+ deferPssForActivityStart();
+ } break;
+
+ case STOP_DEFERRING_PSS_MSG: {
+ final int nesting = mActivityStartingNesting.decrementAndGet();
+ if (nesting <= 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "PSS activity start deferral interval ended; now "
+ + nesting);
+ }
+ if (nesting < 0) {
+ Slog.wtf(TAG, "Activity start nesting undercount!");
+ mActivityStartingNesting.incrementAndGet();
+ }
+ } else {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Still deferring PSS, nesting=" + nesting);
+ }
+ }
+ }
+ break;
+
}
}
};
@@ -8845,6 +8933,12 @@
NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
mHiddenApiBlacklist.registerObserver();
+ final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ActivityThread.currentApplication().getMainExecutor(),
+ mPssDelayConfigListener);
+
synchronized (this) {
mDebugApp = mOrigDebugApp = debugApp;
mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
@@ -8861,6 +8955,7 @@
com.android.internal.R.bool.config_multiuserDelayUserDataLocking);
mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs;
+ mPssDeferralTime = pssDeferralMs;
}
}
@@ -8923,6 +9018,7 @@
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis());
mAtmInternal.updateTopComponentForFactoryTest();
+ mAtmInternal.getLaunchObserverRegistry().registerLaunchObserver(mActivityLaunchObserver);
watchDeviceProvisioning(mContext);
@@ -16146,7 +16242,13 @@
return false;
}
if (mPendingPssProcesses.size() == 0) {
- mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
+ final long deferral = (mPssDeferralTime > 0 && mActivityStartingNesting.get() > 0)
+ ? mPssDeferralTime : 0;
+ if (DEBUG_PSS && deferral > 0) {
+ Slog.d(TAG_PSS, "requestPssLocked() deferring PSS request by "
+ + deferral + " ms");
+ }
+ mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, deferral);
}
if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
proc.pssProcState = procState;
@@ -16156,6 +16258,30 @@
}
/**
+ * Re-defer a posted PSS collection pass, if one exists. Assumes deferral is
+ * currently active policy when called.
+ */
+ private void deferPssIfNeededLocked() {
+ if (mPendingPssProcesses.size() > 0) {
+ mBgHandler.removeMessages(COLLECT_PSS_BG_MSG);
+ mBgHandler.sendEmptyMessageDelayed(COLLECT_PSS_BG_MSG, mPssDeferralTime);
+ }
+ }
+
+ private void deferPssForActivityStart() {
+ synchronized (ActivityManagerService.this) {
+ if (mPssDeferralTime > 0) {
+ if (DEBUG_PSS) {
+ Slog.d(TAG_PSS, "Deferring PSS collection for activity start");
+ }
+ deferPssIfNeededLocked();
+ mActivityStartingNesting.getAndIncrement();
+ mBgHandler.sendEmptyMessageDelayed(STOP_DEFERRING_PSS_MSG, mPssDeferralTime);
+ }
+ }
+ }
+
+ /**
* Schedule PSS collection of all processes.
*/
void requestPssAllProcsLocked(long now, boolean always, boolean memLowered) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 5ade50a..bcfe71b8 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -431,7 +431,7 @@
for (int i = 0; i < N; i++) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
- if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now,
+ if (computeOomAdjLocked(app, app.getCurRawAdj(), TOP_APP, true, now,
true)) {
retryCycles = true;
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 3a78aa2..037293f 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -50,6 +50,7 @@
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.util.ArraySet;
+import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -58,6 +59,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -147,11 +149,9 @@
PermissionInfo perm = dangerousPerms.get(i);
if (perm.isHardRestricted() || perm.backgroundPermission != null) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
} else if (perm.isSoftRestricted()) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(null, null, null,
@@ -167,6 +167,25 @@
}
}
+ /**
+ * Get op that controls the access related to the permission.
+ *
+ * <p>Usually the permission-op relationship is 1:1 but some permissions (e.g. fine location)
+ * {@link AppOpsManager#sOpToSwitch share an op} to control the access.
+ *
+ * @param permission The permission
+ *
+ * @return The op that controls the access of the permission
+ */
+ private static int getSwitchOp(@NonNull String permission) {
+ int op = AppOpsManager.permissionToOpCode(permission);
+ if (op == OP_NONE) {
+ return OP_NONE;
+ }
+
+ return AppOpsManager.opToSwitch(op);
+ }
+
private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
@UserIdInt int changedUserId) {
if (isStarted(changedUserId)) {
@@ -430,40 +449,89 @@
* <p>This processes ops previously added by {@link #addOpIfRestricted}
*/
private void syncPackages() {
+ // Remember which ops were already set. This makes sure that we always set the most
+ // permissive mode if two OpChanges are scheduled. This can e.g. happen if two
+ // permissions change the same op. See {@link #getSwitchOp}.
+ LongSparseLongArray alreadySetAppOps = new LongSparseLongArray();
+
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToChange op = mOpsToAllow.get(i);
+
setUidModeAllowed(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
for (int i = 0; i < allowIfDefaultCount; i++) {
final OpToChange op = mOpsToAllowIfDefault.get(i);
- setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundCount = mOpsToForegroundIfAllow.size();
- for (int i = 0; i < foregroundCount; i++) {
+
+ final int foregroundIfAllowedCount = mOpsToForegroundIfAllow.size();
+ for (int i = 0; i < foregroundIfAllowedCount; i++) {
final OpToChange op = mOpsToForegroundIfAllow.get(i);
- setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundIfAllowCount = mOpsToForeground.size();
- for (int i = 0; i < foregroundIfAllowCount; i++) {
+
+ final int foregroundCount = mOpsToForeground.size();
+ for (int i = 0; i < foregroundCount; i++) {
final OpToChange op = mOpsToForeground.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeForeground(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
final OpToChange op = mOpsToIgnore.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeIgnored(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
for (int i = 0; i < ignoreIfDefaultCount; i++) {
final OpToChange op = mOpsToIgnoreIfDefault.get(i);
- setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
+
final int defaultCount = mOpsToDefault.size();
for (int i = 0; i < defaultCount; i++) {
final OpToChange op = mOpsToDefault.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeDefault(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
}
@@ -479,7 +547,7 @@
private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo,
@NonNull PackageInfo pkg) {
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final int uid = pkg.applicationInfo.uid;
if (!permissionInfo.isRestricted()) {
@@ -581,7 +649,7 @@
}
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final String pkgName = pkg.packageName;
final int uid = pkg.applicationInfo.uid;
@@ -641,7 +709,7 @@
}
for (String permission : pkg.requestedPermissions) {
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
if (opCode == OP_NONE) {
continue;
}
@@ -658,24 +726,27 @@
}
}
- private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
+ private boolean setUidModeAllowedIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
}
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
- private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+ private boolean setUidModeForegroundIfAllow(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
}
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
- private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
+ private boolean setUidModeIgnoredIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
}
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
@@ -692,14 +763,17 @@
}
}
- private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
+ private boolean setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
if (currentMode == requiredModeBefore) {
mAppOpsManager.setUidMode(opCode, uid, newMode);
+ return true;
}
+
+ return false;
}
private void setUidModeDefault(int opCode, int uid, String packageName) {
diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING
index c7f8c07..c7e241b 100644
--- a/services/core/java/com/android/server/policy/TEST_MAPPING
+++ b/services/core/java/com/android/server/policy/TEST_MAPPING
@@ -41,6 +41,9 @@
"options": [
{
"include-filter": "android.permission.cts.SplitPermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
}
]
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index ba23258..af72931 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -25,6 +25,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.NonNull;
import android.app.RemoteAction;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -45,6 +46,7 @@
import android.view.IPinnedStackListener;
import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.internal.util.Preconditions;
import com.android.server.UiThread;
import java.io.PrintWriter;
@@ -326,8 +328,8 @@
boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
synchronized (mService.mGlobalLock) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
- if (mDisplayInfo.equals(displayInfo)) {
- // We are already in the right orientation, ignore
+ if (isSameDimensionAndRotation(mDisplayInfo, displayInfo)) {
+ // No dimension/rotation change, ignore
outBounds.setEmpty();
return false;
} else if (targetBounds.isEmpty()) {
@@ -427,6 +429,15 @@
notifyActionsChanged(mActions);
}
+ private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1,
+ @NonNull DisplayInfo display2) {
+ Preconditions.checkNotNull(display1);
+ Preconditions.checkNotNull(display2);
+ return ((display1.rotation == display2.rotation)
+ && (display1.logicalWidth == display2.logicalWidth)
+ && (display1.logicalHeight == display2.logicalHeight));
+ }
+
/**
* Notifies listeners that the PIP needs to be adjusted for the IME.
*/