Merge "Import translations. DO NOT MERGE" into rvc-dev
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 3f254c0..0647d8a 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -307,8 +307,8 @@
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
- * @see {@link #acquireLease(BlobHandle, int)}
- * @see {@link #acquireLease(BlobHandle, CharSequence)}
+ * @see #acquireLease(BlobHandle, int)
+ * @see #acquireLease(BlobHandle, CharSequence)
*/
public void acquireLease(@NonNull BlobHandle blobHandle, @IdRes int descriptionResId,
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
@@ -367,8 +367,8 @@
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
- * @see {@link #acquireLease(BlobHandle, int, long)}
- * @see {@link #acquireLease(BlobHandle, CharSequence)}
+ * @see #acquireLease(BlobHandle, int, long)
+ * @see #acquireLease(BlobHandle, CharSequence)
*/
public void acquireLease(@NonNull BlobHandle blobHandle, @NonNull CharSequence description,
@CurrentTimeMillisLong long leaseExpiryTimeMillis) throws IOException {
@@ -420,8 +420,8 @@
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
- * @see {@link #acquireLease(BlobHandle, int, long)}
- * @see {@link #acquireLease(BlobHandle, CharSequence, long)}
+ * @see #acquireLease(BlobHandle, int, long)
+ * @see #acquireLease(BlobHandle, CharSequence, long)
*/
public void acquireLease(@NonNull BlobHandle blobHandle, @IdRes int descriptionResId)
throws IOException {
@@ -467,8 +467,8 @@
* {@link #getRemainingLeaseQuotaBytes()} before trying to
* acquire a lease.
*
- * @see {@link #acquireLease(BlobHandle, int)}
- * @see {@link #acquireLease(BlobHandle, CharSequence, long)}
+ * @see #acquireLease(BlobHandle, int)
+ * @see #acquireLease(BlobHandle, CharSequence, long)
*/
public void acquireLease(@NonNull BlobHandle blobHandle, @NonNull CharSequence description)
throws IOException {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index abf78c6..2312635 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -41,7 +41,7 @@
* system will execute this job on your application's {@link android.app.job.JobService}.
* You identify the service component that implements the logic for your job when you
* construct the JobInfo using
- * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
+ * {@link android.app.job.JobInfo.Builder#Builder(int,android.content.ComponentName)}.
* </p>
* <p>
* The framework will be intelligent about when it executes jobs, and attempt to batch
@@ -153,7 +153,7 @@
* method is ignored.
*
* @param jobId unique identifier for the job to be canceled, as supplied to
- * {@link JobInfo.Builder#JobInfo.Builder(int, android.content.ComponentName)
+ * {@link JobInfo.Builder#Builder(int, android.content.ComponentName)
* JobInfo.Builder(int, android.content.ComponentName)}.
*/
public abstract void cancel(int jobId);
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
index fc26e08..dbb5bd3d 100644
--- a/apex/sdkextensions/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -22,6 +22,7 @@
binaries: [ "derive_sdk" ],
prebuilts: [ "cur_sdkinfo" ],
manifest: "manifest.json",
+ min_sdk_version: "current",
}
apex_defaults {
diff --git a/apex/sdkextensions/derive_sdk/Android.bp b/apex/sdkextensions/derive_sdk/Android.bp
index cf49902..c419b51 100644
--- a/apex/sdkextensions/derive_sdk/Android.bp
+++ b/apex/sdkextensions/derive_sdk/Android.bp
@@ -20,13 +20,13 @@
],
proto: {
type: "lite",
+ static: true,
},
sdk_version: "current",
stl: "c++_static",
shared_libs: [ "liblog" ],
static_libs: [
"libbase_ndk",
- "libprotobuf-cpp-lite-ndk",
],
}
@@ -45,7 +45,8 @@
compile_multilib: "prefer32",
stem: "derive_sdk",
apex_available: [ "test_com.android.sdkext" ],
- visibility: [ "//frameworks/base/apex/sdkextensions/testing" ]
+ visibility: [ "//frameworks/base/apex/sdkextensions/testing" ],
+ installable: false,
}
prebuilt_etc {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9a73fdd..3017ec0 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -9344,6 +9344,8 @@
// Return_code 1 indicates success.
// For full list, see frameworks/base/core/java/android/content/pm/PackageManager.java
optional int32 return_code = 4;
+ // Total size of the APKs installed for this package
+ optional int64 apks_size_bytes = 5;
}
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 17720a3..bfae632 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3743,7 +3743,6 @@
* To receive this callback, you must return true from onKeyDown for the current
* event stream.
*
- * @see KeyEvent.Callback#onKeyLongPress()
* @see KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
*/
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 49cc621..9067069 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2450,8 +2450,7 @@
* has access to it.
*
* @see ActivityOptions#setLaunchDisplayId(int)
- * @see android.view.Display.FLAG_PRIVATE
- * @see android.view.Display.TYPE_VIRTUAL
+ * @see android.view.Display#FLAG_PRIVATE
*
* @param context Source context, from which an activity will be started.
* @param displayId Target display id.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 33bacf0..4d21c8d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -6858,10 +6858,7 @@
* @param ops The operations to watch.
* @param callback Where to report changes.
*
- * @see #isOperationActive
* @see #stopWatchingActive
- * @see #startOp(int, int, String, boolean, String, String)
- * @see #finishOp(int, int, String, String)
*/
// TODO: Uncomment below annotation once b/73559440 is fixed
// @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
@@ -6909,10 +6906,7 @@
* long running and it has a clear start and stop delimiters. Unregistering a
* non-registered callback has no effect.
*
- * @see #isOperationActive
* @see #startWatchingActive
- * @see #startOp(int, int, String, boolean, String, String)
- * @see #finishOp(int, int, String, String)
*/
public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) {
synchronized (mActiveWatchers) {
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 1a619bd..2d06ee8 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -205,4 +205,15 @@
* @param {@code true} if the task got focus, {@code false} if it lost it.
*/
void onTaskFocusChanged(int taskId, boolean focused);
+
+ /**
+ * Called when a task changes its requested orientation. It is different from {@link
+ * #onActivityRequestedOrientationChanged(int, int)} in the sense that this method is called
+ * when a task changes requested orientation due to activity launch, dimiss or reparenting.
+ *
+ * @param taskId id of the task.
+ * @param requestedOrientation the new requested orientation of this task as screen orientations
+ * in {@link android.content.pm.ActivityInfo}.
+ */
+ void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation);
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 818a121..e233ade 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -732,7 +732,7 @@
* a non-null value if the intent needs to be intercepted.
*
* <p> Whenever a new activity is started, this method will be called on instances created
- * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
+ * using {@link #ActivityMonitor()} to check if there is a match. In case
* of a match, the activity start will be blocked and the returned result will be used.
*
* @param intent The intent used for starting the activity.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f26b136..a033b82 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3513,7 +3513,7 @@
}
/**
- * @deprecated use {@link Notification.Builder#Notification.Builder(Context, String)}
+ * @deprecated use {@link #Builder(Context, String)}
* instead. All posted Notifications must specify a NotificationChannel Id.
*/
@Deprecated
@@ -3631,7 +3631,7 @@
* @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
* is linked to
*
- * @see Notification.BubbleMetadata.Builder#Builder(String)
+ * @see BubbleMetadata.Builder#Builder(String)
*/
@NonNull
public Builder setShortcutId(String shortcutId) {
@@ -5993,7 +5993,7 @@
* metadata matches the shortcutId set on the notification builder, if one was set.
* If the shortcutId's were specified but do not match, an exception is thrown here.
*
- * @see Notification.BubbleMetadata.Builder#Builder(String)
+ * @see BubbleMetadata.Builder#Builder(String)
* @see #setShortcutId(String)
*/
@NonNull
@@ -7297,7 +7297,7 @@
* Should be unique amongst all individuals in the conversation, and should be
* consistent during re-posts of the notification.
*
- * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence)
+ * @see Message#Message(CharSequence, long, CharSequence)
*
* @return this object for method chaining
*
@@ -7317,7 +7317,7 @@
* Should be <code>null</code> for messages by the current user, in which case
* the platform will insert the user set in {@code MessagingStyle(Person)}.
*
- * @see Message#Notification.MessagingStyle.Message(CharSequence, long, CharSequence)
+ * @see Message#Message(CharSequence, long, CharSequence)
*
* @return this object for method chaining
*/
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index d6df400..eef9c02 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -368,7 +368,7 @@
* </p>
* </p>
*
- * @see {@link #addAutomaticZenRule(AutomaticZenRule)}
+ * @see #addAutomaticZenRule(AutomaticZenRule)
*/
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_AUTOMATIC_ZEN_RULE =
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 47ccc2f..106f8ac 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -1109,10 +1109,16 @@
Slog.v(TAG, "Changing resources "
+ resourcesImpl + " config to: " + config);
}
- int displayId = key.mDisplayId;
- final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
+
tmpConfig.setTo(config);
+ // Apply the override configuration before setting the display adjustments to ensure that
+ // the process config does not override activity display adjustments.
+ final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
+ if (hasOverrideConfiguration) {
+ tmpConfig.updateFrom(key.mOverrideConfiguration);
+ }
+
// Get new DisplayMetrics based on the DisplayAdjustments given to the ResourcesImpl. Update
// a copy if the CompatibilityInfo changed, because the ResourcesImpl object will handle the
// update internally.
@@ -1121,17 +1127,23 @@
daj = new DisplayAdjustments(daj);
daj.setCompatibilityInfo(compat);
}
+
+ final int displayId = key.mDisplayId;
if (displayId == Display.DEFAULT_DISPLAY) {
- daj.setConfiguration(config);
+ daj.setConfiguration(tmpConfig);
}
DisplayMetrics dm = getDisplayMetrics(displayId, daj);
if (displayId != Display.DEFAULT_DISPLAY) {
applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
+
+ // Re-apply the override configuration to ensure that configuration contexts based on
+ // a display context (ex: createDisplayContext().createConfigurationContext()) have the
+ // correct override.
+ if (hasOverrideConfiguration) {
+ tmpConfig.updateFrom(key.mOverrideConfiguration);
+ }
}
- if (hasOverrideConfiguration) {
- tmpConfig.updateFrom(key.mOverrideConfiguration);
- }
resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index bfa91aa..5d8daf8 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -195,4 +195,8 @@
@Override
public void onTaskFocusChanged(int taskId, boolean focused) {
}
+
+ @Override
+ public void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
+ }
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index beb4449..3bc043e 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -805,7 +805,7 @@
* has a work profile that was restored from another work profile with serial number
* {@code ancestralSerialNumber}.
*
- * @see UserManager#getSerialNumberForUser(UserHandle)
+ * @see android.os.UserManager#getSerialNumberForUser(UserHandle)
*/
@Nullable
public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 917eeb8..253c73796 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -103,8 +103,6 @@
/**
* The name of the emergency role
- *
- * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
*/
public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY";
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 09c6849..8472144 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3639,7 +3639,6 @@
* @see android.telephony.CarrierConfigManager
* @see #EUICC_SERVICE
* @see android.telephony.euicc.EuiccManager
- * @see #MMS_SERVICE
* @see android.telephony.MmsManager
* @see #INPUT_METHOD_SERVICE
* @see android.view.inputmethod.InputMethodManager
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7d8a4a4..baaf8f7 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6015,6 +6015,8 @@
FLAG_ACTIVITY_TASK_ON_HOME,
FLAG_ACTIVITY_RETAIN_IN_RECENTS,
FLAG_ACTIVITY_LAUNCH_ADJACENT,
+ FLAG_ACTIVITY_REQUIRE_NON_BROWSER,
+ FLAG_ACTIVITY_REQUIRE_DEFAULT,
FLAG_RECEIVER_REGISTERED_ONLY,
FLAG_RECEIVER_REPLACE_PENDING,
FLAG_RECEIVER_FOREGROUND,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5795cd2..d06a69c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1561,6 +1561,14 @@
*/
public static final int INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED = -124;
+ /**
+ * Installation failed return code: the package was skipped and should be ignored.
+ *
+ * The reason for the skip is undefined.
+ * @hide
+ */
+ public static final int INSTALL_PARSE_FAILED_SKIPPED = -125;
+
/** @hide */
@IntDef(flag = true, prefix = { "DELETE_" }, value = {
DELETE_KEEP_DATA,
@@ -7940,7 +7948,6 @@
*
* @return true if the drawable represents the default activity icon, false otherwise
* @see #getDefaultActivityIcon()
- * @see PackageItemInfo#loadDefaultIcon(PackageManager)
* @see #getActivityIcon
* @see LauncherActivityInfo#getIcon(int)
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index addac98..3b3521f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2001,6 +2001,7 @@
Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
+ pkg.baseCodePath+ ": overlay ignored due to required system property: "
+ propName + " with value: " + propValue);
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_SKIPPED;
return null;
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 197ad74..d3d15c8 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2347,14 +2347,12 @@
String propValue = sa.getString(
R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
if (!PackageParser.checkRequiredSystemProperties(propName, propValue)) {
- Slog.i(TAG, "Skipping target and overlay pair " + target + " and "
+ String message = "Skipping target and overlay pair " + target + " and "
+ pkg.getBaseCodePath()
+ ": overlay ignored due to required system property: "
- + propName + " with value: " + propValue);
- return input.error("Skipping target and overlay pair " + target + " and "
- + pkg.getBaseCodePath()
- + ": overlay ignored due to required system property: "
- + propName + " with value: " + propValue);
+ + propName + " with value: " + propValue;
+ Slog.i(TAG, message);
+ return input.skip(message);
}
return input.success(pkg.setOverlay(true)
diff --git a/core/java/android/content/pm/parsing/result/ParseInput.java b/core/java/android/content/pm/parsing/result/ParseInput.java
index 6b659be..d5898b7 100644
--- a/core/java/android/content/pm/parsing/result/ParseInput.java
+++ b/core/java/android/content/pm/parsing/result/ParseInput.java
@@ -88,6 +88,14 @@
*/
ParseResult<?> enableDeferredError(String packageName, int targetSdkVersion);
+ /**
+ * This will assign errorCode to {@link PackageManager#INSTALL_PARSE_FAILED_SKIPPED, used for
+ * packages which should be ignored by the caller.
+ *
+ * @see #error(int, String, Exception)
+ */
+ <ResultType> ParseResult<ResultType> skip(@NonNull String parseError);
+
/** @see #error(int, String, Exception) */
<ResultType> ParseResult<ResultType> error(int parseError);
diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
index b26bf71..6115206 100644
--- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
+++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
@@ -147,6 +147,11 @@
}
@Override
+ public <ResultType> ParseResult<ResultType> skip(@NonNull String parseError) {
+ return error(PackageManager.INSTALL_PARSE_FAILED_SKIPPED, parseError);
+ }
+
+ @Override
public <ResultType> ParseResult<ResultType> error(int parseError) {
return error(parseError, null);
}
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index afa6303..836624b 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -803,7 +803,7 @@
* @param isMetered {@code true} if the VPN network should be treated as metered regardless
* of underlying network meteredness. Defaults to {@code true}.
* @return this {@link Builder} object to facilitate chaining of method calls
- * @see NetworkCapabilities.NET_CAPABILITY_NOT_METERED
+ * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
*/
@NonNull
public Builder setMetered(boolean isMetered) {
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 63e5107..9c2c5b8 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -836,7 +836,7 @@
* @param isMetered {@code true} if VPN network should be treated as metered regardless of
* underlying network meteredness
* @return this {@link Builder} object to facilitate chaining method calls
- * @see #setUnderlyingNetworks(Networks[])
+ * @see #setUnderlyingNetworks(Network[])
* @see ConnectivityManager#isActiveNetworkMetered()
*/
@NonNull
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index e8af564..02b822a 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1022,7 +1022,6 @@
* behaviors or empty states. Instead, apps should store data needed
* while a user is locked under device protected storage areas.
*
- * @see Context#createCredentialProtectedStorageContext()
* @see Context#createDeviceProtectedStorageContext()
*/
public @NonNull Builder detectCredentialProtectedWhileLocked() {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 1fef071..fd7cdda 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -64,21 +64,16 @@
/**
* A click effect. Use this effect as a baseline, as it's the most common type of click effect.
- *
- * @see #get(int)
*/
public static final int EFFECT_CLICK = Effect.CLICK;
/**
* A double click effect.
- *
- * @see #get(int)
*/
public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK;
/**
* A tick effect. This effect is less strong compared to {@link #EFFECT_CLICK}.
- * @see #get(int)
*/
public static final int EFFECT_TICK = Effect.TICK;
@@ -102,7 +97,6 @@
/**
* A heavy click effect. This effect is stronger than {@link #EFFECT_CLICK}.
- * @see #get(int)
*/
public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK;
diff --git a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java
index 12503f6..89cd430 100644
--- a/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java
+++ b/core/java/android/os/strictmode/CredentialProtectedWhileLockedViolation.java
@@ -28,7 +28,6 @@
* store data needed while a user is locked under device protected storage
* areas.
*
- * @see Context#createCredentialProtectedStorageContext()
* @see Context#createDeviceProtectedStorageContext()
*/
public final class CredentialProtectedWhileLockedViolation extends Violation {
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 9c6c92a..17fae1c 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -797,7 +797,6 @@
* to changes.
*
* @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
- * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
*/
@NonNull
public static final Uri ENTERPRISE_CONTENT_URI =
@@ -1796,7 +1795,6 @@
* to changes.
*
* @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
- * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
*/
@NonNull
public static final Uri ENTERPRISE_CONTENT_URI =
@@ -2010,7 +2008,6 @@
* {@link DevicePolicyManager#setCrossProfileCalendarPackages(ComponentName, Set)}.
*
* @see DevicePolicyManager#getCrossProfileCalendarPackages(ComponentName)
- * @see Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED
*/
@NonNull
public static final Uri ENTERPRISE_CONTENT_URI =
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index a10a456..75840a5 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -24,7 +24,6 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ContentInterface;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -251,14 +250,14 @@
* Get string array identifies the type or types of metadata returned
* using DocumentsContract#getDocumentMetadata.
*
- * @see #getDocumentMetadata(ContentInterface, Uri)
+ * @see #getDocumentMetadata(ContentResolver, Uri)
*/
public static final String METADATA_TYPES = "android:documentMetadataTypes";
/**
* Get Exif information using DocumentsContract#getDocumentMetadata.
*
- * @see #getDocumentMetadata(ContentInterface, Uri)
+ * @see #getDocumentMetadata(ContentResolver, Uri)
*/
public static final String METADATA_EXIF = "android:documentExif";
@@ -266,7 +265,7 @@
* Get total count of all documents currently stored under the given
* directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents.
*
- * @see #getDocumentMetadata(ContentInterface, Uri)
+ * @see #getDocumentMetadata(ContentResolver, Uri)
*/
public static final String METADATA_TREE_COUNT = "android:metadataTreeCount";
@@ -274,7 +273,7 @@
* Get total size of all documents currently stored under the given
* directory tree. Only valid for {@link Document#MIME_TYPE_DIR} documents.
*
- * @see #getDocumentMetadata(ContentInterface, Uri)
+ * @see #getDocumentMetadata(ContentResolver, Uri)
*/
public static final String METADATA_TREE_SIZE = "android:metadataTreeSize";
@@ -405,7 +404,7 @@
* Flag indicating that a document can be represented as a thumbnail.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#getDocumentThumbnail(ContentInterface, Uri,
+ * @see DocumentsContract#getDocumentThumbnail(ContentResolver, Uri,
* Point, CancellationSignal)
* @see DocumentsProvider#openDocumentThumbnail(String, Point,
* android.os.CancellationSignal)
@@ -431,7 +430,7 @@
* Flag indicating that a document is deletable.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#deleteDocument(ContentInterface, Uri)
+ * @see DocumentsContract#deleteDocument(ContentResolver, Uri)
* @see DocumentsProvider#deleteDocument(String)
*/
public static final int FLAG_SUPPORTS_DELETE = 1 << 2;
@@ -469,7 +468,7 @@
* Flag indicating that a document can be renamed.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#renameDocument(ContentInterface, Uri, String)
+ * @see DocumentsContract#renameDocument(ContentResolver, Uri, String)
* @see DocumentsProvider#renameDocument(String, String)
*/
public static final int FLAG_SUPPORTS_RENAME = 1 << 6;
@@ -479,7 +478,7 @@
* within the same document provider.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#copyDocument(ContentInterface, Uri, Uri)
+ * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri)
* @see DocumentsProvider#copyDocument(String, String)
*/
public static final int FLAG_SUPPORTS_COPY = 1 << 7;
@@ -489,7 +488,7 @@
* within the same document provider.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#moveDocument(ContentInterface, Uri, Uri, Uri)
+ * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri)
* @see DocumentsProvider#moveDocument(String, String, String)
*/
public static final int FLAG_SUPPORTS_MOVE = 1 << 8;
@@ -513,7 +512,7 @@
* Flag indicating that a document can be removed from a parent.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#removeDocument(ContentInterface, Uri, Uri)
+ * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri)
* @see DocumentsProvider#removeDocument(String, String)
*/
public static final int FLAG_SUPPORTS_REMOVE = 1 << 10;
@@ -549,7 +548,7 @@
* using DocumentsContract#getDocumentMetadata
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#getDocumentMetadata(ContentInterface, Uri)
+ * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
*/
public static final int FLAG_SUPPORTS_METADATA = 1 << 14;
@@ -750,7 +749,7 @@
* Flag indicating that this root can be ejected.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#ejectRoot(ContentInterface, Uri)
+ * @see DocumentsContract#ejectRoot(ContentResolver, Uri)
* @see DocumentsProvider#ejectRoot(String)
*/
public static final int FLAG_SUPPORTS_EJECT = 1 << 5;
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index c28d2bb..e274460 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -262,7 +262,7 @@
*
* @param condition condition used to trigger the updates.
* @param updates actions to be applied to the
- * {@link #CustomDescription.Builder(RemoteViews) template presentation} when the condition
+ * {@link #Builder(RemoteViews) template presentation} when the condition
* is satisfied.
*
* @return this builder
diff --git a/core/java/android/service/autofill/ImageTransformation.java b/core/java/android/service/autofill/ImageTransformation.java
index 12376e8..974f0ea 100644
--- a/core/java/android/service/autofill/ImageTransformation.java
+++ b/core/java/android/service/autofill/ImageTransformation.java
@@ -123,7 +123,7 @@
* {@link RemoteViews presentation} must contain a {@link ImageView} child with that id.
*
* @deprecated use
- * {@link #ImageTransformation.Builder(AutofillId, Pattern, int, CharSequence)} instead.
+ * {@link #Builder(AutofillId, Pattern, int, CharSequence)} instead.
*/
@Deprecated
public Builder(@NonNull AutofillId id, @NonNull Pattern regex, @DrawableRes int resId) {
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 19961e5..6c22b19 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -144,22 +144,24 @@
final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(),
hostInputToken);
host.setView(suggestionRoot, lp);
- suggestionRoot.setOnClickListener((v) -> {
+
+ // Set the suggestion view to be non-focusable so that if its background is set to a
+ // ripple drawable, the ripple won't be shown initially.
+ suggestionView.setFocusable(false);
+ suggestionView.setOnClickListener((v) -> {
try {
- if (suggestionView.hasOnClickListeners()) {
- suggestionView.callOnClick();
- }
callback.onClick();
} catch (RemoteException e) {
Log.w(TAG, "RemoteException calling onClick()");
}
});
-
- suggestionRoot.setOnLongClickListener((v) -> {
+ final View.OnLongClickListener onLongClickListener =
+ suggestionView.getOnLongClickListener();
+ suggestionView.setOnLongClickListener((v) -> {
+ if (onLongClickListener != null) {
+ onLongClickListener.onLongClick(v);
+ }
try {
- if (suggestionView.hasOnLongClickListeners()) {
- suggestionView.performLongClick();
- }
callback.onLongClick();
} catch (RemoteException e) {
Log.w(TAG, "RemoteException calling onLongClick()");
diff --git a/core/java/android/service/autofill/InlineSuggestionRoot.java b/core/java/android/service/autofill/InlineSuggestionRoot.java
index 653e513..c879653 100644
--- a/core/java/android/service/autofill/InlineSuggestionRoot.java
+++ b/core/java/android/service/autofill/InlineSuggestionRoot.java
@@ -52,13 +52,8 @@
}
@Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return true;
- }
-
- @Override
@SuppressLint("ClickableViewAccessibility")
- public boolean onTouchEvent(@NonNull MotionEvent event) {
+ public boolean dispatchTouchEvent(@NonNull MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mDownX = event.getX();
@@ -80,6 +75,6 @@
}
} break;
}
- return super.onTouchEvent(event);
+ return super.dispatchTouchEvent(event);
}
}
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 4df4362..e640eec 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -719,7 +719,7 @@
*
* <p>The sanitizer can also be used as an alternative for a
* {@link #setValidator(Validator) validator}. If any of the {@code ids} is a
- * {@link #SaveInfo.Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails
+ * {@link #Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails
* because of it, then the save UI is not shown.
*
* @param sanitizer an implementation provided by the Android System.
@@ -777,7 +777,7 @@
* Builds a new {@link SaveInfo} instance.
*
* @throws IllegalStateException if no
- * {@link #SaveInfo.Builder(int, AutofillId[]) required ids},
+ * {@link #Builder(int, AutofillId[]) required ids},
* or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE}
* were set
*/
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index c36a33f..e4fbf9f 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -379,8 +379,6 @@
*
* <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
* app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
- * @see #onEmergencyNumberListChanged
*/
public static final int LISTEN_EMERGENCY_NUMBER_LIST = 0x01000000;
@@ -459,7 +457,7 @@
* <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
* the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
*
- * @see #onRegistrationFailed()
+ * @see #onRegistrationFailed
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
@@ -470,7 +468,7 @@
* <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
* the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
*
- * @see #onBarringInfoChanged()
+ * @see #onBarringInfoChanged
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_BARRING_INFO = 0x80000000;
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 2c260f6..5fcd38e 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -2275,7 +2275,7 @@
/**
* Write an individual field tag by hand.
*
- * @see See <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * See <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
* Encoding</a> for details on the structure of how tags and data are written.
*/
public void writeTag(int id, @WireType int wireType) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0625806..c0c29eb 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1464,8 +1464,23 @@
*/
public static final class DesiredDisplayConfigSpecs {
public int defaultConfig;
- public float minRefreshRate;
- public float maxRefreshRate;
+ /**
+ * The primary refresh rate range represents display manager's general guidance on the
+ * display configs surface flinger will consider when switching refresh rates. Unless
+ * surface flinger has a specific reason to do otherwise, it will stay within this range.
+ */
+ public float primaryRefreshRateMin;
+ public float primaryRefreshRateMax;
+ /**
+ * The app request refresh rate range allows surface flinger to consider more display
+ * configs when switching refresh rates. Although surface flinger will generally stay within
+ * the primary range, specific considerations, such as layer frame rate settings specified
+ * via the setFrameRate() api, may cause surface flinger to go outside the primary
+ * range. Surface flinger never goes outside the app request range. The app request range
+ * will be greater than or equal to the primary refresh rate range, never smaller.
+ */
+ public float appRequestRefreshRateMin;
+ public float appRequestRefreshRateMax;
public DesiredDisplayConfigSpecs() {}
@@ -1473,11 +1488,14 @@
copyFrom(other);
}
- public DesiredDisplayConfigSpecs(
- int defaultConfig, float minRefreshRate, float maxRefreshRate) {
+ public DesiredDisplayConfigSpecs(int defaultConfig, float primaryRefreshRateMin,
+ float primaryRefreshRateMax, float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
this.defaultConfig = defaultConfig;
- this.minRefreshRate = minRefreshRate;
- this.maxRefreshRate = maxRefreshRate;
+ this.primaryRefreshRateMin = primaryRefreshRateMin;
+ this.primaryRefreshRateMax = primaryRefreshRateMax;
+ this.appRequestRefreshRateMin = appRequestRefreshRateMin;
+ this.appRequestRefreshRateMax = appRequestRefreshRateMax;
}
@Override
@@ -1490,8 +1508,10 @@
*/
public boolean equals(DesiredDisplayConfigSpecs other) {
return other != null && defaultConfig == other.defaultConfig
- && minRefreshRate == other.minRefreshRate
- && maxRefreshRate == other.maxRefreshRate;
+ && primaryRefreshRateMin == other.primaryRefreshRateMin
+ && primaryRefreshRateMax == other.primaryRefreshRateMax
+ && appRequestRefreshRateMin == other.appRequestRefreshRateMin
+ && appRequestRefreshRateMax == other.appRequestRefreshRateMax;
}
@Override
@@ -1504,14 +1524,18 @@
*/
public void copyFrom(DesiredDisplayConfigSpecs other) {
defaultConfig = other.defaultConfig;
- minRefreshRate = other.minRefreshRate;
- maxRefreshRate = other.maxRefreshRate;
+ primaryRefreshRateMin = other.primaryRefreshRateMin;
+ primaryRefreshRateMax = other.primaryRefreshRateMax;
+ appRequestRefreshRateMin = other.appRequestRefreshRateMin;
+ appRequestRefreshRateMax = other.appRequestRefreshRateMax;
}
@Override
public String toString() {
- return String.format("defaultConfig=%d min=%.0f max=%.0f", defaultConfig,
- minRefreshRate, maxRefreshRate);
+ return String.format("defaultConfig=%d primaryRefreshRateRange=[%.0f %.0f]"
+ + " appRequestRefreshRateRange=[%.0f %.0f]",
+ defaultConfig, primaryRefreshRateMin, primaryRefreshRateMax,
+ appRequestRefreshRateMin, appRequestRefreshRateMax);
}
}
diff --git a/core/java/android/view/VerifiedInputEvent.java b/core/java/android/view/VerifiedInputEvent.java
index 531b3ed..e2db501 100644
--- a/core/java/android/view/VerifiedInputEvent.java
+++ b/core/java/android/view/VerifiedInputEvent.java
@@ -92,8 +92,6 @@
* time base.
*
* @see InputEvent#getEventTime()
- * @see KeyEvent#getEventTimeNano()
- * @see MotionEvent#getEventTimeNano()
*/
@SuppressLint("MethodNameUnits")
public long getEventTimeNanos() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3102999..facf861 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7263,6 +7263,16 @@
}
/**
+ * @return the registered {@link OnLongClickListener} if there is one, {@code null} otherwise.
+ * @hide
+ */
+ @Nullable
+ public OnLongClickListener getOnLongClickListener() {
+ ListenerInfo li = mListenerInfo;
+ return (li != null) ? li.mOnLongClickListener : null;
+ }
+
+ /**
* Register a callback to be invoked when this view is context clicked. If the view is not
* context clickable, it becomes context clickable.
*
@@ -26175,9 +26185,9 @@
/**
* Returns the View object that had been passed to the
- * {@link #View.DragShadowBuilder(View)}
+ * {@link #DragShadowBuilder(View)}
* constructor. If that View parameter was {@code null} or if the
- * {@link #View.DragShadowBuilder()}
+ * {@link #DragShadowBuilder()}
* constructor was used to instantiate the builder object, this method will return
* null.
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e4dbd637..9a3c706 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -700,7 +700,6 @@
* @see #TYPE_TOAST
* @see #TYPE_SYSTEM_OVERLAY
* @see #TYPE_PRIORITY_PHONE
- * @see #TYPE_STATUS_BAR_PANEL
* @see #TYPE_SYSTEM_DIALOG
* @see #TYPE_KEYGUARD_DIALOG
* @see #TYPE_SYSTEM_ERROR
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 6646c31..eaaaa80 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -5120,7 +5120,7 @@
* Obtains a pooled instance that is a clone of another one.
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
- * constructor {@link AccessibilityNodeInfo.RangeInfo#AccessibilityNodeInfo.RangeInfo(int,
+ * constructor {@link AccessibilityNodeInfo.RangeInfo#RangeInfo(int,
* float, float, float)} instead.
*
* @param other The instance to clone.
@@ -5135,7 +5135,7 @@
* Obtains a pooled instance.
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
- * constructor {@link AccessibilityNodeInfo.RangeInfo#AccessibilityNodeInfo.RangeInfo(int,
+ * constructor {@link AccessibilityNodeInfo.RangeInfo#RangeInfo(int,
* float, float, float)} instead.
*
* @param type The type of the range.
@@ -5271,7 +5271,7 @@
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo} instead.
+ * AccessibilityNodeInfo.CollectionInfo#CollectionInfo} instead.
*
* @param other The instance to clone.
* @hide
@@ -5286,7 +5286,7 @@
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo(int, int,
+ * AccessibilityNodeInfo.CollectionInfo#CollectionInfo(int, int,
* boolean)} instead.
*
* @param rowCount The number of rows, or -1 if count is unknown.
@@ -5303,7 +5303,7 @@
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionInfo#AccessibilityNodeInfo.CollectionInfo(int, int,
+ * AccessibilityNodeInfo.CollectionInfo#CollectionInfo(int, int,
* boolean, int)} instead.
*
* @param rowCount The number of rows.
@@ -5440,7 +5440,7 @@
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo}
+ * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo}
* instead.
*
* @param other The instance to clone.
@@ -5456,7 +5456,7 @@
*
* <p>In most situations object pooling is not beneficial. Create a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo(int,
+ * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int,
* int, int, int, boolean)} instead.
*
* @param rowIndex The row index at which the item is located.
@@ -5476,7 +5476,7 @@
*
* <p>In most situations object pooling is not beneficial. Creates a new instance using the
* constructor {@link
- * AccessibilityNodeInfo.CollectionItemInfo#AccessibilityNodeInfo.CollectionItemInfo(int,
+ * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int,
* int, int, int, boolean, boolean)} instead.
*
* @param rowIndex The row index at which the item is located.
diff --git a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java
index 42a892d..903fc13 100644
--- a/core/java/android/view/inspector/StaticInspectionCompanionProvider.java
+++ b/core/java/android/view/inspector/StaticInspectionCompanionProvider.java
@@ -21,8 +21,6 @@
/**
* An inspection companion provider that finds companions as inner classes or generated code.
- *
- * @see android.processor.view.inspector.PlatformInspectableProcessor
*/
public class StaticInspectionCompanionProvider implements InspectionCompanionProvider {
/**
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index fb96210..b35eb06 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -714,9 +714,7 @@
/**
* Callback object to be called when the toast is shown or hidden.
*
- * <p>Callback methods will be called on the looper thread used for the {@link Toast} object.
- *
- * @see #makeText(Context, Looper, CharSequence, int)
+ * @see #makeText(Context, CharSequence, int)
* @see #addCallback(Callback)
*/
public abstract static class Callback {
diff --git a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
index 4786d41..0e703fa 100644
--- a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
+++ b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
@@ -26,6 +26,7 @@
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.util.DisplayMetrics;
import android.util.TypedValue;
/**
@@ -99,12 +100,13 @@
}
private int getSensitivity(Resources userRes, String side) {
+ final DisplayMetrics dm = userRes.getDisplayMetrics();
final float defaultInset = userRes.getDimension(
- com.android.internal.R.dimen.config_backGestureInset);
+ com.android.internal.R.dimen.config_backGestureInset) / dm.density;
final float backGestureInset = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
BACK_GESTURE_EDGE_WIDTH, defaultInset);
final float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, backGestureInset,
- userRes.getDisplayMetrics());
+ dm);
final float scale = Settings.Secure.getFloatForUser(
mContext.getContentResolver(), side, 1.0f, UserHandle.USER_CURRENT);
return (int) (inset * scale);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5869787..36b4b6a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -174,8 +174,10 @@
jclass clazz;
jmethodID ctor;
jfieldID defaultConfig;
- jfieldID minRefreshRate;
- jfieldID maxRefreshRate;
+ jfieldID primaryRefreshRateMin;
+ jfieldID primaryRefreshRateMax;
+ jfieldID appRequestRefreshRateMin;
+ jfieldID appRequestRefreshRateMax;
} gDesiredDisplayConfigSpecsClassInfo;
class JNamedColorSpace {
@@ -919,13 +921,24 @@
jint defaultConfig = env->GetIntField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.defaultConfig);
- jfloat minRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
- gDesiredDisplayConfigSpecsClassInfo.minRefreshRate);
- jfloat maxRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
- gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate);
+ jfloat primaryRefreshRateMin =
+ env->GetFloatField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin);
+ jfloat primaryRefreshRateMax =
+ env->GetFloatField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMax);
+ jfloat appRequestRefreshRateMin =
+ env->GetFloatField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMin);
+ jfloat appRequestRefreshRateMax =
+ env->GetFloatField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax);
- size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(
- token, defaultConfig, minRefreshRate, maxRefreshRate);
+ size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(token, defaultConfig,
+ primaryRefreshRateMin,
+ primaryRefreshRateMax,
+ appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
@@ -934,16 +947,23 @@
if (token == nullptr) return nullptr;
int32_t defaultConfig;
- float minRefreshRate;
- float maxRefreshRate;
- if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig, &minRefreshRate,
- &maxRefreshRate) != NO_ERROR) {
+ float primaryRefreshRateMin;
+ float primaryRefreshRateMax;
+ float appRequestRefreshRateMin;
+ float appRequestRefreshRateMax;
+ if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig,
+ &primaryRefreshRateMin,
+ &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax) !=
+ NO_ERROR) {
return nullptr;
}
return env->NewObject(gDesiredDisplayConfigSpecsClassInfo.clazz,
- gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig, minRefreshRate,
- maxRefreshRate);
+ gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig,
+ primaryRefreshRateMin, primaryRefreshRateMax, appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
}
static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
@@ -1757,13 +1777,17 @@
gDesiredDisplayConfigSpecsClassInfo.clazz =
MakeGlobalRefOrDie(env, desiredDisplayConfigSpecsClazz);
gDesiredDisplayConfigSpecsClassInfo.ctor =
- GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFF)V");
+ GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFFFF)V");
gDesiredDisplayConfigSpecsClassInfo.defaultConfig =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "defaultConfig", "I");
- gDesiredDisplayConfigSpecsClassInfo.minRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "minRefreshRate", "F");
- gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "maxRefreshRate", "F");
+ gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "primaryRefreshRateMin", "F");
+ gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMax =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "primaryRefreshRateMax", "F");
+ gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMin =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMin", "F");
+ gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMax", "F");
return err;
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a8d1605..b92bbd6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4820,7 +4820,7 @@
May be a string value, which is a comma-separated language tag list, such as "ja-JP,zh-CN".
When not specified or an empty string is given, it will fallback to the default one.
{@see android.os.LocaleList#forLanguageTags(String)}
- {@see android.text.TextView#setTextLocales(android.os.LocaleList)} -->
+ {@see android.widget.TextView#setTextLocales(android.os.LocaleList)} -->
<attr name="textLocale" format="string" />
<!-- Text color for links. -->
<attr name="textColorLink" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 34417e6..a93dacf 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -44,8 +44,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
+import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.View;
@@ -367,6 +370,58 @@
}
@Test
+ public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final Configuration oldActivityConfig =
+ new Configuration(activity.getResources().getConfiguration());
+ final DisplayMetrics oldActivityMetrics = new DisplayMetrics();
+ activity.getDisplay().getMetrics(oldActivityMetrics);
+ final Resources oldAppResources = activity.getApplication().getResources();
+ final Configuration oldAppConfig =
+ new Configuration(oldAppResources.getConfiguration());
+ final DisplayMetrics oldApplicationMetrics = new DisplayMetrics();
+ oldApplicationMetrics.setTo(oldAppResources.getDisplayMetrics());
+ assertEquals("Process config must match the top activity config by default",
+ 0, oldActivityConfig.diffPublicOnly(oldAppConfig));
+ assertEquals("Process config must match the top activity config by default",
+ oldActivityMetrics, oldApplicationMetrics);
+
+ // Update the application configuration separately from activity config
+ final Configuration newAppConfig = new Configuration(oldAppConfig);
+ newAppConfig.densityDpi += 100;
+ newAppConfig.screenHeightDp += 100;
+ final Rect newBounds = new Rect(newAppConfig.windowConfiguration.getAppBounds());
+ newBounds.bottom += 100;
+ newAppConfig.windowConfiguration.setAppBounds(newBounds);
+ newAppConfig.windowConfiguration.setBounds(newBounds);
+ newAppConfig.seq++;
+
+ final ActivityThread activityThread = activity.getActivityThread();
+ activityThread.handleConfigurationChanged(newAppConfig);
+
+ // Verify that application config update was applied, but didn't change activity config.
+ assertEquals("Activity config must not change if the process config changes",
+ oldActivityConfig, activity.getResources().getConfiguration());
+
+ final DisplayMetrics newActivityMetrics = new DisplayMetrics();
+ activity.getDisplay().getMetrics(newActivityMetrics);
+ assertEquals("Activity display size must not change if the process config changes",
+ oldActivityMetrics, newActivityMetrics);
+ final Resources newAppResources = activity.getApplication().getResources();
+ assertEquals("Application config must be updated",
+ newAppConfig, newAppResources.getConfiguration());
+ final DisplayMetrics newApplicationMetrics = new DisplayMetrics();
+ newApplicationMetrics.setTo(newAppResources.getDisplayMetrics());
+ assertNotEquals("Application display size must be updated after config update",
+ oldApplicationMetrics, newApplicationMetrics);
+ assertNotEquals("Application display size must be updated after config update",
+ newActivityMetrics, newApplicationMetrics);
+ });
+ }
+
+ @Test
public void testResumeAfterNewIntent() {
final Activity activity = mActivityTestRule.launchActivity(new Intent());
final ActivityThread activityThread = activity.getActivityThread();
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 752695f..22f5489 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -998,7 +998,7 @@
* Sets the rotation value for the display list around the Z axis.
*
* @param rotation The rotation value of the display list, in degrees
- * @see View#setRotationZ(float)
+ * @see View#setRotation(float)
* @see #getRotationZ()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e70529b..9cf12f1 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -617,7 +617,7 @@
* {@link #setTintList(ColorStateList) tint}.
* </p>
*
- * @see {@link #setColorFilter(ColorFilter)} }
+ * @see #setColorFilter(ColorFilter)
* @deprecated use {@link #setColorFilter(ColorFilter)} with an instance
* of {@link android.graphics.BlendModeColorFilter}
*/
diff --git a/graphics/java/android/graphics/fonts/FontStyle.java b/graphics/java/android/graphics/fonts/FontStyle.java
index af517d6..09799fd 100644
--- a/graphics/java/android/graphics/fonts/FontStyle.java
+++ b/graphics/java/android/graphics/fonts/FontStyle.java
@@ -217,7 +217,7 @@
/**
* Gets the weight value
*
- * @see FontStyle#setWeight(int)
+ * @see #FontStyle(int, int)
* @return a weight value
*/
public @IntRange(from = 0, to = 1000) int getWeight() {
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 54622c5..babcfc3 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -320,7 +320,7 @@
/**
* Returns the array of tab stops in pixels.
*
- * @see #setTabStops(float[], int)
+ * @see #setTabStops
*/
public @Nullable float[] getTabStops() {
return mVariableTabStops;
@@ -329,7 +329,7 @@
/**
* Returns the default tab stops in pixels.
*
- * @see #setTabStop(float[], int)
+ * @see #setTabStops
*/
public @Px @FloatRange(from = 0) float getDefaultTabStop() {
return mDefaultTabStop;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6761435..31e4555 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -27,7 +27,6 @@
#include "DamageAccumulator.h"
#include "pipeline/skia/SkiaDisplayList.h"
#endif
-#include "utils/FatVector.h"
#include "utils/MathUtils.h"
#include "utils/StringUtils.h"
#include "utils/TraceUtils.h"
@@ -37,6 +36,7 @@
#include <atomic>
#include <sstream>
#include <string>
+#include <ui/FatVector.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index d55e5b0..c0ec217 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -27,6 +27,8 @@
#include <androidfw/ResourceTypes.h>
+#include <ui/FatVector.h>
+
#include "AnimatorManager.h"
#include "CanvasTransform.h"
#include "Debug.h"
@@ -35,7 +37,6 @@
#include "RenderProperties.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaLayer.h"
-#include "utils/FatVector.h"
#include <vector>
diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp
index 0ce04a2..a2fef1e 100644
--- a/libs/hwui/jni/FontFamily.cpp
+++ b/libs/hwui/jni/FontFamily.cpp
@@ -29,9 +29,9 @@
#include <hwui/MinikinSkia.h>
#include <hwui/Typeface.h>
-#include <utils/FatVector.h>
#include <minikin/FontFamily.h>
#include <minikin/LocaleList.h>
+#include <ui/FatVector.h>
#include <memory>
@@ -104,7 +104,7 @@
static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
jint weight, jint italic) {
- uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
+ FatVector<SkFontArguments::Axis, 2> skiaAxes;
for (const auto& axis : builder->axes) {
skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
}
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index 7e8f8d8..5714cd1 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -28,8 +28,8 @@
#include <hwui/MinikinSkia.h>
#include <hwui/Typeface.h>
-#include <utils/FatVector.h>
#include <minikin/FontFamily.h>
+#include <ui/FatVector.h>
#include <memory>
@@ -93,7 +93,7 @@
sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
release_global_ref, reinterpret_cast<void*>(fontRef)));
- uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes;
+ FatVector<SkFontArguments::Axis, 2> skiaAxes;
for (const auto& axis : builder->axes) {
skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value});
}
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
index cfc0f9b..d669f84 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h
@@ -21,7 +21,7 @@
#include <SkCanvas.h>
#include <SkDrawable.h>
-#include <utils/FatVector.h>
+#include <ui/FatVector.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c19b187..335bcdc 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -440,6 +440,12 @@
if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ // Notify the callbacks, even if there's nothing to draw so they aren't waiting
+ // indefinitely
+ for (auto& func : mFrameCompleteCallbacks) {
+ std::invoke(func, mFrameNumber);
+ }
+ mFrameCompleteCallbacks.clear();
return;
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index cae3e3b..206b58f 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -27,7 +27,6 @@
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "renderstate/RenderState.h"
-#include "utils/FatVector.h"
#include "utils/TimeUtils.h"
#include "utils/TraceUtils.h"
@@ -40,6 +39,8 @@
#include <utils/Mutex.h>
#include <thread>
+#include <ui/FatVector.h>
+
namespace android {
namespace uirenderer {
namespace renderthread {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index a5355fc..ba70afc 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -23,13 +23,13 @@
#include <GrContext.h>
#include <GrTypes.h>
#include <android/sync.h>
+#include <ui/FatVector.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
-#include "utils/FatVector.h"
#include "utils/TraceUtils.h"
namespace android {
diff --git a/libs/hwui/tests/unit/FatVectorTests.cpp b/libs/hwui/tests/unit/FatVectorTests.cpp
index 8523e6c..6585a62 100644
--- a/libs/hwui/tests/unit/FatVectorTests.cpp
+++ b/libs/hwui/tests/unit/FatVectorTests.cpp
@@ -15,7 +15,7 @@
*/
#include <gtest/gtest.h>
-#include <utils/FatVector.h>
+#include <ui/FatVector.h>
#include <tests/common/TestUtils.h>
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
deleted file mode 100644
index 49f1984..0000000
--- a/libs/hwui/utils/FatVector.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#ifndef ANDROID_FAT_VECTOR_H
-#define ANDROID_FAT_VECTOR_H
-
-#include "utils/Macros.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <utils/Log.h>
-#include <type_traits>
-
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-template <typename T, size_t SIZE>
-class InlineStdAllocator {
-public:
- struct Allocation {
- PREVENT_COPY_AND_ASSIGN(Allocation);
-
- public:
- Allocation(){};
- // char array instead of T array, so memory is uninitialized, with no destructors run
- char array[sizeof(T) * SIZE];
- bool inUse = false;
- };
-
- typedef T value_type; // needed to implement std::allocator
- typedef T* pointer; // needed to implement std::allocator
-
- explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {}
- InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {}
- ~InlineStdAllocator() {}
-
- T* allocate(size_t num, const void* = 0) {
- if (!mAllocation.inUse && num <= SIZE) {
- mAllocation.inUse = true;
- return (T*)mAllocation.array;
- } else {
- return (T*)malloc(num * sizeof(T));
- }
- }
-
- void deallocate(pointer p, size_t num) {
- if (p == (T*)mAllocation.array) {
- mAllocation.inUse = false;
- } else {
- // 'free' instead of delete here - destruction handled separately
- free(p);
- }
- }
- Allocation& mAllocation;
-};
-
-/**
- * std::vector with SIZE elements preallocated into an internal buffer.
- *
- * Useful for avoiding the cost of malloc in cases where only SIZE or
- * fewer elements are needed in the common case.
- */
-template <typename T, size_t SIZE>
-class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> {
-public:
- FatVector()
- : std::vector<T, InlineStdAllocator<T, SIZE>>(
- InlineStdAllocator<T, SIZE>(mAllocation)) {
- this->reserve(SIZE);
- }
-
- explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); }
-
-private:
- typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
-};
-
-} // namespace uirenderer
-} // namespace android
-
-#endif // ANDROID_FAT_VECTOR_H
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index 4e70501..4c0850b 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -80,9 +80,9 @@
* <p>An {@code AudioFocusRequest} instance always contains one of the four types of requests
* explained above. It is passed when building an {@code AudioFocusRequest} instance with its
* builder in the {@link Builder} constructor
- * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(int)}, or
+ * {@link AudioFocusRequest.Builder#Builder(int)}, or
* with {@link AudioFocusRequest.Builder#setFocusGain(int)} after copying an existing instance with
- * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(AudioFocusRequest)}.
+ * {@link AudioFocusRequest.Builder#Builder(AudioFocusRequest)}.
*
* <h3>Qualifying your focus request</h3>
* <h4>Use case requiring a focus request</h4>
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1d229b80..9f3fc5d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1357,7 +1357,7 @@
* Can only be called only if the AudioTrack is opened in offload mode
* {@see Builder#setOffloadedPlayback(boolean)}.
* Can only be called only if the AudioTrack is in state {@link #PLAYSTATE_PLAYING}
- * {@see #getPlaystate()}.
+ * {@see #getPlayState()}.
* Use this method in the same thread as any write() operation.
*/
public void setOffloadEndOfStream() {
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 1617b87..559a61d 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -535,7 +535,7 @@
* if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can
* be used to query the actual {@link Bitmap.Config}.
*
- * @see {@link #getFrameAtTime(long, int, BitmapParams)}
+ * @see #getFrameAtTime(long, int, BitmapParams)
*/
public @Nullable Bitmap getFrameAtTime(long timeUs, @Option int option) {
if (option < OPTION_PREVIOUS_SYNC ||
@@ -581,7 +581,7 @@
* @return A Bitmap containing a representative video frame, which
* can be null, if such a frame cannot be retrieved.
*
- * @see {@link #getFrameAtTime(long, int)}
+ * @see #getFrameAtTime(long, int)
*/
public @Nullable Bitmap getFrameAtTime(
long timeUs, @Option int option, @NonNull BitmapParams params) {
@@ -623,7 +623,7 @@
* be used to query the actual {@link Bitmap.Config}.
* @throws IllegalArgumentException if passed in invalid option or width by height
* is less than or equal to 0.
- * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
+ * @see #getScaledFrameAtTime(long, int, int, int, BitmapParams)
*/
public @Nullable Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
@IntRange(from=1) int dstWidth, @IntRange(from=1) int dstHeight) {
@@ -668,7 +668,7 @@
* scaled video frame, which can be null, if such a frame cannot be retrieved.
* @throws IllegalArgumentException if passed in invalid option or width by height
* is less than or equal to 0.
- * @see {@link #getScaledFrameAtTime(long, int, int, int)}
+ * @see #getScaledFrameAtTime(long, int, int, int)
*/
public @Nullable Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
@IntRange(from=1) int dstWidth, @IntRange(from=1) int dstHeight,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 1306657..c483d0e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -692,6 +692,7 @@
</activity>
<activity android:name=".controls.management.ControlsFavoritingActivity"
+ android:label="@string/controls_favorite_default_title"
android:theme="@style/Theme.ControlsManagement"
android:excludeFromRecents="true"
android:showForAllUsers="true"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index bd75116..eb15262 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -124,7 +124,7 @@
val collator = Collator.getInstance(resources.configuration.locales[0])
comparator = compareBy(collator) { it.structureName }
appName = intent.getCharSequenceExtra(EXTRA_APP)
- structureExtra = intent.getCharSequenceExtra(EXTRA_STRUCTURE) ?: ""
+ structureExtra = intent.getCharSequenceExtra(EXTRA_STRUCTURE)
component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
fromProviderSelector = intent.getBooleanExtra(EXTRA_FROM_PROVIDER_SELECTOR, false)
@@ -206,7 +206,9 @@
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val name = listOfStructures[position].structureName
- titleView.text = if (!TextUtils.isEmpty(name)) name else appName
+ val title = if (!TextUtils.isEmpty(name)) name else appName
+ titleView.text = title
+ setTitle(title)
}
override fun onPageScrolled(
@@ -261,7 +263,6 @@
val title = structureExtra
?: (appName ?: resources.getText(R.string.controls_favorite_default_title))
- setTitle(title)
titleView = requireViewById<TextView>(R.id.title).apply {
text = title
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 7091d98..9055479 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -19,6 +19,8 @@
import android.app.Dialog
import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
import android.os.Vibrator
import android.os.VibrationEffect
import android.service.controls.Control
@@ -26,10 +28,12 @@
import android.service.controls.actions.CommandAction
import android.util.Log
import android.view.HapticFeedbackConstants
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.R
import javax.inject.Inject
import javax.inject.Singleton
@@ -38,6 +42,7 @@
class ControlActionCoordinatorImpl @Inject constructor(
private val context: Context,
private val bgExecutor: DelayableExecutor,
+ @Main private val uiExecutor: DelayableExecutor,
private val activityStarter: ActivityStarter,
private val keyguardStateController: KeyguardStateController,
private val globalActionsComponent: GlobalActionsComponent
@@ -110,9 +115,24 @@
}
private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
- dialog = DetailDialog(cvh, intent).also {
- it.setOnDismissListener { _ -> dialog = null }
- it.show()
+ bgExecutor.execute {
+ val activities: List<ResolveInfo> = cvh.context.packageManager.queryIntentActivities(
+ intent,
+ PackageManager.MATCH_DEFAULT_ONLY
+ )
+
+ uiExecutor.execute {
+ // make sure the intent is valid before attempting to open the dialog
+ if (activities.isNotEmpty()) {
+ dialog = DetailDialog(cvh, intent).also {
+ it.setOnDismissListener { _ -> dialog = null }
+ it.show()
+ }
+ } else {
+ cvh.setTransientStatus(
+ cvh.context.resources.getString(R.string.controls_error_failed))
+ }
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index fb6b093..4e4c82c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -31,6 +31,13 @@
fun show(parent: ViewGroup, dismissGlobalActions: Runnable)
fun hide()
+
+ /**
+ * Request all open dialogs be closed. Set [immediately] to true to dismiss without
+ * animations.
+ */
+ fun closeDialogs(immediately: Boolean)
+
fun onRefreshState(componentName: ComponentName, controls: List<Control>)
fun onActionResponse(
componentName: ComponentName,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 3c54ad9..52d564d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -503,15 +503,24 @@
}
}
- override fun hide() {
- Log.d(ControlsUiController.TAG, "hide()")
- hidden = true
- popup?.dismissImmediate()
+ override fun closeDialogs(immediately: Boolean) {
+ if (immediately) {
+ popup?.dismissImmediate()
+ } else {
+ popup?.dismiss()
+ }
+ popup = null
controlViewsById.forEach {
it.value.dismiss()
}
controlActionCoordinator.closeDialogs()
+ }
+
+ override fun hide() {
+ hidden = true
+
+ closeDialogs(true)
controlsController.get().unsubscribe()
parent.removeAllViews()
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 9823a91..3dc0ff3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -145,6 +145,10 @@
template.isChecked())
true
}
+ AccessibilityNodeInfo.ACTION_LONG_CLICK -> {
+ cvh.controlActionCoordinator.longPress(cvh)
+ true
+ }
AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS.getId() -> {
if (arguments == null || !arguments.containsKey(
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)) {
@@ -152,8 +156,8 @@
} else {
val value = arguments.getFloat(
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)
- val level = rangeToLevelValue(value - rangeTemplate.getCurrentValue())
- updateRange(level, template.isChecked(), /* isDragging */ false)
+ val level = rangeToLevelValue(value)
+ updateRange(level, template.isChecked(), /* isDragging */ true)
endUpdateRange()
true
}
@@ -168,7 +172,7 @@
host: ViewGroup,
child: View,
event: AccessibilityEvent
- ): Boolean = false
+ ): Boolean = true
})
}
@@ -180,14 +184,12 @@
fun updateRange(level: Int, checked: Boolean, isDragging: Boolean) {
val newLevel = if (checked) Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, level)) else MIN_LEVEL
- if (newLevel == clipLayer.level) return
-
rangeAnimator?.cancel()
if (isDragging) {
clipLayer.level = newLevel
val isEdge = newLevel == MIN_LEVEL || newLevel == MAX_LEVEL
cvh.controlActionCoordinator.drag(isEdge)
- } else {
+ } else if (newLevel != clipLayer.level) {
rangeAnimator = ValueAnimator.ofInt(cvh.clipLayer.level, newLevel).apply {
addUpdateListener {
cvh.clipLayer.level = it.animatedValue as Int
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index cf9e141..cf3538c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -23,6 +23,10 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -2174,24 +2178,7 @@
mShowing = true;
mHadTopUi = mNotificationShadeWindowController.getForceHasTopUi();
mNotificationShadeWindowController.setForceHasTopUi(true);
- mBackgroundDrawable.setAlpha(0);
- mContainer.setTranslationX(mGlobalActionsLayout.getAnimationOffsetX());
- mContainer.setTranslationY(mGlobalActionsLayout.getAnimationOffsetY());
- mContainer.setAlpha(0);
- mContainer.animate()
- .alpha(1)
- .translationX(0)
- .translationY(0)
- .setDuration(450)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setUpdateListener(animation -> {
- float animatedValue = animation.getAnimatedFraction();
- int alpha = (int) (animatedValue * mScrimAlpha * 255);
- mBackgroundDrawable.setAlpha(alpha);
- mDepthController.updateGlobalDialogVisibility(animatedValue,
- mGlobalActionsLayout);
- })
- .start();
+
ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView();
root.setOnApplyWindowInsetsListener((v, windowInsets) -> {
if (mUseControlsLayout) {
@@ -2205,29 +2192,66 @@
if (mControlsUiController != null) {
mControlsUiController.show(mControlsView, this::dismissForControlsActivity);
}
+
+ mBackgroundDrawable.setAlpha(0);
+ float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
+ ObjectAnimator alphaAnimator =
+ ObjectAnimator.ofFloat(mContainer, "transitionAlpha", 0f, 1f);
+ alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ alphaAnimator.setDuration(183);
+ alphaAnimator.addUpdateListener((animation) -> {
+ float animatedValue = animation.getAnimatedFraction();
+ int alpha = (int) (animatedValue * mScrimAlpha * 255);
+ mBackgroundDrawable.setAlpha(alpha);
+ mDepthController.updateGlobalDialogVisibility(animatedValue,
+ mGlobalActionsLayout);
+ });
+
+ ObjectAnimator xAnimator =
+ ObjectAnimator.ofFloat(mContainer, "translationX", xOffset, 0f);
+ alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ alphaAnimator.setDuration(350);
+
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(alphaAnimator, xAnimator);
+ animatorSet.start();
}
@Override
public void dismiss() {
dismissWithAnimation(() -> {
mContainer.setTranslationX(0);
- mContainer.setTranslationY(0);
- mContainer.setAlpha(1);
- mContainer.animate()
- .alpha(0)
- .translationX(mGlobalActionsLayout.getAnimationOffsetX())
- .translationY(mGlobalActionsLayout.getAnimationOffsetY())
- .setDuration(450)
- .withEndAction(this::completeDismiss)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setUpdateListener(animation -> {
- float animatedValue = 1f - animation.getAnimatedFraction();
- int alpha = (int) (animatedValue * mScrimAlpha * 255);
- mBackgroundDrawable.setAlpha(alpha);
- mDepthController.updateGlobalDialogVisibility(animatedValue,
- mGlobalActionsLayout);
- })
- .start();
+ ObjectAnimator alphaAnimator =
+ ObjectAnimator.ofFloat(mContainer, "transitionAlpha", 1f, 0f);
+ alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ alphaAnimator.setDuration(233);
+ alphaAnimator.addUpdateListener((animation) -> {
+ float animatedValue = 1f - animation.getAnimatedFraction();
+ int alpha = (int) (animatedValue * mScrimAlpha * 255);
+ mBackgroundDrawable.setAlpha(alpha);
+ mDepthController.updateGlobalDialogVisibility(animatedValue,
+ mGlobalActionsLayout);
+ });
+
+ float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
+ ObjectAnimator xAnimator =
+ ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset);
+ alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ alphaAnimator.setDuration(350);
+
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(alphaAnimator, xAnimator);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ completeDismiss();
+ }
+ });
+
+ animatorSet.start();
+
+ // close first, as popup windows will not fade during the animation
+ dismissOverflow(false);
+ if (mControlsUiController != null) mControlsUiController.closeDialogs(false);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
index 2f32d97..c7612d4 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
@@ -90,11 +90,11 @@
@Override
public float getAnimationOffsetX() {
- return 0;
+ return getAnimationDistance();
}
@Override
public float getAnimationOffsetY() {
- return -getAnimationDistance();
+ return 0f;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
index 1425100..f72a74b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -19,6 +19,7 @@
import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.PlaybackState
+import android.os.SystemClock
import android.view.MotionEvent
import android.view.View
import android.widget.SeekBar
@@ -31,6 +32,38 @@
private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
+private fun PlaybackState.isInMotion(): Boolean {
+ return this.state == PlaybackState.STATE_PLAYING ||
+ this.state == PlaybackState.STATE_FAST_FORWARDING ||
+ this.state == PlaybackState.STATE_REWINDING
+}
+
+/**
+ * Gets the playback position while accounting for the time since the [PlaybackState] was last
+ * retrieved.
+ *
+ * This method closely follows the implementation of
+ * [MediaSessionRecord#getStateWithUpdatedPosition].
+ */
+private fun PlaybackState.computePosition(duration: Long): Long {
+ var currentPosition = this.position
+ if (this.isInMotion()) {
+ val updateTime = this.getLastPositionUpdateTime()
+ val currentTime = SystemClock.elapsedRealtime()
+ if (updateTime > 0) {
+ var position = (this.playbackSpeed * (currentTime - updateTime)).toLong() +
+ this.getPosition()
+ if (duration >= 0 && position > duration) {
+ position = duration.toLong()
+ } else if (position < 0) {
+ position = 0
+ }
+ currentPosition = position
+ }
+ }
+ return currentPosition
+}
+
/** ViewModel for seek bar in QS media player. */
class SeekBarViewModel(val bgExecutor: DelayableExecutor) {
@@ -98,7 +131,8 @@
@AnyThread
private fun checkPlaybackPosition(): Runnable = bgExecutor.executeDelayed({
- val currentPosition = controller?.playbackState?.position?.toInt()
+ val duration = _data?.duration ?: -1
+ val currentPosition = playbackState?.computePosition(duration.toLong())?.toInt()
if (currentPosition != null && _data.elapsedTime != currentPosition) {
_data = _data.copy(elapsedTime = currentPosition)
}
@@ -109,13 +143,7 @@
@WorkerThread
private fun shouldPollPlaybackPosition(): Boolean {
- val state = playbackState?.state
- val moving = if (state == null) false else
- state == PlaybackState.STATE_PLAYING ||
- state == PlaybackState.STATE_BUFFERING ||
- state == PlaybackState.STATE_FAST_FORWARDING ||
- state == PlaybackState.STATE_REWINDING
- return moving && listening
+ return listening && playbackState?.isInMotion() ?: false
}
/** Gets a listener to attach to the seek bar to handle seeking. */
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 7295f327..8d797f1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -190,6 +190,7 @@
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
+ private PictureInPictureParams mPictureInPictureParams;
public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@@ -213,6 +214,10 @@
return new Rect(mLastReportedBounds);
}
+ public boolean isInPip() {
+ return mInPip;
+ }
+
/**
* Registers {@link PipTransitionCallback} to receive transition callbacks.
*/
@@ -257,8 +262,9 @@
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) {
Objects.requireNonNull(info, "Requires RunningTaskInfo");
+ mPictureInPictureParams = info.pictureInPictureParams;
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- info.topActivity, getAspectRatioOrDefault(info.pictureInPictureParams),
+ info.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(info.topActivityInfo));
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
mTaskInfo = info;
@@ -304,6 +310,7 @@
Log.wtf(TAG, "Unrecognized token: " + token);
return;
}
+ mPictureInPictureParams = null;
mInPip = false;
}
@@ -311,7 +318,7 @@
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
final PictureInPictureParams newParams = info.pictureInPictureParams;
- if (!shouldUpdateDestinationBounds(newParams)) {
+ if (!applyPictureInPictureParams(newParams)) {
Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
return;
}
@@ -359,7 +366,7 @@
}
final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTaskInfo.topActivity, getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams),
+ mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
if (newDestinationBounds.equals(currentDestinationBounds)) return;
if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
@@ -373,12 +380,14 @@
* @return {@code true} if the aspect ratio is changed since no other parameters within
* {@link PictureInPictureParams} would affect the bounds.
*/
- private boolean shouldUpdateDestinationBounds(PictureInPictureParams params) {
- if (params == null || mTaskInfo.pictureInPictureParams == null) {
- return params != mTaskInfo.pictureInPictureParams;
+ private boolean applyPictureInPictureParams(@NonNull PictureInPictureParams params) {
+ final boolean changed = (mPictureInPictureParams == null) ? true : !Objects.equals(
+ mPictureInPictureParams.getAspectRatioRational(), params.getAspectRatioRational());
+ if (changed) {
+ mPictureInPictureParams = params;
+ mPipBoundsHandler.onAspectRatioChanged(params.getAspectRatio());
}
- return !Objects.equals(mTaskInfo.pictureInPictureParams.getAspectRatioRational(),
- params.getAspectRatioRational());
+ return changed;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 00f693d..b1e4d67 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -168,7 +168,10 @@
void synchronizePinnedStackBounds() {
cancelAnimations();
mBounds.set(mPipTaskOrganizer.getLastReportedBounds());
- mFloatingContentCoordinator.onContentMoved(this);
+
+ if (mPipTaskOrganizer.isInPip()) {
+ mFloatingContentCoordinator.onContentMoved(this);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 6748e3f..0e8c1b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -36,6 +36,7 @@
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.ISystemGestureExclusionListener;
@@ -232,13 +233,14 @@
mIsBackGestureAllowed =
!mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
+ final DisplayMetrics dm = res.getDisplayMetrics();
final float defaultGestureHeight = res.getDimension(
- com.android.internal.R.dimen.navigation_bar_gesture_height);
+ com.android.internal.R.dimen.navigation_bar_gesture_height) / dm.density;
final float gestureHeight = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.BACK_GESTURE_BOTTOM_HEIGHT,
defaultGestureHeight);
- mBottomGestureHeight = TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, gestureHeight, res.getDisplayMetrics());
+ mBottomGestureHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gestureHeight,
+ dm);
// Reduce the default touch slop to ensure that we can intercept the gesture
// before the app starts to react to it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
index 28a3d6a..cde575d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -362,28 +362,21 @@
@Test
fun taskUpdatesProgress() {
- // GIVEN that the PlaybackState contins the current position
- val position = 200L
+ // GIVEN that the PlaybackState contins the initial position
+ val initialPosition = 0L
val state = PlaybackState.Builder().run {
- setState(PlaybackState.STATE_PLAYING, position, 1f)
+ setState(PlaybackState.STATE_PLAYING, initialPosition, 1f)
build()
}
whenever(mockController.getPlaybackState()).thenReturn(state)
viewModel.updateController(mockController, Color.RED)
- // AND the playback state advances
- val nextPosition = 300L
- val nextState = PlaybackState.Builder().run {
- setState(PlaybackState.STATE_PLAYING, nextPosition, 1f)
- build()
- }
- whenever(mockController.getPlaybackState()).thenReturn(nextState)
// WHEN the task runs
with(fakeExecutor) {
advanceClockToNext()
runAllReady()
}
- // THEN elapsed time is captured
- assertThat(viewModel.progress.value!!.elapsedTime).isEqualTo(nextPosition.toInt())
+ // THEN elapsed time has increased
+ assertThat(viewModel.progress.value!!.elapsedTime).isGreaterThan(initialPosition.toInt())
}
@Test
diff --git a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
index 12d6c2c..d074f15 100644
--- a/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
+++ b/packages/Tethering/res/values-mcc310-mnc004-ne/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"Tethering has no internet"</string>
+ <string name="no_upstream_notification_title" msgid="5030042590486713460">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string>
<string name="no_upstream_notification_message" msgid="3843613362272973447">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
<string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
<string name="upstream_roaming_notification_title" msgid="3015912166812283303">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
diff --git a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml
index 05b90692..528a1e5 100644
--- a/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml
+++ b/packages/Tethering/res/values-mcc310-mnc004-zh-rTW/strings.xml
@@ -16,9 +16,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過數據連線連上網際網路"</string>
+ <string name="no_upstream_notification_title" msgid="5030042590486713460">"無法透過網路共用連上網際網路"</string>
<string name="no_upstream_notification_message" msgid="3843613362272973447">"裝置無法連線"</string>
- <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉數據連線"</string>
- <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"無線基地台或數據連線已開啟"</string>
+ <string name="no_upstream_notification_disable_button" msgid="6385491461813507624">"關閉網路共用"</string>
+ <string name="upstream_roaming_notification_title" msgid="3015912166812283303">"無線基地台或網路共用已開啟"</string>
<string name="upstream_roaming_notification_message" msgid="6724434706748439902">"使用漫遊服務可能須支付額外費用"</string>
</resources>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
index 0a0aa21..1503244 100644
--- a/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
+++ b/packages/Tethering/res/values-mcc311-mnc480-ne/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"Tethering has no internet"</string>
+ <string name="no_upstream_notification_title" msgid="611650570559011140">"टेदरिङमार्फत इन्टरनेट कनेक्सन प्राप्त हुन सकेन"</string>
<string name="no_upstream_notification_message" msgid="6508394877641864863">"यन्त्रहरू कनेक्ट गर्न सकिएन"</string>
<string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"टेदरिङ निष्क्रिय पार्नुहोस्"</string>
<string name="upstream_roaming_notification_title" msgid="6032901176124830787">"हटस्पट वा टेदरिङ सक्रिय छ"</string>
diff --git a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml
index ea01b94..cd653df 100644
--- a/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml
+++ b/packages/Tethering/res/values-mcc311-mnc480-zh-rTW/strings.xml
@@ -16,9 +16,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過數據連線連上網際網路"</string>
+ <string name="no_upstream_notification_title" msgid="611650570559011140">"無法透過網路共用連上網際網路"</string>
<string name="no_upstream_notification_message" msgid="6508394877641864863">"裝置無法連線"</string>
- <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉數據連線"</string>
- <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"無線基地台或數據連線已開啟"</string>
+ <string name="no_upstream_notification_disable_button" msgid="7609346639290990508">"關閉網路共用"</string>
+ <string name="upstream_roaming_notification_title" msgid="6032901176124830787">"無線基地台或網路共用已開啟"</string>
<string name="upstream_roaming_notification_message" msgid="7599056263326217523">"使用漫遊服務可能須支付額外費用"</string>
</resources>
diff --git a/packages/Tethering/res/values-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml
index 9d738a7..50a50bf 100644
--- a/packages/Tethering/res/values-zh-rTW/strings.xml
+++ b/packages/Tethering/res/values-zh-rTW/strings.xml
@@ -16,11 +16,11 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="tethered_notification_title" msgid="6426563586025792944">"數據連線或無線基地台已啟用"</string>
+ <string name="tethered_notification_title" msgid="6426563586025792944">"網路共用或無線基地台已啟用"</string>
<string name="tethered_notification_message" msgid="64800879503420696">"輕觸即可進行設定。"</string>
- <string name="disable_tether_notification_title" msgid="3004509127903564191">"數據連線已停用"</string>
+ <string name="disable_tether_notification_title" msgid="3004509127903564191">"網路共用已停用"</string>
<string name="disable_tether_notification_message" msgid="6717523799293901476">"詳情請洽你的管理員"</string>
- <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與數據連線狀態"</string>
+ <string name="notification_channel_tethering_status" msgid="2663463891530932727">"無線基地台與網路共用狀態"</string>
<string name="no_upstream_notification_title" msgid="1204601824631788482"></string>
<string name="no_upstream_notification_message" msgid="8586582938243032621"></string>
<string name="no_upstream_notification_disable_button" msgid="8800919436924640822"></string>
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 35089d6..20d1b98 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -325,7 +325,7 @@
@GuardedBy("mLock")
private CountDownLatch mCountDownLatch = new CountDownLatch(0);
- @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(
+ @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
boolean isInlineRequest) {
mCountDownLatch = new CountDownLatch(isInlineRequest ? 2 : 1);
mPendingFillRequest = null;
@@ -338,6 +338,7 @@
mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
mCountDownLatch.countDown();
maybeRequestFillLocked();
+ viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
} : null;
}
@@ -716,18 +717,23 @@
mService.getRemoteInlineSuggestionRenderServiceLocked();
if (isInlineSuggestionsEnabledByAutofillProviderLocked() && remoteRenderService != null) {
Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
- mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ true);
+ mAssistReceiver.newAutofillRequestLocked(viewState,
+ /*isInlineRequest=*/ true);
if (inlineSuggestionsRequestConsumer != null) {
final AutofillId focusedId = mCurrentViewId;
remoteRenderService.getInlineSuggestionsRendererInfo(
new RemoteCallback((extras) -> {
- mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
- focusedId, inlineSuggestionsRequestConsumer, extras);
- }
- ));
+ synchronized (mLock) {
+ mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
+ focusedId, inlineSuggestionsRequestConsumer, extras);
+ }
+ }, mHandler)
+ );
+ viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
} else {
- mAssistReceiver.newAutofillRequestLocked(/*isInlineRequest=*/ false);
+ mAssistReceiver.newAutofillRequestLocked(viewState,
+ /*isInlineRequest=*/ false);
}
// Now request the assist structure data.
@@ -2368,7 +2374,9 @@
*/
@GuardedBy("mLock")
private boolean shouldStartNewPartitionLocked(@NonNull AutofillId id) {
- if (mResponses == null) {
+ final ViewState currentView = mViewStates.get(id);
+ if (mResponses == null && currentView != null
+ && (currentView.getState() & ViewState.STATE_PENDING_CREATE_INLINE_REQUEST) == 0) {
return true;
}
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 9114576..adb1e3e 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -80,6 +80,8 @@
public static final int STATE_CHAR_REMOVED = 0x4000;
/** Showing inline suggestions is not allowed for this View. */
public static final int STATE_INLINE_DISABLED = 0x8000;
+ /** The View is waiting for an inline suggestions request from IME.*/
+ public static final int STATE_PENDING_CREATE_INLINE_REQUEST = 0x10000;
public final AutofillId id;
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 3dbf2c6..16d83ec 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -116,6 +116,7 @@
viewMessage = res.getString(R.string.user_switching_message, mNewUser.name);
}
}
+ view.setAccessibilityPaneTitle(viewMessage);
((TextView) view.findViewById(R.id.message)).setText(viewMessage);
setView(view);
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 4a1afb2..041bedc 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1819,7 +1819,8 @@
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.sync_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(context, 0,
- new Intent(Settings.ACTION_SYNC_SETTINGS), 0, null, UserHandle.of(userId)));
+ new Intent(Settings.ACTION_SYNC_SETTINGS), PendingIntent.FLAG_IMMUTABLE, null,
+ UserHandle.of(userId)));
return intent;
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 612fd39..c54ebf8 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -152,6 +152,47 @@
return votes;
}
+ private static final class VoteSummary {
+ public float minRefreshRate;
+ public float maxRefreshRate;
+ public int width;
+ public int height;
+
+ VoteSummary() {
+ reset();
+ }
+
+ public void reset() {
+ minRefreshRate = 0f;
+ maxRefreshRate = Float.POSITIVE_INFINITY;
+ width = Vote.INVALID_SIZE;
+ height = Vote.INVALID_SIZE;
+ }
+ }
+
+ // VoteSummary is returned as an output param to cut down a bit on the number of temporary
+ // objects.
+ private void summarizeVotes(
+ SparseArray<Vote> votes, int lowestConsideredPriority, /*out*/ VoteSummary summary) {
+ summary.reset();
+ for (int priority = Vote.MAX_PRIORITY; priority >= lowestConsideredPriority; priority--) {
+ Vote vote = votes.get(priority);
+ if (vote == null) {
+ continue;
+ }
+ // For refresh rates, just use the tightest bounds of all the votes
+ summary.minRefreshRate = Math.max(summary.minRefreshRate, vote.refreshRateRange.min);
+ summary.maxRefreshRate = Math.min(summary.maxRefreshRate, vote.refreshRateRange.max);
+ // For display size, use only the first vote we come across (i.e. the highest
+ // priority vote that includes the width / height).
+ if (summary.height == Vote.INVALID_SIZE && summary.width == Vote.INVALID_SIZE
+ && vote.height > 0 && vote.width > 0) {
+ summary.width = vote.width;
+ summary.height = vote.height;
+ }
+ }
+ }
+
/**
* Calculates the refresh rate ranges and display modes that the system is allowed to freely
* switch between based on global and display-specific constraints.
@@ -174,52 +215,31 @@
}
int[] availableModes = new int[]{defaultMode.getModeId()};
- float minRefreshRate = 0f;
- float maxRefreshRate = Float.POSITIVE_INFINITY;
+ VoteSummary primarySummary = new VoteSummary();
int lowestConsideredPriority = Vote.MIN_PRIORITY;
while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
- minRefreshRate = 0f;
- maxRefreshRate = Float.POSITIVE_INFINITY;
- int height = Vote.INVALID_SIZE;
- int width = Vote.INVALID_SIZE;
-
- for (int priority = Vote.MAX_PRIORITY;
- priority >= lowestConsideredPriority; priority--) {
- Vote vote = votes.get(priority);
- if (vote == null) {
- continue;
- }
- // For refresh rates, just use the tightest bounds of all the votes
- minRefreshRate = Math.max(minRefreshRate, vote.refreshRateRange.min);
- maxRefreshRate = Math.min(maxRefreshRate, vote.refreshRateRange.max);
- // For display size, use only the first vote we come across (i.e. the highest
- // priority vote that includes the width / height).
- if (height == Vote.INVALID_SIZE && width == Vote.INVALID_SIZE
- && vote.height > 0 && vote.width > 0) {
- width = vote.width;
- height = vote.height;
- }
- }
+ summarizeVotes(votes, lowestConsideredPriority, primarySummary);
// If we don't have anything specifying the width / height of the display, just use
// the default width and height. We don't want these switching out from underneath
// us since it's a pretty disruptive behavior.
- if (height == Vote.INVALID_SIZE || width == Vote.INVALID_SIZE) {
- width = defaultMode.getPhysicalWidth();
- height = defaultMode.getPhysicalHeight();
+ if (primarySummary.height == Vote.INVALID_SIZE
+ || primarySummary.width == Vote.INVALID_SIZE) {
+ primarySummary.width = defaultMode.getPhysicalWidth();
+ primarySummary.height = defaultMode.getPhysicalHeight();
}
- availableModes = filterModes(modes, width, height, minRefreshRate, maxRefreshRate);
+ availableModes = filterModes(modes, primarySummary);
if (availableModes.length > 0) {
if (DEBUG) {
Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
+ " with lowest priority considered "
+ Vote.priorityToString(lowestConsideredPriority)
+ " and constraints: "
- + "width=" + width
- + ", height=" + height
- + ", minRefreshRate=" + minRefreshRate
- + ", maxRefreshRate=" + maxRefreshRate);
+ + "width=" + primarySummary.width
+ + ", height=" + primarySummary.height
+ + ", minRefreshRate=" + primarySummary.minRefreshRate
+ + ", maxRefreshRate=" + primarySummary.maxRefreshRate);
}
break;
}
@@ -228,10 +248,10 @@
Slog.w(TAG, "Couldn't find available modes with lowest priority set to "
+ Vote.priorityToString(lowestConsideredPriority)
+ " and with the following constraints: "
- + "width=" + width
- + ", height=" + height
- + ", minRefreshRate=" + minRefreshRate
- + ", maxRefreshRate=" + maxRefreshRate);
+ + "width=" + primarySummary.width
+ + ", height=" + primarySummary.height
+ + ", minRefreshRate=" + primarySummary.minRefreshRate
+ + ", maxRefreshRate=" + primarySummary.maxRefreshRate);
}
// If we haven't found anything with the current set of votes, drop the
@@ -239,6 +259,20 @@
lowestConsideredPriority++;
}
+ VoteSummary appRequestSummary = new VoteSummary();
+ summarizeVotes(
+ votes, Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, appRequestSummary);
+ appRequestSummary.minRefreshRate =
+ Math.min(appRequestSummary.minRefreshRate, primarySummary.minRefreshRate);
+ appRequestSummary.maxRefreshRate =
+ Math.max(appRequestSummary.maxRefreshRate, primarySummary.maxRefreshRate);
+ if (DEBUG) {
+ Slog.i(TAG,
+ String.format("App request range: [%.0f %.0f]",
+ appRequestSummary.minRefreshRate,
+ appRequestSummary.maxRefreshRate));
+ }
+
int baseModeId = defaultMode.getModeId();
if (availableModes.length > 0) {
baseModeId = availableModes[0];
@@ -246,20 +280,23 @@
// filterModes function is going to filter the modes based on the voting system. If
// the application requests a given mode with preferredModeId function, it will be
// stored as baseModeId.
- return new DesiredDisplayModeSpecs(
- baseModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
+ return new DesiredDisplayModeSpecs(baseModeId,
+ new RefreshRateRange(
+ primarySummary.minRefreshRate, primarySummary.maxRefreshRate),
+ new RefreshRateRange(
+ appRequestSummary.minRefreshRate, appRequestSummary.maxRefreshRate));
}
}
- private int[] filterModes(Display.Mode[] supportedModes,
- int width, int height, float minRefreshRate, float maxRefreshRate) {
+ private int[] filterModes(Display.Mode[] supportedModes, VoteSummary summary) {
ArrayList<Display.Mode> availableModes = new ArrayList<>();
for (Display.Mode mode : supportedModes) {
- if (mode.getPhysicalWidth() != width || mode.getPhysicalHeight() != height) {
+ if (mode.getPhysicalWidth() != summary.width
+ || mode.getPhysicalHeight() != summary.height) {
if (DEBUG) {
Slog.w(TAG, "Discarding mode " + mode.getModeId() + ", wrong size"
- + ": desiredWidth=" + width
- + ": desiredHeight=" + height
+ + ": desiredWidth=" + summary.width
+ + ": desiredHeight=" + summary.height
+ ": actualWidth=" + mode.getPhysicalWidth()
+ ": actualHeight=" + mode.getPhysicalHeight());
}
@@ -269,13 +306,13 @@
// Some refresh rates are calculated based on frame timings, so they aren't *exactly*
// equal to expected refresh rate. Given that, we apply a bit of tolerance to this
// comparison.
- if (refreshRate < (minRefreshRate - FLOAT_TOLERANCE)
- || refreshRate > (maxRefreshRate + FLOAT_TOLERANCE)) {
+ if (refreshRate < (summary.minRefreshRate - FLOAT_TOLERANCE)
+ || refreshRate > (summary.maxRefreshRate + FLOAT_TOLERANCE)) {
if (DEBUG) {
Slog.w(TAG, "Discarding mode " + mode.getModeId()
+ ", outside refresh rate bounds"
- + ": minRefreshRate=" + minRefreshRate
- + ", maxRefreshRate=" + maxRefreshRate
+ + ": minRefreshRate=" + summary.minRefreshRate
+ + ", maxRefreshRate=" + summary.maxRefreshRate
+ ", modeRefreshRate=" + refreshRate);
}
continue;
@@ -535,7 +572,7 @@
/**
* Information about the desired display mode to be set by the system. Includes the base
- * mode ID and refresh rate range.
+ * mode ID and the primary and app request refresh rate ranges.
*
* We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the
* distinction between the config ID / physical index that
@@ -548,17 +585,28 @@
*/
public int baseModeId;
/**
- * The refresh rate range.
+ * The primary refresh rate range.
*/
- public final RefreshRateRange refreshRateRange;
+ public final RefreshRateRange primaryRefreshRateRange;
+ /**
+ * The app request refresh rate range. Lower priority considerations won't be included in
+ * this range, allowing surface flinger to consider additional refresh rates for apps that
+ * call setFrameRate(). This range will be greater than or equal to the primary refresh rate
+ * range, never smaller.
+ */
+ public final RefreshRateRange appRequestRefreshRateRange;
public DesiredDisplayModeSpecs() {
- refreshRateRange = new RefreshRateRange();
+ primaryRefreshRateRange = new RefreshRateRange();
+ appRequestRefreshRateRange = new RefreshRateRange();
}
- public DesiredDisplayModeSpecs(int baseModeId, @NonNull RefreshRateRange refreshRateRange) {
+ public DesiredDisplayModeSpecs(int baseModeId,
+ @NonNull RefreshRateRange primaryRefreshRateRange,
+ @NonNull RefreshRateRange appRequestRefreshRateRange) {
this.baseModeId = baseModeId;
- this.refreshRateRange = refreshRateRange;
+ this.primaryRefreshRateRange = primaryRefreshRateRange;
+ this.appRequestRefreshRateRange = appRequestRefreshRateRange;
}
/**
@@ -566,8 +614,10 @@
*/
@Override
public String toString() {
- return String.format("baseModeId=%d min=%.0f max=%.0f", baseModeId,
- refreshRateRange.min, refreshRateRange.max);
+ return String.format("baseModeId=%d primaryRefreshRateRange=[%.0f %.0f]"
+ + " appRequestRefreshRateRange=[%.0f %.0f]",
+ baseModeId, primaryRefreshRateRange.min, primaryRefreshRateRange.max,
+ appRequestRefreshRateRange.min, appRequestRefreshRateRange.max);
}
/**
* Checks whether the two objects have the same values.
@@ -587,7 +637,11 @@
if (baseModeId != desiredDisplayModeSpecs.baseModeId) {
return false;
}
- if (!refreshRateRange.equals(desiredDisplayModeSpecs.refreshRateRange)) {
+ if (!primaryRefreshRateRange.equals(desiredDisplayModeSpecs.primaryRefreshRateRange)) {
+ return false;
+ }
+ if (!appRequestRefreshRateRange.equals(
+ desiredDisplayModeSpecs.appRequestRefreshRateRange)) {
return false;
}
return true;
@@ -595,7 +649,7 @@
@Override
public int hashCode() {
- return Objects.hash(baseModeId, refreshRateRange);
+ return Objects.hash(baseModeId, primaryRefreshRateRange, appRequestRefreshRateRange);
}
/**
@@ -603,8 +657,10 @@
*/
public void copyFrom(DesiredDisplayModeSpecs other) {
baseModeId = other.baseModeId;
- refreshRateRange.min = other.refreshRateRange.min;
- refreshRateRange.max = other.refreshRateRange.max;
+ primaryRefreshRateRange.min = other.primaryRefreshRateRange.min;
+ primaryRefreshRateRange.max = other.primaryRefreshRateRange.max;
+ appRequestRefreshRateRange.min = other.appRequestRefreshRateRange.min;
+ appRequestRefreshRateRange.max = other.appRequestRefreshRateRange.max;
}
}
@@ -637,12 +693,17 @@
// LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
public static final int PRIORITY_LOW_POWER_MODE = 5;
- // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
- // appropriate, as well as priorityToString.
+ // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
+ // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS;
public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
+ // The cutoff for the app request refresh rate range. Votes with priorities lower than this
+ // value will not be considered when constructing the app request refresh rate range.
+ public static final int APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF =
+ PRIORITY_APP_REQUEST_REFRESH_RATE;
+
/**
* A value signifying an invalid width or height in a vote.
*/
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 6132467..4f5a02a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -310,9 +310,14 @@
// list of available modes will take care of updating display config specs.
if (activeBaseMode != NO_DISPLAY_MODE_ID) {
if (mDisplayModeSpecs.baseModeId != activeBaseMode
- || mDisplayModeSpecs.refreshRateRange.min != configSpecs.minRefreshRate
- || mDisplayModeSpecs.refreshRateRange.max
- != configSpecs.maxRefreshRate) {
+ || mDisplayModeSpecs.primaryRefreshRateRange.min
+ != configSpecs.primaryRefreshRateMin
+ || mDisplayModeSpecs.primaryRefreshRateRange.max
+ != configSpecs.primaryRefreshRateMax
+ || mDisplayModeSpecs.appRequestRefreshRateRange.min
+ != configSpecs.appRequestRefreshRateMin
+ || mDisplayModeSpecs.appRequestRefreshRateRange.max
+ != configSpecs.appRequestRefreshRateMax) {
mDisplayModeSpecsInvalid = true;
sendTraversalRequestLocked();
}
@@ -799,8 +804,10 @@
LocalDisplayDevice::setDesiredDisplayModeSpecsAsync, this,
getDisplayTokenLocked(),
new SurfaceControl.DesiredDisplayConfigSpecs(baseConfigId,
- mDisplayModeSpecs.refreshRateRange.min,
- mDisplayModeSpecs.refreshRateRange.max)));
+ mDisplayModeSpecs.primaryRefreshRateRange.min,
+ mDisplayModeSpecs.primaryRefreshRateRange.max,
+ mDisplayModeSpecs.appRequestRefreshRateRange.min,
+ mDisplayModeSpecs.appRequestRefreshRateRange.max)));
}
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index fad0a7d..8bb7c0f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1312,7 +1312,7 @@
intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
final PendingIntent pendingIntent = PendingIntent.getActivity(
- mContext, 0, new Intent(mConfig.settingsAction), 0);
+ mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
ApplicationInfo appInfo = null;
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 4872b66..acce699 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
@@ -49,6 +50,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.utils.TimingsTraceAndSlog;
import com.google.android.collect.Lists;
@@ -480,7 +482,7 @@
if (allPkgs.length == 0) {
return;
}
- int flags = PackageManager.GET_META_DATA
+ final int flags = PackageManager.GET_META_DATA
| PackageManager.GET_SIGNING_CERTIFICATES
| PackageManager.GET_SIGNATURES;
ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>();
@@ -489,7 +491,7 @@
for (ApexInfo ai : allPkgs) {
File apexFile = new File(ai.modulePath);
- parallelPackageParser.submit(apexFile, flags);
+ parallelPackageParser.submit(apexFile, 0);
parsingApexInfo.put(apexFile, ai);
}
@@ -502,8 +504,18 @@
ApexInfo ai = parsingApexInfo.get(parseResult.scanFile);
if (throwable == null) {
+ // Unfortunately, ParallelPackageParser won't collect certificates for us. We
+ // need to manually collect them here.
+ ParsedPackage pp = parseResult.parsedPackage;
+ try {
+ pp.setSigningDetails(
+ ParsingPackageUtils.collectCertificates(pp, false));
+ } catch (PackageParserException e) {
+ throw new IllegalStateException(
+ "Unable to collect certificates for " + ai.modulePath, e);
+ }
final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate(
- parseResult.parsedPackage, ai, flags);
+ pp, ai, flags);
if (packageInfo == null) {
throw new IllegalStateException("Unable to generate package info: "
+ ai.modulePath);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 33a1116..3df044f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1847,13 +1847,44 @@
}
}
- private void logDataLoaderInstallationSession(int returnCode, String extraMessage) {
+ private void logDataLoaderInstallationSession(int returnCode) {
+ // Skip logging the side-loaded app installations, as those are private and aren't reported
+ // anywhere; app stores already have a record of the installation and that's why reporting
+ // it here is fine
+ final String packageNameToLog =
+ (params.installFlags & PackageManager.INSTALL_FROM_ADB) == 0 ? mPackageName : "";
final long currentTimestamp = System.currentTimeMillis();
FrameworkStatsLog.write(FrameworkStatsLog.PACKAGE_INSTALLER_V2_REPORTED,
isIncrementalInstallation(),
- mPackageName,
+ packageNameToLog,
currentTimestamp - createdMillis,
- returnCode);
+ returnCode,
+ getApksSize());
+ }
+
+ private long getApksSize() {
+ final PackageSetting ps = mPm.getPackageSetting(mPackageName);
+ if (ps == null) {
+ return 0;
+ }
+ final File apkDirOrPath = ps.codePath;
+ if (apkDirOrPath == null) {
+ return 0;
+ }
+ if (apkDirOrPath.isFile() && apkDirOrPath.getName().toLowerCase().endsWith(".apk")) {
+ return apkDirOrPath.length();
+ }
+ if (!apkDirOrPath.isDirectory()) {
+ return 0;
+ }
+ final File[] files = apkDirOrPath.listFiles();
+ long apksSize = 0;
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].getName().toLowerCase().endsWith(".apk")) {
+ apksSize += files[i].length();
+ }
+ }
+ return apksSize;
}
/**
@@ -2879,7 +2910,7 @@
mCallback.onSessionFinished(this, success);
if (isDataLoaderInstallation()) {
- logDataLoaderInstallationSession(returnCode, msg);
+ logDataLoaderInstallationSession(returnCode);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a4d74f0..f288f1f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2072,8 +2072,18 @@
int autoRevokePermissionsMode,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver, int dataLoaderType) {
- final boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
+ boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null;
+ final String packageName = res.name;
+ final PackageSetting pkgSetting = succeeded ? getPackageSetting(packageName) : null;
+ if (succeeded && pkgSetting == null) {
+ Slog.e(TAG, packageName + " was removed before handlePackagePostInstall "
+ + "could be executed");
+ res.returnCode = INSTALL_FAILED_PACKAGE_CHANGED;
+ res.returnMsg = "Package was removed before install could complete.";
+ notifyInstallObserver(res, installObserver);
+ return;
+ }
if (succeeded) {
// Send the removed broadcasts
@@ -2117,8 +2127,6 @@
mInstantAppRegistry.onPackageInstalledLPw(res.pkg, res.newUsers);
}
- final String packageName = res.pkg.getPackageName();
-
// Determine the set of users who are adding this package for
// the first time vs. those who are seeing an update.
int[] firstUserIds = EMPTY_INT_ARRAY;
@@ -2126,7 +2134,7 @@
int[] updateUserIds = EMPTY_INT_ARRAY;
int[] instantUserIds = EMPTY_INT_ARRAY;
final boolean allNewUsers = res.origUsers == null || res.origUsers.length == 0;
- final PackageSetting ps = getPackageSetting(res.pkg.getPackageName());
+ final PackageSetting ps = pkgSetting;
for (int newUser : res.newUsers) {
final boolean isInstantApp = ps.getInstantApp(newUser);
if (allNewUsers) {
@@ -2263,7 +2271,7 @@
if (packageExternalStorageType != StorageEnums.UNKNOWN) {
FrameworkStatsLog.write(
FrameworkStatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
- packageExternalStorageType, res.pkg.getPackageName());
+ packageExternalStorageType, packageName);
}
}
if (DEBUG_INSTALL) {
@@ -2295,12 +2303,9 @@
if (packageIsBrowser(packageName, userId)) {
// If this browser is restored from user's backup, do not clear
// default-browser state for this user
- synchronized (mLock) {
- final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
- if (pkgSetting.getInstallReason(userId)
- != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
- mPermissionManager.setDefaultBrowser(null, true, true, userId);
- }
+ if (pkgSetting.getInstallReason(userId)
+ != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
+ mPermissionManager.setDefaultBrowser(null, true, true, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index a635f98..9051d85 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -22,7 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.DownloadManager;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
@@ -60,6 +59,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
import com.android.internal.util.ArrayUtils;
@@ -222,10 +222,75 @@
private final Context mContext;
private final Object mLock = new Object();
private final PackageManagerInternal mServiceInternal;
- private final PermissionManagerService mPermissionManager;
- DefaultPermissionGrantPolicy(Context context, Looper looper,
- @NonNull PermissionManagerService permissionManager) {
+ /** Directly interact with the PackageManger */
+ private final PackageManagerWrapper NO_PM_CACHE = new PackageManagerWrapper() {
+ @Override
+ public int getPermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ return mContext.getPackageManager().getPermissionFlags(permission, pkg.packageName,
+ user);
+ }
+
+ @Override
+ public void updatePermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ int flagMask, int flagValues, @NonNull UserHandle user) {
+ mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+ flagMask, flagValues, user);
+ }
+
+ @Override
+ public void grantPermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ mContext.getPackageManager().grantRuntimePermission(pkg.packageName, permission,
+ user);
+ }
+
+ @Override
+ public void revokePermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ mContext.getPackageManager().revokeRuntimePermission(pkg.packageName, permission,
+ user);
+ }
+
+ @Override
+ public boolean isGranted(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ return mContext.createContextAsUser(user, 0).getPackageManager().checkPermission(
+ permission, pkg.packageName) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ @Override
+ public @Nullable PermissionInfo getPermissionInfo(@NonNull String permissionName) {
+ if (permissionName == null) {
+ return null;
+ }
+
+ try {
+ return mContext.getPackageManager().getPermissionInfo(permissionName, 0);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, "Permission not found: " + permissionName);
+ return null;
+ }
+ }
+
+ @Override
+ public @Nullable PackageInfo getPackageInfo(@NonNull String pkg) {
+ if (pkg == null) {
+ return null;
+ }
+
+ try {
+ return mContext.getPackageManager().getPackageInfo(pkg,
+ DEFAULT_PACKAGE_INFO_QUERY_FLAGS);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, "Package not found: " + pkg);
+ return null;
+ }
+ }
+ };
+
+ DefaultPermissionGrantPolicy(Context context, Looper looper) {
mContext = context;
mHandler = new Handler(looper) {
@Override
@@ -233,13 +298,12 @@
if (msg.what == MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS) {
synchronized (mLock) {
if (mGrantExceptions == null) {
- mGrantExceptions = readDefaultPermissionExceptionsLocked();
+ mGrantExceptions = readDefaultPermissionExceptionsLocked(NO_PM_CACHE);
}
}
}
}
};
- mPermissionManager = permissionManager;
mServiceInternal = LocalServices.getService(PackageManagerInternal.class);
}
@@ -293,24 +357,30 @@
}
public void grantDefaultPermissions(int userId) {
- grantPermissionsToSysComponentsAndPrivApps(userId);
- grantDefaultSystemHandlerPermissions(userId);
- grantDefaultPermissionExceptions(userId);
+ DelayingPackageManagerCache pm = new DelayingPackageManagerCache();
+
+ grantPermissionsToSysComponentsAndPrivApps(pm, userId);
+ grantDefaultSystemHandlerPermissions(pm, userId);
+ grantDefaultPermissionExceptions(pm, userId);
+
+ // Apply delayed state
+ pm.apply();
}
- private void grantRuntimePermissionsForSystemPackage(int userId, PackageInfo pkg) {
+ private void grantRuntimePermissionsForSystemPackage(PackageManagerWrapper pm,
+ int userId, PackageInfo pkg) {
Set<String> permissions = new ArraySet<>();
for (String permission : pkg.requestedPermissions) {
- final BasePermission bp = mPermissionManager.getPermission(permission);
- if (bp == null) {
+ final PermissionInfo perm = pm.getPermissionInfo(permission);
+ if (perm == null) {
continue;
}
- if (bp.isRuntime()) {
+ if (perm.isRuntime()) {
permissions.add(permission);
}
}
if (!permissions.isEmpty()) {
- grantRuntimePermissions(pkg, permissions, true /*systemFixed*/, userId);
+ grantRuntimePermissions(pm, pkg, permissions, true /*systemFixed*/, userId);
}
}
@@ -318,7 +388,8 @@
mHandler.sendEmptyMessage(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);
}
- private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
+ private void grantPermissionsToSysComponentsAndPrivApps(DelayingPackageManagerCache pm,
+ int userId) {
Log.i(TAG, "Granting permissions to platform components for user " + userId);
List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(
DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM);
@@ -326,72 +397,76 @@
if (pkg == null) {
continue;
}
- if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
+
+ // Package info is already loaded, cache it
+ pm.addPackageInfo(pkg.packageName, pkg);
+
+ if (!pm.isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
|| !doesPackageSupportRuntimePermissions(pkg)
|| ArrayUtils.isEmpty(pkg.requestedPermissions)) {
continue;
}
- grantRuntimePermissionsForSystemPackage(userId, pkg);
+ grantRuntimePermissionsForSystemPackage(pm, userId, pkg);
}
}
@SafeVarargs
- private final void grantIgnoringSystemPackage(String packageName, int userId,
- Set<String>... permissionGroups) {
- grantPermissionsToPackage(packageName, userId, true /* ignoreSystemPackage */,
+ private final void grantIgnoringSystemPackage(PackageManagerWrapper pm, String packageName,
+ int userId, Set<String>... permissionGroups) {
+ grantPermissionsToPackage(pm, packageName, userId, true /* ignoreSystemPackage */,
true /*whitelistRestrictedPermissions*/, permissionGroups);
}
@SafeVarargs
- private final void grantSystemFixedPermissionsToSystemPackage(String packageName, int userId,
- Set<String>... permissionGroups) {
- grantPermissionsToSystemPackage(
- packageName, userId, true /* systemFixed */, permissionGroups);
- }
-
- @SafeVarargs
- private final void grantPermissionsToSystemPackage(
+ private final void grantSystemFixedPermissionsToSystemPackage(PackageManagerWrapper pm,
String packageName, int userId, Set<String>... permissionGroups) {
- grantPermissionsToSystemPackage(
- packageName, userId, false /* systemFixed */, permissionGroups);
+ grantPermissionsToSystemPackage(pm, packageName, userId, true /* systemFixed */,
+ permissionGroups);
}
@SafeVarargs
- private final void grantPermissionsToSystemPackage(String packageName, int userId,
- boolean systemFixed, Set<String>... permissionGroups) {
- if (!isSystemPackage(packageName)) {
+ private final void grantPermissionsToSystemPackage(PackageManagerWrapper pm,
+ String packageName, int userId, Set<String>... permissionGroups) {
+ grantPermissionsToSystemPackage(pm, packageName, userId, false /* systemFixed */,
+ permissionGroups);
+ }
+
+ @SafeVarargs
+ private final void grantPermissionsToSystemPackage(PackageManagerWrapper pm, String packageName,
+ int userId, boolean systemFixed, Set<String>... permissionGroups) {
+ if (!pm.isSystemPackage(packageName)) {
return;
}
- grantPermissionsToPackage(getSystemPackageInfo(packageName),
+ grantPermissionsToPackage(pm, pm.getSystemPackageInfo(packageName),
userId, systemFixed, false /* ignoreSystemPackage */,
true /*whitelistRestrictedPermissions*/, permissionGroups);
}
@SafeVarargs
- private final void grantPermissionsToPackage(String packageName, int userId,
- boolean ignoreSystemPackage, boolean whitelistRestrictedPermissions,
+ private final void grantPermissionsToPackage(PackageManagerWrapper pm, String packageName,
+ int userId, boolean ignoreSystemPackage, boolean whitelistRestrictedPermissions,
Set<String>... permissionGroups) {
- grantPermissionsToPackage(getPackageInfo(packageName),
+ grantPermissionsToPackage(pm, pm.getPackageInfo(packageName),
userId, false /* systemFixed */, ignoreSystemPackage,
whitelistRestrictedPermissions, permissionGroups);
}
@SafeVarargs
- private final void grantPermissionsToPackage(PackageInfo packageInfo, int userId,
- boolean systemFixed, boolean ignoreSystemPackage,
+ private final void grantPermissionsToPackage(PackageManagerWrapper pm, PackageInfo packageInfo,
+ int userId, boolean systemFixed, boolean ignoreSystemPackage,
boolean whitelistRestrictedPermissions, Set<String>... permissionGroups) {
if (packageInfo == null) {
return;
}
if (doesPackageSupportRuntimePermissions(packageInfo)) {
for (Set<String> permissionGroup : permissionGroups) {
- grantRuntimePermissions(packageInfo, permissionGroup, systemFixed,
+ grantRuntimePermissions(pm, packageInfo, permissionGroup, systemFixed,
ignoreSystemPackage, whitelistRestrictedPermissions, userId);
}
}
}
- private void grantDefaultSystemHandlerPermissions(int userId) {
+ private void grantDefaultSystemHandlerPermissions(PackageManagerWrapper pm, int userId) {
Log.i(TAG, "Granting permissions to default platform handlers for user " + userId);
final PackagesProvider locationPackagesProvider;
@@ -434,7 +509,7 @@
syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
// Installer
- grantSystemFixedPermissionsToSystemPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
ArrayUtils.firstOrNull(getKnownPackages(
PackageManagerInternal.PACKAGE_INSTALLER, userId)),
userId, STORAGE_PERMISSIONS);
@@ -442,68 +517,68 @@
// Verifier
final String verifier = ArrayUtils.firstOrNull(getKnownPackages(
PackageManagerInternal.PACKAGE_VERIFIER, userId));
- grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS);
- grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm, verifier, userId, STORAGE_PERMISSIONS);
+ grantPermissionsToSystemPackage(pm, verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
// SetupWizard
- grantPermissionsToSystemPackage(
+ grantPermissionsToSystemPackage(pm,
ArrayUtils.firstOrNull(getKnownPackages(
PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId,
PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
CAMERA_PERMISSIONS);
// Camera
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(MediaStore.ACTION_IMAGE_CAPTURE, userId),
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, MediaStore.ACTION_IMAGE_CAPTURE, userId),
userId, CAMERA_PERMISSIONS, MICROPHONE_PERMISSIONS, STORAGE_PERMISSIONS);
// Sound recorder
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
MediaStore.Audio.Media.RECORD_SOUND_ACTION, userId),
userId, MICROPHONE_PERMISSIONS);
// Media provider
- grantSystemFixedPermissionsToSystemPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
getDefaultProviderAuthorityPackage(MediaStore.AUTHORITY, userId), userId,
STORAGE_PERMISSIONS);
// Downloads provider
- grantSystemFixedPermissionsToSystemPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
getDefaultProviderAuthorityPackage("downloads", userId), userId,
STORAGE_PERMISSIONS);
// Downloads UI
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
DownloadManager.ACTION_VIEW_DOWNLOADS, userId),
userId, STORAGE_PERMISSIONS);
// Storage provider
- grantSystemFixedPermissionsToSystemPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId),
userId, STORAGE_PERMISSIONS);
// CertInstaller
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId,
- STORAGE_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, Credentials.INSTALL_ACTION, userId),
+ userId, STORAGE_PERMISSIONS);
// Dialer
if (dialerAppPackageNames == null) {
String dialerPackage =
- getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);
- grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
+ getDefaultSystemHandlerActivityPackage(pm, Intent.ACTION_DIAL, userId);
+ grantDefaultPermissionsToDefaultSystemDialerApp(pm, dialerPackage, userId);
} else {
for (String dialerAppPackageName : dialerAppPackageNames) {
- grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);
+ grantDefaultPermissionsToDefaultSystemDialerApp(pm, dialerAppPackageName, userId);
}
}
// Sim call manager
if (simCallManagerPackageNames != null) {
for (String simCallManagerPackageName : simCallManagerPackageNames) {
- grantDefaultPermissionsToDefaultSystemSimCallManager(
+ grantDefaultPermissionsToDefaultSystemSimCallManager(pm,
simCallManagerPackageName, userId);
}
}
@@ -511,77 +586,79 @@
// Use Open Wifi
if (useOpenWifiAppPackageNames != null) {
for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) {
- grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
+ grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(pm,
useOpenWifiPackageName, userId);
}
}
// SMS
if (smsAppPackageNames == null) {
- String smsPackage = getDefaultSystemHandlerActivityPackageForCategory(
+ String smsPackage = getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_MESSAGING, userId);
- grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
+ grantDefaultPermissionsToDefaultSystemSmsApp(pm, smsPackage, userId);
} else {
for (String smsPackage : smsAppPackageNames) {
- grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
+ grantDefaultPermissionsToDefaultSystemSmsApp(pm, smsPackage, userId);
}
}
// Cell Broadcast Receiver
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(Intents.SMS_CB_RECEIVED_ACTION, userId),
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, Intents.SMS_CB_RECEIVED_ACTION, userId),
userId, SMS_PERMISSIONS);
// Carrier Provisioning Service
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerServicePackage(Intents.SMS_CARRIER_PROVISION_ACTION, userId),
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerServicePackage(pm, Intents.SMS_CARRIER_PROVISION_ACTION,
+ userId),
userId, SMS_PERMISSIONS);
// Calendar
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackageForCategory(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_CALENDAR, userId),
userId, CALENDAR_PERMISSIONS, CONTACTS_PERMISSIONS);
// Calendar provider
String calendarProvider =
getDefaultProviderAuthorityPackage(CalendarContract.AUTHORITY, userId);
- grantPermissionsToSystemPackage(calendarProvider, userId,
+ grantPermissionsToSystemPackage(pm, calendarProvider, userId,
CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS);
- grantSystemFixedPermissionsToSystemPackage(calendarProvider, userId, CALENDAR_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm, calendarProvider, userId,
+ CALENDAR_PERMISSIONS);
// Calendar provider sync adapters
- grantPermissionToEachSystemPackage(
- getHeadlessSyncAdapterPackages(calendarSyncAdapterPackages, userId),
+ grantPermissionToEachSystemPackage(pm,
+ getHeadlessSyncAdapterPackages(pm, calendarSyncAdapterPackages, userId),
userId, CALENDAR_PERMISSIONS);
// Contacts
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackageForCategory(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_CONTACTS, userId),
userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
// Contacts provider sync adapters
- grantPermissionToEachSystemPackage(
- getHeadlessSyncAdapterPackages(contactsSyncAdapterPackages, userId),
+ grantPermissionToEachSystemPackage(pm,
+ getHeadlessSyncAdapterPackages(pm, contactsSyncAdapterPackages, userId),
userId, CONTACTS_PERMISSIONS);
// Contacts provider
String contactsProviderPackage =
getDefaultProviderAuthorityPackage(ContactsContract.AUTHORITY, userId);
- grantSystemFixedPermissionsToSystemPackage(contactsProviderPackage, userId,
+ grantSystemFixedPermissionsToSystemPackage(pm, contactsProviderPackage, userId,
CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
- grantPermissionsToSystemPackage(contactsProviderPackage, userId, STORAGE_PERMISSIONS);
+ grantPermissionsToSystemPackage(pm, contactsProviderPackage, userId, STORAGE_PERMISSIONS);
// Device provisioning
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
userId, CONTACTS_PERMISSIONS);
// Email
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackageForCategory(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_EMAIL, userId),
userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS);
@@ -589,19 +666,19 @@
String browserPackage = ArrayUtils.firstOrNull(getKnownPackages(
PackageManagerInternal.PACKAGE_BROWSER, userId));
if (browserPackage == null) {
- browserPackage = getDefaultSystemHandlerActivityPackageForCategory(
+ browserPackage = getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_BROWSER, userId);
- if (!isSystemPackage(browserPackage)) {
+ if (!pm.isSystemPackage(browserPackage)) {
browserPackage = null;
}
}
- grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */,
+ grantPermissionsToPackage(pm, browserPackage, userId, false /* ignoreSystemPackage */,
true /*whitelistRestrictedPermissions*/, FOREGROUND_LOCATION_PERMISSIONS);
// Voice interaction
if (voiceInteractPackageNames != null) {
for (String voiceInteractPackageName : voiceInteractPackageNames) {
- grantPermissionsToSystemPackage(voiceInteractPackageName, userId,
+ grantPermissionsToSystemPackage(pm, voiceInteractPackageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
@@ -609,8 +686,8 @@
if (ActivityManager.isLowRamDeviceStatic()) {
// Allow voice search on low-ram devices
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
userId, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
@@ -618,25 +695,26 @@
// Voice recognition
Intent voiceRecoIntent = new Intent(RecognitionService.SERVICE_INTERFACE)
.addCategory(Intent.CATEGORY_DEFAULT);
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerServicePackage(voiceRecoIntent, userId), userId,
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerServicePackage(pm, voiceRecoIntent, userId), userId,
MICROPHONE_PERMISSIONS);
// Location
if (locationPackageNames != null) {
for (String packageName : locationPackageNames) {
- grantPermissionsToSystemPackage(packageName, userId,
+ grantPermissionsToSystemPackage(pm, packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
- grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+ grantSystemFixedPermissionsToSystemPackage(pm, packageName, userId,
ALWAYS_LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
}
if (locationExtraPackageNames != null) {
// Also grant location permission to location extra packages.
for (String packageName : locationExtraPackageNames) {
- grantPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
+ grantPermissionsToSystemPackage(pm, packageName, userId,
+ ALWAYS_LOCATION_PERMISSIONS);
}
}
@@ -644,72 +722,72 @@
Intent musicIntent = new Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_DEFAULT)
.setDataAndType(Uri.fromFile(new File("foo.mp3")), AUDIO_MIME_TYPE);
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(musicIntent, userId), userId,
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, musicIntent, userId), userId,
STORAGE_PERMISSIONS);
// Home
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.addCategory(Intent.CATEGORY_LAUNCHER_APP);
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId,
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, homeIntent, userId), userId,
ALWAYS_LOCATION_PERMISSIONS);
// Watches
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
// Home application on watches
- String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(
+ String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_HOME_MAIN, userId);
- grantPermissionsToSystemPackage(wearPackage, userId,
+ grantPermissionsToSystemPackage(pm, wearPackage, userId,
CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
- grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm, wearPackage, userId, PHONE_PERMISSIONS);
// Fitness tracking on watches
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId,
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, ACTION_TRACK, userId), userId,
SENSORS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
// Print Spooler
- grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId,
- ALWAYS_LOCATION_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm, PrintManager.PRINT_SPOOLER_PACKAGE_NAME,
+ userId, ALWAYS_LOCATION_PERMISSIONS);
// EmergencyInfo
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
// NFC Tag viewer
Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
.setType("vnd.android.cursor.item/ndef_msg");
- grantPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(nfcTagIntent, userId), userId,
+ grantPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm, nfcTagIntent, userId), userId,
CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
// Storage Manager
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
StorageManager.ACTION_MANAGE_STORAGE, userId),
userId, STORAGE_PERMISSIONS);
// Companion devices
- grantSystemFixedPermissionsToSystemPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, userId,
ALWAYS_LOCATION_PERMISSIONS);
// Ringtone Picker
- grantSystemFixedPermissionsToSystemPackage(
- getDefaultSystemHandlerActivityPackage(
+ grantSystemFixedPermissionsToSystemPackage(pm,
+ getDefaultSystemHandlerActivityPackage(pm,
RingtoneManager.ACTION_RINGTONE_PICKER, userId),
userId, STORAGE_PERMISSIONS);
// TextClassifier Service
for (String textClassifierPackage :
getKnownPackages(PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER, userId)) {
- grantPermissionsToSystemPackage(textClassifierPackage, userId,
+ grantPermissionsToSystemPackage(pm, textClassifierPackage, userId,
COARSE_BACKGROUND_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
}
@@ -717,7 +795,7 @@
String contentCapturePackageName =
mContext.getPackageManager().getContentCaptureServicePackageName();
if (!TextUtils.isEmpty(contentCapturePackageName)) {
- grantPermissionsToSystemPackage(contentCapturePackageName, userId,
+ grantPermissionsToSystemPackage(pm, contentCapturePackageName, userId,
PHONE_PERMISSIONS, SMS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS);
}
@@ -726,36 +804,37 @@
String attentionServicePackageName =
mContext.getPackageManager().getAttentionServicePackageName();
if (!TextUtils.isEmpty(attentionServicePackageName)) {
- grantPermissionsToSystemPackage(attentionServicePackageName, userId,
+ grantPermissionsToSystemPackage(pm, attentionServicePackageName, userId,
CAMERA_PERMISSIONS);
}
// There is no real "marker" interface to identify the shared storage backup, it is
// hardcoded in BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE.
- grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId,
+ grantSystemFixedPermissionsToSystemPackage(pm, "com.android.sharedstoragebackup", userId,
STORAGE_PERMISSIONS);
// System Captions Service
String systemCaptionsServicePackageName =
mContext.getPackageManager().getSystemCaptionsServicePackageName();
if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) {
- grantPermissionsToSystemPackage(systemCaptionsServicePackageName, userId,
+ grantPermissionsToSystemPackage(pm, systemCaptionsServicePackageName, userId,
MICROPHONE_PERMISSIONS);
}
}
- private String getDefaultSystemHandlerActivityPackageForCategory(String category, int userId) {
- return getDefaultSystemHandlerActivityPackage(
+ private String getDefaultSystemHandlerActivityPackageForCategory(PackageManagerWrapper pm,
+ String category, int userId) {
+ return getDefaultSystemHandlerActivityPackage(pm,
new Intent(Intent.ACTION_MAIN).addCategory(category), userId);
}
@SafeVarargs
- private final void grantPermissionToEachSystemPackage(
+ private final void grantPermissionToEachSystemPackage(PackageManagerWrapper pm,
ArrayList<String> packages, int userId, Set<String>... permissions) {
if (packages == null) return;
final int count = packages.size();
for (int i = 0; i < count; i++) {
- grantPermissionsToSystemPackage(packages.get(i), userId, permissions);
+ grantPermissionsToSystemPackage(pm, packages.get(i), userId, permissions);
}
}
@@ -763,7 +842,7 @@
return mServiceInternal.getKnownPackageNames(knownPkgId, userId);
}
- private void grantDefaultPermissionsToDefaultSystemDialerApp(
+ private void grantDefaultPermissionsToDefaultSystemDialerApp(PackageManagerWrapper pm,
String dialerPackage, int userId) {
if (dialerPackage == null) {
return;
@@ -771,43 +850,51 @@
boolean isPhonePermFixed =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
if (isPhonePermFixed) {
- grantSystemFixedPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(pm, dialerPackage, userId,
+ PHONE_PERMISSIONS);
} else {
- grantPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+ grantPermissionsToSystemPackage(pm, dialerPackage, userId, PHONE_PERMISSIONS);
}
- grantPermissionsToSystemPackage(dialerPackage, userId,
+ grantPermissionsToSystemPackage(pm, dialerPackage, userId,
CONTACTS_PERMISSIONS, SMS_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
}
- private void grantDefaultPermissionsToDefaultSystemSmsApp(String smsPackage, int userId) {
- grantPermissionsToSystemPackage(smsPackage, userId,
+ private void grantDefaultPermissionsToDefaultSystemSmsApp(PackageManagerWrapper pm,
+ String smsPackage, int userId) {
+ grantPermissionsToSystemPackage(pm, smsPackage, userId,
PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
STORAGE_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
}
- private void grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
+ private void grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(PackageManagerWrapper pm,
String useOpenWifiPackage, int userId) {
- grantPermissionsToSystemPackage(useOpenWifiPackage, userId, ALWAYS_LOCATION_PERMISSIONS);
+ grantPermissionsToSystemPackage(pm, useOpenWifiPackage, userId,
+ ALWAYS_LOCATION_PERMISSIONS);
}
public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default Use Open WiFi app for user:" + userId);
- grantIgnoringSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
+ grantIgnoringSystemPackage(NO_PM_CACHE, packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
}
public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
+ grantDefaultPermissionsToDefaultSimCallManager(NO_PM_CACHE, packageName, userId);
+ }
+
+ private void grantDefaultPermissionsToDefaultSimCallManager(PackageManagerWrapper pm,
+ String packageName, int userId) {
if (packageName == null) {
return;
}
Log.i(TAG, "Granting permissions to sim call manager for user:" + userId);
- grantPermissionsToPackage(packageName, userId, false /* ignoreSystemPackage */,
+ grantPermissionsToPackage(pm, packageName, userId, false /* ignoreSystemPackage */,
true /*whitelistRestrictedPermissions*/, PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS);
}
- private void grantDefaultPermissionsToDefaultSystemSimCallManager(
+ private void grantDefaultPermissionsToDefaultSystemSimCallManager(PackageManagerWrapper pm,
String packageName, int userId) {
- if (isSystemPackage(packageName)) {
- grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
+ if (pm.isSystemPackage(packageName)) {
+ grantDefaultPermissionsToDefaultSimCallManager(pm, packageName, userId);
}
}
@@ -817,7 +904,7 @@
return;
}
for (String packageName : packageNames) {
- grantPermissionsToSystemPackage(packageName, userId,
+ grantPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, SMS_PERMISSIONS);
}
}
@@ -828,7 +915,7 @@
return;
}
for (String packageName : packageNames) {
- grantPermissionsToSystemPackage(packageName, userId,
+ grantPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
CAMERA_PERMISSIONS, CONTACTS_PERMISSIONS);
}
@@ -843,7 +930,7 @@
for (String packageName : packageNames) {
// Grant these permissions as system-fixed, so that nobody can accidentally
// break cellular data.
- grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+ grantSystemFixedPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
}
@@ -855,17 +942,20 @@
return;
}
for (String packageName : packageNames) {
- PackageInfo pkg = getSystemPackageInfo(packageName);
- if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
- revokeRuntimePermissions(packageName, PHONE_PERMISSIONS, true, userId);
- revokeRuntimePermissions(packageName, ALWAYS_LOCATION_PERMISSIONS, true, userId);
+ PackageInfo pkg = NO_PM_CACHE.getSystemPackageInfo(packageName);
+ if (NO_PM_CACHE.isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+ revokeRuntimePermissions(NO_PM_CACHE, packageName, PHONE_PERMISSIONS, true,
+ userId);
+ revokeRuntimePermissions(NO_PM_CACHE, packageName, ALWAYS_LOCATION_PERMISSIONS,
+ true, userId);
}
}
}
public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
Log.i(TAG, "Granting permissions to active LUI app for user:" + userId);
- grantSystemFixedPermissionsToSystemPackage(packageName, userId, CAMERA_PERMISSIONS);
+ grantSystemFixedPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
+ CAMERA_PERMISSIONS);
}
public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
@@ -874,23 +964,27 @@
return;
}
for (String packageName : packageNames) {
- PackageInfo pkg = getSystemPackageInfo(packageName);
- if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
- revokeRuntimePermissions(packageName, CAMERA_PERMISSIONS, true, userId);
+ PackageInfo pkg = NO_PM_CACHE.getSystemPackageInfo(packageName);
+ if (NO_PM_CACHE.isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+ revokeRuntimePermissions(NO_PM_CACHE, packageName, CAMERA_PERMISSIONS, true,
+ userId);
}
}
}
public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default browser for user:" + userId);
- grantPermissionsToSystemPackage(packageName, userId, FOREGROUND_LOCATION_PERMISSIONS);
+ grantPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
+ FOREGROUND_LOCATION_PERMISSIONS);
}
- private String getDefaultSystemHandlerActivityPackage(String intentAction, int userId) {
- return getDefaultSystemHandlerActivityPackage(new Intent(intentAction), userId);
+ private String getDefaultSystemHandlerActivityPackage(PackageManagerWrapper pm,
+ String intentAction, int userId) {
+ return getDefaultSystemHandlerActivityPackage(pm, new Intent(intentAction), userId);
}
- private String getDefaultSystemHandlerActivityPackage(Intent intent, int userId) {
+ private String getDefaultSystemHandlerActivityPackage(PackageManagerWrapper pm, Intent intent,
+ int userId) {
ResolveInfo handler = mContext.getPackageManager().resolveActivityAsUser(
intent, DEFAULT_INTENT_QUERY_FLAGS, userId);
if (handler == null || handler.activityInfo == null) {
@@ -900,14 +994,15 @@
return null;
}
String packageName = handler.activityInfo.packageName;
- return isSystemPackage(packageName) ? packageName : null;
+ return pm.isSystemPackage(packageName) ? packageName : null;
}
- private String getDefaultSystemHandlerServicePackage(String intentAction, int userId) {
- return getDefaultSystemHandlerServicePackage(new Intent(intentAction), userId);
+ private String getDefaultSystemHandlerServicePackage(PackageManagerWrapper pm,
+ String intentAction, int userId) {
+ return getDefaultSystemHandlerServicePackage(pm, new Intent(intentAction), userId);
}
- private String getDefaultSystemHandlerServicePackage(
+ private String getDefaultSystemHandlerServicePackage(PackageManagerWrapper pm,
Intent intent, int userId) {
List<ResolveInfo> handlers = mContext.getPackageManager().queryIntentServicesAsUser(
intent, DEFAULT_INTENT_QUERY_FLAGS, userId);
@@ -918,14 +1013,14 @@
for (int i = 0; i < handlerCount; i++) {
ResolveInfo handler = handlers.get(i);
String handlerPackage = handler.serviceInfo.packageName;
- if (isSystemPackage(handlerPackage)) {
+ if (pm.isSystemPackage(handlerPackage)) {
return handlerPackage;
}
}
return null;
}
- private ArrayList<String> getHeadlessSyncAdapterPackages(
+ private ArrayList<String> getHeadlessSyncAdapterPackages(PackageManagerWrapper pm,
String[] syncAdapterPackageNames, int userId) {
ArrayList<String> syncAdapterPackages = new ArrayList<>();
@@ -940,7 +1035,7 @@
continue;
}
- if (isSystemPackage(syncAdapterPackageName)) {
+ if (pm.isSystemPackage(syncAdapterPackageName)) {
syncAdapterPackages.add(syncAdapterPackageName);
}
}
@@ -957,27 +1052,15 @@
return null;
}
- private boolean isSystemPackage(String packageName) {
- return isSystemPackage(getPackageInfo(packageName));
- }
-
- private boolean isSystemPackage(PackageInfo pkg) {
- if (pkg == null) {
- return false;
- }
- return pkg.applicationInfo.isSystemApp()
- && !isSysComponentOrPersistentPlatformSignedPrivApp(pkg);
- }
-
- private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissions,
- boolean systemFixed, int userId) {
- grantRuntimePermissions(pkg, permissions, systemFixed, false,
+ private void grantRuntimePermissions(PackageManagerWrapper pm, PackageInfo pkg,
+ Set<String> permissions, boolean systemFixed, int userId) {
+ grantRuntimePermissions(pm, pkg, permissions, systemFixed, false,
true /*whitelistRestrictedPermissions*/, userId);
}
- private void revokeRuntimePermissions(String packageName, Set<String> permissions,
- boolean systemFixed, int userId) {
- PackageInfo pkg = getSystemPackageInfo(packageName);
+ private void revokeRuntimePermissions(PackageManagerWrapper pm, String packageName,
+ Set<String> permissions, boolean systemFixed, int userId) {
+ PackageInfo pkg = pm.getSystemPackageInfo(packageName);
if (pkg == null || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
return;
}
@@ -990,8 +1073,8 @@
}
UserHandle user = UserHandle.of(userId);
- final int flags = mContext.getPackageManager()
- .getPermissionFlags(permission, packageName, user);
+ final int flags = pm.getPermissionFlags(permission, pm.getPackageInfo(packageName),
+ user);
// We didn't get this through the default grant policy. Move along.
if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) == 0) {
@@ -1007,7 +1090,7 @@
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) {
continue;
}
- mContext.getPackageManager().revokeRuntimePermission(packageName, permission, user);
+ pm.revokePermission(permission, pkg, user);
if (DEBUG) {
Log.i(TAG, "revoked " + (systemFixed ? "fixed " : "not fixed ")
@@ -1017,7 +1100,7 @@
// Remove the GRANTED_BY_DEFAULT flag without touching the others.
// Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains
// sticky once set.
- mContext.getPackageManager().updatePermissionFlags(permission, packageName,
+ pm.updatePermissionFlags(permission, pkg,
PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, user);
}
}
@@ -1040,25 +1123,8 @@
| PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) != 0;
}
- /**
- * Return the background permission for a permission.
- *
- * @param permission The name of the foreground permission
- *
- * @return The name of the background permission or {@code null} if the permission has no
- * background permission
- */
- private @Nullable String getBackgroundPermission(@NonNull String permission) {
- try {
- return mContext.getPackageManager().getPermissionInfo(permission,
- 0).backgroundPermission;
- } catch (NameNotFoundException e) {
- return null;
- }
- }
-
- private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissionsWithoutSplits,
- boolean systemFixed, boolean ignoreSystemPackage,
+ private void grantRuntimePermissions(PackageManagerWrapper pm, PackageInfo pkg,
+ Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
boolean whitelistRestrictedPermissions, int userId) {
UserHandle user = UserHandle.of(userId);
if (pkg == null) {
@@ -1072,7 +1138,8 @@
// Intersect the requestedPermissions for a factory image with that of its current update
// in case the latter one removed a <uses-permission>
- String[] requestedByNonSystemPackage = getPackageInfo(pkg.packageName).requestedPermissions;
+ String[] requestedByNonSystemPackage = pm.getPackageInfo(pkg.packageName)
+ .requestedPermissions;
int size = requestedPermissions.length;
for (int i = 0; i < size; i++) {
if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) {
@@ -1081,14 +1148,6 @@
}
requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new);
- PackageManager pm;
- try {
- pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
- user).getPackageManager();
- } catch (NameNotFoundException doesNotHappen) {
- throw new IllegalStateException(doesNotHappen);
- }
-
final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
ApplicationInfo applicationInfo = pkg.applicationInfo;
@@ -1123,7 +1182,7 @@
if (!ignoreSystemPackage
&& applicationInfo != null
&& applicationInfo.isUpdatedSystemApp()) {
- final PackageInfo disabledPkg = getSystemPackageInfo(
+ final PackageInfo disabledPkg = pm.getSystemPackageInfo(
mServiceInternal.getDisabledSystemPackageName(pkg.packageName));
if (disabledPkg != null) {
if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) {
@@ -1145,7 +1204,7 @@
int numOther = 0;
for (int i = 0; i < numRequestedPermissions; i++) {
String permission = requestedPermissions[i];
- if (getBackgroundPermission(permission) != null) {
+ if (pm.getBackgroundPermission(permission) != null) {
sortedRequestedPermissions[numForeground] = permission;
numForeground++;
} else {
@@ -1166,8 +1225,7 @@
}
if (permissions.contains(permission)) {
- final int flags = mContext.getPackageManager().getPermissionFlags(
- permission, pkg.packageName, user);
+ final int flags = pm.getPermissionFlags(permission, pkg, user);
// If we are trying to grant as system fixed and already system fixed
// then the system can change the system fixed grant state.
@@ -1194,9 +1252,8 @@
newFlags |= (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT);
// If we are whitelisting the permission, update the exempt flag before grant.
- if (whitelistRestrictedPermissions && isPermissionRestricted(permission)) {
- mContext.getPackageManager().updatePermissionFlags(permission,
- pkg.packageName,
+ if (whitelistRestrictedPermissions && pm.isPermissionRestricted(permission)) {
+ pm.updatePermissionFlags(permission, pkg,
PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT,
PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
}
@@ -1204,82 +1261,15 @@
// If the system tries to change a system fixed permission from one fixed
// state to another we need to drop the fixed flag to allow the grant.
if (changingGrantForSystemFixed) {
- mContext.getPackageManager().updatePermissionFlags(permission,
- pkg.packageName, flags,
+ pm.updatePermissionFlags(permission, pkg, flags,
flags & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, user);
}
- if (pm.checkPermission(permission, pkg.packageName)
- != PackageManager.PERMISSION_GRANTED) {
- mContext.getPackageManager()
- .grantRuntimePermission(pkg.packageName, permission, user);
+ if (!pm.isGranted(permission, pkg, user)) {
+ pm.grantPermission(permission, pkg, user);
}
- mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
- newFlags, newFlags, user);
-
- int uid = UserHandle.getUid(userId,
- UserHandle.getAppId(pkg.applicationInfo.uid));
-
- List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
- .get(permission);
- if (fgPerms != null) {
- int numFgPerms = fgPerms.size();
- for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
- String fgPerm = fgPerms.get(fgPermNum);
-
- if (pm.checkPermission(fgPerm, pkg.packageName)
- == PackageManager.PERMISSION_GRANTED) {
- // Upgrade the app-op state of the fg permission to allow bg access
- // TODO: Dont' call app ops from package manager code.
- mContext.getSystemService(AppOpsManager.class).setUidMode(
- AppOpsManager.permissionToOp(fgPerm), uid,
- AppOpsManager.MODE_ALLOWED);
-
- break;
- }
- }
- }
-
- String bgPerm = getBackgroundPermission(permission);
- String op = AppOpsManager.permissionToOp(permission);
- if (bgPerm == null) {
- if (op != null) {
- // TODO: Dont' call app ops from package manager code.
- mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid,
- AppOpsManager.MODE_ALLOWED);
- }
- } else {
- int mode;
- if (pm.checkPermission(bgPerm, pkg.packageName)
- == PackageManager.PERMISSION_GRANTED) {
- mode = AppOpsManager.MODE_ALLOWED;
- } else {
- mode = AppOpsManager.MODE_FOREGROUND;
- }
-
- mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid, mode);
- }
-
- if (DEBUG) {
- Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
- + permission + " to default handler " + pkg);
-
- int appOp = AppOpsManager.permissionToOpCode(permission);
- if (appOp != AppOpsManager.OP_NONE
- && AppOpsManager.opToDefaultMode(appOp)
- != AppOpsManager.MODE_ALLOWED) {
- // Permission has a corresponding appop which is not allowed by default
- // We must allow it as well, as it's usually checked alongside the
- // permission
- if (DEBUG) {
- Log.i(TAG, "Granting OP_" + AppOpsManager.opToName(appOp)
- + " to " + pkg.packageName);
- }
- mContext.getSystemService(AppOpsManager.class).setUidMode(
- appOp, pkg.applicationInfo.uid, AppOpsManager.MODE_ALLOWED);
- }
- }
+ pm.updatePermissionFlags(permission, pkg, newFlags, newFlags, user);
}
// If a component gets a permission for being the default handler A
@@ -1291,57 +1281,14 @@
Log.i(TAG, "Granted not fixed " + permission + " to default handler "
+ pkg);
}
- mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+ pm.updatePermissionFlags(permission, pkg,
PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, user);
}
}
}
}
- private PackageInfo getSystemPackageInfo(String pkg) {
- return getPackageInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY);
- }
-
- private PackageInfo getPackageInfo(String pkg) {
- return getPackageInfo(pkg, 0 /* extraFlags */);
- }
-
- private PackageInfo getPackageInfo(String pkg,
- @PackageManager.PackageInfoFlags int extraFlags) {
- if (pkg == null) {
- return null;
- }
- try {
- return mContext.getPackageManager().getPackageInfo(pkg,
- DEFAULT_PACKAGE_INFO_QUERY_FLAGS | extraFlags);
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "PackageNot found: " + pkg, e);
- return null;
- }
- }
-
- private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) {
- if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
- return true;
- }
- if (!pkg.applicationInfo.isPrivilegedApp()) {
- return false;
- }
- final PackageInfo disabledPkg = getSystemPackageInfo(
- mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName));
- if (disabledPkg != null) {
- ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo;
- if (disabledPackageAppInfo != null
- && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
- return false;
- }
- } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
- return false;
- }
- return mServiceInternal.isPlatformSigned(pkg.packageName);
- }
-
- private void grantDefaultPermissionExceptions(int userId) {
+ private void grantDefaultPermissionExceptions(PackageManagerWrapper pm, int userId) {
mHandler.removeMessages(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);
synchronized (mLock) {
@@ -1350,7 +1297,7 @@
// performed for every user. If there is an entry then the app
// is on the system image and supports runtime permissions.
if (mGrantExceptions == null) {
- mGrantExceptions = readDefaultPermissionExceptionsLocked();
+ mGrantExceptions = readDefaultPermissionExceptionsLocked(pm);
}
}
@@ -1358,12 +1305,12 @@
final int exceptionCount = mGrantExceptions.size();
for (int i = 0; i < exceptionCount; i++) {
String packageName = mGrantExceptions.keyAt(i);
- PackageInfo pkg = getSystemPackageInfo(packageName);
+ PackageInfo pkg = pm.getSystemPackageInfo(packageName);
List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
final int permissionGrantCount = permissionGrants.size();
for (int j = 0; j < permissionGrantCount; j++) {
DefaultPermissionGrant permissionGrant = permissionGrants.get(j);
- if (!isPermissionDangerous(permissionGrant.name)) {
+ if (!pm.isPermissionDangerous(permissionGrant.name)) {
Log.w(TAG, "Ignoring permission " + permissionGrant.name
+ " which isn't dangerous");
continue;
@@ -1376,7 +1323,7 @@
permissions.add(permissionGrant.name);
- grantRuntimePermissions(pkg, permissions, permissionGrant.fixed,
+ grantRuntimePermissions(pm, pkg, permissions, permissionGrant.fixed,
permissionGrant.whitelisted, true /*whitelistRestrictedPermissions*/,
userId);
}
@@ -1416,7 +1363,7 @@
}
private @NonNull ArrayMap<String, List<DefaultPermissionGrant>>
- readDefaultPermissionExceptionsLocked() {
+ readDefaultPermissionExceptionsLocked(PackageManagerWrapper pm) {
File[] files = getDefaultPermissionFiles();
if (files == null) {
return new ArrayMap<>(0);
@@ -1440,7 +1387,7 @@
) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(str, null);
- parse(parser, grantExceptions);
+ parse(pm, parser, grantExceptions);
} catch (XmlPullParserException | IOException e) {
Slog.w(TAG, "Error reading default permissions file " + file, e);
}
@@ -1449,8 +1396,9 @@
return grantExceptions;
}
- private void parse(XmlPullParser parser, Map<String, List<DefaultPermissionGrant>>
- outGrantExceptions) throws IOException, XmlPullParserException {
+ private void parse(PackageManagerWrapper pm, XmlPullParser parser,
+ Map<String, List<DefaultPermissionGrant>> outGrantExceptions)
+ throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1459,15 +1407,16 @@
continue;
}
if (TAG_EXCEPTIONS.equals(parser.getName())) {
- parseExceptions(parser, outGrantExceptions);
+ parseExceptions(pm, parser, outGrantExceptions);
} else {
Log.e(TAG, "Unknown tag " + parser.getName());
}
}
}
- private void parseExceptions(XmlPullParser parser, Map<String, List<DefaultPermissionGrant>>
- outGrantExceptions) throws IOException, XmlPullParserException {
+ private void parseExceptions(PackageManagerWrapper pm, XmlPullParser parser,
+ Map<String, List<DefaultPermissionGrant>> outGrantExceptions)
+ throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1482,7 +1431,7 @@
outGrantExceptions.get(packageName);
if (packageExceptions == null) {
// The package must be on the system image
- PackageInfo packageInfo = getSystemPackageInfo(packageName);
+ PackageInfo packageInfo = pm.getSystemPackageInfo(packageName);
if (packageInfo == null) {
Log.w(TAG, "No such package:" + packageName);
@@ -1490,7 +1439,7 @@
continue;
}
- if (!isSystemPackage(packageInfo)) {
+ if (!pm.isSystemPackage(packageInfo)) {
Log.w(TAG, "Unknown system package:" + packageName);
XmlUtils.skipCurrentTag(parser);
continue;
@@ -1549,21 +1498,349 @@
&& pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
}
- private boolean isPermissionRestricted(String name) {
- try {
- return mContext.getPackageManager().getPermissionInfo(name, 0).isRestricted();
- } catch (NameNotFoundException e) {
- return false;
+ /**
+ * A wrapper for package manager calls done by this class
+ */
+ private abstract class PackageManagerWrapper {
+ abstract int getPermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user);
+
+ abstract void updatePermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ int flagMask, int flagValues, @NonNull UserHandle user);
+
+ abstract void grantPermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user);
+
+ abstract void revokePermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user);
+
+ abstract boolean isGranted(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user);
+
+ abstract @Nullable PermissionInfo getPermissionInfo(@NonNull String permissionName);
+
+ abstract @Nullable PackageInfo getPackageInfo(@NonNull String pkg);
+
+ @Nullable PackageInfo getSystemPackageInfo(@NonNull String pkg) {
+ PackageInfo pi = getPackageInfo(pkg);
+ if (pi == null || !pi.applicationInfo.isSystemApp()) {
+ return null;
+ }
+ return pi;
+ }
+
+ boolean isPermissionRestricted(@NonNull String name) {
+ PermissionInfo pi = getPermissionInfo(name);
+ if (pi == null) {
+ return false;
+ }
+
+ return pi.isRestricted();
+ }
+
+ boolean isPermissionDangerous(@NonNull String name) {
+ PermissionInfo pi = getPermissionInfo(name);
+ if (pi == null) {
+ return false;
+ }
+
+ return pi.getProtection() == PermissionInfo.PROTECTION_DANGEROUS;
+ }
+
+ /**
+ * Return the background permission for a permission.
+ *
+ * @param permission The name of the foreground permission
+ *
+ * @return The name of the background permission or {@code null} if the permission has no
+ * background permission
+ */
+ @Nullable String getBackgroundPermission(@NonNull String permission) {
+ PermissionInfo pi = getPermissionInfo(permission);
+ if (pi == null) {
+ return null;
+ }
+
+ return pi.backgroundPermission;
+ }
+
+ boolean isSystemPackage(@Nullable String packageName) {
+ return isSystemPackage(getPackageInfo(packageName));
+ }
+
+ boolean isSystemPackage(@Nullable PackageInfo pkg) {
+ if (pkg == null) {
+ return false;
+ }
+ return pkg.applicationInfo.isSystemApp()
+ && !isSysComponentOrPersistentPlatformSignedPrivApp(pkg);
+ }
+
+ boolean isSysComponentOrPersistentPlatformSignedPrivApp(@NonNull PackageInfo pkg) {
+ if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
+ return true;
+ }
+ if (!pkg.applicationInfo.isPrivilegedApp()) {
+ return false;
+ }
+ final PackageInfo disabledPkg = getSystemPackageInfo(
+ mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName));
+ if (disabledPkg != null) {
+ ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo;
+ if (disabledPackageAppInfo != null
+ && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
+ return false;
+ }
+ } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
+ return false;
+ }
+ return mServiceInternal.isPlatformSigned(pkg.packageName);
}
}
- private boolean isPermissionDangerous(String name) {
- try {
- final PermissionInfo pi = mContext.getPackageManager().getPermissionInfo(name, 0);
- return (pi.getProtection() == PermissionInfo.PROTECTION_DANGEROUS);
- } catch (NameNotFoundException e) {
- // When unknown assume it's dangerous to be on the safe side
- return true;
+ /**
+ * Do package manager calls but cache state and delay any change until {@link #apply()} is
+ * called
+ */
+ private class DelayingPackageManagerCache extends PackageManagerWrapper {
+ /** uid -> permission -> isGranted, flags */
+ private SparseArray<ArrayMap<String, PermissionState>> mDelayedPermissionState =
+ new SparseArray<>();
+ /** userId -> context */
+ private SparseArray<Context> mUserContexts = new SparseArray<>();
+ /** Permission name -> info */
+ private ArrayMap<String, PermissionInfo> mPermissionInfos = new ArrayMap<>();
+ /** Package name -> info */
+ private ArrayMap<String, PackageInfo> mPackageInfos = new ArrayMap<>();
+
+ /**
+ * Apply the cached state
+ */
+ void apply() {
+ PackageManager.corkPackageInfoCache();
+ for (int uidIdx = 0; uidIdx < mDelayedPermissionState.size(); uidIdx++) {
+ for (int permIdx = 0; permIdx < mDelayedPermissionState.valueAt(uidIdx).size();
+ permIdx++) {
+ try {
+ mDelayedPermissionState.valueAt(uidIdx).valueAt(permIdx).apply();
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "Cannot set permission " + mDelayedPermissionState.valueAt(
+ uidIdx).keyAt(permIdx) + " of uid " + mDelayedPermissionState.keyAt(
+ uidIdx), e);
+ }
+ }
+ }
+ PackageManager.uncorkPackageInfoCache();
+ }
+
+ void addPackageInfo(@NonNull String packageName, @NonNull PackageInfo pkg) {
+ mPackageInfos.put(packageName, pkg);
+ }
+
+ private @NonNull Context createContextAsUser(@NonNull UserHandle user) {
+ int index = mUserContexts.indexOfKey(user.getIdentifier());
+ if (index >= 0) {
+ return mUserContexts.valueAt(index);
+ }
+
+ Context uc = mContext.createContextAsUser(user, 0);
+
+ mUserContexts.put(user.getIdentifier(), uc);
+
+ return uc;
+ }
+
+ private @NonNull PermissionState getPermissionState(@NonNull String permission,
+ @NonNull PackageInfo pkg, @NonNull UserHandle user) {
+ int uid = UserHandle.getUid(user.getIdentifier(),
+ UserHandle.getAppId(pkg.applicationInfo.uid));
+ int uidIdx = mDelayedPermissionState.indexOfKey(uid);
+
+ ArrayMap<String, PermissionState> uidState;
+ if (uidIdx >= 0) {
+ uidState = mDelayedPermissionState.valueAt(uidIdx);
+ } else {
+ uidState = new ArrayMap<>();
+ mDelayedPermissionState.put(uid, uidState);
+ }
+
+ int permIdx = uidState.indexOfKey(permission);
+
+ PermissionState permState;
+ if (permIdx >= 0) {
+ permState = uidState.valueAt(permIdx);
+ } else {
+ permState = new PermissionState(permission, pkg, user);
+ uidState.put(permission, permState);
+ }
+
+ return permState;
+ }
+
+ @Override
+ public int getPermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ PermissionState state = getPermissionState(permission, pkg, user);
+ state.initFlags();
+ return state.newFlags;
+ }
+
+ @Override
+ public void updatePermissionFlags(@NonNull String permission, @NonNull PackageInfo pkg,
+ int flagMask, int flagValues, @NonNull UserHandle user) {
+ PermissionState state = getPermissionState(permission, pkg, user);
+ state.initFlags();
+ state.newFlags |= flagValues & flagMask;
+ }
+
+ @Override
+ public void grantPermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ PermissionState state = getPermissionState(permission, pkg, user);
+ state.initGranted();
+ state.newGranted = true;
+ }
+
+ @Override
+ public void revokePermission(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ PermissionState state = getPermissionState(permission, pkg, user);
+ state.initGranted();
+ state.newGranted = false;
+ }
+
+ @Override
+ public boolean isGranted(@NonNull String permission, @NonNull PackageInfo pkg,
+ @NonNull UserHandle user) {
+ PermissionState state = getPermissionState(permission, pkg, user);
+ state.initGranted();
+ return state.newGranted;
+ }
+
+ @Override
+ public @Nullable PermissionInfo getPermissionInfo(@NonNull String permissionName) {
+ int index = mPermissionInfos.indexOfKey(permissionName);
+ if (index >= 0) {
+ return mPermissionInfos.valueAt(index);
+ }
+
+ PermissionInfo pi = NO_PM_CACHE.getPermissionInfo(permissionName);
+ mPermissionInfos.put(permissionName, pi);
+
+ return pi;
+ }
+
+ @Override
+ public @Nullable PackageInfo getPackageInfo(@NonNull String pkg) {
+ int index = mPackageInfos.indexOfKey(pkg);
+ if (index >= 0) {
+ return mPackageInfos.valueAt(index);
+ }
+
+ PackageInfo pi = NO_PM_CACHE.getPackageInfo(pkg);
+ mPackageInfos.put(pkg, pi);
+
+ return pi;
+ }
+
+ /**
+ * State of a single permission belonging to a single uid
+ */
+ private class PermissionState {
+ private final @NonNull String mPermission;
+ private final @NonNull PackageInfo mPkgRequestingPerm;
+ private final @NonNull UserHandle mUser;
+
+ /** Permission flags when the state was created */
+ private @Nullable Integer mOriginalFlags;
+ /** Altered permission flags or {@code null} if no change was requested */
+ @Nullable Integer newFlags;
+
+ /** Grant state when the state was created */
+ private @Nullable Boolean mOriginalGranted;
+ /** Altered grant state or {@code null} if no change was requested */
+ @Nullable Boolean newGranted;
+
+ private PermissionState(@NonNull String permission,
+ @NonNull PackageInfo pkgRequestingPerm, @NonNull UserHandle user) {
+ mPermission = permission;
+ mPkgRequestingPerm = pkgRequestingPerm;
+ mUser = user;
+ }
+
+ /**
+ * Apply the changes to the permission to the system
+ */
+ void apply() {
+ if (DEBUG) {
+ Slog.i(TAG, "Granting " + mPermission + " to user " + mUser.getIdentifier()
+ + " pkg=" + mPkgRequestingPerm.packageName + " granted=" + newGranted
+ + " flags=" + Integer.toBinaryString(newFlags));
+ }
+
+ int flagsToAdd = 0;
+ int flagsToRemove = 0;
+ if (newFlags != null) {
+ flagsToAdd = newFlags & ~mOriginalFlags;
+ flagsToRemove = mOriginalFlags & ~newFlags;
+ }
+
+ // Need to remove e.g. SYSTEM_FIXED flags first as otherwise permission cannot be
+ // changed
+ if (flagsToRemove != 0) {
+ NO_PM_CACHE.updatePermissionFlags(mPermission, mPkgRequestingPerm,
+ flagsToRemove, 0, mUser);
+ }
+
+ // Need to unrestrict first as otherwise permission grants might fail
+ if ((flagsToAdd & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0) {
+ int newRestrictionExcemptFlags =
+ flagsToAdd & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
+
+ NO_PM_CACHE.updatePermissionFlags(mPermission,
+ mPkgRequestingPerm, newRestrictionExcemptFlags, -1, mUser);
+ }
+
+ if (newGranted != null && newGranted != mOriginalGranted) {
+ if (newGranted) {
+ NO_PM_CACHE.grantPermission(mPermission, mPkgRequestingPerm, mUser);
+ } else {
+ NO_PM_CACHE.revokePermission(mPermission, mPkgRequestingPerm, mUser);
+ }
+ }
+
+ if ((flagsToAdd & ~PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0) {
+ int newFlags =
+ flagsToAdd & ~PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
+
+ NO_PM_CACHE.updatePermissionFlags(mPermission, mPkgRequestingPerm, newFlags,
+ -1, mUser);
+ }
+ }
+
+ /**
+ * Load the state of the flags before first use
+ */
+ void initFlags() {
+ if (newFlags == null) {
+ mOriginalFlags = NO_PM_CACHE.getPermissionFlags(mPermission, mPkgRequestingPerm,
+ mUser);
+ newFlags = mOriginalFlags;
+ }
+ }
+
+ /**
+ * Load the grant state before first use
+ */
+ void initGranted() {
+ if (newGranted == null) {
+ // Don't call NO_PM_CACHE here so that contexts are reused
+ mOriginalGranted = createContextAsUser(mUser).getPackageManager()
+ .checkPermission(mPermission, mPkgRequestingPerm.packageName)
+ == PackageManager.PERMISSION_GRANTED;
+ newGranted = mOriginalGranted;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a18f90b..45ebbb6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -388,7 +388,7 @@
Watchdog.getInstance().addThread(mHandler);
mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
- context, mHandlerThread.getLooper(), this);
+ context, mHandlerThread.getLooper());
SystemConfig systemConfig = SystemConfig.getInstance();
mSystemPermissions = systemConfig.getSystemPermissions();
mGlobalGids = systemConfig.getGlobalGids();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5df84f2..5f8e9ff 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1192,8 +1192,9 @@
final Configuration newConfig = new Configuration();
newConfig.setTo(task.getRequestedOverrideConfiguration());
Rect outBounds = newConfig.windowConfiguration.getBounds();
- task.adjustForMinimalTaskDimensions(outBounds, outBounds);
- task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
+ final Configuration parentConfig = task.getParent().getConfiguration();
+ task.adjustForMinimalTaskDimensions(outBounds, outBounds, parentConfig);
+ task.computeConfigResourceOverrides(newConfig, parentConfig);
}
Task getTask() {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index d71381e..df1f174 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2957,8 +2957,8 @@
final int taskId = activity != null
? mStackSupervisor.getNextTaskIdForUser(activity.mUserId)
: mStackSupervisor.getNextTaskIdForUser();
- task = Task.create(
- mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
+ task = new ActivityStack(mAtmService, taskId, info, intent, voiceSession,
+ voiceInteractor, null /* taskDescription */, this);
// add the task to stack first, mTaskPositioner might need the stack association
addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9868446..72e3838 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1393,6 +1393,13 @@
final WindowContainer orientationSource = getLastOrientationSource();
final ActivityRecord r =
orientationSource != null ? orientationSource.asActivityRecord() : null;
+ if (r != null && r.getTask() != null
+ && orientation != r.getTask().mLastReportedRequestedOrientation) {
+ final Task task = r.getTask();
+ task.mLastReportedRequestedOrientation = orientation;
+ mAtmService.getTaskChangeNotificationController()
+ .notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
+ }
// Currently there is no use case from non-activity.
if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) {
// Display orientation should be deferred until the top fixed rotation is finished.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6c872a6..8903609 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -232,11 +232,6 @@
// Do not move the stack as a part of reparenting
static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
- /**
- * The factory used to create {@link Task}. This allows OEM subclass {@link Task}.
- */
- private static TaskFactory sTaskFactory;
-
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
@@ -368,6 +363,14 @@
@Surface.Rotation
private int mRotation;
+ /**
+ * Last requested orientation reported to DisplayContent. This is different from {@link
+ * #mOrientation} in the sense that this takes activities' requested orientation into
+ * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
+ * to notify for activities that don't specify any orientation.
+ */
+ int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
// For comparison with DisplayContent bounds.
private Rect mTmpRect = new Rect();
// For handling display rotations.
@@ -1822,22 +1825,16 @@
}
}
- void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
- final Rect parentBounds = getParent() != null ? getParent().getBounds() : null;
- if (bounds == null
- || (bounds.isEmpty() && (parentBounds == null || parentBounds.isEmpty()))) {
- return;
- }
+ void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds,
+ @NonNull Configuration parentConfig) {
int minWidth = mMinWidth;
int minHeight = mMinHeight;
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (!inPinnedWindowingMode() && getStack() != null) {
+ if (!inPinnedWindowingMode()) {
final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
- final DisplayContent display = getDisplayContent();
- final float density =
- (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+ final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
final int defaultMinSize = (int) (defaultMinSizeDp * density);
if (minWidth == INVALID_MIN_SIZE) {
@@ -1850,6 +1847,7 @@
if (bounds.isEmpty()) {
// If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
// do, we can just skip.
+ final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
return;
}
@@ -2444,12 +2442,13 @@
}
if (isLeafTask()) {
- resolveLeafOnlyOverrideConfigs(newParentConfig);
+ resolveLeafOnlyOverrideConfigs(newParentConfig, mTmpBounds /* previousBounds */);
}
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
}
- void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig) {
+ private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
+ Rect previousBounds) {
int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
@@ -2462,9 +2461,12 @@
computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
newParentConfig.windowConfiguration.getBounds(),
newParentConfig.orientation);
+ // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
+ // the parent or display is smaller than the size, the content may be cropped.
+ return;
}
- adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
+ adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig);
if (windowingMode == WINDOWING_MODE_FREEFORM) {
// by policy, make sure the window remains within parent somewhere
final float density =
@@ -4062,316 +4064,239 @@
}
}
- @VisibleForTesting
- static TaskFactory getTaskFactory() {
- if (sTaskFactory == null) {
- setTaskFactory(new TaskFactory());
- }
- return sTaskFactory;
- }
-
- static void setTaskFactory(TaskFactory factory) {
- sTaskFactory = factory;
- }
-
- static Task create(ActivityTaskManagerService service, int taskId, int activityType,
- ActivityInfo info, Intent intent, boolean createdByOrganizer) {
- return getTaskFactory().create(service, taskId, activityType, info, intent,
- createdByOrganizer);
- }
-
- static Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor, ActivityStack stack) {
- return getTaskFactory().create(
- service, taskId, info, intent, voiceSession, voiceInteractor, stack);
- }
-
static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
throws IOException, XmlPullParserException {
- return getTaskFactory().restoreFromXml(in, stackSupervisor);
- }
+ Intent intent = null;
+ Intent affinityIntent = null;
+ ArrayList<ActivityRecord> activities = new ArrayList<>();
+ ComponentName realActivity = null;
+ boolean realActivitySuspended = false;
+ ComponentName origActivity = null;
+ String affinity = null;
+ String rootAffinity = null;
+ boolean hasRootAffinity = false;
+ String windowLayoutAffinity = null;
+ boolean rootHasReset = false;
+ boolean autoRemoveRecents = false;
+ boolean askedCompatMode = false;
+ int taskType = 0;
+ int userId = 0;
+ boolean userSetupComplete = true;
+ int effectiveUid = -1;
+ String lastDescription = null;
+ long lastTimeOnTop = 0;
+ boolean neverRelinquishIdentity = true;
+ int taskId = INVALID_TASK_ID;
+ final int outerDepth = in.getDepth();
+ TaskDescription taskDescription = new TaskDescription();
+ int taskAffiliation = INVALID_TASK_ID;
+ int taskAffiliationColor = 0;
+ int prevTaskId = INVALID_TASK_ID;
+ int nextTaskId = INVALID_TASK_ID;
+ int callingUid = -1;
+ String callingPackage = "";
+ String callingFeatureId = null;
+ int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+ boolean supportsPictureInPicture = false;
+ Rect lastNonFullscreenBounds = null;
+ int minWidth = INVALID_MIN_SIZE;
+ int minHeight = INVALID_MIN_SIZE;
+ int persistTaskVersion = 0;
- /**
- * A factory class used to create {@link Task} or its subclass if any. This can be
- * specified when system boots by setting it with
- * {@link #setTaskFactory(TaskFactory)}.
- */
- static class TaskFactory {
- Task create(ActivityTaskManagerService service, int taskId, int activityType,
- ActivityInfo info, Intent intent, boolean createdByOrganizer) {
- return new ActivityStack(service, taskId, activityType, info, intent,
- createdByOrganizer);
- }
-
- Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor, ActivityStack stack) {
- return new ActivityStack(service, taskId, info, intent, voiceSession, voiceInteractor,
- null /*taskDescription*/, stack);
- }
-
- /**
- * Should only be used when we're restoring {@link Task} from storage.
- */
- Task create(ActivityTaskManagerService service, int taskId, Intent intent,
- Intent affinityIntent, String affinity, String rootAffinity,
- ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
- boolean autoRemoveRecents, boolean askedCompatMode, int userId,
- int effectiveUid, String lastDescription,
- long lastTimeMoved, boolean neverRelinquishIdentity,
- TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
- int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
- @Nullable String callingFeatureId, int resizeMode,
- boolean supportsPictureInPicture, boolean realActivitySuspended,
- boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
- return new ActivityStack(service, taskId, intent, affinityIntent, affinity,
- rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
- askedCompatMode, userId, effectiveUid, lastDescription,
- lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
- prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
- callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
- userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
- null /*_voiceSession*/, null /*_voiceInteractor*/, stack);
- }
-
- Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
- throws IOException, XmlPullParserException {
- Intent intent = null;
- Intent affinityIntent = null;
- ArrayList<ActivityRecord> activities = new ArrayList<>();
- ComponentName realActivity = null;
- boolean realActivitySuspended = false;
- ComponentName origActivity = null;
- String affinity = null;
- String rootAffinity = null;
- boolean hasRootAffinity = false;
- String windowLayoutAffinity = null;
- boolean rootHasReset = false;
- boolean autoRemoveRecents = false;
- boolean askedCompatMode = false;
- int taskType = 0;
- int userId = 0;
- boolean userSetupComplete = true;
- int effectiveUid = -1;
- String lastDescription = null;
- long lastTimeOnTop = 0;
- boolean neverRelinquishIdentity = true;
- int taskId = INVALID_TASK_ID;
- final int outerDepth = in.getDepth();
- TaskDescription taskDescription = new TaskDescription();
- int taskAffiliation = INVALID_TASK_ID;
- int taskAffiliationColor = 0;
- int prevTaskId = INVALID_TASK_ID;
- int nextTaskId = INVALID_TASK_ID;
- int callingUid = -1;
- String callingPackage = "";
- String callingFeatureId = null;
- int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
- boolean supportsPictureInPicture = false;
- Rect lastNonFullscreenBounds = null;
- int minWidth = INVALID_MIN_SIZE;
- int minHeight = INVALID_MIN_SIZE;
- int persistTaskVersion = 0;
-
- for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
- final String attrName = in.getAttributeName(attrNdx);
- final String attrValue = in.getAttributeValue(attrNdx);
- if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: attribute name="
- + attrName + " value=" + attrValue);
- switch (attrName) {
- case ATTR_TASKID:
- if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
- break;
- case ATTR_REALACTIVITY:
- realActivity = ComponentName.unflattenFromString(attrValue);
- break;
- case ATTR_REALACTIVITY_SUSPENDED:
- realActivitySuspended = Boolean.valueOf(attrValue);
- break;
- case ATTR_ORIGACTIVITY:
- origActivity = ComponentName.unflattenFromString(attrValue);
- break;
- case ATTR_AFFINITY:
- affinity = attrValue;
- break;
- case ATTR_ROOT_AFFINITY:
- rootAffinity = attrValue;
- hasRootAffinity = true;
- break;
- case ATTR_WINDOW_LAYOUT_AFFINITY:
- windowLayoutAffinity = attrValue;
- break;
- case ATTR_ROOTHASRESET:
- rootHasReset = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_AUTOREMOVERECENTS:
- autoRemoveRecents = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_ASKEDCOMPATMODE:
- askedCompatMode = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_USERID:
- userId = Integer.parseInt(attrValue);
- break;
- case ATTR_USER_SETUP_COMPLETE:
- userSetupComplete = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_EFFECTIVE_UID:
- effectiveUid = Integer.parseInt(attrValue);
- break;
- case ATTR_TASKTYPE:
- taskType = Integer.parseInt(attrValue);
- break;
- case ATTR_LASTDESCRIPTION:
- lastDescription = attrValue;
- break;
- case ATTR_LASTTIMEMOVED:
- lastTimeOnTop = Long.parseLong(attrValue);
- break;
- case ATTR_NEVERRELINQUISH:
- neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_TASK_AFFILIATION:
- taskAffiliation = Integer.parseInt(attrValue);
- break;
- case ATTR_PREV_AFFILIATION:
- prevTaskId = Integer.parseInt(attrValue);
- break;
- case ATTR_NEXT_AFFILIATION:
- nextTaskId = Integer.parseInt(attrValue);
- break;
- case ATTR_TASK_AFFILIATION_COLOR:
- taskAffiliationColor = Integer.parseInt(attrValue);
- break;
- case ATTR_CALLING_UID:
- callingUid = Integer.parseInt(attrValue);
- break;
- case ATTR_CALLING_PACKAGE:
- callingPackage = attrValue;
- break;
- case ATTR_CALLING_FEATURE_ID:
- callingFeatureId = attrValue;
- break;
- case ATTR_RESIZE_MODE:
- resizeMode = Integer.parseInt(attrValue);
- break;
- case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
- supportsPictureInPicture = Boolean.parseBoolean(attrValue);
- break;
- case ATTR_NON_FULLSCREEN_BOUNDS:
- lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
- break;
- case ATTR_MIN_WIDTH:
- minWidth = Integer.parseInt(attrValue);
- break;
- case ATTR_MIN_HEIGHT:
- minHeight = Integer.parseInt(attrValue);
- break;
- case ATTR_PERSIST_TASK_VERSION:
- persistTaskVersion = Integer.parseInt(attrValue);
- break;
- default:
- if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
- Slog.w(TAG, "Task: Unknown attribute=" + attrName);
- }
- }
+ for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
+ final String attrName = in.getAttributeName(attrNdx);
+ final String attrValue = in.getAttributeValue(attrNdx);
+ if (TaskPersister.DEBUG) {
+ Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value="
+ + attrValue);
}
- taskDescription.restoreFromXml(in);
-
- int event;
- while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
- && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
- if (event == XmlPullParser.START_TAG) {
- final String name = in.getName();
- if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
- "Task: START_TAG name=" + name);
- if (TAG_AFFINITYINTENT.equals(name)) {
- affinityIntent = Intent.restoreFromXml(in);
- } else if (TAG_INTENT.equals(name)) {
- intent = Intent.restoreFromXml(in);
- } else if (TAG_ACTIVITY.equals(name)) {
- ActivityRecord activity =
- ActivityRecord.restoreFromXml(in, stackSupervisor);
- if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: activity="
- + activity);
- if (activity != null) {
- activities.add(activity);
- }
- } else {
- handleUnknownTag(name, in);
+ switch (attrName) {
+ case ATTR_TASKID:
+ if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
+ break;
+ case ATTR_REALACTIVITY:
+ realActivity = ComponentName.unflattenFromString(attrValue);
+ break;
+ case ATTR_REALACTIVITY_SUSPENDED:
+ realActivitySuspended = Boolean.valueOf(attrValue);
+ break;
+ case ATTR_ORIGACTIVITY:
+ origActivity = ComponentName.unflattenFromString(attrValue);
+ break;
+ case ATTR_AFFINITY:
+ affinity = attrValue;
+ break;
+ case ATTR_ROOT_AFFINITY:
+ rootAffinity = attrValue;
+ hasRootAffinity = true;
+ break;
+ case ATTR_WINDOW_LAYOUT_AFFINITY:
+ windowLayoutAffinity = attrValue;
+ break;
+ case ATTR_ROOTHASRESET:
+ rootHasReset = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_AUTOREMOVERECENTS:
+ autoRemoveRecents = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_ASKEDCOMPATMODE:
+ askedCompatMode = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_USERID:
+ userId = Integer.parseInt(attrValue);
+ break;
+ case ATTR_USER_SETUP_COMPLETE:
+ userSetupComplete = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_EFFECTIVE_UID:
+ effectiveUid = Integer.parseInt(attrValue);
+ break;
+ case ATTR_TASKTYPE:
+ taskType = Integer.parseInt(attrValue);
+ break;
+ case ATTR_LASTDESCRIPTION:
+ lastDescription = attrValue;
+ break;
+ case ATTR_LASTTIMEMOVED:
+ lastTimeOnTop = Long.parseLong(attrValue);
+ break;
+ case ATTR_NEVERRELINQUISH:
+ neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_TASK_AFFILIATION:
+ taskAffiliation = Integer.parseInt(attrValue);
+ break;
+ case ATTR_PREV_AFFILIATION:
+ prevTaskId = Integer.parseInt(attrValue);
+ break;
+ case ATTR_NEXT_AFFILIATION:
+ nextTaskId = Integer.parseInt(attrValue);
+ break;
+ case ATTR_TASK_AFFILIATION_COLOR:
+ taskAffiliationColor = Integer.parseInt(attrValue);
+ break;
+ case ATTR_CALLING_UID:
+ callingUid = Integer.parseInt(attrValue);
+ break;
+ case ATTR_CALLING_PACKAGE:
+ callingPackage = attrValue;
+ break;
+ case ATTR_CALLING_FEATURE_ID:
+ callingFeatureId = attrValue;
+ break;
+ case ATTR_RESIZE_MODE:
+ resizeMode = Integer.parseInt(attrValue);
+ break;
+ case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
+ supportsPictureInPicture = Boolean.parseBoolean(attrValue);
+ break;
+ case ATTR_NON_FULLSCREEN_BOUNDS:
+ lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
+ break;
+ case ATTR_MIN_WIDTH:
+ minWidth = Integer.parseInt(attrValue);
+ break;
+ case ATTR_MIN_HEIGHT:
+ minHeight = Integer.parseInt(attrValue);
+ break;
+ case ATTR_PERSIST_TASK_VERSION:
+ persistTaskVersion = Integer.parseInt(attrValue);
+ break;
+ default:
+ if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
+ Slog.w(TAG, "Task: Unknown attribute=" + attrName);
}
- }
}
- if (!hasRootAffinity) {
- rootAffinity = affinity;
- } else if ("@".equals(rootAffinity)) {
- rootAffinity = null;
- }
- if (effectiveUid <= 0) {
- Intent checkIntent = intent != null ? intent : affinityIntent;
- effectiveUid = 0;
- if (checkIntent != null) {
- IPackageManager pm = AppGlobals.getPackageManager();
- try {
- ApplicationInfo ai = pm.getApplicationInfo(
- checkIntent.getComponent().getPackageName(),
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
- if (ai != null) {
- effectiveUid = ai.uid;
- }
- } catch (RemoteException e) {
+ }
+ taskDescription.restoreFromXml(in);
+
+ int event;
+ while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
+ && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
+ if (event == XmlPullParser.START_TAG) {
+ final String name = in.getName();
+ if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name);
+ if (TAG_AFFINITYINTENT.equals(name)) {
+ affinityIntent = Intent.restoreFromXml(in);
+ } else if (TAG_INTENT.equals(name)) {
+ intent = Intent.restoreFromXml(in);
+ } else if (TAG_ACTIVITY.equals(name)) {
+ ActivityRecord activity =
+ ActivityRecord.restoreFromXml(in, stackSupervisor);
+ if (TaskPersister.DEBUG) {
+ Slog.d(TaskPersister.TAG, "Task: activity=" + activity);
}
- }
- Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
- + ": effectiveUid=" + effectiveUid);
- }
-
- if (persistTaskVersion < 1) {
- // We need to convert the resize mode of home activities saved before version one if
- // they are marked as RESIZE_MODE_RESIZEABLE to
- // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
- // before version 1 and the system didn't resize home activities before then.
- if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
- resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
- }
- } else {
- // This activity has previously marked itself explicitly as both resizeable and
- // supporting picture-in-picture. Since there is no longer a requirement for
- // picture-in-picture activities to be resizeable, we can mark this simply as
- // resizeable and supporting picture-in-picture separately.
- if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
- resizeMode = RESIZE_MODE_RESIZEABLE;
- supportsPictureInPicture = true;
+ if (activity != null) {
+ activities.add(activity);
+ }
+ } else {
+ Slog.e(TAG, "restoreTask: Unexpected name=" + name);
+ XmlUtils.skipCurrentTag(in);
}
}
-
- final Task task = create(stackSupervisor.mService,
- taskId, intent, affinityIntent,
- affinity, rootAffinity, realActivity, origActivity, rootHasReset,
- autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- lastTimeOnTop, neverRelinquishIdentity, taskDescription,
- taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
- callingPackage, callingFeatureId, resizeMode, supportsPictureInPicture,
- realActivitySuspended, userSetupComplete, minWidth, minHeight, null /*stack*/);
- task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
- task.setBounds(lastNonFullscreenBounds);
- task.mWindowLayoutAffinity = windowLayoutAffinity;
-
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- task.addChild(activities.get(activityNdx));
+ }
+ if (!hasRootAffinity) {
+ rootAffinity = affinity;
+ } else if ("@".equals(rootAffinity)) {
+ rootAffinity = null;
+ }
+ if (effectiveUid <= 0) {
+ Intent checkIntent = intent != null ? intent : affinityIntent;
+ effectiveUid = 0;
+ if (checkIntent != null) {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(
+ checkIntent.getComponent().getPackageName(),
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
+ if (ai != null) {
+ effectiveUid = ai.uid;
+ }
+ } catch (RemoteException e) {
+ }
}
-
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
- return task;
+ Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
+ + ": effectiveUid=" + effectiveUid);
}
- void handleUnknownTag(String name, XmlPullParser in)
- throws IOException, XmlPullParserException {
- Slog.e(TAG, "restoreTask: Unexpected name=" + name);
- XmlUtils.skipCurrentTag(in);
+ if (persistTaskVersion < 1) {
+ // We need to convert the resize mode of home activities saved before version one if
+ // they are marked as RESIZE_MODE_RESIZEABLE to
+ // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
+ // before version 1 and the system didn't resize home activities before then.
+ if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
+ resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+ }
+ } else {
+ // This activity has previously marked itself explicitly as both resizeable and
+ // supporting picture-in-picture. Since there is no longer a requirement for
+ // picture-in-picture activities to be resizeable, we can mark this simply as
+ // resizeable and supporting picture-in-picture separately.
+ if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
+ resizeMode = RESIZE_MODE_RESIZEABLE;
+ supportsPictureInPicture = true;
+ }
}
+
+ final Task task = new ActivityStack(stackSupervisor.mService, taskId, intent,
+ affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
+ autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
+ lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation,
+ prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
+ callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
+ userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
+ null /*_voiceSession*/, null /*_voiceInteractor*/, null /* stack */);
+ task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
+ task.setBounds(lastNonFullscreenBounds);
+ task.mWindowLayoutAffinity = windowLayoutAffinity;
+
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ task.addChild(activities.get(activityNdx));
+ }
+
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
+ return task;
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 4b0e293..df0fa9c 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -60,6 +60,7 @@
private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
private static final int NOTIFY_TASK_FOCUS_CHANGED_MSG = 27;
+ private static final int NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG = 28;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -178,6 +179,10 @@
l.onTaskFocusChanged(m.arg1, m.arg2 != 0);
};
+ private final TaskStackConsumer mNotifyTaskRequestedOrientationChanged = (l, m) -> {
+ l.onTaskRequestedOrientationChanged(m.arg1, m.arg2);
+ };
+
@FunctionalInterface
public interface TaskStackConsumer {
void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -269,6 +274,9 @@
case NOTIFY_TASK_FOCUS_CHANGED_MSG:
forAllRemoteListeners(mNotifyTaskFocusChanged, msg);
break;
+ case NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG:
+ forAllRemoteListeners(mNotifyTaskRequestedOrientationChanged, msg);
+ break;
}
if (msg.obj instanceof SomeArgs) {
((SomeArgs) msg.obj).recycle();
@@ -558,4 +566,12 @@
forAllLocalListeners(mNotifyTaskFocusChanged, msg);
msg.sendToTarget();
}
+
+ /** @see android.app.ITaskStackListener#onTaskRequestedOrientationChanged(int, int) */
+ void notifyTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG,
+ taskId, requestedOrientation);
+ forAllLocalListeners(mNotifyTaskRequestedOrientationChanged, msg);
+ msg.sendToTarget();
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 3dc6723..75295e6 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -959,7 +959,7 @@
windowingMode = WINDOWING_MODE_UNDEFINED;
}
- final ActivityStack stack = (ActivityStack) Task.create(mAtmService, stackId, activityType,
+ final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType,
info, intent, createdByOrganizer);
if (launchRootTask != null) {
launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
index 27fa36b..dc3fa2a 100644
--- a/services/people/java/com/android/server/people/data/ConversationInfo.java
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -62,8 +62,6 @@
private static final int FLAG_DEMOTED = 1 << 6;
- private static final int FLAG_NOTIFICATION_SETTING_CHANGED = 1 << 7;
-
@IntDef(flag = true, prefix = {"FLAG_"}, value = {
FLAG_IMPORTANT,
FLAG_NOTIFICATION_SILENCED,
@@ -72,7 +70,6 @@
FLAG_PERSON_BOT,
FLAG_CONTACT_STARRED,
FLAG_DEMOTED,
- FLAG_NOTIFICATION_SETTING_CHANGED,
})
@Retention(RetentionPolicy.SOURCE)
private @interface ConversationFlags {
@@ -188,11 +185,6 @@
return hasConversationFlags(FLAG_CONTACT_STARRED);
}
- /** Whether the conversation's notification setting has ever been changed by the user. */
- boolean isNotificationSettingChanged() {
- return hasConversationFlags(FLAG_NOTIFICATION_SETTING_CHANGED);
- }
-
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -499,10 +491,6 @@
return setConversationFlag(FLAG_CONTACT_STARRED, value);
}
- Builder setNotificationSettingChanged(boolean value) {
- return setConversationFlag(FLAG_NOTIFICATION_SETTING_CHANGED, value);
- }
-
private Builder setConversationFlag(@ConversationFlags int flags, boolean value) {
if (value) {
return addConversationFlags(flags);
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 8e1141d..d9ca415 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -16,8 +16,6 @@
package com.android.server.people.data;
-import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -60,9 +58,11 @@
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ChooserActivity;
import com.android.internal.content.PackageMonitor;
@@ -106,8 +106,7 @@
private final SparseArray<BroadcastReceiver> mBroadcastReceivers = new SparseArray<>();
private final SparseArray<ContentObserver> mContactsContentObservers = new SparseArray<>();
private final SparseArray<ScheduledFuture<?>> mUsageStatsQueryFutures = new SparseArray<>();
- private final SparseArray<NotificationListenerService> mNotificationListeners =
- new SparseArray<>();
+ private final SparseArray<NotificationListener> mNotificationListeners = new SparseArray<>();
private final SparseArray<PackageMonitor> mPackageMonitors = new SparseArray<>();
private ContentObserver mCallLogContentObserver;
private ContentObserver mMmsSmsContentObserver;
@@ -272,6 +271,7 @@
}
pruneUninstalledPackageData(userData);
+ final NotificationListener notificationListener = mNotificationListeners.get(userId);
userData.forAllPackages(packageData -> {
if (signal.isCanceled()) {
return;
@@ -284,6 +284,20 @@
packageData.getEventStore().deleteEventHistories(EventStore.CATEGORY_SMS);
}
packageData.pruneOrphanEvents();
+ if (notificationListener != null) {
+ String packageName = packageData.getPackageName();
+ packageData.forAllConversations(conversationInfo -> {
+ if (conversationInfo.isShortcutCached()
+ && conversationInfo.getNotificationChannelId() == null
+ && !notificationListener.hasActiveNotifications(
+ packageName, conversationInfo.getShortcutId())) {
+ mShortcutServiceInternal.uncacheShortcuts(userId,
+ mContext.getPackageName(), packageName,
+ Collections.singletonList(conversationInfo.getShortcutId()),
+ userId);
+ }
+ });
+ }
});
}
@@ -337,7 +351,7 @@
Contacts.CONTENT_URI, /* notifyForDescendants= */ true,
contactsContentObserver, userId);
- NotificationListener notificationListener = new NotificationListener();
+ NotificationListener notificationListener = new NotificationListener(userId);
mNotificationListeners.put(userId, notificationListener);
try {
notificationListener.registerAsSystemService(mContext,
@@ -753,14 +767,27 @@
/** Listener for the notifications and their settings changes. */
private class NotificationListener extends NotificationListenerService {
- // Conversation shortcut ID -> Number of active notifications
- private final Map<String, Integer> mActiveNotifCounts = new ArrayMap<>();
+ private final int mUserId;
+
+ // Conversation package name + shortcut ID -> Number of active notifications
+ @GuardedBy("this")
+ private final Map<Pair<String, String>, Integer> mActiveNotifCounts = new ArrayMap<>();
+
+ private NotificationListener(int userId) {
+ mUserId = userId;
+ }
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
+ if (sbn.getUser().getIdentifier() != mUserId) {
+ return;
+ }
String shortcutId = sbn.getNotification().getShortcutId();
PackageData packageData = getPackageIfConversationExists(sbn, conversationInfo -> {
- mActiveNotifCounts.merge(shortcutId, 1, Integer::sum);
+ synchronized (this) {
+ mActiveNotifCounts.merge(
+ Pair.create(sbn.getPackageName(), shortcutId), 1, Integer::sum);
+ }
});
if (packageData != null) {
@@ -771,26 +798,32 @@
}
@Override
- public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
- int reason) {
+ public synchronized void onNotificationRemoved(StatusBarNotification sbn,
+ RankingMap rankingMap, int reason) {
+ if (sbn.getUser().getIdentifier() != mUserId) {
+ return;
+ }
String shortcutId = sbn.getNotification().getShortcutId();
PackageData packageData = getPackageIfConversationExists(sbn, conversationInfo -> {
- int count = mActiveNotifCounts.getOrDefault(shortcutId, 0) - 1;
- if (count <= 0) {
- mActiveNotifCounts.remove(sbn.getNotification().getShortcutId());
- // The shortcut was cached by Notification Manager synchronously when the
- // associated notification was posted. Uncache it here when all the associated
- // notifications are removed.
- if (conversationInfo.isShortcutCached()
- && !conversationInfo.isNotificationSettingChanged()) {
- int userId = sbn.getUser().getIdentifier();
- mShortcutServiceInternal.uncacheShortcuts(userId,
- mContext.getPackageName(), sbn.getPackageName(),
- Collections.singletonList(conversationInfo.getShortcutId()),
- userId);
+ Pair<String, String> conversationKey =
+ Pair.create(sbn.getPackageName(), shortcutId);
+ synchronized (this) {
+ int count = mActiveNotifCounts.getOrDefault(conversationKey, 0) - 1;
+ if (count <= 0) {
+ mActiveNotifCounts.remove(conversationKey);
+ // The shortcut was cached by Notification Manager synchronously when the
+ // associated notification was posted. Uncache it here when all the
+ // associated notifications are removed.
+ if (conversationInfo.isShortcutCached()
+ && conversationInfo.getNotificationChannelId() == null) {
+ mShortcutServiceInternal.uncacheShortcuts(mUserId,
+ mContext.getPackageName(), sbn.getPackageName(),
+ Collections.singletonList(conversationInfo.getShortcutId()),
+ mUserId);
+ }
+ } else {
+ mActiveNotifCounts.put(conversationKey, count);
}
- } else {
- mActiveNotifCounts.put(shortcutId, count);
}
});
@@ -806,6 +839,9 @@
@Override
public void onNotificationChannelModified(String pkg, UserHandle user,
NotificationChannel channel, int modificationType) {
+ if (user.getIdentifier() != mUserId) {
+ return;
+ }
PackageData packageData = getPackage(pkg, user.getIdentifier());
String shortcutId = channel.getConversationId();
if (packageData == null || shortcutId == null) {
@@ -816,16 +852,7 @@
if (conversationInfo == null) {
return;
}
- boolean isNotificationSettingChanged =
- conversationInfo.isImportant() != channel.isImportantConversation()
- || conversationInfo.isDemoted() != channel.isDemoted()
- || channel.hasUserSetImportance()
- || (channel.getUserLockedFields() & USER_LOCKED_ALLOW_BUBBLE) != 0;
ConversationInfo.Builder builder = new ConversationInfo.Builder(conversationInfo);
- if (modificationType == NOTIFICATION_CHANNEL_OR_GROUP_UPDATED
- && isNotificationSettingChanged) {
- builder.setNotificationSettingChanged(true);
- }
switch (modificationType) {
case NOTIFICATION_CHANNEL_OR_GROUP_ADDED:
case NOTIFICATION_CHANNEL_OR_GROUP_UPDATED:
@@ -848,6 +875,28 @@
}
conversationStore.addOrUpdate(builder.build());
}
+
+ synchronized void cleanupCachedShortcuts() {
+ for (Pair<String, String> conversationKey : mActiveNotifCounts.keySet()) {
+ String packageName = conversationKey.first;
+ String shortcutId = conversationKey.second;
+ PackageData packageData = getPackage(packageName, mUserId);
+ ConversationInfo conversationInfo =
+ packageData != null ? packageData.getConversationInfo(shortcutId) : null;
+ if (conversationInfo != null
+ && conversationInfo.isShortcutCached()
+ && conversationInfo.getNotificationChannelId() == null) {
+ mShortcutServiceInternal.uncacheShortcuts(mUserId,
+ mContext.getPackageName(), packageName,
+ Collections.singletonList(shortcutId),
+ mUserId);
+ }
+ }
+ }
+
+ synchronized boolean hasActiveNotifications(String packageName, String shortcutId) {
+ return mActiveNotifCounts.containsKey(Pair.create(packageName, shortcutId));
+ }
}
/**
@@ -917,7 +966,16 @@
@Override
public void onReceive(Context context, Intent intent) {
- forAllUnlockedUsers(userData -> userData.forAllPackages(PackageData::saveToDisk));
+ forAllUnlockedUsers(userData -> {
+ NotificationListener listener = mNotificationListeners.get(userData.getUserId());
+ // Clean up the cached shortcuts because all the notifications are cleared after
+ // system shutdown. The associated shortcuts need to be uncached to keep in sync
+ // unless the settings are changed by the user.
+ if (listener != null) {
+ listener.cleanupCachedShortcuts();
+ }
+ userData.forAllPackages(PackageData::saveToDisk);
+ });
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 6d15302..8abddc8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -308,7 +308,7 @@
doReturn(0).when(() -> SurfaceControl.getActiveColorMode(display.token));
doReturn(new int[] { 0 }).when(
() -> SurfaceControl.getDisplayColorModes(display.token));
- doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f))
+ doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f))
.when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(display.token));
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 08bd1ee..8137c36 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -16,7 +16,6 @@
package com.android.server.display;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.content.Context;
@@ -30,7 +29,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
-import com.android.server.display.DisplayModeDirector.RefreshRateRange;
import com.android.server.display.DisplayModeDirector.Vote;
import com.google.common.truth.Truth;
@@ -79,10 +77,12 @@
int displayId = 0;
// With no votes present, DisplayModeDirector should allow any refresh rate.
- assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/60,
- new RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
+ DesiredDisplayModeSpecs modeSpecs =
createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
- displayId));
+ displayId);
+ Truth.assertThat(modeSpecs.baseModeId).isEqualTo(60);
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f);
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY);
int numPriorities =
DisplayModeDirector.Vote.MAX_PRIORITY - DisplayModeDirector.Vote.MIN_PRIORITY + 1;
@@ -101,10 +101,12 @@
int priority = Vote.MIN_PRIORITY + i;
votes.put(priority, Vote.forRefreshRates(minFps + i, maxFps - i));
director.injectVotesByDisplay(votesByDisplay);
- assertEquals(new DesiredDisplayModeSpecs(
- /*baseModeId=*/minFps + i,
- new RefreshRateRange(minFps + i, maxFps - i)),
- director.getDesiredDisplayModeSpecs(displayId));
+ modeSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i);
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.min)
+ .isEqualTo((float) (minFps + i));
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.max)
+ .isEqualTo((float) (maxFps - i));
}
}
@@ -119,9 +121,10 @@
votes.put(Vote.MAX_PRIORITY, Vote.forRefreshRates(65, 85));
votes.put(Vote.MIN_PRIORITY, Vote.forRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
- assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/70,
- new RefreshRateRange(70, 80)),
- director.getDesiredDisplayModeSpecs(displayId));
+ modeSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(modeSpecs.baseModeId).isEqualTo(70);
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(70f);
+ Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(80f);
}
}
@@ -140,8 +143,8 @@
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
- Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60);
}
@@ -159,34 +162,77 @@
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
- Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
- Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
-
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
- Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
- Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ }
+ @Test
+ public void testAppRequestRefreshRateRange() {
+ // Confirm that the app request range doesn't include low brightness or min refresh rate
+ // settings, but does include everything else.
+ assertTrue(
+ Vote.PRIORITY_LOW_BRIGHTNESS < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
+ < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
+ >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ int displayId = 0;
+ DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(displayId, votes);
+ votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
+ director.injectVotesByDisplay(votesByDisplay);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
+ Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
+ director.injectVotesByDisplay(votesByDisplay);
+ desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+
+ votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(75, 75));
+ director.injectVotesByDisplay(votesByDisplay);
+ desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75);
+ Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min)
+ .isWithin(FLOAT_TOLERANCE)
+ .of(75);
+ Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max)
+ .isWithin(FLOAT_TOLERANCE)
+ .of(75);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
index ea8aa6b..70d6cf8 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
@@ -54,7 +54,6 @@
.setPersonImportant(true)
.setPersonBot(true)
.setContactStarred(true)
- .setNotificationSettingChanged(true)
.build();
assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
@@ -71,7 +70,6 @@
assertTrue(conversationInfo.isPersonImportant());
assertTrue(conversationInfo.isPersonBot());
assertTrue(conversationInfo.isContactStarred());
- assertTrue(conversationInfo.isNotificationSettingChanged());
}
@Test
@@ -94,7 +92,6 @@
assertFalse(conversationInfo.isPersonImportant());
assertFalse(conversationInfo.isPersonBot());
assertFalse(conversationInfo.isContactStarred());
- assertFalse(conversationInfo.isNotificationSettingChanged());
}
@Test
@@ -112,7 +109,6 @@
.setPersonImportant(true)
.setPersonBot(true)
.setContactStarred(true)
- .setNotificationSettingChanged(true)
.build();
ConversationInfo destination = new ConversationInfo.Builder(source)
@@ -132,6 +128,5 @@
assertTrue(destination.isPersonImportant());
assertTrue(destination.isPersonBot());
assertFalse(destination.isContactStarred());
- assertTrue(destination.isNotificationSettingChanged());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index e51ab9db..1a2032a 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -49,6 +49,7 @@
import android.app.prediction.AppTargetEvent;
import android.app.prediction.AppTargetId;
import android.app.usage.UsageStatsManagerInternal;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -95,8 +96,6 @@
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -125,18 +124,19 @@
@Mock private TelephonyManager mTelephonyManager;
@Mock private TelecomManager mTelecomManager;
@Mock private ContentResolver mContentResolver;
- @Mock private ScheduledExecutorService mExecutorService;
@Mock private JobScheduler mJobScheduler;
- @Mock private ScheduledFuture mScheduledFuture;
@Mock private StatusBarNotification mStatusBarNotification;
@Mock private Notification mNotification;
@Captor private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
+ @Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
+ private ScheduledExecutorService mExecutorService;
private NotificationChannel mNotificationChannel;
private DataManager mDataManager;
private CancellationSignal mCancellationSignal;
private ShortcutChangeCallback mShortcutChangeCallback;
+ private BroadcastReceiver mShutdownBroadcastReceiver;
private TestInjector mInjector;
@Before
@@ -182,13 +182,7 @@
when(mContext.getSystemServiceName(JobScheduler.class)).thenReturn(
Context.JOB_SCHEDULER_SERVICE);
- when(mExecutorService.scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(
- TimeUnit.class))).thenReturn(mScheduledFuture);
- doAnswer(ans -> {
- Runnable runnable = (Runnable) ans.getArguments()[0];
- runnable.run();
- return null;
- }).when(mExecutorService).execute(any(Runnable.class));
+ mExecutorService = new MockScheduledExecutorService();
when(mUserManager.getEnabledProfiles(USER_ID_PRIMARY))
.thenReturn(Arrays.asList(
@@ -221,6 +215,9 @@
verify(mShortcutServiceInternal).addShortcutChangeCallback(
mShortcutChangeCallbackCaptor.capture());
mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any());
+ mShutdownBroadcastReceiver = mBroadcastReceiverCaptor.getValue();
}
@After
@@ -459,7 +456,7 @@
}
@Test
- public void testShortcutNotUncachedIfSettingChanged() {
+ public void testShortcutNotUncachedIfNotificationChannelCreated() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
@@ -473,7 +470,6 @@
shortcut.setCached();
mDataManager.addOrUpdateConversationInfo(shortcut);
- mNotificationChannel.setImportantConversation(true);
listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
@@ -530,7 +526,6 @@
assertTrue(conversationInfo.isImportant());
assertFalse(conversationInfo.isNotificationSilenced());
assertFalse(conversationInfo.isDemoted());
- assertTrue(conversationInfo.isNotificationSettingChanged());
}
@Test
@@ -563,6 +558,51 @@
}
@Test
+ public void testUncacheShortcutWhenShutdown() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+
+ listenerService.onNotificationPosted(mStatusBarNotification);
+ shortcut.setCached();
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ mShutdownBroadcastReceiver.onReceive(mContext, new Intent());
+ verify(mShortcutServiceInternal).uncacheShortcuts(
+ anyInt(), any(), eq(TEST_PKG_NAME),
+ eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+ }
+
+ @Test
+ public void testDoNotUncacheShortcutWhenShutdownIfNotificationChannelCreated() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+
+ listenerService.onNotificationPosted(mStatusBarNotification);
+ shortcut.setCached();
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY),
+ mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ mShutdownBroadcastReceiver.onReceive(mContext, new Intent());
+ verify(mShortcutServiceInternal, never()).uncacheShortcuts(
+ anyInt(), any(), eq(TEST_PKG_NAME),
+ eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+ }
+
+ @Test
public void testShortcutAddedOrUpdated() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -722,6 +762,22 @@
}
@Test
+ public void testPruneInactiveCachedShortcuts() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ shortcut.setCached();
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
+
+ verify(mShortcutServiceInternal).uncacheShortcuts(
+ anyInt(), any(), eq(TEST_PKG_NAME),
+ eq(Collections.singletonList(TEST_SHORTCUT_ID)), eq(USER_ID_PRIMARY));
+ }
+
+ @Test
public void testBackupAndRestoration()
throws IntentFilter.MalformedMimeTypeException {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
diff --git a/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java b/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
index aecbc8d..8cb846f 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
@@ -96,7 +96,6 @@
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
TimeUnit unit) {
- Preconditions.checkState(unit == TimeUnit.MILLISECONDS);
return new MockScheduledFuture<>(command, period, unit);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 7b1b2d2..6de08fd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -23,6 +23,7 @@
import android.content.pm.FeatureInfo
import android.content.pm.InstrumentationInfo
import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
import android.content.pm.PackageParser
import android.content.pm.PackageUserState
import android.content.pm.PermissionInfo
@@ -168,6 +169,11 @@
private fun <T> tryOrNull(block: () -> T) = try {
block()
+ } catch (e: PackageParser.PackageParserException) {
+ if (e.error != PackageManager.INSTALL_PARSE_FAILED_SKIPPED) {
+ thrownInSetUp.add(e)
+ }
+ null
} catch (t: Throwable) {
thrownInSetUp.add(t)
null
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index f1c3906..60390dc 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -126,7 +126,7 @@
mIntervalStats.majorVersion = 7;
mIntervalStats.minorVersion = 8;
- mIntervalStats.beginTime = time;
+ mIntervalStats.beginTime = time - 1;
mIntervalStats.interactiveTracker.count = 2;
mIntervalStats.interactiveTracker.duration = 111111;
mIntervalStats.nonInteractiveTracker.count = 3;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 7e7d69a..fdc9401 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -54,6 +54,10 @@
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityViewTestActivity" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityInActivityView"
android:resizeableActivity="true" />
+ <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$LandscapeActivity"
+ android:screenOrientation="sensorLandscape"
+ android:showWhenLocked="true"
+ android:turnScreenOn="true" />
<activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity"
android:showWhenLocked="true" android:allowEmbedded="true"/>
</application>
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 60875de..fb24d86 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -49,7 +49,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -67,16 +66,12 @@
import android.graphics.Rect;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.service.voice.IVoiceInteractionSession;
import android.util.DisplayMetrics;
import android.util.Xml;
import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
-import com.android.internal.app.IVoiceInteractor;
-import com.android.server.wm.Task.TaskFactory;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -122,11 +117,6 @@
assertEquals(expected.mLastNonFullscreenBounds, actual.mLastNonFullscreenBounds);
}
- @Test
- public void testDefaultTaskFactoryNotNull() throws Exception {
- assertNotNull(Task.getTaskFactory());
- }
-
/** Ensure we have no chance to modify the original intent. */
@Test
public void testCopyBaseIntentForTaskInfo() {
@@ -139,23 +129,6 @@
}
@Test
- public void testCreateTestRecordUsingCustomizedFactory() throws Exception {
- TestTaskFactory factory = new TestTaskFactory();
- Task.setTaskFactory(factory);
-
- try {
- assertFalse(factory.mCreated);
-
- Task.create(mService, 0 /*taskId*/, 0 /*activityType*/,
- new ActivityInfo(), new Intent(), false /* createdByOrganizer */);
-
- assertTrue(factory.mCreated);
- } finally {
- Task.setTaskFactory(null);
- }
- }
-
- @Test
public void testReturnsToHomeStack() throws Exception {
final Task task = createTask(1);
spyOn(task);
@@ -448,6 +421,21 @@
}
@Test
+ public void testFullScreenTaskNotAdjustedByMinimalSize() {
+ final Task fullscreenTask = new TaskBuilder(mSupervisor).build();
+ final Rect originalTaskBounds = new Rect(fullscreenTask.getBounds());
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.windowLayout = new ActivityInfo.WindowLayout(0 /* width */, 0 /* widthFraction */,
+ 0 /* height */, 0 /* heightFraction */, 0 /* gravity */,
+ originalTaskBounds.width() * 2 /* minWidth */,
+ originalTaskBounds.height() * 2 /* minHeight */);
+ fullscreenTask.setMinDimensions(aInfo);
+ fullscreenTask.onConfigurationChanged(fullscreenTask.getParent().getConfiguration());
+
+ assertEquals(originalTaskBounds, fullscreenTask.getBounds());
+ }
+
+ @Test
public void testInsetDisregardedWhenFreeformOverlapsNavBar() {
TaskDisplayArea taskDisplayArea = mService.mRootWindowContainer.getDefaultTaskDisplayArea();
ActivityStack stack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
@@ -525,8 +513,9 @@
info.packageName = DEFAULT_COMPONENT_PACKAGE_NAME;
info.targetActivity = targetClassName;
- final Task task = Task.create(mService, 1 /* taskId */, info, intent,
- null /* voiceSession */, null /* voiceInteractor */, null /*stack*/);
+ final Task task = new ActivityStack(mService, 1 /* taskId */, info, intent,
+ null /* voiceSession */, null /* voiceInteractor */, null /* taskDescriptor */,
+ null /*stack*/);
assertEquals("The alias activity component should be saved in task intent.", aliasClassName,
task.intent.getComponent().getClassName());
@@ -1023,48 +1012,4 @@
0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/,
null /*stack*/);
}
-
- private static class TestTaskFactory extends TaskFactory {
- private boolean mCreated = false;
-
- @Override
- Task create(ActivityTaskManagerService service, int taskId, int activityType,
- ActivityInfo info, Intent intent, boolean createdByOrganizer) {
- mCreated = true;
- return null;
- }
-
- @Override
- Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor, ActivityStack stack) {
- mCreated = true;
- return null;
- }
-
- @Override
- Task create(ActivityTaskManagerService service, int taskId, Intent intent,
- Intent affinityIntent, String affinity, String rootAffinity,
- ComponentName realActivity,
- ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
- boolean askedCompatMode, int userId, int effectiveUid, String lastDescription,
- long lastTimeMoved,
- boolean neverRelinquishIdentity,
- ActivityManager.TaskDescription lastTaskDescription,
- int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
- int callingUid, String callingPackage, String callingFeatureId, int resizeMode,
- boolean supportsPictureInPicture,
- boolean realActivitySuspended, boolean userSetupComplete, int minWidth,
- int minHeight, ActivityStack stack) {
- mCreated = true;
- return null;
- }
-
- @Override
- Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
- throws IOException, XmlPullParserException {
- mCreated = true;
- return null;
- }
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 9872faa..4e92ea0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
@@ -41,6 +42,7 @@
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
@@ -56,8 +58,10 @@
import org.junit.Before;
import org.junit.Test;
+import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
/**
* Build/Install/Run:
@@ -391,6 +395,42 @@
}
};
+ @Presubmit
+ @FlakyTest(bugId = 150409355)
+ @Test
+ public void testNotifyTaskRequestedOrientationChanged() throws Exception {
+ final ArrayBlockingQueue<int[]> taskIdAndOrientationQueue = new ArrayBlockingQueue<>(10);
+ registerTaskStackChangedListener(new TaskStackListener() {
+ @Override
+ public void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
+ int[] taskIdAndOrientation = new int[2];
+ taskIdAndOrientation[0] = taskId;
+ taskIdAndOrientation[1] = requestedOrientation;
+ taskIdAndOrientationQueue.offer(taskIdAndOrientation);
+ }
+ });
+
+ final LandscapeActivity activity =
+ (LandscapeActivity) startTestActivity(LandscapeActivity.class);
+
+ int[] taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
+ candidate -> candidate[0] == activity.getTaskId());
+ assertNotNull(taskIdAndOrientation);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, taskIdAndOrientation[1]);
+
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
+ candidate -> candidate[0] == activity.getTaskId());
+ assertNotNull(taskIdAndOrientation);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, taskIdAndOrientation[1]);
+
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
+ candidate -> candidate[0] == activity.getTaskId());
+ assertNotNull(taskIdAndOrientation);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, taskIdAndOrientation[1]);
+ }
+
/**
* Starts the provided activity and returns the started instance.
*/
@@ -432,6 +472,19 @@
}
}
+ private <T> T waitForResult(ArrayBlockingQueue<T> queue, Predicate<T> predicate) {
+ try {
+ final long timeout = SystemClock.uptimeMillis() + TimeUnit.SECONDS.toMillis(15);
+ T result;
+ do {
+ result = queue.poll(timeout - SystemClock.uptimeMillis(), TimeUnit.MILLISECONDS);
+ } while (result != null && !predicate.test(result));
+ return result;
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+
public static class TestActivity extends Activity {
boolean mIsResumed = false;
@@ -563,4 +616,6 @@
// Activity that has {@link android.R.attr#resizeableActivity} attribute set to {@code true}
public static class ActivityInActivityView extends TestActivity {}
+
+ public static class LandscapeActivity extends TestActivity {}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 9fdb9d8..d65b084 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -204,7 +204,7 @@
.when(windowConfiguration).getWindowingMode();
// Prevent adjust task dimensions
- doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
+ doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any());
final Rect stackBounds = new Rect(200, 200, 800, 1000);
// Update surface position and size by the given bounds.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index aa68c69..2ea58a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -507,7 +507,7 @@
Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
Configuration c = new Configuration(task1.getRequestedOverrideConfiguration());
c.windowConfiguration.setBounds(newSize);
- doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
+ doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any());
task1.onRequestedOverrideConfigurationChanged(c);
assertEquals(newSize, stack.getBounds());
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 8fadf5e..5ee3b48 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -253,10 +253,6 @@
}
break;
}
- if (event.mTimeStamp == 0) {
- //mTimestamp not set, assume default value 0 plus beginTime
- event.mTimeStamp = beginTime;
- }
return event;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 932784d..463fc37 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -149,10 +149,6 @@
break;
}
}
- if (stats.mLastTimeUsed == 0) {
- // mLastTimeUsed was not assigned, assume default value of 0 plus beginTime;
- stats.mLastTimeUsed = statsOut.beginTime;
- }
proto.end(token);
}
@@ -289,10 +285,6 @@
configActive = proto.readBoolean(IntervalStatsProto.Configuration.ACTIVE);
break;
case ProtoInputStream.NO_MORE_FIELDS:
- if (configStats.mLastTimeActive == 0) {
- //mLastTimeActive was not assigned, assume default value of 0 plus beginTime
- configStats.mLastTimeActive = statsOut.beginTime;
- }
if (configActive) {
statsOut.activeConfiguration = configStats.mConfiguration;
}
@@ -336,21 +328,21 @@
// Package not in Stringpool for some reason, write full string instead
proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
}
- // Time attributes stored as an offset of the beginTime.
- proto.write(IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
- usageStats.mLastTimeUsed - stats.beginTime);
+ UsageStatsProtoV2.writeOffsetTimestamp(proto,
+ IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
+ usageStats.mLastTimeUsed, stats.beginTime);
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS,
usageStats.mTotalTimeInForeground);
proto.write(IntervalStatsProto.UsageStats.LAST_EVENT,
usageStats.mLastEvent);
- // Time attributes stored as an offset of the beginTime.
- proto.write(IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
- usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
+ UsageStatsProtoV2.writeOffsetTimestamp(proto,
+ IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
+ usageStats.mLastTimeForegroundServiceUsed, stats.beginTime);
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
usageStats.mTotalTimeForegroundServiceUsed);
- // Time attributes stored as an offset of the beginTime.
- proto.write(IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS,
- usageStats.mLastTimeVisible - stats.beginTime);
+ UsageStatsProtoV2.writeOffsetTimestamp(proto,
+ IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS,
+ usageStats.mLastTimeVisible, stats.beginTime);
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS,
usageStats.mTotalTimeVisible);
proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
@@ -411,8 +403,9 @@
throws IllegalArgumentException {
final long token = proto.start(fieldId);
configStats.mConfiguration.dumpDebug(proto, IntervalStatsProto.Configuration.CONFIG);
- proto.write(IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
- configStats.mLastTimeActive - stats.beginTime);
+ UsageStatsProtoV2.writeOffsetTimestamp(proto,
+ IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
+ configStats.mLastTimeActive, stats.beginTime);
proto.write(IntervalStatsProto.Configuration.TOTAL_TIME_ACTIVE_MS,
configStats.mTotalTimeActive);
proto.write(IntervalStatsProto.Configuration.COUNT, configStats.mActivationCount);
@@ -439,7 +432,8 @@
proto.write(IntervalStatsProto.Event.CLASS, event.mClass);
}
}
- proto.write(IntervalStatsProto.Event.TIME_MS, event.mTimeStamp - stats.beginTime);
+ UsageStatsProtoV2.writeOffsetTimestamp(proto, IntervalStatsProto.Event.TIME_MS,
+ event.mTimeStamp, stats.beginTime);
proto.write(IntervalStatsProto.Event.FLAGS, event.mFlags);
proto.write(IntervalStatsProto.Event.TYPE, event.mEventType);
proto.write(IntervalStatsProto.Event.INSTANCE_ID, event.mInstanceId);
@@ -566,10 +560,6 @@
}
break;
case ProtoInputStream.NO_MORE_FIELDS:
- if (statsOut.endTime == 0) {
- // endTime not assigned, assume default value of 0 plus beginTime
- statsOut.endTime = statsOut.beginTime;
- }
statsOut.upgradeIfNeeded();
return;
}
@@ -585,7 +575,8 @@
public static void write(OutputStream out, IntervalStats stats)
throws IOException, IllegalArgumentException {
final ProtoOutputStream proto = new ProtoOutputStream(out);
- proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
+ proto.write(IntervalStatsProto.END_TIME_MS,
+ UsageStatsProtoV2.getOffsetTimestamp(stats.endTime, stats.beginTime));
proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
// String pool should be written before the rest of the usage stats
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
index e4aa9fe..e6d2841 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -30,6 +30,7 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.concurrent.TimeUnit;
/**
* UsageStats reader/writer V2 for Protocol Buffer format.
@@ -37,6 +38,8 @@
final class UsageStatsProtoV2 {
private static final String TAG = "UsageStatsProtoV2";
+ private static final long ONE_HOUR_MS = TimeUnit.HOURS.toMillis(1);
+
// Static-only utility class.
private UsageStatsProtoV2() {}
@@ -88,10 +91,6 @@
UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS);
break;
case ProtoInputStream.NO_MORE_FIELDS:
- // mLastTimeUsed was not read, assume default value of 0 plus beginTime
- if (stats.mLastTimeUsed == 0) {
- stats.mLastTimeUsed = beginTime;
- }
return stats;
}
}
@@ -219,10 +218,6 @@
IntervalStatsObfuscatedProto.Configuration.ACTIVE);
break;
case ProtoInputStream.NO_MORE_FIELDS:
- // mLastTimeActive was not assigned, assume default value of 0 plus beginTime
- if (configStats.mLastTimeActive == 0) {
- configStats.mLastTimeActive = stats.beginTime;
- }
if (configActive) {
stats.activeConfiguration = configStats.mConfiguration;
}
@@ -282,27 +277,40 @@
EventObfuscatedProto.LOCUS_ID_TOKEN) - 1;
break;
case ProtoInputStream.NO_MORE_FIELDS:
- // timeStamp was not read, assume default value 0 plus beginTime
- if (event.mTimeStamp == 0) {
- event.mTimeStamp = beginTime;
- }
return event.mPackageToken == PackagesTokenData.UNASSIGNED_TOKEN ? null : event;
}
}
}
+ static void writeOffsetTimestamp(ProtoOutputStream proto, long fieldId,
+ long timestamp, long beginTime) {
+ // timestamps will only be written if they're after the begin time
+ // a grace period of one hour before the begin time is allowed because of rollover logic
+ final long rolloverGracePeriod = beginTime - ONE_HOUR_MS;
+ if (timestamp > rolloverGracePeriod) {
+ // time attributes are stored as an offset of the begin time (given offset)
+ proto.write(fieldId, getOffsetTimestamp(timestamp, beginTime));
+ }
+ }
+
+ static long getOffsetTimestamp(long timestamp, long offset) {
+ final long offsetTimestamp = timestamp - offset;
+ // add one ms to timestamp if 0 to ensure it's written to proto (default values are ignored)
+ return offsetTimestamp == 0 ? offsetTimestamp + 1 : offsetTimestamp;
+ }
+
private static void writeUsageStats(ProtoOutputStream proto, final long beginTime,
final UsageStats stats) throws IllegalArgumentException {
- // Time attributes stored as an offset of the beginTime.
proto.write(UsageStatsObfuscatedProto.PACKAGE_TOKEN, stats.mPackageToken + 1);
- proto.write(UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS, stats.mLastTimeUsed - beginTime);
+ writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS,
+ stats.mLastTimeUsed, beginTime);
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_ACTIVE_MS, stats.mTotalTimeInForeground);
- proto.write(UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS,
- stats.mLastTimeForegroundServiceUsed - beginTime);
+ writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS,
+ stats.mLastTimeForegroundServiceUsed, beginTime);
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_SERVICE_USED_MS,
stats.mTotalTimeForegroundServiceUsed);
- proto.write(UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS,
- stats.mLastTimeVisible - beginTime);
+ writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS,
+ stats.mLastTimeVisible, beginTime);
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS, stats.mTotalTimeVisible);
proto.write(UsageStatsObfuscatedProto.APP_LAUNCH_COUNT, stats.mAppLaunchCount);
try {
@@ -361,8 +369,8 @@
throws IllegalArgumentException {
configStats.mConfiguration.dumpDebug(proto,
IntervalStatsObfuscatedProto.Configuration.CONFIG);
- proto.write(IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS,
- configStats.mLastTimeActive - statsBeginTime);
+ writeOffsetTimestamp(proto, IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS,
+ configStats.mLastTimeActive, statsBeginTime);
proto.write(IntervalStatsObfuscatedProto.Configuration.TOTAL_TIME_ACTIVE_MS,
configStats.mTotalTimeActive);
proto.write(IntervalStatsObfuscatedProto.Configuration.COUNT, configStats.mActivationCount);
@@ -375,7 +383,7 @@
if (event.mClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
proto.write(EventObfuscatedProto.CLASS_TOKEN, event.mClassToken + 1);
}
- proto.write(EventObfuscatedProto.TIME_MS, event.mTimeStamp - statsBeginTime);
+ writeOffsetTimestamp(proto, EventObfuscatedProto.TIME_MS, event.mTimeStamp, statsBeginTime);
proto.write(EventObfuscatedProto.FLAGS, event.mFlags);
proto.write(EventObfuscatedProto.TYPE, event.mEventType);
proto.write(EventObfuscatedProto.INSTANCE_ID, event.mInstanceId);
@@ -489,10 +497,6 @@
}
break;
case ProtoInputStream.NO_MORE_FIELDS:
- // endTime not assigned, assume default value of 0 plus beginTime
- if (stats.endTime == 0) {
- stats.endTime = stats.beginTime;
- }
// update the begin and end time stamps for all usage stats
final int usageStatsSize = stats.packageStatsObfuscated.size();
for (int i = 0; i < usageStatsSize; i++) {
@@ -514,7 +518,8 @@
public static void write(OutputStream out, IntervalStats stats)
throws IOException, IllegalArgumentException {
final ProtoOutputStream proto = new ProtoOutputStream(out);
- proto.write(IntervalStatsObfuscatedProto.END_TIME_MS, stats.endTime - stats.beginTime);
+ proto.write(IntervalStatsObfuscatedProto.END_TIME_MS,
+ getOffsetTimestamp(stats.endTime, stats.beginTime));
proto.write(IntervalStatsObfuscatedProto.MAJOR_VERSION, stats.majorVersion);
proto.write(IntervalStatsObfuscatedProto.MINOR_VERSION, stats.minorVersion);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 170bee8..42e2bbf 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -443,6 +443,8 @@
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ enforceDetectionPermissions(detectionService);
+
if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "startRecognition(): id = " + soundModelId);
@@ -1532,6 +1534,16 @@
}
}
+ private void enforceDetectionPermissions(ComponentName detectionService) {
+ PackageManager packageManager = mContext.getPackageManager();
+ String packageName = detectionService.getPackageName();
+ if (packageManager.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(detectionService.getPackageName() + " does not have"
+ + " permission " + Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+ }
+ }
+
//=================================================================
// For logging
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index eb553d3..f2f1412 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -399,7 +399,7 @@
* Optional extra for communicating the call network technology used by a
* {@link android.telecom.Connection} to Telecom and InCallUI.
*
- * @see {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}.
+ * {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}.
*/
public static final String EXTRA_CALL_NETWORK_TYPE =
"android.telecom.extra.CALL_NETWORK_TYPE";
diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java
index 36fa5cc..3d5c6aa 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -62,8 +62,6 @@
* {@link TelephonyManager#NETWORK_TYPE_LTE} network and has E-UTRA-NR Dual Connectivity(EN-DC)
* capability or is currently connected to the secondary
* {@link TelephonyManager#NETWORK_TYPE_NR} cellular network on millimeter wave bands.
- *
- * @see AccessNetworkConstants.NgranBands#FREQUENCY_RANGE_GROUP_2
*/
public static final int OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE = 4;
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index bd531da..43db1d9ce 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -140,8 +140,7 @@
}
/**
- * Receives IMS capability status updates from the ImsService. This information is also
- * available via the {@see #isAvailable(int, int)} method below.
+ * Receives IMS capability status updates from the ImsService.
*
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
@@ -194,8 +193,6 @@
* If unavailable, the feature is not able to support the unavailable capability at this
* time.
*
- * This information can also be queried using the {@see #isAvailable(int, int)} API.
- *
* @param capabilities The new availability of the capabilities.
*/
public void onCapabilitiesStatusChanged(
@@ -496,8 +493,7 @@
/**
* Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
* availability updates for the subscription specified in
- * {@link ImsManager#getImsMmTelManager(int)}. The method {@see #isAvailable(int, int)}
- * can also be used to query this information at any time.
+ * {@link ImsManager#getImsMmTelManager(int)}.
*
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
@@ -639,7 +635,6 @@
* @see android.telephony.CarrierConfigManager#KEY_HIDE_ENHANCED_4G_LTE_BOOL
* @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL
* @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL
- * @see #setAdvancedCallingSettingEnabled(boolean)
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user's setting for advanced calling is enabled, false otherwise.
@@ -858,7 +853,6 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user’s “Video Calling” setting is currently enabled.
- * @see #setVtSettingEnabled(boolean)
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -933,7 +927,6 @@
*
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
- * @see #setVoWiFiSettingEnabled(boolean)
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(anyOf = {
@@ -1011,7 +1004,6 @@
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user's setting for Voice over WiFi while roaming is enabled, false
* if disabled.
- * @see #setVoWiFiRoamingSettingEnabled(boolean)
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(anyOf = {
@@ -1130,7 +1122,6 @@
* - {@link #WIFI_MODE_WIFI_ONLY}
* - {@link #WIFI_MODE_CELLULAR_PREFERRED}
* - {@link #WIFI_MODE_WIFI_PREFERRED}
- * @see #setVoWiFiSettingEnabled(boolean)
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(anyOf = {
@@ -1315,7 +1306,6 @@
*
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
- * @see android.telecom.TelecomManager#getCurrentTtyMode
* @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index 1dbaff5..e085dec 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -270,7 +270,7 @@
* inactive subscription, it will result in a no-op.
*
* @param c The {@link RegistrationCallback} to be removed.
- * @see SubscriptionManager.OnSubscriptionsChangedListener
+ * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 0b25d6f..b3b7b20 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -218,13 +218,7 @@
* {@link MmTelCapabilities#CAPABILITY_TYPE_UT}, and
* {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}.
*
- * The capabilities of this MmTelFeature will be set by the framework and can be queried with
- * {@see #queryCapabilityStatus()}.
- *
- * This MmTelFeature can then return the status of each of these capabilities (enabled or not)
- * by sending a {@see #notifyCapabilitiesStatusChanged} callback to the framework. The current
- * status can also be queried using {@see #queryCapabilityStatus()}.
- * @see #isCapable(int)
+ * The capabilities of this MmTelFeature will be set by the framework.
*/
public static class MmTelCapabilities extends Capabilities {
diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java
index 00cb243..689ace5b 100644
--- a/wifi/java/android/net/wifi/WpsInfo.java
+++ b/wifi/java/android/net/wifi/WpsInfo.java
@@ -22,7 +22,7 @@
/**
* A class representing Wi-Fi Protected Setup
*
- * {@see WifiP2pConfig}
+ * {@see android.net.wifi.p2p.WifiP2pConfig}
*/
public class WpsInfo implements Parcelable {