Merge "Remove flags for wallet and alarm" into sc-dev
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 0c07fa0..0709ff5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -17,11 +17,10 @@
import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
import static android.os.Process.INVALID_UID;
-import static android.os.UserHandle.USER_NULL;
+import android.Manifest;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.app.ActivityManager;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchMigrationHelper;
import android.app.appsearch.AppSearchResult;
@@ -63,6 +62,7 @@
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.stats.LoggerInstanceManager;
import com.android.server.appsearch.stats.PlatformLogger;
+import com.android.server.appsearch.util.PackageUtil;
import com.android.server.usage.StorageStatsManagerLocal;
import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
@@ -124,8 +124,10 @@
}
private void registerReceivers() {
- mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
- new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new UserActionReceiver(),
+ new IntentFilter(Intent.ACTION_USER_REMOVED),
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
//TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
@@ -135,8 +137,10 @@
packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
packageChangedFilter.addDataScheme("package");
packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
- packageChangedFilter, /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new PackageChangedReceiver(),
+ packageChangedFilter,
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
}
@@ -148,12 +152,13 @@
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED:
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
- if (userId == USER_NULL) {
- Log.e(TAG, "userId is missing in the intent: " + intent);
+ UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle == null) {
+ Log.e(TAG, "Extra "
+ + Intent.EXTRA_USER + " is missing in the intent: " + intent);
return;
}
- handleUserRemoved(UserHandle.of(userId));
+ handleUserRemoved(userHandle);
break;
default:
Log.e(TAG, "Received unknown intent: " + intent);
@@ -1183,13 +1188,9 @@
Objects.requireNonNull(actualCallingUser);
Objects.requireNonNull(claimedCallingPackage);
- int claimedCallingUid;
- try {
- Context claimedCallingContext =
- mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0);
- claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid(
- claimedCallingPackage, /*flags=*/ 0);
- } catch (PackageManager.NameNotFoundException e) {
+ int claimedCallingUid = PackageUtil.getPackageUidAsUser(
+ mContext, claimedCallingPackage, actualCallingUser);
+ if (claimedCallingUid == INVALID_UID) {
throw new SecurityException(
"Specified calling package [" + claimedCallingPackage + "] not found");
}
@@ -1257,23 +1258,44 @@
*
* <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
*
+ * @param requestedUser The user which the caller is requesting to execute as.
+ * @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
*/
// TODO(b/173553485) verifying that the caller has permission to access target user's data
// TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
// TODO(b/173553485) Implement SystemService.onUserStopping()
@NonNull
- private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) {
+ private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
int callingPid = Binder.getCallingPid();
- int finalUserId = ActivityManager.handleIncomingUser(
+ UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
+ if (callingUser.equals(requestedUser)) {
+ return requestedUser;
+ }
+ // Duplicates UserController#ensureNotSpecialUser
+ if (requestedUser.getIdentifier() < 0) {
+ throw new IllegalArgumentException(
+ "Call does not support special user " + requestedUser);
+ }
+ boolean canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS,
callingPid,
- callingUid,
- userHandle.getIdentifier(),
- /*allowAll=*/ false,
- /*requireFull=*/ false,
- /*name=*/ null,
- /*callerPackage=*/ null);
- return UserHandle.of(finalUserId);
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ if (!canInteractAcrossUsers) {
+ canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ callingPid,
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+ if (canInteractAcrossUsers) {
+ return requestedUser;
+ }
+ throw new SecurityException(
+ "Permission denied while calling from uid " + callingUid
+ + " with " + requestedUser + "; Need to run as either the calling user ("
+ + callingUser + "), or with one of the following permissions: "
+ + Manifest.permission.INTERACT_ACROSS_USERS + " or "
+ + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
}
// TODO(b/179160886): Cache the previous storage stats.
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index beb4d24..0775272 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -172,11 +172,6 @@
@Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userHandle);
- // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too
- return AppSearchImpl.create(
- appSearchDir,
- userContext,
- userHandle.getIdentifier(),
- /*logger=*/ null);
+ return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null);
}
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index a940dde..29cb57c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -201,7 +201,6 @@
public static AppSearchImpl create(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable AppSearchLogger logger)
throws AppSearchException {
Objects.requireNonNull(icingDir);
@@ -213,8 +212,7 @@
initStatsBuilder = new InitializeStats.Builder();
}
- AppSearchImpl appSearchImpl =
- new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder);
+ AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder);
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
appSearchImpl.initializeVisibilityStore();
@@ -238,7 +236,6 @@
private AppSearchImpl(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable InitializeStats.Builder initStatsBuilder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
@@ -256,7 +253,7 @@
"Constructing IcingSearchEngine, response",
Objects.hashCode(mIcingSearchEngineLocked));
- mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId);
+ mVisibilityStoreLocked = new VisibilityStore(this, userContext);
// The core initialization procedure. If any part of this fails, we bail into
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 7d0ce41..c857fb6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -36,6 +35,7 @@
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.android.server.appsearch.util.PackageUtil;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -493,21 +493,13 @@
@GuardedBy("mLock")
private int getPackageUidAsUserLocked(@NonNull String packageName) {
Integer packageUid = mPackageUidCacheLocked.get(packageName);
- if (packageUid != null) {
- return packageUid;
+ if (packageUid == null) {
+ packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle);
+ if (packageUid != Process.INVALID_UID) {
+ mPackageUidCacheLocked.put(packageName, packageUid);
+ }
}
-
- // TODO(b/173532925) since VisibilityStore has the same method, we can make this a
- // utility function
- try {
- packageUid = mContext.getPackageManager().getPackageUidAsUser(
- packageName, mUserHandle.getIdentifier());
- mPackageUidCacheLocked.put(packageName, packageUid);
- return packageUid;
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
- }
- return Process.INVALID_UID;
+ return packageUid;
}
//
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
new file mode 100644
index 0000000..53a1bed
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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.appsearch.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+
+/**
+ * Utilities for interacting with {@link android.content.pm.PackageManager},
+ * {@link android.os.UserHandle}, and other parts of dealing with apps and binder.
+ *
+ * @hide
+ */
+public class PackageUtil {
+ private PackageUtil() {}
+
+ /**
+ * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
+ * find the UID.
+ */
+ public static int getPackageUidAsUser(
+ @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) {
+ Context userContext = context.createContextAsUser(user, /*flags=*/ 0);
+ return getPackageUid(userContext, packageName);
+ }
+
+ /**
+ * Finds the UID of the {@code packageName} in the given {@code context}. Returns
+ * {@link Process#INVALID_UID} if unable to find the UID.
+ */
+ public static int getPackageUid(@NonNull Context context, @NonNull String packageName) {
+ try {
+ return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return Process.INVALID_UID;
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
index acff792..95ed368 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
@@ -18,7 +18,6 @@
import static android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA;
import android.annotation.NonNull;
-import android.annotation.UserIdInt;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
@@ -27,7 +26,6 @@
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -35,6 +33,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
+import com.android.server.appsearch.util.PackageUtil;
import com.google.android.icing.proto.PersistType;
@@ -67,9 +66,6 @@
* @hide
*/
public class VisibilityStore {
-
- private static final String TAG = "AppSearchVisibilityStore";
-
/** No-op user id that won't have any visibility settings. */
public static final int NO_OP_USER_ID = -1;
@@ -95,9 +91,6 @@
// Context of the user that the call is being made as.
private final Context mUserContext;
- // User ID of the caller who we're checking visibility settings for.
- private final int mUserId;
-
/** Stores the schemas that are platform-hidden. All values are prefixed. */
private final NotPlatformSurfaceableMap mNotPlatformSurfaceableMap =
new NotPlatformSurfaceableMap();
@@ -112,13 +105,9 @@
* @param appSearchImpl AppSearchImpl instance
* @param userContext Context of the user that the call is being made as
*/
- public VisibilityStore(
- @NonNull AppSearchImpl appSearchImpl,
- @NonNull Context userContext,
- @UserIdInt int userId) {
+ public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
mAppSearchImpl = appSearchImpl;
- mUserContext = userContext;
- mUserId = userId;
+ mUserContext = Objects.requireNonNull(userContext);
}
/**
@@ -348,6 +337,9 @@
Set<PackageIdentifier> packageIdentifiers =
mPackageAccessibleMap.getAccessiblePackages(
packageName, databaseName, prefixedSchema);
+ if (packageIdentifiers.isEmpty()) {
+ return false;
+ }
for (PackageIdentifier packageIdentifier : packageIdentifiers) {
// TODO(b/169883602): Consider caching the UIDs of packages. Looking this up in the
// package manager could be costly. We would also need to update the cache on
@@ -357,9 +349,10 @@
// the callerUid since clients can createContextAsUser with some other user, and then
// make calls to us. So just check if the appId portion of the uid is the same. This is
// essentially UserHandle.isSameApp, but that's not a system API for us to use.
- int callerAppId = UserHandle.getAppId((callerUid));
- int userAppId =
- UserHandle.getAppId(getPackageUidAsUser(packageIdentifier.getPackageName()));
+ int callerAppId = UserHandle.getAppId(callerUid);
+ int packageUid =
+ PackageUtil.getPackageUid(mUserContext, packageIdentifier.getPackageName());
+ int userAppId = UserHandle.getAppId(packageUid);
if (callerAppId != userAppId) {
continue;
}
@@ -401,17 +394,4 @@
@NonNull String packageName, @NonNull String databaseName) {
return ID_PREFIX + PrefixUtil.createPrefix(packageName, databaseName);
}
-
- /**
- * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
- * find the UID.
- */
- private int getPackageUidAsUser(@NonNull String packageName) {
- try {
- return mUserContext.getPackageManager().getPackageUidAsUser(packageName, mUserId);
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
- }
- return Process.INVALID_UID;
- }
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 25fd254..7cb8bc0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -604,6 +604,14 @@
String ownerPkgName, int ownerUid);
/**
+ * Effectively PendingIntent.getActivityForUser(), but the PendingIntent is
+ * owned by the given uid rather than by the caller (i.e. the system).
+ */
+ public abstract PendingIntent getPendingIntentActivityAsApp(
+ int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+ String ownerPkgName, int ownerUid);
+
+ /**
* @return mBootTimeTempAllowlistDuration of ActivityManagerConstants.
*/
public abstract long getBootTimeTempAllowListDuration();
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index 24ca72c..0e31567 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -119,7 +119,7 @@
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
try {
- platformCompat.setOverridesOnReleaseBuilds(config, packageName);
+ platformCompat.putOverridesOnReleaseBuilds(config, packageName);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 76b9865..1e650a8 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -40,7 +40,6 @@
import android.util.Pair;
import android.util.Slog;
-import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import libcore.io.IoUtils;
@@ -357,14 +356,14 @@
"versionCodeMajor",
0);
int revisionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "revisionCode", 0);
- boolean coreApp = parser.getAttributeBooleanValue("", "coreApp", false);
+ boolean coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
boolean isolatedSplits = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
"isolatedSplits", false);
boolean isFeatureSplit = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
"isFeatureSplit", false);
boolean isSplitRequired = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
"isSplitRequired", false);
- String configForSplit = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "configForSplit");
+ String configForSplit = parser.getAttributeValue(null, "configForSplit");
int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
diff --git a/core/java/android/os/incremental/IncrementalMetrics.java b/core/java/android/os/incremental/IncrementalMetrics.java
index c44b7d9..534525a 100644
--- a/core/java/android/os/incremental/IncrementalMetrics.java
+++ b/core/java/android/os/incremental/IncrementalMetrics.java
@@ -90,7 +90,7 @@
* @return total duration in milliseconds of delayed reads
*/
public long getTotalDelayedReadsDurationMillis() {
- return mData.getInt(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
+ return mData.getLong(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
}
/**
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 941e9aa..603df1e 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -157,7 +157,7 @@
private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
private static final boolean ENABLE_WALLPAPER_DIMMING =
- SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", false);
+ SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true);
private final ArrayList<Engine> mActiveEngines
= new ArrayList<Engine>();
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index f718d40..418d16e 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -168,7 +168,7 @@
* @param packageName the package name of the app whose changes will be overridden
* @throws SecurityException if overriding changes is not permitted
*/
- void setOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
+ void putOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
/**
* Adds overrides to compatibility changes.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bf59f4d..5ac2336 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4980,6 +4980,11 @@
<!-- List containing the allowed install sources for accessibility service. -->
<string-array name="config_accessibility_allowed_install_source" translatable="false"/>
+ <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED -->
+ <bool name="config_assistLongPressHomeEnabledDefault">true</bool>
+ <!-- Default value for Settings.ASSIST_TOUCH_GESTURE_ENABLED -->
+ <bool name="config_assistTouchGestureEnabledDefault">true</bool>
+
<!-- The amount of dimming to apply to wallpapers with mid range luminance. 0 displays
the wallpaper at full brightness. 1 displays the wallpaper as fully black. -->
<item name="config_wallpaperDimAmount" format="float" type="dimen">0.05</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7006d93..b574415 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4394,5 +4394,8 @@
<java-symbol type="dimen" name="starting_surface_icon_size" />
<java-symbol type="dimen" name="starting_surface_default_icon_size" />
+ <java-symbol type="bool" name="config_assistLongPressHomeEnabledDefault" />
+ <java-symbol type="bool" name="config_assistTouchGestureEnabledDefault" />
+
<java-symbol type="dimen" name="config_wallpaperDimAmount" />
</resources>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 1163536..d757a8c 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -39,11 +39,7 @@
<axis tag="wdth" stylevalue="100" />
<axis tag="wght" stylevalue="300" />
</font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
+ <font weight="400" style="normal">RobotoStatic-Regular.ttf</font>
<font weight="500" style="normal">Roboto-Regular.ttf
<axis tag="ital" stylevalue="0" />
<axis tag="wdth" stylevalue="100" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index b88751a..61f7fac 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1387,6 +1387,7 @@
static {
// Preload Roboto-Regular.ttf in Zygote for improving app launch performance.
preloadFontFile("/system/fonts/Roboto-Regular.ttf");
+ preloadFontFile("/system/fonts/RobotoStatic-Regular.ttf");
String locale = SystemProperties.get("persist.sys.locale", "en-US");
String script = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale)).getScript();
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 4da2a28..67484d4 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -21,18 +21,13 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
-import android.os.Build;
-import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterDefs;
-import android.telephony.TelephonyManager;
-import android.util.ArraySet;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.nio.charset.StandardCharsets;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
+import java.security.ProviderException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
@@ -41,7 +36,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Random;
-import java.util.Set;
/**
* Utilities for attesting the device's hardware identifiers.
@@ -110,92 +104,6 @@
}
}
- @NonNull private static KeymasterArguments prepareAttestationArgumentsForDeviceId(
- Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
- DeviceIdAttestationException {
- // Verify that device ID attestation types are provided.
- if (idTypes == null) {
- throw new NullPointerException("Missing id types");
- }
-
- return prepareAttestationArguments(context, idTypes, attestationChallenge);
- }
-
- /**
- * Prepares Keymaster Arguments with attestation data.
- * @hide should only be used by KeyChain.
- */
- @NonNull public static KeymasterArguments prepareAttestationArguments(Context context,
- @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
- DeviceIdAttestationException {
- // Check method arguments, retrieve requested device IDs and prepare attestation arguments.
- if (attestationChallenge == null) {
- throw new NullPointerException("Missing attestation challenge");
- }
- final KeymasterArguments attestArgs = new KeymasterArguments();
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, attestationChallenge);
- // Return early if the caller did not request any device identifiers to be included in the
- // attestation record.
- if (idTypes == null) {
- return attestArgs;
- }
- final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
- for (int idType : idTypes) {
- idTypesSet.add(idType);
- }
- TelephonyManager telephonyService = null;
- if (idTypesSet.contains(ID_TYPE_IMEI) || idTypesSet.contains(ID_TYPE_MEID)) {
- telephonyService = (TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE);
- if (telephonyService == null) {
- throw new DeviceIdAttestationException("Unable to access telephony service");
- }
- }
- for (final Integer idType : idTypesSet) {
- switch (idType) {
- case ID_TYPE_SERIAL:
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
- Build.getSerial().getBytes(StandardCharsets.UTF_8));
- break;
- case ID_TYPE_IMEI: {
- final String imei = telephonyService.getImei(0);
- if (imei == null) {
- throw new DeviceIdAttestationException("Unable to retrieve IMEI");
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
- imei.getBytes(StandardCharsets.UTF_8));
- break;
- }
- case ID_TYPE_MEID: {
- final String meid = telephonyService.getMeid(0);
- if (meid == null) {
- throw new DeviceIdAttestationException("Unable to retrieve MEID");
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
- meid.getBytes(StandardCharsets.UTF_8));
- break;
- }
- case USE_INDIVIDUAL_ATTESTATION: {
- attestArgs.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION);
- break;
- }
- default:
- throw new IllegalArgumentException("Unknown device ID type " + idType);
- }
- }
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
- Build.BRAND.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
- Build.DEVICE.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
- Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
- Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
- attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
- Build.MODEL.getBytes(StandardCharsets.UTF_8));
- return attestArgs;
- }
-
/**
* Performs attestation of the device's identifiers. This method returns a certificate chain
* whose first element contains the requested device identifiers in an extension. The device's
@@ -229,6 +137,13 @@
@NonNull public static X509Certificate[] attestDeviceIds(Context context,
@NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
DeviceIdAttestationException {
+ if (attestationChallenge == null) {
+ throw new NullPointerException("Missing attestation challenge");
+ }
+ if (idTypes == null) {
+ throw new NullPointerException("Missing id types");
+ }
+
String keystoreAlias = generateRandomAlias();
KeyGenParameterSpec.Builder builder =
new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN)
@@ -265,6 +180,12 @@
if (e.getCause() instanceof DeviceIdAttestationException) {
throw (DeviceIdAttestationException) e.getCause();
}
+ // Illegal argument errors are wrapped up by a ProviderException. Catch those so that
+ // we can unwrap them into a more meaningful exception type for the caller.
+ if (e instanceof ProviderException
+ && e.getCause() instanceof IllegalArgumentException) {
+ throw (IllegalArgumentException) e.getCause();
+ }
throw new DeviceIdAttestationException("Unable to perform attestation", e);
}
}
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index dddf2c1..70f03d2 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -44,7 +44,7 @@
<dimen name="pip_bottom_offset_buffer">1dp</dimen>
<!-- The corner radius for PiP window. -->
- <dimen name="pip_corner_radius">8dp</dimen>
+ <dimen name="pip_corner_radius">16dp</dimen>
<!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
<dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index a2c6567..c46b559 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -435,7 +435,8 @@
SurfaceControl.Transaction tx, float fraction) {
final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
setCurrentValue(alpha);
- getSurfaceTransactionHelper().alpha(tx, leash, alpha);
+ getSurfaceTransactionHelper().alpha(tx, leash, alpha)
+ .round(tx, leash, shouldApplyCornerRadius());
tx.apply();
}
@@ -526,16 +527,22 @@
float angle = (1.0f - fraction) * startingAngle;
setCurrentValue(bounds);
if (inScaleTransition() || sourceHintRect == null) {
-
if (isOutPipDirection) {
getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
} else {
- getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle);
+ getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle)
+ .round(tx, leash, base, bounds);
}
} else {
final Rect insets = computeInsets(fraction);
getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
initialSourceValue, bounds, insets);
+ if (shouldApplyCornerRadius()) {
+ final Rect destinationBounds = new Rect(bounds);
+ destinationBounds.inset(insets);
+ getSurfaceTransactionHelper().round(tx, leash,
+ initialContainerRect, destinationBounds);
+ }
}
if (!handlePipTransaction(leash, tx, bounds)) {
tx.apply();
@@ -564,9 +571,11 @@
x = fraction * (end.left - start.left) + start.left;
y = fraction * (end.bottom - start.top) + start.top;
}
- getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash,
- initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection,
- rotationDelta == ROTATION_270 /* clockwise */);
+ getSurfaceTransactionHelper()
+ .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
+ insets, degree, x, y, isOutPipDirection,
+ rotationDelta == ROTATION_270 /* clockwise */)
+ .round(tx, leash, initialContainerRect, bounds);
tx.apply();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
index 48a15d8..9fa3f69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
@@ -186,6 +186,18 @@
}
/**
+ * Operates the round corner radius on a given transaction and leash, scaled by bounds
+ * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+ */
+ public PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash,
+ Rect fromBounds, Rect toBounds) {
+ final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+ / Math.hypot(toBounds.width(), toBounds.height()));
+ tx.setCornerRadius(leash, mCornerRadius * scale);
+ return this;
+ }
+
+ /**
* Re-parents the snapshot to the parent's surface control and shows it.
*/
public PipSurfaceTransactionHelper reparentAndShowSurfaceSnapshot(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index e1b198c..7d032ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -184,6 +184,7 @@
mTaskOrganizer.applyTransaction(wct);
// The final task bounds will be applied by onFixedRotationFinished so that all
// coordinates are in new rotation.
+ mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
mDeferredAnimEndTransaction = tx;
return;
}
@@ -1041,7 +1042,9 @@
}
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
- mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, toBounds, degrees);
+ mSurfaceTransactionHelper
+ .scale(tx, mLeash, startBounds, toBounds, degrees)
+ .round(tx, mLeash, startBounds, toBounds);
if (mPipMenuController.isMenuVisible()) {
mPipMenuController.movePipMenu(mLeash, tx, toBounds);
} else {
@@ -1216,6 +1219,7 @@
// Just a resize in PIP
taskBounds = destinationBounds;
}
+ mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
wct.setBounds(mToken, taskBounds);
wct.setBoundsChangeTransaction(mToken, tx);
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index c482fc1..e7432ac 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -31,7 +31,7 @@
// Cache size limits.
static const size_t maxKeySize = 1024;
-static const size_t maxValueSize = 512 * 1024;
+static const size_t maxValueSize = 2 * 1024 * 1024;
static const size_t maxTotalSize = 1024 * 1024;
ShaderCache::ShaderCache() {
diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
index 1755657..63c52a1 100644
--- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
@@ -26,9 +26,9 @@
*/
oneway interface IMediaRoute2ProviderServiceCallback {
// TODO: Change it to updateRoutes?
- void updateState(in MediaRoute2ProviderInfo providerInfo);
+ void notifyProviderUpdated(in MediaRoute2ProviderInfo providerInfo);
void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo);
- void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+ void notifySessionsUpdated(in List<RoutingSessionInfo> sessionInfo);
void notifySessionReleased(in RoutingSessionInfo sessionInfo);
void notifyRequestFailed(long requestId, int reason);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 93fe06a..49e0411 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -141,6 +141,7 @@
private final Object mSessionLock = new Object();
private final Object mRequestIdsLock = new Object();
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
+ private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false);
private MediaRoute2ProviderServiceStub mStub;
private IMediaRoute2ProviderServiceCallback mRemoteCallback;
private volatile MediaRoute2ProviderInfo mProviderInfo;
@@ -287,16 +288,8 @@
Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
return;
}
-
- if (mRemoteCallback == null) {
- return;
- }
- try {
- mRemoteCallback.notifySessionUpdated(sessionInfo);
- } catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify session info changed.");
- }
}
+ scheduleUpdateSessions();
}
/**
@@ -479,6 +472,7 @@
void setCallback(IMediaRoute2ProviderServiceCallback callback) {
mRemoteCallback = callback;
schedulePublishState();
+ scheduleUpdateSessions();
}
void schedulePublishState() {
@@ -497,12 +491,40 @@
}
try {
- mRemoteCallback.updateState(mProviderInfo);
+ mRemoteCallback.notifyProviderUpdated(mProviderInfo);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to publish provider state.", ex);
}
}
+ void scheduleUpdateSessions() {
+ if (mSessionUpdateScheduled.compareAndSet(false, true)) {
+ mHandler.post(this::updateSessions);
+ }
+ }
+
+ private void updateSessions() {
+ if (!mSessionUpdateScheduled.compareAndSet(true, false)) {
+ return;
+ }
+
+ if (mRemoteCallback == null) {
+ return;
+ }
+
+ List<RoutingSessionInfo> sessions;
+ synchronized (mSessionLock) {
+ sessions = new ArrayList<>(mSessionInfo.values());
+ }
+
+ try {
+ mRemoteCallback.notifySessionsUpdated(sessions);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session info changed.");
+ }
+
+ }
+
/**
* Adds a requestId in the request ID list whose max size is {@link #MAX_REQUEST_IDS_SIZE}.
* When the max size is reached, the first element is removed (FIFO).
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 7f645ba..31d848d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -35,43 +35,11 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
- <TextView
- android:id="@+id/logout"
- android:layout_height="@dimen/logout_button_layout_height"
- android:layout_width="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="@dimen/logout_button_margin_bottom"
- android:gravity="center"
- android:paddingLeft="@dimen/logout_button_padding_horizontal"
- android:paddingRight="@dimen/logout_button_padding_horizontal"
- android:background="@drawable/logout_button_background"
- android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
- android:textAllCaps="true"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="13sp"
- android:text="@*android:string/global_action_logout" />
-
<include
layout="@layout/keyguard_clock_switch"
android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
-
- <TextView
- android:id="@+id/owner_info"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/date_owner_info_margin"
- android:layout_gravity="center_horizontal"
- android:layout_centerHorizontal="true"
- android:textColor="?attr/wallpaperTextColorSecondary"
- android:textSize="@dimen/widget_label_font_size"
- android:letterSpacing="0.05"
- android:ellipsize="marquee"
- android:singleLine="true" />
<FrameLayout
android:id="@+id/status_view_media_container"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
index d0e3d3c..51cab0a 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
@@ -29,12 +29,12 @@
android:paddingTop="@dimen/status_bar_padding_top"
android:minHeight="48dp">
- <LinearLayout
+ <FrameLayout
+ android:id="@+id/date_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_weight="1"
- android:orientation="horizontal"
android:gravity="center_vertical|start" >
<com.android.systemui.statusbar.policy.DateView
@@ -46,7 +46,7 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.QS.Status"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
- </LinearLayout>
+ </FrameLayout>
<android.widget.Space
android:id="@+id/space"
@@ -59,21 +59,22 @@
<FrameLayout
android:id="@+id/header_text_container"
android:layout_height="match_parent"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:gravity="center"
/>
- <LinearLayout
+ <FrameLayout
+ android:id="@+id/privacy_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:minHeight="48dp"
android:layout_weight="1"
- android:orientation="horizontal"
android:gravity="center_vertical|end" >
<include layout="@layout/ongoing_privacy_chip" />
- </LinearLayout>
+ </FrameLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-land/integers.xml b/packages/SystemUI/res/values-land/integers.xml
new file mode 100644
index 0000000..5937a07
--- /dev/null
+++ b/packages/SystemUI/res/values-land/integers.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<resources>
+ <integer name="qs_security_footer_maxLines">1</integer>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 96eda3d..2362a1a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -20,17 +20,10 @@
import android.app.IActivityManager;
import android.content.Context;
import android.graphics.Color;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
-import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
@@ -45,26 +38,18 @@
/**
* View consisting of:
* - keyguard clock
- * - logout button (on certain managed devices)
- * - owner information (if set)
* - media player (split shade mode only)
*/
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final String TAG = "KeyguardStatusView";
- private static final int MARQUEE_DELAY_MS = 2000;
private final LockPatternUtils mLockPatternUtils;
private final IActivityManager mIActivityManager;
private ViewGroup mStatusViewContainer;
- private TextView mLogoutView;
private KeyguardClockSwitch mClockView;
- private TextView mOwnerInfo;
- private boolean mCanShowOwnerInfo = true; // by default, try to show the owner information here
private KeyguardSliceView mKeyguardSlice;
- private Runnable mPendingMarqueeStart;
- private Handler mHandler;
private View mMediaHostContainer;
private float mDarkAmount = 0;
@@ -91,64 +76,17 @@
super(context, attrs, defStyle);
mIActivityManager = ActivityManager.getService();
mLockPatternUtils = new LockPatternUtils(getContext());
- mHandler = new Handler();
- onDensityOrFontScaleChanged();
- }
-
- void setEnableMarquee(boolean enabled) {
- if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
- if (enabled) {
- if (mPendingMarqueeStart == null) {
- mPendingMarqueeStart = () -> {
- setEnableMarqueeImpl(true);
- mPendingMarqueeStart = null;
- };
- mHandler.postDelayed(mPendingMarqueeStart, MARQUEE_DELAY_MS);
- }
- } else {
- if (mPendingMarqueeStart != null) {
- mHandler.removeCallbacks(mPendingMarqueeStart);
- mPendingMarqueeStart = null;
- }
- setEnableMarqueeImpl(false);
- }
- }
-
- private void setEnableMarqueeImpl(boolean enabled) {
- if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
- if (mOwnerInfo != null) mOwnerInfo.setSelected(enabled);
- }
-
- void setCanShowOwnerInfo(boolean canShowOwnerInfo) {
- mCanShowOwnerInfo = canShowOwnerInfo;
- mOwnerInfo = findViewById(R.id.owner_info);
- if (mOwnerInfo != null) {
- if (mCanShowOwnerInfo) {
- mOwnerInfo.setVisibility(VISIBLE);
- updateOwnerInfo();
- } else {
- mOwnerInfo.setVisibility(GONE);
- mOwnerInfo = null;
- }
- }
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mStatusViewContainer = findViewById(R.id.status_view_container);
- mLogoutView = findViewById(R.id.logout);
- if (mLogoutView != null) {
- mLogoutView.setOnClickListener(this::onLogoutClicked);
- }
mClockView = findViewById(R.id.keyguard_clock_container);
if (KeyguardClockAccessibilityDelegate.isNeeded(mContext)) {
mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
}
- if (mCanShowOwnerInfo) {
- mOwnerInfo = findViewById(R.id.owner_info);
- }
mKeyguardSlice = findViewById(R.id.keyguard_status_area);
mTextColor = mClockView.getCurrentTextColor();
@@ -158,7 +96,6 @@
mMediaHostContainer = findViewById(R.id.status_view_media_container);
- updateOwnerInfo();
updateDark();
}
@@ -173,60 +110,6 @@
mShowingHeader = hasHeader;
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- layoutOwnerInfo();
- }
-
- int getLogoutButtonHeight() {
- if (mLogoutView == null) {
- return 0;
- }
- return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
- }
-
- int getOwnerInfoHeight() {
- if (mOwnerInfo == null) {
- return 0;
- }
- return mOwnerInfo.getVisibility() == VISIBLE ? mOwnerInfo.getHeight() : 0;
- }
-
- void updateLogoutView(boolean shouldShowLogout) {
- if (mLogoutView == null) {
- return;
- }
- mLogoutView.setVisibility(shouldShowLogout ? VISIBLE : GONE);
- // Logout button will stay in language of user 0 if we don't set that manually.
- mLogoutView.setText(mContext.getResources().getString(
- com.android.internal.R.string.global_action_logout));
- }
-
- void onDensityOrFontScaleChanged() {
- if (mOwnerInfo != null) {
- mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.widget_label_font_size));
- loadBottomMargin();
- }
- }
-
- void updateOwnerInfo() {
- if (mOwnerInfo == null) return;
- String info = mLockPatternUtils.getDeviceOwnerInfo();
- if (info == null) {
- // Use the current user owner information if enabled.
- final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
- KeyguardUpdateMonitor.getCurrentUser());
- if (ownerInfoEnabled) {
- info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
- }
- }
- mOwnerInfo.setText(info);
- updateDark();
- }
-
void setDarkAmount(float darkAmount) {
if (mDarkAmount == darkAmount) {
return;
@@ -238,17 +121,6 @@
}
void updateDark() {
- boolean dark = mDarkAmount == 1;
- if (mLogoutView != null) {
- mLogoutView.setAlpha(dark ? 0 : 1);
- }
-
- if (mOwnerInfo != null) {
- boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
- mOwnerInfo.setVisibility(hasText ? VISIBLE : GONE);
- layoutOwnerInfo();
- }
-
final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
mKeyguardSlice.setDarkAmount(mDarkAmount);
mClockView.setTextColor(blendedTextColor);
@@ -277,13 +149,8 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardStatusView:");
- pw.println(" mOwnerInfo: " + (mOwnerInfo == null
- ? "null" : mOwnerInfo.getVisibility() == VISIBLE));
pw.println(" mDarkAmount: " + mDarkAmount);
pw.println(" mTextColor: " + Integer.toHexString(mTextColor));
- if (mLogoutView != null) {
- pw.println(" logout visible: " + (mLogoutView.getVisibility() == VISIBLE));
- }
if (mClockView != null) {
mClockView.dump(fd, pw, args);
}
@@ -297,28 +164,4 @@
mIconTopMarginWithHeader = getResources().getDimensionPixelSize(
R.dimen.widget_vertical_padding_with_header);
}
-
- private void layoutOwnerInfo() {
- if (mOwnerInfo != null && mOwnerInfo.getVisibility() != GONE) {
- // Animate owner info during wake-up transition
- mOwnerInfo.setAlpha(1f - mDarkAmount);
-
- float ratio = mDarkAmount;
- // Calculate how much of it we should crop in order to have a smooth transition
- int collapsed = mOwnerInfo.getTop() - mOwnerInfo.getPaddingTop();
- int expanded = mOwnerInfo.getBottom() + mOwnerInfo.getPaddingBottom();
- int toRemove = (int) ((expanded - collapsed) * ratio);
- setBottom(getMeasuredHeight() - toRemove);
- }
- }
-
- private void onLogoutClicked(View view) {
- int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
- try {
- mIActivityManager.switchUser(UserHandle.USER_SYSTEM);
- mIActivityManager.stopUser(currentUserId, true /*force*/, null);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to logout user", re);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index e4cabcb..32935c2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import android.graphics.Rect;
-import android.os.UserHandle;
import android.util.Slog;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -97,8 +96,6 @@
@Override
public void onInit() {
mKeyguardClockSwitchController.init();
- mView.setEnableMarquee(mKeyguardUpdateMonitor.isDeviceInteractive());
- mView.updateLogoutView(shouldShowLogout());
}
@Override
@@ -143,20 +140,6 @@
}
/**
- * Get the height of the logout button.
- */
- public int getLogoutButtonHeight() {
- return mView.getLogoutButtonHeight();
- }
-
- /**
- * Get the height of the owner information view.
- */
- public int getOwnerInfoHeight() {
- return mView.getOwnerInfoHeight();
- }
-
- /**
* Set keyguard status view alpha.
*/
public void setAlpha(float alpha) {
@@ -254,11 +237,6 @@
mKeyguardClockSwitchController.refresh();
}
- private boolean shouldShowLogout() {
- return mKeyguardUpdateMonitor.isLogoutEnabled()
- && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
- }
-
private final ConfigurationController.ConfigurationListener mConfigurationListener =
new ConfigurationController.ConfigurationListener() {
@Override
@@ -269,7 +247,6 @@
@Override
public void onDensityOrFontScaleChanged() {
mKeyguardClockSwitchController.onDensityOrFontScaleChanged();
- mView.onDensityOrFontScaleChanged();
}
};
@@ -277,8 +254,6 @@
@Override
public void onLockScreenModeChanged(int mode) {
mKeyguardSliceViewController.updateLockScreenMode(mode);
- mView.setCanShowOwnerInfo(false);
- mView.updateLogoutView(false);
}
@Override
@@ -301,31 +276,12 @@
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
refreshTime();
- mView.updateOwnerInfo();
- mView.updateLogoutView(shouldShowLogout());
}
}
@Override
- public void onStartedWakingUp() {
- mView.setEnableMarquee(true);
- }
-
- @Override
- public void onFinishedGoingToSleep(int why) {
- mView.setEnableMarquee(false);
- }
-
- @Override
public void onUserSwitchComplete(int userId) {
mKeyguardClockSwitchController.refreshFormat();
- mView.updateOwnerInfo();
- mView.updateLogoutView(shouldShowLogout());
- }
-
- @Override
- public void onLogoutEnabledChanged() {
- mView.updateLogoutView(shouldShowLogout());
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 4418696..ff3cb21 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -62,6 +62,7 @@
private final DozeParameters mDozeParameters;
private final DozeLog mDozeLog;
private final Lazy<StatusBarStateController> mStatusBarStateController;
+ private final TunerService mTunerService;
private boolean mKeyguardShowing;
private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
@@ -102,8 +103,15 @@
mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
mDozeLog = dozeLog;
- tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+ mTunerService = tunerService;
mStatusBarStateController = statusBarStateController;
+
+ mTunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+ }
+
+ @Override
+ public void destroy() {
+ mTunerService.removeTunable(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a159984..56efafb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1651,14 +1651,19 @@
Trace.endSection();
}
- /** Hide the keyguard and let {@code runner} handle the animation. */
+ /**
+ * Hide the keyguard and let {@code runner} handle the animation.
+ *
+ * This method should typically be called after {@link ViewMediatorCallback#keyguardDonePending}
+ * was called, when we are ready to hide the keyguard.
+ */
public void hideWithAnimation(IRemoteAnimationRunner runner) {
- if (!mShowing) {
+ if (!mKeyguardDonePending) {
return;
}
mKeyguardExitAnimationRunner = runner;
- hideLocked();
+ mViewMediatorCallback.readyForKeyguardDone();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index d8b342a..3e5e140 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -1447,10 +1447,14 @@
private void updateAssistantEntrypoints() {
mAssistantAvailable = mAssistManagerLazy.get()
.getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+ boolean longPressDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
mLongPressHomeEnabled = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 1) != 0;
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0) != 0;
+ boolean gestureDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
mAssistantTouchGestureEnabled = Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, 1) != 0;
+ Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0) != 0;
if (mOverviewProxyService.getProxy() != null) {
try {
mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 01a6684..ad4886c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.animation.UniqueObjectHostView;
import java.util.ArrayList;
import java.util.List;
@@ -384,12 +385,17 @@
private void switchSecurityFooter() {
if (mSecurityFooter != null) {
if (mContext.getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null
- && !mSecurityFooter.getParent().equals(mHeaderContainer)) {
+ == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null) {
// Adding the security view to the header, that enables us to avoid scrolling
switchToParent(mSecurityFooter, mHeaderContainer, 0);
} else {
- switchToParent(mSecurityFooter, this, -1);
+ // Where should this go? If there's media, right before it. Otherwise, at the end.
+ View mediaView = findViewByPredicate(v -> v instanceof UniqueObjectHostView);
+ int index = -1;
+ if (mediaView != null) {
+ index = indexOfChild(mediaView);
+ }
+ switchToParent(mSecurityFooter, this, index);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index f668722..08a68bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -68,7 +68,9 @@
private Space mDatePrivacySeparator;
private View mClockIconsSeparator;
private boolean mShowClockIconsSeparator;
- private ViewGroup mRightLayout;
+ private View mRightLayout;
+ private View mDateContainer;
+ private View mPrivacyContainer;
private BatteryMeterView mBatteryRemainingIcon;
private StatusIconContainer mIconContainer;
@@ -129,6 +131,8 @@
mSecurityHeaderView = findViewById(R.id.header_text_container);
mClockIconsSeparator = findViewById(R.id.separator);
mRightLayout = findViewById(R.id.rightLayout);
+ mDateContainer = findViewById(R.id.date_container);
+ mPrivacyContainer = findViewById(R.id.privacy_container);
mClockView = findViewById(R.id.clock);
mDatePrivacySeparator = findViewById(R.id.space);
@@ -179,6 +183,7 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
+ setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
}
@Override
@@ -187,6 +192,18 @@
updateResources();
}
+ private void setDatePrivacyContainersWidth(boolean landscape) {
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mDateContainer.getLayoutParams();
+ lp.width = landscape ? WRAP_CONTENT : 0;
+ lp.weight = landscape ? 0f : 1f;
+ mDateContainer.setLayoutParams(lp);
+
+ lp = (LinearLayout.LayoutParams) mPrivacyContainer.getLayoutParams();
+ lp.width = landscape ? WRAP_CONTENT : 0;
+ lp.weight = landscape ? 0f : 1f;
+ mPrivacyContainer.setLayoutParams(lp);
+ }
+
void updateResources() {
Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index b18f191..4136624 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -61,12 +61,6 @@
private static final float HORIZONTAL_ANIMATION_END = 0.2f;
/**
- * At which point from [0,1] does the alpha animation end (or start when
- * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
- */
- private static final float ALPHA_ANIMATION_END = 0.0f;
-
- /**
* At which point from [0,1] does the horizontal collapse animation start (or start when
* expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
*/
@@ -497,10 +491,10 @@
float targetValue;
if (isAppearing) {
- mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
+ mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
targetValue = 1.0f;
} else {
- mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+ mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
targetValue = 0.0f;
}
mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
@@ -584,19 +578,21 @@
}
private void updateAppearRect() {
- float inverseFraction = (1.0f - mAppearAnimationFraction);
- float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
- float translateYTotalAmount = translationFraction * mAnimationTranslationY;
- mAppearAnimationTranslation = translateYTotalAmount;
+ float interpolatedFraction = mCurrentAppearInterpolator.getInterpolation(
+ mAppearAnimationFraction);
+ mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY;
final int actualHeight = getActualHeight();
- float bottom = actualHeight * mAppearAnimationFraction;
+ float bottom = actualHeight * interpolatedFraction;
- setOutlineRect(0, mAppearAnimationTranslation,
- getWidth(), bottom + mAppearAnimationTranslation);
+ setOutlineRect(0, mAppearAnimationTranslation, getWidth(),
+ bottom + mAppearAnimationTranslation);
}
- private float getAppearAnimationFraction() {
- return mAppearAnimationFraction >= 0 ? mAppearAnimationFraction : 1;
+ private float getInterpolatedAppearAnimationFraction() {
+ if (mAppearAnimationFraction >= 0) {
+ return mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction);
+ }
+ return 1.0f;
}
private void updateAppearAnimationAlpha() {
@@ -629,18 +625,14 @@
@Override
public float getCurrentBackgroundRadiusTop() {
- float fraction = getAppearAnimationFraction();
- return isHeadsUpAnimatingAway() || isHeadsUp()
- ? mOutlineRadius * fraction
- : super.getCurrentBackgroundRadiusTop();
+ float fraction = getInterpolatedAppearAnimationFraction();
+ return MathUtils.lerp(0, super.getCurrentBackgroundRadiusTop(), fraction);
}
@Override
public float getCurrentBackgroundRadiusBottom() {
- float fraction = getAppearAnimationFraction();
- return isHeadsUpAnimatingAway() || isHeadsUp()
- ? mOutlineRadius * fraction
- : super.getCurrentBackgroundRadiusBottom();
+ float fraction = getInterpolatedAppearAnimationFraction();
+ return MathUtils.lerp(0, super.getCurrentBackgroundRadiusBottom(), fraction);
}
private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 3728388..5134c62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -249,9 +249,18 @@
@Override
public boolean setTopRoundness(float topRoundness, boolean animate) {
if (mTopRoundness != topRoundness) {
+ float diff = Math.abs(topRoundness - mTopRoundness);
mTopRoundness = topRoundness;
+ boolean shouldAnimate = animate;
+ if (PropertyAnimator.isAnimating(this, TOP_ROUNDNESS) && diff > 0.5f) {
+ // Fail safe:
+ // when we've been animating previously and we're now getting an update in the
+ // other direction, make sure to animate it too, otherwise, the localized updating
+ // may make the start larger than 1.0.
+ shouldAnimate = true;
+ }
PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
- ROUNDNESS_PROPERTIES, animate);
+ ROUNDNESS_PROPERTIES, shouldAnimate);
return true;
}
return false;
@@ -286,9 +295,18 @@
@Override
public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
if (mBottomRoundness != bottomRoundness) {
+ float diff = Math.abs(bottomRoundness - mBottomRoundness);
mBottomRoundness = bottomRoundness;
+ boolean shouldAnimate = animate;
+ if (PropertyAnimator.isAnimating(this, BOTTOM_ROUNDNESS) && diff > 0.5f) {
+ // Fail safe:
+ // when we've been animating previously and we're now getting an update in the
+ // other direction, make sure to animate it too, otherwise, the localized updating
+ // may make the start larger than 1.0.
+ shouldAnimate = true;
+ }
PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
- ROUNDNESS_PROPERTIES, animate);
+ ROUNDNESS_PROPERTIES, shouldAnimate);
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
deleted file mode 100644
index 24e1f32..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2015 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.systemui.statusbar.notification.stack;
-
-import android.graphics.Path;
-import android.view.animation.PathInterpolator;
-
-/**
- * An interpolator specifically designed for the appear animation of heads up notifications.
- */
-public class HeadsUpAppearInterpolator extends PathInterpolator {
-
- private static float X1 = 250f;
- private static float X2 = 200f;
- private static float XTOT = (X1 + X2);;
-
- public HeadsUpAppearInterpolator() {
- super(getAppearPath());
- }
-
- private static Path getAppearPath() {
- Path path = new Path();
- path.moveTo(0, 0);
- float y1 = 90f;
- float y2 = 80f;
- path.cubicTo(X1 * 0.8f / XTOT, y1 / y2,
- X1 * 0.8f / XTOT, y1 / y2,
- X1 / XTOT, y1 / y2);
- path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2,
- (X1 + X2 * 0.2f) / XTOT, 1.0f,
- 1.0f , 1.0f);
- return path;
- }
-
- public static float getFractionUntilOvershoot() {
- return X1 / XTOT;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index 4b49e3a..23aefd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -18,7 +18,6 @@
import android.content.res.Resources;
import android.util.MathUtils;
-import android.view.View;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
@@ -199,7 +198,7 @@
mExpanded = expandedHeight != 0.0f;
mAppearFraction = appearFraction;
if (mTrackedHeadsUp != null) {
- updateView(mTrackedHeadsUp, true);
+ updateView(mTrackedHeadsUp, false /* animate */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index a6bba93..dec9888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -548,7 +548,11 @@
@Override
public void onHeadsUpUnPinned(NotificationEntry entry) {
- mNotificationRoundnessManager.updateView(entry.getRow(), true /* animate */);
+ ExpandableNotificationRow row = entry.getRow();
+ // update the roundedness posted, because we might be animating away the
+ // headsup soon, so no need to set the roundedness to 0 and then back to 1.
+ row.post(() -> mNotificationRoundnessManager.updateView(row,
+ true /* animate */));
}
@Override
@@ -557,7 +561,9 @@
NotificationEntry topEntry = mHeadsUpManager.getTopEntry();
mView.setNumHeadsUp(numEntries);
mView.setTopHeadsUpEntry(topEntry);
- mNotificationRoundnessManager.updateView(entry.getRow(), false /* animate */);
+ generateHeadsUpAnimation(entry, isHeadsUp);
+ ExpandableNotificationRow row = entry.getRow();
+ mNotificationRoundnessManager.updateView(row, true /* animate */);
}
};
@@ -1234,7 +1240,7 @@
return mView.getFirstChildNotGone();
}
- public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
+ private void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
mView.generateHeadsUpAnimation(entry, isHeadsUp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 83dc6df..4fd2064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -21,7 +21,6 @@
import android.animation.ValueAnimator;
import android.util.Property;
import android.view.View;
-import android.view.animation.Interpolator;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.R;
@@ -50,11 +49,8 @@
public static final int ANIMATION_DURATION_SWIPE = 260;
public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
- public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550;
- public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED
- = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
- * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
- public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+ public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400;
+ public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 400;
public static final int ANIMATION_DURATION_PULSE_APPEAR =
KeyguardSliceView.DEFAULT_ANIM_DURATION;
public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
@@ -64,8 +60,6 @@
public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
private static final int MAX_STAGGER_COUNT = 5;
- private static final HeadsUpAppearInterpolator HEADS_UP_APPEAR_INTERPOLATOR =
- new HeadsUpAppearInterpolator();
private final int mGoToFullShadeAppearingTranslation;
private final int mPulsingAppearingTranslation;
@@ -115,14 +109,6 @@
public boolean wasAdded(View view) {
return mNewAddChildren.contains(view);
}
-
- @Override
- public Interpolator getCustomInterpolator(View child, Property property) {
- if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) {
- return HEADS_UP_APPEAR_INTERPOLATOR;
- }
- return null;
- }
};
}
@@ -422,7 +408,7 @@
if (event.headsUpFromBottom) {
mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
} else {
- changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED,
+ changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR,
true /* isHeadsUpAppear */);
}
mHeadsUpAppearChildren.add(changingView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index e30c53f..fda24c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1319,8 +1319,7 @@
mNotificationStackScrollLayoutController.getHeight()
- minPadding
- shelfSize
- - bottomPadding
- - mKeyguardStatusViewController.getLogoutButtonHeight();
+ - bottomPadding;
int count = 0;
ExpandableView previousView = null;
@@ -4150,11 +4149,6 @@
entry.setHeadsUpIsVisible();
}
}
-
- @Override
- public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, isHeadsUp);
- }
}
private class HeightListener implements QS.HeightListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 06aedaa..09779d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2118,7 +2118,12 @@
return;
}
- mKeyguardViewMediator.hideWithAnimation(runner);
+ // We post to the main thread for 2 reasons:
+ // 1. KeyguardViewMediator is not thread-safe.
+ // 2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
+ // ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur when doing
+ // dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
+ mMainThreadHandler.post(() -> mKeyguardViewMediator.hideWithAnimation(runner));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
index 02a07e4..de5a363 100644
--- a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
@@ -37,20 +37,16 @@
private final SparseArray<Boolean> mCallStrengthConfigs = new SparseArray<>();
private final SparseArray<Boolean> mNoCallingConfigs = new SparseArray<>();
private final CarrierConfigManager mCarrierConfigManager;
- private final boolean mDefaultCallStrengthConfig;
- private final boolean mDefaultNoCallingConfig;
+ private boolean mDefaultCallStrengthConfigLoaded;
+ private boolean mDefaultCallStrengthConfig;
+ private boolean mDefaultNoCallingConfigLoaded;
+ private boolean mDefaultNoCallingConfig;
@Inject
public CarrierConfigTracker(Context context) {
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
context.registerReceiver(
this, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
- mDefaultCallStrengthConfig =
- CarrierConfigManager.getDefaultConfig().getBoolean(
- CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
- mDefaultNoCallingConfig =
- CarrierConfigManager.getDefaultConfig().getBoolean(
- CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
}
@Override
@@ -81,6 +77,12 @@
if (mCallStrengthConfigs.indexOfKey(subId) >= 0) {
return mCallStrengthConfigs.get(subId);
}
+ if (!mDefaultCallStrengthConfigLoaded) {
+ mDefaultCallStrengthConfig =
+ CarrierConfigManager.getDefaultConfig().getBoolean(
+ CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
+ mDefaultCallStrengthConfigLoaded = true;
+ }
return mDefaultCallStrengthConfig;
}
@@ -91,6 +93,12 @@
if (mNoCallingConfigs.indexOfKey(subId) >= 0) {
return mNoCallingConfigs.get(subId);
}
+ if (!mDefaultNoCallingConfigLoaded) {
+ mDefaultNoCallingConfig =
+ CarrierConfigManager.getDefaultConfig().getBoolean(
+ CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
+ mDefaultNoCallingConfigLoaded = true;
+ }
return mDefaultNoCallingConfig;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 86b5287..c994d7c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7842,7 +7842,9 @@
incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
: -1,
incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
- : 0
+ : 0,
+ incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+ : -1
);
final int relaunchReason = r == null ? RELAUNCH_REASON_NONE
@@ -16176,6 +16178,14 @@
public PendingIntent getPendingIntentActivityAsApp(
int requestCode, @NonNull Intent intent, int flags, Bundle options,
String ownerPkg, int ownerUid) {
+ return getPendingIntentActivityAsApp(requestCode, new Intent[] { intent }, flags,
+ options, ownerPkg, ownerUid);
+ }
+
+ @Override
+ public PendingIntent getPendingIntentActivityAsApp(
+ int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+ String ownerPkg, int ownerUid) {
// system callers must explicitly set mutability state
final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0;
final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0;
@@ -16185,15 +16195,21 @@
}
final Context context = ActivityManagerService.this.mContext;
- String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
- intent.migrateExtraStreamToClipData(context);
- intent.prepareToLeaveProcess(context);
+ final ContentResolver resolver = context.getContentResolver();
+ final int len = intents.length;
+ final String[] resolvedTypes = new String[len];
+ for (int i = 0; i < len; i++) {
+ final Intent intent = intents[i];
+ resolvedTypes[i] = intent.resolveTypeIfNeeded(resolver);
+ intent.migrateExtraStreamToClipData(context);
+ intent.prepareToLeaveProcess(context);
+ }
IIntentSender target =
ActivityManagerService.this.getIntentSenderWithFeatureAsApp(
INTENT_SENDER_ACTIVITY, ownerPkg,
context.getAttributionTag(), null, null, requestCode,
- new Intent[] { intent },
- resolvedType != null ? new String[] { resolvedType } : null,
+ intents,
+ resolvedTypes,
flags, options, UserHandle.getUserId(ownerUid), ownerUid);
return target != null ? new PendingIntent(target) : null;
}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 508bd06..b2266f6 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -470,7 +470,9 @@
incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
: -1,
incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
- : 0);
+ : 0,
+ incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+ : -1);
final ProcessRecord parentPr = parentProcess != null
? (ProcessRecord) parentProcess.mOwner : null;
mService.addErrorToDropBox("anr", mApp, mApp.processName, activityShortComponentName,
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 96db1ad..75367d2 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -647,9 +647,9 @@
final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
overrides);
try {
- mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+ mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
@@ -671,9 +671,9 @@
final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
overrides);
try {
- mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+ mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2a1c055..55128be 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4502,8 +4502,12 @@
Slog.i("AppOpsDebug", "tag " + attributionTag + " found in "
+ packageName);
} else {
+ ArrayList<String> tagList = new ArrayList<>();
+ for (int i = 0; i < pkg.getAttributions().size(); i++) {
+ tagList.add(pkg.getAttributions().get(i).tag);
+ }
Slog.i("AppOpsDebug", "tag " + attributionTag + " missing from "
- + packageName);
+ + packageName + ", tags: " + tagList);
}
}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index eba53fb..2cd68b0 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -207,15 +207,6 @@
}
@Override
- public void setOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
- String packageName) {
- // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
- checkCompatChangeOverrideOverridablePermission();
- checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
- mCompatConfig.addOverrides(overrides, packageName);
- }
-
- @Override
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
checkCompatChangeOverridePermission();
Map<Long, PackageOverride> overridesMap = new HashMap<>();
@@ -230,6 +221,15 @@
}
@Override
+ public void putOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
+ String packageName) {
+ // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
+ checkCompatChangeOverrideOverridablePermission();
+ checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
+ mCompatConfig.addOverrides(overrides, packageName);
+ }
+
+ @Override
public int enableTargetSdkChanges(String packageName, int targetSdkVersion) {
checkCompatChangeOverridePermission();
int numChanges =
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index edc9d7c..204ebfc 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -47,7 +47,7 @@
mUniqueId = componentName.flattenToShortString();
}
- public void setCallback(MediaRoute2ProviderServiceProxy.Callback callback) {
+ public void setCallback(Callback callback) {
mCallback = callback;
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index ab38dca..21f61ca 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -16,6 +16,10 @@
package com.android.server.media;
+import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
@@ -43,6 +47,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -64,6 +69,7 @@
private Connection mActiveConnection;
private boolean mConnectionReady;
+ private boolean mIsManagerScanning;
private RouteDiscoveryPreference mLastDiscoveryPreference = null;
@GuardedBy("mLock")
@@ -86,6 +92,13 @@
pw.println(prefix + " mConnectionReady=" + mConnectionReady);
}
+ public void setManagerScanning(boolean managerScanning) {
+ if (mIsManagerScanning != managerScanning) {
+ mIsManagerScanning = managerScanning;
+ updateBinding();
+ }
+ }
+
@Override
public void requestCreateSession(long requestId, String packageName, String routeId,
Bundle sessionHints) {
@@ -209,7 +222,8 @@
// Bind when there is a discovery preference or an active route session.
return (mLastDiscoveryPreference != null
&& !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
- || !getSessionInfos().isEmpty();
+ || !getSessionInfos().isEmpty()
+ || mIsManagerScanning;
}
return false;
}
@@ -311,13 +325,12 @@
}
}
- private void onProviderStateUpdated(Connection connection,
- MediaRoute2ProviderInfo providerInfo) {
+ private void onProviderUpdated(Connection connection, MediaRoute2ProviderInfo providerInfo) {
if (mActiveConnection != connection) {
return;
}
if (DEBUG) {
- Slog.d(TAG, this + ": State changed ");
+ Slog.d(TAG, this + ": updated");
}
setAndNotifyProviderState(providerInfo);
}
@@ -350,40 +363,44 @@
mCallback.onSessionCreated(this, requestId, newSession);
}
- private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) {
+ private int findSessionByIdLocked(RoutingSessionInfo session) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ private void onSessionsUpdated(Connection connection, List<RoutingSessionInfo> sessions) {
if (mActiveConnection != connection) {
return;
}
- if (updatedSession == null) {
- Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from "
- + mComponentName);
- return;
- }
- updatedSession = assignProviderIdForSession(updatedSession);
-
- boolean found = false;
+ int targetIndex = 0;
synchronized (mLock) {
- for (int i = 0; i < mSessionInfos.size(); i++) {
- if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) {
- mSessionInfos.set(i, updatedSession);
- found = true;
- break;
+ for (RoutingSessionInfo session : sessions) {
+ if (session == null) continue;
+ session = assignProviderIdForSession(session);
+
+ int sourceIndex = findSessionByIdLocked(session);
+ if (sourceIndex < 0) {
+ mSessionInfos.add(targetIndex++, session);
+ dispatchSessionCreated(REQUEST_ID_NONE, session);
+ } else if (sourceIndex < targetIndex) {
+ Slog.w(TAG, "Ignoring duplicate session ID: " + session.getId());
+ } else {
+ mSessionInfos.set(sourceIndex, session);
+ Collections.swap(mSessionInfos, sourceIndex, targetIndex++);
+ dispatchSessionUpdated(session);
}
}
-
- if (!found) {
- for (RoutingSessionInfo releasingSession : mReleasingSessions) {
- if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) {
- return;
- }
- }
- Slog.w(TAG, "onSessionUpdated: Matching session info not found");
- return;
+ for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) {
+ RoutingSessionInfo releasedSession = mSessionInfos.remove(i);
+ dispatchSessionReleased(releasedSession);
}
}
-
- mCallback.onSessionUpdated(this, updatedSession);
}
private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
@@ -424,6 +441,21 @@
mCallback.onSessionReleased(this, releaedSession);
}
+ private void dispatchSessionCreated(long requestId, RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionCreated, this, requestId, session));
+ }
+
+ private void dispatchSessionUpdated(RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionUpdated, this, session));
+ }
+
+ private void dispatchSessionReleased(RoutingSessionInfo session) {
+ mHandler.sendMessage(
+ obtainMessage(mCallback::onSessionReleased, this, session));
+ }
+
private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) {
return new RoutingSessionInfo.Builder(sessionInfo)
.setOwnerPackageName(mComponentName.getPackageName())
@@ -436,7 +468,7 @@
return;
}
- if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
+ if (requestId == REQUEST_ID_NONE) {
Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
return;
}
@@ -561,16 +593,16 @@
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
- mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
+ void postProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
+ mHandler.post(() -> onProviderUpdated(Connection.this, providerInfo));
}
void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) {
mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo));
}
- void postSessionUpdated(RoutingSessionInfo sessionInfo) {
- mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
+ void postSessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
+ mHandler.post(() -> onSessionsUpdated(Connection.this, sessionInfo));
}
void postSessionReleased(RoutingSessionInfo sessionInfo) {
@@ -595,10 +627,10 @@
}
@Override
- public void updateState(MediaRoute2ProviderInfo providerInfo) {
+ public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderStateUpdated(providerInfo);
+ connection.postProviderUpdated(providerInfo);
}
}
@@ -611,10 +643,10 @@
}
@Override
- public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+ public void notifySessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postSessionUpdated(sessionInfo);
+ connection.postSessionsUpdated(sessionInfo);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1dbc8a9..168ca55 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -2156,6 +2156,8 @@
List<RouterRecord> routerRecords = getRouterRecords();
List<ManagerRecord> managerRecords = getManagerRecords();
+ boolean shouldBindProviders = false;
+
if (service.mPowerManager.isInteractive()) {
boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
manager.mIsScanning && service.mActivityManager
@@ -2166,6 +2168,7 @@
discoveryPreferences = routerRecords.stream()
.map(record -> record.mDiscoveryPreference)
.collect(Collectors.toList());
+ shouldBindProviders = true;
} else {
discoveryPreferences = routerRecords.stream().filter(record ->
service.mActivityManager.getPackageImportance(record.mPackageName)
@@ -2175,6 +2178,13 @@
}
}
+ for (MediaRoute2Provider provider : mRouteProviders) {
+ if (provider instanceof MediaRoute2ProviderServiceProxy) {
+ ((MediaRoute2ProviderServiceProxy) provider)
+ .setManagerScanning(shouldBindProviders);
+ }
+ }
+
synchronized (service.mLock) {
RouteDiscoveryPreference newPreference =
new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b135e88..9370b14 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -698,14 +698,13 @@
}
final long ident = Binder.clearCallingIdentity();
try {
- return injectCreatePendingIntent(mContext.createPackageContextAsUser(packageName,
- 0, user), 0 /* requestCode */, intents, FLAG_MUTABLE, opts, user);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Cannot create pending intent from shortcut " + shortcutId, e);
+ return injectCreatePendingIntent(0 /* requestCode */, intents,
+ FLAG_MUTABLE, opts, packageName, mPackageManagerInternal.getPackageUid(
+ packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO,
+ user.getIdentifier()));
} finally {
Binder.restoreCallingIdentity(ident);
}
- return null;
}
@Override
@@ -812,10 +811,10 @@
}
@VisibleForTesting
- PendingIntent injectCreatePendingIntent(Context context, int requestCode,
- @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
- return PendingIntent.getActivitiesAsUser(context, requestCode, intents, flags, options,
- user);
+ PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+ int flags, Bundle options, String ownerPackage, int ownerUserId) {
+ return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
+ flags, options, ownerPackage, ownerUserId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d58a6aa..c812fc8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -22340,7 +22340,7 @@
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(userId)) {
+ if (StorageManager.isUserKeyUnlocked(userId)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(userId)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -25246,7 +25246,7 @@
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) {
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -25586,7 +25586,7 @@
StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
final int flags;
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(user.id)) {
flags = StorageManager.FLAG_STORAGE_DE;
@@ -25600,7 +25600,7 @@
// Note: this code block is executed with the Installer lock
// already held, since it's invoked as a side-effect of
// executeBatchLI()
- if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+ if (StorageManager.isUserKeyUnlocked(user.id)) {
// Prepare app data on external storage; currently this is used to
// setup any OBB dirs that were created by the installer correctly.
int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index a6c93de..70b5c62 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -64,6 +64,11 @@
"android:activity_recognition_allow_listed_tags";
private static final String ACTIVITY_RECOGNITION_TAGS_SEPARATOR = ";";
+ private static ArraySet<String> sExpectedTags = new ArraySet<>(new String[] {
+ "awareness_provider", "activity_recognition_provider", "network_location_provider",
+ "network_location_calibration", "fused_location_provider", "geofencer_provider"});
+
+
@NonNull
private final Object mLock = new Object();
@@ -222,8 +227,14 @@
if (resolvedCode != code) {
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
mLocationTags)) {
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
+ Log.i("AppOpsDebugRemapping", "remapping " + packageName + " location "
+ + "for tag " + attributionTag);
+ }
return resolvedCode;
- } else if (packageName.equals("com.google.android.gms")) {
+ } else if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName + " code "
+ code + " for tag " + attributionTag);
}
@@ -232,10 +243,14 @@
if (resolvedCode != code) {
if (isDatasourceAttributionTag(uid, packageName, attributionTag,
mActivityRecognitionTags)) {
- Log.i("AppOpsDebugRemapping", "remapping " + packageName + " code "
- + code + " to " + resolvedCode + " for tag " + attributionTag);
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
+ Log.i("AppOpsDebugRemapping", "remapping " + packageName + " "
+ + "activity recognition for tag " + attributionTag);
+ }
return resolvedCode;
- } else if (packageName.equals("com.google.android.gms")) {
+ } else if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName
+ " code " + code + " for tag " + attributionTag);
}
@@ -351,13 +366,15 @@
if (appIdTags != null) {
final ArraySet<String> packageTags = appIdTags.get(packageName);
if (packageTags != null && packageTags.contains(attributionTag)) {
- if (packageName.equals("com.google.android.gms")) {
+ if (packageName.equals("com.google.android.gms")
+ && !sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", packageName + " tag "
+ attributionTag + " in " + packageTags);
}
return true;
}
- if (packageName.equals("com.google.android.gms")) {
+ if (packageName.equals("com.google.android.gms")
+ && sExpectedTags.contains(attributionTag)) {
Log.i("AppOpsDebugRemapping", packageName + " tag " + attributionTag
+ " NOT in " + packageTags);
}
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 7b4b23e..31e2ede 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -268,7 +268,9 @@
matrix.postRotate(90);
}
matrix.postTranslate(dx, dy);
- t.setMatrix(pinnedTask.getSurfaceControl(), matrix, new float[9]);
+ final SurfaceControl leash = pinnedTask.getSurfaceControl();
+ t.setMatrix(leash, matrix, new float[9])
+ .setCornerRadius(leash, pipTx.mCornerRadius);
Slog.i(TAG, "Seamless rotation PiP tx=" + pipTx + " pos=" + dx + "," + dy);
return;
}
diff --git a/services/core/jni/stats/SurfaceFlingerPuller.cpp b/services/core/jni/stats/SurfaceFlingerPuller.cpp
index 0e28da7..8873673 100644
--- a/services/core/jni/stats/SurfaceFlingerPuller.cpp
+++ b/services/core/jni/stats/SurfaceFlingerPuller.cpp
@@ -158,7 +158,8 @@
atom.total_jank_frames_sf_prediction_error(),
atom.total_jank_frames_app_buffer_stuffing(),
atom.display_refresh_rate_bucket(), atom.render_rate_bucket(),
- frameRateVote.value(), appDeadlineMisses.value());
+ frameRateVote.value(), appDeadlineMisses.value(),
+ atom.game_mode());
}
return AStatsManager_PULL_SUCCESS;
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index 755795d..3bcbcbdb 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -25,11 +25,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,13 +50,15 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
/** This tests AppSearchImpl when it's running with a platform-backed VisibilityStore. */
public class AppSearchImplPlatformTest {
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private AppSearchImpl mAppSearchImpl;
private int mGlobalQuerierUid;
@@ -57,20 +66,28 @@
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
mAppSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mGlobalQuerierUid =
@@ -85,14 +102,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Set schema1
String prefix = PrefixUtil.createPrefix("package", "database");
@@ -145,19 +167,16 @@
/*schemaVersion=*/ 0);
// Check that "schema1" still has the same visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isFalse();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isFalse(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -172,19 +191,16 @@
.isTrue();
// "schema2" has default visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema2",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isTrue();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema2",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isTrue(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -207,14 +223,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -320,8 +341,10 @@
@Test
public void testSetSchema_defaultPlatformVisible() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -348,8 +371,10 @@
@Test
public void testSetSchema_platformHidden() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -378,8 +403,9 @@
String packageName = "com.package";
// Make sure package doesn't global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageName, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, packageName)).thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -410,12 +436,16 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure foo doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -439,4 +469,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java b/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
deleted file mode 100644
index 60e1a8f..0000000
--- a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-// TODO(b/169883602): This is purposely a different package from the path so that AppSearchImplTest
-// can use it without an extra import. This should be moved into a proper package once
-// AppSearchImpl-VisibilityStore's dependencies are refactored.
-package com.android.server.appsearch.external.localstorage;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.content.pm.PackageManager;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Mock to help test package name, UID, and certificate verification. */
-public class MockPackageManager {
-
- @Mock private PackageManager mMockPackageManager;
-
- public MockPackageManager() {
- MockitoAnnotations.initMocks(this);
- }
-
- @NonNull
- public PackageManager getMockPackageManager() {
- return mMockPackageManager;
- }
-
- /** Mock a checkPermission call. */
- public void mockCheckPermission(String permission, String packageName, int permissionResult) {
- when(mMockPackageManager.checkPermission(permission, packageName))
- .thenReturn(permissionResult);
- }
-
- /** Mock a NameNotFoundException if the package name isn't installed. */
- public void mockThrowsNameNotFoundException(String packageName) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the exception
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code uid} contains the {@code packageName} */
- public void mockGetPackageUidAsUser(String packageName, @UserIdInt int callerUserId, int uid) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), eq(callerUserId)))
- .thenReturn(uid);
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), eq(callerUserId)))
- .thenReturn(uid);
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the method.
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code packageName} has been signed with {@code sha256Cert}. */
- public void mockAddSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(true);
- }
-
- /** Mocks that {@code packageName} has NOT been signed with {@code sha256Cert}. */
- public void mockRemoveSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(false);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index d9cfc54..6ac4d13 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -25,10 +25,17 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,39 +50,47 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
public class VisibilityStoreTest {
-
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
- private AppSearchImpl mAppSearchImpl;
private VisibilityStore mVisibilityStore;
private int mUid;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
- mAppSearchImpl =
+ AppSearchImpl appSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
- mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
+ mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
}
/**
@@ -103,8 +118,10 @@
@Test
public void testSetVisibility_platformSurfaceable() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
mVisibilityStore.setVisibility(
"package",
@@ -210,10 +227,13 @@
int uidNotFooOrBar = 3;
// Make sure none of them have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameBar, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameBar))
+ .thenReturn(PERMISSION_DENIED);
// By default, a schema isn't package accessible.
assertThat(
@@ -237,32 +257,43 @@
ImmutableList.of(new PackageIdentifier(packageNameBar, sha256CertBar))));
// Should fail if PackageManager doesn't see that it has the proper certificate
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockRemoveSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(false);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// Should fail if PackageManager doesn't think the package belongs to the uid
- mMockPackageManager.mockGetPackageUidAsUser(
- packageNameFoo, mContext.getUserId(), uidNotFooOrBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidNotFooOrBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// But if uid and certificate match, then we should have access
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -278,15 +309,21 @@
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -302,11 +339,13 @@
int uidFoo = 1;
// Pretend we can't find the Foo package.
- mMockPackageManager.mockThrowsNameNotFoundException(packageNameFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException());
// Make sure "foo" doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Grant package access
mVisibilityStore.setVisibility(
@@ -332,10 +371,12 @@
int uidFoo = 1;
// Set it up such that the test package has global query privileges, but "foo" doesn't.
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
mVisibilityStore.setVisibility(
/*packageName=*/ "",
@@ -354,8 +395,11 @@
mUid))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
/*packageName=*/ "",
@@ -365,4 +409,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 031532b..5a8c44c 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -86,7 +86,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
}
@@ -494,9 +493,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
// Insert schema
List<AppSearchSchema> schemas =
@@ -557,9 +554,7 @@
// Initialize AppSearchImpl. This should cause a reset.
appSearchImpl.close();
- appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, testLogger);
+ appSearchImpl = AppSearchImpl.create(appsearchDir, context, testLogger);
// Check recovery state
InitializeStats initStats = testLogger.mInitializeStats;
@@ -1688,7 +1683,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
// Initial check that we could do something at first.
@@ -1836,9 +1830,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1864,8 +1856,7 @@
// That document should be visible even from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1877,9 +1868,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1929,8 +1918,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
@@ -1951,9 +1939,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -2011,8 +1997,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index d1ca759..f0a6ef1 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -40,7 +40,6 @@
import com.android.server.appsearch.proto.QueryStatsProto;
import com.android.server.appsearch.proto.ScoringSpecProto;
import com.android.server.appsearch.proto.TermMatchType;
-import com.android.server.appsearch.visibilitystore.VisibilityStore;
import org.junit.Before;
import org.junit.Rule;
@@ -64,7 +63,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
mLogger = new TestLogger();
}
@@ -292,7 +290,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
mLogger);
InitializeStats iStats = mLogger.mInitializeStats;
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 734f05a..7e1639e 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
@@ -29,46 +30,46 @@
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.SparseIntArray;
import androidx.test.core.app.ApplicationProvider;
-import com.android.server.appsearch.external.localstorage.MockPackageManager;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Map;
public class PlatformLoggerTest {
private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
private static final String TEST_PACKAGE_NAME = "packageName";
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
- }
-
- static int calculateHashCodeMd5withBigInteger(@NonNull String str) throws
- NoSuchAlgorithmException, UnsupportedEncodingException {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(str.getBytes(/*charsetName=*/ "UTF-8"));
- byte[] digest = md.digest();
- return new BigInteger(digest).intValue();
+ }
+ };
}
@Test
@@ -294,39 +295,51 @@
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
TEST_DEFAULT_SAMPLING_INTERVAL,
/*samplingIntervals=*/ new SparseIntArray()));
- mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(testPackageName, /*flags=*/0)).thenReturn(testUid);
- //
// First time, no cache
- //
PlatformLogger.ExtraStats extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
-
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Second time, we have cache
- //
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// Count is still one since we will use the cache
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Remove the cache and try again
- //
assertThat(logger.removeCachedUidForPackage(testPackageName)).isEqualTo(testUid);
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// count increased by 1 since cache is cleared
- verify(mMockPackageManager.getMockPackageManager(), times(2)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(2))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
}
+
+ private static int calculateHashCodeMd5withBigInteger(@NonNull String str)
+ throws NoSuchAlgorithmException {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(str.getBytes(StandardCharsets.UTF_8));
+ byte[] digest = md.digest();
+ return new BigInteger(digest).intValue();
+ }
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f6baa6bb..7df2dd6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -635,8 +635,8 @@
}
@Override
- PendingIntent injectCreatePendingIntent(Context context, int requestCode,
- @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
+ PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+ int flags, Bundle options, String ownerPackage, int ownerUserId) {
return new PendingIntent(mock(IIntentSender.class));
}
}