Merge "Update battery saver footer strings" into sc-dev
diff --git a/StubLibraries.bp b/StubLibraries.bp
index a83cb4d..aa073fe 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -310,13 +310,9 @@
]
java_defaults {
- name: "android_defaults_stubs_current",
- libs: [ "stub-annotations" ],
- static_libs: [
- // License notices from art module
- "art-notices-for-framework-stubs-jar",
- "framework-res-package-jar", // Export package of framework-res
- ],
+ name: "android-non-updatable_defaults_stubs_current",
+ libs: ["stub-annotations"],
+ static_libs: ["framework-res-package-jar"], // Export package of framework-res
errorprone: {
javacflags: [
"-XepDisableAllChecks",
@@ -326,6 +322,64 @@
system_modules: "none",
java_version: "1.8",
compile_dex: true,
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ tag: ".jar",
+ dest: "android-non-updatable.jar",
+ }
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":api-stubs-docs-non-updatable"],
+ libs: modules_public_stubs,
+ dist: {
+ dir: "apistubs/android/public",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.system",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [ ":system-api-stubs-docs-non-updatable" ],
+ libs: modules_system_stubs,
+ dist: {
+ dir: "apistubs/android/system",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.module_lib",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":module-lib-api-stubs-docs-non-updatable"],
+ libs: [
+ "sdk_system_current_android",
+ // NOTE: The below can be removed once the prebuilt stub contains IKE.
+ "sdk_system_current_android.net.ipsec.ike",
+ ],
+ dist: {
+ dir: "apistubs/android/module-lib",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.test",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":test-api-stubs-docs-non-updatable"],
+ libs: modules_system_stubs,
+ dist: {
+ dir: "apistubs/android/test",
+ },
+}
+
+java_defaults {
+ name: "android_defaults_stubs_current",
+ static_libs: ["art-notices-for-framework-stubs-jar"], // License notices from art module
+ sdk_version: "none",
+ system_modules: "none",
+ java_version: "1.8",
+ compile_dex: true,
}
java_defaults {
@@ -339,8 +393,8 @@
java_library_static {
name: "android_stubs_current",
- srcs: [ ":api-stubs-docs-non-updatable" ],
static_libs: modules_public_stubs + [
+ "android-non-updatable.stubs",
"private-stub-annotations-jar",
],
defaults: ["android_defaults_stubs_current"],
@@ -348,8 +402,8 @@
java_library_static {
name: "android_system_stubs_current",
- srcs: [ ":system-api-stubs-docs-non-updatable" ],
static_libs: modules_system_stubs + [
+ "android-non-updatable.stubs.system",
"private-stub-annotations-jar",
],
defaults: [
@@ -371,10 +425,10 @@
java_library_static {
name: "android_test_stubs_current",
- srcs: [ ":test-api-stubs-docs-non-updatable" ],
// Modules do not have test APIs, but we want to include their SystemApis, like we include
// the SystemApi of framework-non-updatable-sources.
static_libs: modules_system_stubs + [
+ "android-non-updatable.stubs.test",
"private-stub-annotations-jar",
],
defaults: [
@@ -396,17 +450,14 @@
java_library_static {
name: "android_module_lib_stubs_current",
- srcs: [ ":module-lib-api-stubs-docs-non-updatable" ],
defaults: [
"android_defaults_stubs_current",
"android_stubs_dists_default",
],
- libs: [
- "sdk_system_current_android",
- // NOTE: The below can be removed once the prebuilt stub contains IKE.
- "sdk_system_current_android.net.ipsec.ike",
+ static_libs: [
+ "android-non-updatable.stubs.module_lib",
+ "art.module.public.api.stubs",
],
- static_libs: ["art.module.public.api.stubs"],
dist: {
dir: "apistubs/android/module-lib",
},
diff --git a/core/api/current.txt b/core/api/current.txt
index 62aacac..aad6b37 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3960,6 +3960,7 @@
method public boolean isImmersive();
method public boolean isInMultiWindowMode();
method public boolean isInPictureInPictureMode();
+ method public boolean isLaunchedFromBubble();
method public boolean isLocalVoiceInteractionSupported();
method public boolean isTaskRoot();
method public boolean isVoiceInteraction();
@@ -7202,7 +7203,6 @@
method public boolean isComplianceAcknowledgementRequired();
method public boolean isDeviceIdAttestationSupported();
method public boolean isDeviceOwnerApp(String);
- method public boolean isEnterpriseNetworkPreferenceEnabled();
method public boolean isEphemeralUser(@NonNull android.content.ComponentName);
method public boolean isKeyPairGrantedToWifiAuth(@NonNull String);
method public boolean isLockTaskPermitted(String);
@@ -7213,6 +7213,7 @@
method public boolean isOrganizationOwnedDeviceWithManagedProfile();
method public boolean isOverrideApnEnabled(@NonNull android.content.ComponentName);
method public boolean isPackageSuspended(@NonNull android.content.ComponentName, String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public boolean isPreferentialNetworkServiceEnabled();
method public boolean isProfileOwnerApp(String);
method public boolean isProvisioningAllowed(@NonNull String);
method public boolean isResetPasswordTokenActive(android.content.ComponentName);
@@ -7264,7 +7265,6 @@
method public void setDelegatedScopes(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.lang.String>);
method public void setDeviceOwnerLockScreenInfo(@NonNull android.content.ComponentName, CharSequence);
method public void setEndUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
- method public void setEnterpriseNetworkPreferenceEnabled(boolean);
method public void setFactoryResetProtectionPolicy(@NonNull android.content.ComponentName, @Nullable android.app.admin.FactoryResetProtectionPolicy);
method public int setGlobalPrivateDnsModeOpportunistic(@NonNull android.content.ComponentName);
method @WorkerThread public int setGlobalPrivateDnsModeSpecifiedHost(@NonNull android.content.ComponentName, @NonNull String);
@@ -7307,6 +7307,7 @@
method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean);
+ method public void setPreferentialNetworkServiceEnabled(boolean);
method public void setProfileEnabled(@NonNull android.content.ComponentName);
method public void setProfileName(@NonNull android.content.ComponentName, String);
method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo);
@@ -11222,7 +11223,6 @@
field public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
field public static final String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
field public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
- field public static final String EXTRA_IS_BUBBLED = "android.intent.extra.IS_BUBBLED";
field public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 5242782..d560ead 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -8020,14 +8020,14 @@
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int) throws java.lang.RuntimeException;
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStoppedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastDisabled(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastEnabled(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOff();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOn();
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRadioPowerState(boolean, int) throws java.lang.RuntimeException;
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRadioPowerState(boolean, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRssiChanged(@IntRange(from=0xffffff81, to=0) int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStartedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStoppedFromSource(@NonNull android.os.WorkSource);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 63e9010..04dd04c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -137,6 +137,7 @@
method public void setLaunchActivityType(int);
method public void setLaunchTaskId(int);
method public void setLaunchWindowingMode(int);
+ method public void setLaunchedFromBubble(boolean);
method public void setTaskAlwaysOnTop(boolean);
method public void setTaskOverlay(boolean, boolean);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f0d5a89..45120b6 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -899,6 +899,9 @@
/** The options for scene transition. */
ActivityOptions mPendingOptions;
+ /** Whether this activity was launched from a bubble. **/
+ boolean mLaunchedFromBubble;
+
private static final class ManagedCursor {
ManagedCursor(Cursor cursor) {
mCursor = cursor;
@@ -6790,6 +6793,25 @@
return getSharedPreferences(getLocalClassName(), mode);
}
+ /**
+ * Indicates whether this activity is launched from a bubble. A bubble is a floating shortcut
+ * on the screen that expands to show an activity.
+ *
+ * If your activity can be used normally or as a bubble, you might use this method to check
+ * if the activity is bubbled to modify any behaviour that might be different between the
+ * normal activity and the bubbled activity. For example, if you normally cancel the
+ * notification associated with the activity when you open the activity, you might not want to
+ * do that when you're bubbled as that would remove the bubble.
+ *
+ * @return {@code true} if the activity is launched from a bubble.
+ *
+ * @see Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata)
+ * @see Notification.BubbleMetadata.Builder#Builder(String)
+ */
+ public boolean isLaunchedFromBubble() {
+ return mLaunchedFromBubble;
+ }
+
private void ensureSearchManager() {
if (mSearchManager != null) {
return;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 006b2b5..c21de62 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -323,6 +323,9 @@
/** See {@link #setRemoveWithTaskOrganizer(boolean)}. */
private static final String KEY_REMOVE_WITH_TASK_ORGANIZER =
"android.activity.removeWithTaskOrganizer";
+ /** See {@link #setLaunchedFromBubble(boolean)}. */
+ private static final String KEY_LAUNCHED_FROM_BUBBLE =
+ "android.activity.launchTypeBubble";
/**
* @see #setLaunchCookie
@@ -410,6 +413,7 @@
private boolean mOverrideTaskTransition;
private int mSplashScreenThemeResId;
private boolean mRemoveWithTaskOrganizer;
+ private boolean mLaunchedFromBubble;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -1161,6 +1165,7 @@
mOverrideTaskTransition = opts.getBoolean(KEY_OVERRIDE_TASK_TRANSITION);
mSplashScreenThemeResId = opts.getInt(KEY_SPLASH_SCREEN_THEME);
mRemoveWithTaskOrganizer = opts.getBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER);
+ mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE);
}
/**
@@ -1647,6 +1652,23 @@
}
/**
+ * Sets whether this activity is launched from a bubble.
+ * @hide
+ */
+ @TestApi
+ public void setLaunchedFromBubble(boolean fromBubble) {
+ mLaunchedFromBubble = fromBubble;
+ }
+
+ /**
+ * @return whether the activity was launched from a bubble.
+ * @hide
+ */
+ public boolean getLaunchedFromBubble() {
+ return mLaunchedFromBubble;
+ }
+
+ /**
* Update the current values in this ActivityOptions from those supplied
* in <var>otherOptions</var>. Any values
* defined in <var>otherOptions</var> replace those in the base options.
@@ -1883,6 +1905,9 @@
if (mRemoveWithTaskOrganizer) {
b.putBoolean(KEY_REMOVE_WITH_TASK_ORGANIZER, mRemoveWithTaskOrganizer);
}
+ if (mLaunchedFromBubble) {
+ b.putBoolean(KEY_LAUNCHED_FROM_BUBBLE, mLaunchedFromBubble);
+ }
return b;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 35890c8..8ff14b0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -594,6 +594,9 @@
*/
FixedRotationAdjustments mPendingFixedRotationAdjustments;
+ /** Whether this activiy was launched from a bubble. */
+ boolean mLaunchedFromBubble;
+
@LifecycleState
private int mLifecycleState = PRE_ON_CREATE;
@@ -613,7 +616,7 @@
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
- IBinder shareableActivityToken) {
+ IBinder shareableActivityToken, boolean launchedFromBubble) {
this.token = token;
this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken;
@@ -634,6 +637,7 @@
compatInfo);
mActivityOptions = activityOptions;
mPendingFixedRotationAdjustments = fixedRotationAdjustments;
+ mLaunchedFromBubble = launchedFromBubble;
init();
}
@@ -3549,6 +3553,7 @@
activity.mPendingOptions = r.mActivityOptions;
r.mActivityOptions = null;
}
+ activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0ca0b85..a60f1ca 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -10205,13 +10205,8 @@
* <p>The shortcut activity will be used when the bubble is expanded. This will display
* the shortcut activity in a floating window over the existing foreground activity.</p>
*
- * <p>When the shortcut is displayed in a bubble, there will be an intent
- * extra set on the activity, {@link Intent#EXTRA_IS_BUBBLED}
- * with {@code true}. You may check this in the onCreate of your activity via:
- *
- * <pre class="prettyprint">
- * boolean isBubbled = getIntent().getBooleanExtra(Intent.EXTRA_IS_BUBBLED, false);
- * </pre>
+ * <p>When the activity is launched from a bubble,
+ * {@link Activity#isLaunchedFromBubble()} will return with {@code true}.
* </p>
*
* <p>If the shortcut has not been published when the bubble notification is sent,
@@ -10242,13 +10237,8 @@
* app content in a floating window over the existing foreground activity. The intent
* should point to a resizable activity. </p>
*
- * <p>When the activity is displayed in a bubble, there will be an intent
- * extra set on the activity, {@link Intent#EXTRA_IS_BUBBLED}
- * with {@code true}. You may check this in the onCreate of your activity via:
- *
- * <pre class="prettyprint">
- * boolean isBubbled = getIntent().getBooleanExtra(Intent.EXTRA_IS_BUBBLED, false);
- * </pre>
+ * <p>When the activity is launched from a bubble,
+ * {@link Activity#isLaunchedFromBubble()} will return with {@code true}.
* </p>
*
* @throws NullPointerException if intent is null.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1594e70..fa3c767 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10121,45 +10121,51 @@
}
/**
- * Sets whether enterprise network preference is enabled on the work profile.
+ * Sets whether preferential network service is enabled on the work profile.
+ * For example, an organization can have a deal/agreement with a carrier that all of
+ * the work data from its employees’ devices will be sent via a network service dedicated
+ * for enterprise use.
*
- * For example, a corporation can have a deal/agreement with a carrier that all of its
- * employees’ devices use data on a network preference dedicated for enterprise use.
+ * An example of a supported preferential network service is the Enterprise
+ * slice on 5G networks.
*
- * By default, enterprise network preference is enabled on the work profile on supported
+ * By default, preferential network service is enabled on the work profile on supported
* carriers and devices. Admins can explicitly disable it with this API.
+ * On fully-managed devices this method is unsupported because all traffic is considered
+ * work traffic.
*
* <p>This method can only be called by the profile owner of a managed profile.
- *
- * @param enabled whether enterprise network preference should be enabled.
+ * @param enabled whether preferential network service should be enabled.
* @throws SecurityException if the caller is not the profile owner.
**/
- public void setEnterpriseNetworkPreferenceEnabled(boolean enabled) {
- throwIfParentInstance("setEnterpriseNetworkPreferenceEnabled");
- if (mService != null) {
- try {
- mService.setEnterpriseNetworkPreferenceEnabled(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ public void setPreferentialNetworkServiceEnabled(boolean enabled) {
+ throwIfParentInstance("setPreferentialNetworkServiceEnabled");
+ if (mService == null) {
+ return;
+ }
+
+ try {
+ mService.setPreferentialNetworkServiceEnabled(enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
/**
- * Indicates whether whether enterprise network preference is enabled.
+ * Indicates whether preferential network service is enabled.
*
* <p>This method can be called by the profile owner of a managed profile.
*
- * @return whether whether enterprise network preference is enabled.
+ * @return whether preferential network service is enabled.
* @throws SecurityException if the caller is not the profile owner.
*/
- public boolean isEnterpriseNetworkPreferenceEnabled() {
- throwIfParentInstance("isEnterpriseNetworkPreferenceEnabled");
+ public boolean isPreferentialNetworkServiceEnabled() {
+ throwIfParentInstance("isPreferentialNetworkServiceEnabled");
if (mService == null) {
return false;
}
try {
- return mService.isEnterpriseNetworkPreferenceEnabled(myUserId());
+ return mService.isPreferentialNetworkServiceEnabled(myUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8a8c69c..05b0be4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -274,8 +274,8 @@
void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled);
boolean isSecondaryLockscreenEnabled(in UserHandle userHandle);
- void setEnterpriseNetworkPreferenceEnabled(in boolean enabled);
- boolean isEnterpriseNetworkPreferenceEnabled(int userHandle);
+ void setPreferentialNetworkServiceEnabled(in boolean enabled);
+ boolean isPreferentialNetworkServiceEnabled(int userHandle);
void setLockTaskPackages(in ComponentName who, in String[] packages);
String[] getLockTaskPackages(in ComponentName who);
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 9f8fcc1..e281a02 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -72,6 +72,7 @@
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
private IBinder mShareableActivityToken;
+ private boolean mLaunchedFromBubble;
/**
* It is only non-null if the process is the first time to launch activity. It is only an
* optimization for quick look up of the interface so the field is ignored for comparison.
@@ -96,7 +97,8 @@
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
- client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken);
+ client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
+ mLaunchedFromBubble);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -120,7 +122,8 @@
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController,
- FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
+ FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
+ boolean launchedFromBubble) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
instance = new LaunchActivityItem();
@@ -128,7 +131,8 @@
setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
voiceInteractor, procState, state, persistentState, pendingResults,
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
- activityClientController, fixedRotationAdjustments, shareableActivityToken);
+ activityClientController, fixedRotationAdjustments, shareableActivityToken,
+ launchedFromBubble);
return instance;
}
@@ -136,7 +140,7 @@
@Override
public void recycle() {
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
- null, false, null, null, null, null, null);
+ null, false, null, null, null, null, null, false);
ObjectPool.recycle(this);
}
@@ -166,6 +170,7 @@
dest.writeStrongInterface(mActivityClientController);
dest.writeTypedObject(mFixedRotationAdjustments, flags);
dest.writeStrongBinder(mShareableActivityToken);
+ dest.writeBoolean(mLaunchedFromBubble);
}
/** Read from Parcel. */
@@ -183,7 +188,8 @@
in.readTypedObject(ProfilerInfo.CREATOR),
in.readStrongBinder(),
IActivityClientController.Stub.asInterface(in.readStrongBinder()),
- in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder());
+ in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder(),
+ in.readBoolean());
}
public static final @NonNull Creator<LaunchActivityItem> CREATOR =
@@ -293,7 +299,8 @@
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController,
- FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
+ FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
+ boolean launchedFromBubble) {
instance.mIntent = intent;
instance.mIdent = ident;
instance.mInfo = info;
@@ -314,5 +321,6 @@
instance.mActivityClientController = activityClientController;
instance.mFixedRotationAdjustments = fixedRotationAdjustments;
instance.mShareableActivityToken = shareableActivityToken;
+ instance.mLaunchedFromBubble = launchedFromBubble;
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a482b8c..9ad017c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6177,16 +6177,6 @@
*/
public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
- /**
- * A boolean extra indicating whether an activity is bubbled. Set on the shortcut or
- * pending intent provided for the bubble. If the extra is not present or false, then it is not
- * bubbled.
- *
- * @see android.app.Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata)
- * @see android.app.Notification.BubbleMetadata.Builder#Builder(String)
- */
- public static final String EXTRA_IS_BUBBLED = "android.intent.extra.IS_BUBBLED";
-
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index e47478a..2c088e2 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -429,10 +429,9 @@
* @param uid Uid of this event. For the active state it represents the uid that was responsible
* for waking the radio, or -1 if the system was responsible for waking the radio.
* For inactive state, the UID should always be -1.
- * @throws RuntimeException if there are binder remote-invocation errors.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
- public void reportMobileRadioPowerState(boolean isActive, int uid) throws RuntimeException {
+ public void reportMobileRadioPowerState(boolean isActive, int uid) {
try {
mBatteryStats.noteMobileRadioPowerState(getDataConnectionPowerState(isActive),
SystemClock.elapsedRealtimeNanos(), uid);
@@ -448,10 +447,9 @@
* @param uid Uid of this event. For the active state it represents the uid that was responsible
* for waking the radio, or -1 if the system was responsible for waking the radio.
* For inactive state, the UID should always be -1.
- * @throws RuntimeException if there are binder remote-invocation errors.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
- public void reportWifiRadioPowerState(boolean isActive, int uid) throws RuntimeException {
+ public void reportWifiRadioPowerState(boolean isActive, int uid) {
try {
mBatteryStats.noteWifiRadioPowerState(getDataConnectionPowerState(isActive),
SystemClock.elapsedRealtimeNanos(), uid);
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 40c658f..a06a857 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -22,6 +22,8 @@
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.EINVAL;
+import static android.system.OsConstants.ENOSYS;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.O_ACCMODE;
import static android.system.OsConstants.O_APPEND;
@@ -441,7 +443,19 @@
final StructStat st_in = Os.fstat(in);
final StructStat st_out = Os.fstat(out);
if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) {
- return copyInternalSendfile(in, out, count, signal, executor, listener);
+ try {
+ return copyInternalSendfile(in, out, count, signal, executor, listener);
+ } catch (ErrnoException e) {
+ if (e.errno == EINVAL || e.errno == ENOSYS) {
+ // sendfile(2) will fail in at least any of the following conditions:
+ // 1. |in| doesn't support mmap(2)
+ // 2. |out| was opened with O_APPEND
+ // We fallback to userspace copy if that fails
+ return copyInternalUserspace(in, out, count, signal, executor,
+ listener);
+ }
+ throw e;
+ }
} else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) {
return copyInternalSplice(in, out, count, signal, executor, listener);
}
diff --git a/core/tests/coretests/src/android/app/admin/OWNERS b/core/tests/coretests/src/android/app/admin/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/core/tests/coretests/src/android/app/admin/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index 1a06789e..75da0bf 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -111,6 +111,7 @@
private IBinder mAssistToken;
private IBinder mShareableActivityToken;
private FixedRotationAdjustments mFixedRotationAdjustments;
+ private boolean mLaunchedFromBubble;
LaunchActivityItemBuilder setIntent(Intent intent) {
mIntent = intent;
@@ -207,13 +208,18 @@
return this;
}
+ LaunchActivityItemBuilder setLaunchedFromBubble(boolean launchedFromBubble) {
+ mLaunchedFromBubble = launchedFromBubble;
+ return this;
+ }
+
LaunchActivityItem build() {
return LaunchActivityItem.obtain(mIntent, mIdent, mInfo,
mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
null /* activityClientController */, mFixedRotationAdjustments,
- mShareableActivityToken);
+ mShareableActivityToken, mLaunchedFromBubble);
}
}
}
diff --git a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
deleted file mode 100644
index 1c6b3cc..0000000
--- a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.time;
-
-import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
-import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.TimestampedValue;
-
-import org.junit.Test;
-
-public class ExternalTimeSuggestionTest {
-
- private static final TimestampedValue<Long> ARBITRARY_TIME =
- new TimestampedValue<>(1111L, 2222L);
-
- @Test
- public void testEquals() {
- ExternalTimeSuggestion one = new ExternalTimeSuggestion(
- ARBITRARY_TIME.getReferenceTimeMillis(),
- ARBITRARY_TIME.getValue());
- assertEquals(one, one);
-
- ExternalTimeSuggestion two = new ExternalTimeSuggestion(
- ARBITRARY_TIME.getReferenceTimeMillis(),
- ARBITRARY_TIME.getValue());
- assertEquals(one, two);
- assertEquals(two, one);
-
- ExternalTimeSuggestion three = new ExternalTimeSuggestion(
- ARBITRARY_TIME.getReferenceTimeMillis() + 1,
- ARBITRARY_TIME.getValue());
- assertNotEquals(one, three);
- assertNotEquals(three, one);
-
- // DebugInfo must not be considered in equals().
- one.addDebugInfo("Debug info 1");
- two.addDebugInfo("Debug info 2");
- assertEquals(one, two);
- }
-
- @Test
- public void testParcelable() {
- ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(
- ARBITRARY_TIME.getReferenceTimeMillis(),
- ARBITRARY_TIME.getValue());
- assertRoundTripParcelable(suggestion);
-
- // DebugInfo should also be stored (but is not checked by equals())
- suggestion.addDebugInfo("This is debug info");
- ExternalTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
- assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
- }
-}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 1a86678..c1e72fe 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -228,6 +228,27 @@
}
@Test
+ public void testCopyFileWithAppend() throws Exception {
+ final File src = new File(mTarget, "src");
+ final File dest = new File(mTarget, "dest");
+
+ byte[] expected = new byte[10];
+ byte[] actual = new byte[10];
+ new Random().nextBytes(expected);
+ writeFile(src, expected);
+
+ try (FileInputStream in = new FileInputStream(src);
+ FileOutputStream out = new FileOutputStream(dest, true /* append */)) {
+ // sendfile(2) fails if output fd is opened with O_APPEND, but FileUtils#copy should
+ // fallback to userspace copy
+ FileUtils.copy(in, out);
+ }
+
+ actual = readFile(dest);
+ assertArrayEquals(expected, actual);
+ }
+
+ @Test
public void testIsFilenameSafe() throws Exception {
assertTrue(FileUtils.isFilenameSafe(new File("foobar")));
assertTrue(FileUtils.isFilenameSafe(new File("a_b-c=d.e/0,1+23")));
@@ -577,7 +598,6 @@
final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
- final File invalidVideoCameraDir = new File(cameraDir, ".invalidVideo-" + nonce + ".mp4");
final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
@@ -589,9 +609,6 @@
FileDescriptor pfdValidImageCameraDir =
ParcelFileDescriptor.open(validImageCameraDir,
MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
- FileDescriptor pfdInvalidVideoCameraDir =
- ParcelFileDescriptor.open(invalidVideoCameraDir,
- MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
FileDescriptor pfdValidVideoNonCameraDir =
ParcelFileDescriptor.open(validVideoNonCameraDir,
@@ -603,13 +620,11 @@
assertNotNull(convertToModernFd(pfdValidVideoCameraDir));
assertNull(convertToModernFd(pfdValidImageCameraDir));
- assertNull(convertToModernFd(pfdInvalidVideoCameraDir));
assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
assertNull(convertToModernFd(pfdValidImageNonCameraDir));
} finally {
validVideoCameraDir.delete();
validImageCameraDir.delete();
- invalidVideoCameraDir.delete();
validVideoNonCameraDir.delete();
validImageNonCameraDir.delete();
}
diff --git a/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java b/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
deleted file mode 100644
index 777bda9..0000000
--- a/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.timezone;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.reflect.Field;
-
-/** Utility methods related to {@link Parcelable} objects used in several tests. */
-final class ParcelableTestSupport {
-
- private ParcelableTestSupport() {}
-
- /** Returns the result of parceling and unparceling the argument. */
- @SuppressWarnings("unchecked")
- public static <T extends Parcelable> T roundTripParcelable(T parcelable) {
- Parcel parcel = Parcel.obtain();
- parcel.writeTypedObject(parcelable, 0);
- parcel.setDataPosition(0);
-
- Parcelable.Creator<T> creator;
- try {
- Field creatorField = parcelable.getClass().getField("CREATOR");
- creator = (Parcelable.Creator<T>) creatorField.get(null);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new AssertionError(e);
- }
- T toReturn = parcel.readTypedObject(creator);
- parcel.recycle();
- return toReturn;
- }
-
- public static <T extends Parcelable> void assertRoundTripParcelable(T instance) {
- assertEquals(instance, roundTripParcelable(instance));
- }
-}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
deleted file mode 100644
index f805555..0000000
--- a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.timezone;
-
-import static android.service.timezone.ParcelableTestSupport.assertRoundTripParcelable;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import static java.util.Collections.singletonList;
-
-import org.junit.Test;
-
-import java.util.List;
-
-public class TimeZoneProviderSuggestionTest {
-
- private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 9999;
-
- private static final List<String> ARBITRARY_TIME_ZONE_IDS = singletonList("Europe/London");
-
- @Test(expected = RuntimeException.class)
- public void testInvalidTimeZoneIds() {
- new TimeZoneProviderSuggestion.Builder()
- .setTimeZoneIds(null);
- }
-
- @Test
- public void testEquals() {
- TimeZoneProviderSuggestion.Builder builder1 = new TimeZoneProviderSuggestion.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- assertEquals(one, one);
- }
-
- TimeZoneProviderSuggestion.Builder builder2 = new TimeZoneProviderSuggestion.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- TimeZoneProviderSuggestion two = builder2.build();
- assertEquals(one, two);
- assertEquals(two, one);
- }
-
- builder1.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- TimeZoneProviderSuggestion two = builder2.build();
- assertNotEquals(one, two);
- assertNotEquals(two, one);
- }
-
- builder2.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- TimeZoneProviderSuggestion two = builder2.build();
- assertEquals(one, two);
- assertEquals(two, one);
- }
-
- builder2.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- TimeZoneProviderSuggestion two = builder2.build();
- assertNotEquals(one, two);
- assertNotEquals(two, one);
- }
-
- builder1.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
- {
- TimeZoneProviderSuggestion one = builder1.build();
- TimeZoneProviderSuggestion two = builder2.build();
- assertEquals(one, two);
- assertEquals(two, one);
- }
- }
-
- @Test
- public void testParcelable_noTimeZoneIds() {
- TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
- assertRoundTripParcelable(builder.build());
- }
-
- @Test
- public void testParcelable_withTimeZoneIds() {
- TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
- .setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
- assertRoundTripParcelable(builder.build());
- }
-}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 0808186..269d842 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -298,7 +298,8 @@
null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
mThread /* client */, null /* asssitToken */,
- null /* fixedRotationAdjustments */, null /* shareableActivityToken */);
+ null /* fixedRotationAdjustments */, null /* shareableActivityToken */,
+ false /* launchedFromBubble */);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 4ff1ce9..11c1464 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.bubbles;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
@@ -78,6 +79,8 @@
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import java.io.FileDescriptor;
@@ -124,6 +127,7 @@
private final LauncherApps mLauncherApps;
private final IStatusBarService mBarService;
private final WindowManager mWindowManager;
+ private final TaskStackListenerImpl mTaskStackListener;
private final ShellTaskOrganizer mTaskOrganizer;
// Used to post to main UI thread
@@ -194,6 +198,7 @@
WindowManager windowManager,
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps,
+ TaskStackListenerImpl taskStackListener,
UiEventLogger uiEventLogger,
ShellTaskOrganizer organizer,
ShellExecutor mainExecutor,
@@ -204,7 +209,7 @@
return new BubbleController(context, data, synchronizer, floatingContentCoordinator,
new BubbleDataRepository(context, launcherApps, mainExecutor),
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
- logger, organizer, positioner, mainExecutor, mainHandler);
+ logger, taskStackListener, organizer, positioner, mainExecutor, mainHandler);
}
/**
@@ -221,6 +226,7 @@
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps,
BubbleLogger bubbleLogger,
+ TaskStackListenerImpl taskStackListener,
ShellTaskOrganizer organizer,
BubblePositioner positioner,
ShellExecutor mainExecutor,
@@ -238,6 +244,7 @@
mLogger = bubbleLogger;
mMainExecutor = mainExecutor;
mMainHandler = mainHandler;
+ mTaskStackListener = taskStackListener;
mTaskOrganizer = organizer;
mSurfaceSynchronizer = synchronizer;
mCurrentUserId = ActivityManager.getCurrentUser();
@@ -319,6 +326,42 @@
packageName, validShortcuts, DISMISS_SHORTCUT_REMOVED);
}
}, mMainHandler);
+
+ mTaskStackListener.addListener(new TaskStackListenerCallback() {
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ if (mSysuiProxy == null) {
+ return;
+ }
+
+ mSysuiProxy.isNotificationShadeExpand((expand) -> {
+ mMainExecutor.execute(() -> {
+ int expandedId = INVALID_TASK_ID;
+ if (mStackView != null && mStackView.getExpandedBubble() != null
+ && isStackExpanded() && !mStackView.isExpansionAnimating()
+ && !expand) {
+ expandedId = mStackView.getExpandedBubble().getTaskId();
+ }
+
+ if (expandedId != INVALID_TASK_ID && expandedId != taskId) {
+ mBubbleData.setExpanded(false);
+ }
+ });
+ });
+ }
+
+ @Override
+ public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+ boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+ for (Bubble b : mBubbleData.getBubbles()) {
+ if (task.taskId == b.getTaskId()) {
+ mBubbleData.setSelectedBubble(b);
+ mBubbleData.setExpanded(true);
+ return;
+ }
+ }
+ }
+ });
}
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 9ef3fb5..abe1f71 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -154,6 +154,7 @@
}
try {
options.setTaskAlwaysOnTop(true);
+ options.setLaunchedFromBubble(true);
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
@@ -163,7 +164,6 @@
// Apply flags to make behaviour match documentLaunchMode=always.
fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- fillInIntent.putExtra(Intent.EXTRA_IS_BUBBLED, true);
if (mBubble != null) {
mBubble.setIntentActive();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 98978b5..9fc8aef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -248,6 +248,8 @@
/** Callback to tell SysUi components execute some methods. */
interface SysuiProxy {
+ void isNotificationShadeExpand(Consumer<Boolean> callback);
+
void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback);
void getShouldRestoredEntries(ArraySet<String> savedBubbleKeys,
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index e0f6379..7433cf9 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -432,14 +432,27 @@
const ARect& destination, int32_t transform) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
- CHECK_VALID_RECT(source);
CHECK_VALID_RECT(destination);
+ Rect sourceRect = static_cast<const Rect&>(source);
+ // Adjust the source so its top and left are not negative
+ sourceRect.left = std::max(sourceRect.left, 0);
+ sourceRect.top = std::max(sourceRect.top, 0);
+ LOG_ALWAYS_FATAL_IF(sourceRect.isEmpty(), "invalid arg passed as source argument");
+
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
- transaction->setCrop(surfaceControl, static_cast<const Rect&>(source));
- transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));
+ transaction->setCrop(surfaceControl, sourceRect);
+
+ float dsdx = (destination.right - destination.left) /
+ static_cast<float>(sourceRect.right - sourceRect.left);
+ float dsdy = (destination.bottom - destination.top) /
+ static_cast<float>(sourceRect.bottom - sourceRect.top);
+
+ transaction->setPosition(surfaceControl, destination.left - (sourceRect.left * dsdx),
+ destination.top - (sourceRect.top * dsdy));
+ transaction->setMatrix(surfaceControl, dsdx, 0, 0, dsdy);
transaction->setTransform(surfaceControl, transform);
bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -458,16 +471,18 @@
transaction->setCrop(surfaceControl, static_cast<const Rect&>(source));
}
-void ASurfaceTransaction_setPosition(ASurfaceTransaction* aSurfaceTransaction,
- ASurfaceControl* aSurfaceControl, const ARect& destination) {
- CHECK_NOT_NULL(aSurfaceTransaction);
+void ASurfaceTransaction_setPosition(ASurfaceTransaction* /* aSurfaceTransaction */,
+ ASurfaceControl* /* aSurfaceControl */,
+ const ARect& /* destination */) {
+ // TODO: Fix this function
+ /* CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
CHECK_VALID_RECT(destination);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
- transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));
+ transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));*/
}
void ASurfaceTransaction_setTransform(ASurfaceTransaction* aSurfaceTransaction,
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index caf7f49..4719772 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -133,16 +133,6 @@
method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
- public final class TcpRepairWindow {
- ctor public TcpRepairWindow(int, int, int, int, int, int);
- field public final int maxWindow;
- field public final int rcvWnd;
- field public final int rcvWndScale;
- field public final int rcvWup;
- field public final int sndWl1;
- field public final int sndWnd;
- }
-
public final class TestNetworkInterface implements android.os.Parcelable {
ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
method public int describeContents();
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 2ac019d..63e0fe9 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -260,15 +260,15 @@
public static final class NetworkAgentConfig.Builder {
ctor public NetworkAgentConfig.Builder();
method @NonNull public android.net.NetworkAgentConfig build();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setNat64DetectionEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setProvisioningNotificationEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
index 3f058d8..ad8396b 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
@@ -311,26 +311,28 @@
}
/**
- * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
- * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to
+ * save power and reduce idle traffic on networks that are known to be IPv6-only without a
+ * NAT64. By default, NAT64 detection is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableNat64Detection() {
- mConfig.skip464xlat = true;
+ public Builder setNat64DetectionEnabled(boolean enabled) {
+ mConfig.skip464xlat = !enabled;
return this;
}
/**
- * Disables the "Sign in to network" notification. Used if the network transport will
- * perform its own carrier-specific provisioning procedure.
+ * Enables or disables the "Sign in to network" notification. Used if the network transport
+ * will perform its own carrier-specific provisioning procedure. By default, the
+ * notification is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableProvisioningNotification() {
- mConfig.provisioningNotificationDisabled = true;
+ public Builder setProvisioningNotificationEnabled(boolean enabled) {
+ mConfig.provisioningNotificationDisabled = !enabled;
return this;
}
diff --git a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
index f062fa9..86034f0 100644
--- a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
+++ b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
@@ -16,15 +16,12 @@
package android.net;
-import android.annotation.SystemApi;
-
/**
* Corresponds to C's {@code struct tcp_repair_window} from
* include/uapi/linux/tcp.h
*
* @hide
*/
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TcpRepairWindow {
public final int sndWl1;
public final int sndWnd;
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/main_switch_bar.xml
new file mode 100644
index 0000000..3ce9421
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/main_switch_bar.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:background="?android:attr/colorBackground"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/frame"
+ android:minHeight="@dimen/min_switch_bar_height"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingLeft="@dimen/switchbar_margin_start"
+ android:paddingRight="@dimen/switchbar_margin_end">
+
+ <TextView
+ android:id="@+id/switch_text"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_marginRight="16dp"
+ android:layout_gravity="center_vertical"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:textAlignment="viewStart"
+ style="@style/MainSwitchText" />
+
+ <ImageView
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:tint="?android:attr/colorAccent"
+ android:theme="@android:style/Theme.Material"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="@dimen/restricted_icon_margin_end"
+ android:src="@*android:drawable/ic_info"
+ android:visibility="gone" />
+
+ <Switch
+ android:id="@android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:track="@drawable/track_selector"
+ android:thumb="@drawable/thumb_selector"
+ android:theme="@style/Settings.MainSwitch"/>
+ </LinearLayout>
+
+ <View
+ android:id="@+id/below_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?android:attr/listDivider" />
+</LinearLayout>
+
+
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
index 85c01c5..5dc3209 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2020 The Android Open Source Project
+ Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,58 +18,40 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="?android:attr/colorBackground"
- android:orientation="vertical">
+ android:layout_width="match_parent">
- <LinearLayout
- android:id="@+id/frame"
- android:minHeight="@dimen/min_switch_bar_height"
+ <TextView
+ android:id="@+id/switch_text"
android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="?android:attr/selectableItemBackground"
- android:paddingLeft="@dimen/switchbar_margin_start"
- android:paddingRight="@dimen/switchbar_margin_end">
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title"
+ android:textSize="16sp"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ android:layout_marginStart="@dimen/switchbar_subsettings_margin_start"
+ android:textAlignment="viewStart"/>
- <TextView
- android:id="@+id/switch_text"
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_marginRight="16dp"
- android:layout_gravity="center_vertical"
- android:maxLines="2"
- android:ellipsize="end"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:textAlignment="viewStart"
- style="@style/MainSwitchText" />
+ <ImageView
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:tint="?android:attr/colorAccent"
+ android:theme="@android:style/Theme.Material"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="@dimen/restricted_icon_margin_end"
+ android:src="@*android:drawable/ic_info"
+ android:visibility="gone"/>
- <ImageView
- android:id="@+id/restricted_icon"
- android:layout_width="@dimen/restricted_icon_size"
- android:layout_height="@dimen/restricted_icon_size"
- android:tint="?android:attr/colorAccent"
- android:theme="@android:style/Theme.Material"
- android:layout_gravity="center_vertical"
- android:layout_marginEnd="@dimen/restricted_icon_margin_end"
- android:src="@*android:drawable/ic_info"
- android:visibility="gone" />
-
- <Switch
- android:id="@android:id/switch_widget"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:track="@drawable/track_selector"
- android:thumb="@drawable/thumb_selector"
- android:theme="@style/Settings.MainSwitch"/>
- </LinearLayout>
-
- <View
- android:id="@+id/below_divider"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="?android:attr/listDivider" />
+ <Switch
+ android:id="@android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="@dimen/switchbar_subsettings_margin_end"
+ android:theme="@style/Widget.SwitchBar.Switch"/>
</LinearLayout>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
index 147db77..e54569e 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
@@ -20,4 +20,6 @@
<color name="thumb_off">#BFFFFFFF</color>
<color name="track_off">@*android:color/material_grey_600</color>
+ <color name="switchbar_switch_track_tint">#82000000</color>
+ <color name="switchbar_switch_thumb_tint">@android:color/black</color>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-sw600dp/dmiens.xml b/packages/SettingsLib/MainSwitchPreference/res/values-sw600dp/dmiens.xml
new file mode 100644
index 0000000..c6bb77d
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-sw600dp/dmiens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+
+ <!-- SwitchBar sub settings margin start / end -->
+ <dimen name="switchbar_subsettings_margin_start">80dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp-land/dmiens.xml b/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp-land/dmiens.xml
new file mode 100644
index 0000000..3e941c2
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp-land/dmiens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+
+ <!-- SwitchBar sub settings margin start / end -->
+ <dimen name="switchbar_subsettings_margin_start">128dp</dimen>
+ <dimen name="switchbar_subsettings_margin_end">128dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp/dmiens.xml b/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp/dmiens.xml
new file mode 100644
index 0000000..2f040da
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-sw720dp/dmiens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+
+ <!-- SwitchBar sub settings margin start / end -->
+ <dimen name="switchbar_subsettings_margin_start">80dp</dimen>
+ <dimen name="switchbar_subsettings_margin_end">80dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
index 147db77..b5a73b1 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
@@ -20,4 +20,7 @@
<color name="thumb_off">#BFFFFFFF</color>
<color name="track_off">@*android:color/material_grey_600</color>
+ <color name="switchbar_background_color">@*android:color/material_grey_600</color>
+ <color name="switchbar_switch_track_tint">#BFFFFFFF</color>
+ <color name="switchbar_switch_thumb_tint">@android:color/white</color>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
index b145c9b..c471bcd 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
@@ -34,4 +34,8 @@
<!-- Restricted icon in switch bar -->
<dimen name="restricted_icon_margin_end">16dp</dimen>
+
+ <!-- SwitchBar sub settings margin start / end -->
+ <dimen name="switchbar_subsettings_margin_start">72dp</dimen>
+ <dimen name="switchbar_subsettings_margin_end">16dp</dimen>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml b/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml
index 59b5899..e058097 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/styles.xml
@@ -25,4 +25,10 @@
<item name="android:switchMinWidth">@dimen/min_switch_width</item>
</style>
+ <style name="Widget.SwitchBar.Switch" parent="@android:style/Widget.Material.CompoundButton.Switch">
+ <item name="android:trackTint">@color/switchbar_switch_track_tint</item>
+ <item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
+ <item name="android:minHeight">48dp</item>
+ <item name="android:minWidth">48dp</item>
+ </style>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
index ae9261c..2be3f0d 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
@@ -28,7 +28,8 @@
import android.widget.Switch;
import android.widget.TextView;
-import androidx.core.content.res.TypedArrayUtils;
+import androidx.annotation.ColorInt;
+import androidx.core.os.BuildCompat;
import java.util.ArrayList;
import java.util.List;
@@ -42,8 +43,11 @@
private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
- private View mAboveDivider;
- private View mBelowDivider;
+ @ColorInt
+ private int mBackgroundColor;
+ @ColorInt
+ private int mBackgroundActivatedColor;
+
protected TextView mTextView;
protected Switch mSwitch;
@@ -66,6 +70,14 @@
LayoutInflater.from(context).inflate(resourceId(context, "layout", "main_switch_bar"),
this);
+ if (!BuildCompat.isAtLeastS()) {
+ final TypedArray a = context.obtainStyledAttributes(
+ new int[]{android.R.attr.colorAccent});
+ mBackgroundActivatedColor = a.getColor(0, 0);
+ mBackgroundColor = context.getColor(R.color.switchbar_background_color);
+ a.recycle();
+ }
+
setFocusable(true);
setClickable(true);
@@ -80,12 +92,13 @@
final TypedArray a = context.obtainStyledAttributes(attrs,
androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
0 /*defStyleRes*/);
- final CharSequence title = TypedArrayUtils.getText(a,
- androidx.preference.R.styleable.Preference_title,
+ final CharSequence title = a.getText(
androidx.preference.R.styleable.Preference_android_title);
setTitle(title);
a.recycle();
}
+
+ setBackground(true);
}
@Override
@@ -105,6 +118,7 @@
if (mSwitch != null) {
mSwitch.setChecked(checked);
}
+ setBackground(checked);
}
/**
@@ -189,6 +203,14 @@
}
}
+ private void setBackground(boolean checked) {
+ if (BuildCompat.isAtLeastS()) {
+ return;
+ }
+
+ setBackgroundColor(checked ? mBackgroundActivatedColor : mBackgroundColor);
+ }
+
static class SavedState extends BaseSavedState {
boolean mChecked;
boolean mVisible;
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
index ebeffcc..1f7f8d4 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
@@ -20,7 +20,6 @@
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.TwoStatePreference;
@@ -79,8 +78,7 @@
final TypedArray a = context.obtainStyledAttributes(attrs,
androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
0 /*defStyleRes*/);
- final CharSequence title = TypedArrayUtils.getText(a,
- androidx.preference.R.styleable.Preference_title,
+ final CharSequence title = a.getText(
androidx.preference.R.styleable.Preference_android_title);
setTitle(title);
a.recycle();
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
index 17b6805..d092666 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
@@ -19,7 +19,7 @@
<dimen name="preference_title_font_size">20sp</dimen>
<dimen name="icon_min_width">48dp</dimen>
<dimen name="preference_padding_start">24dp</dimen>
- <dimen name="preference_padding_end">24dp</dimen>
+ <dimen name="preference_padding_end">16dp</dimen>
<dimen name="app_preference_padding_start">20dp</dimen>
<dimen name="app_icon_min_width">52dp</dimen>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values/styles_preference.xml b/packages/SettingsLib/SettingsTheme/res/values/styles_preference.xml
index 17596ac2..dcbdc07 100644
--- a/packages/SettingsLib/SettingsTheme/res/values/styles_preference.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values/styles_preference.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<resources>
+ <!--DEPRECATED. It will remove after all of client team migrated to new style. -->
<style name="PreferenceTheme" parent="@style/PreferenceThemeOverlay">
<item name="preferenceCategoryStyle">@style/SettingsCategoryPreference</item>
<item name="preferenceStyle">@style/SettingsPreference</item>
@@ -27,6 +28,18 @@
<item name="footerPreferenceStyle">@style/Preference.Material</item>
</style>
+ <style name="SettingsPreferenceTheme" parent="@style/PreferenceThemeOverlay">
+ <item name="preferenceCategoryStyle">@style/SettingsCategoryPreference</item>
+ <item name="preferenceStyle">@style/SettingsPreference</item>
+ <item name="checkBoxPreferenceStyle">@style/SettingsCheckBoxPreference</item>
+ <item name="dialogPreferenceStyle">@style/SettingsPreference</item>
+ <item name="editTextPreferenceStyle">@style/SettingsEditTextPreference</item>
+ <item name="dropdownPreferenceStyle">@style/SettingsDropdownPreference</item>
+ <item name="switchPreferenceStyle">@style/SettingsSwitchPreference</item>
+ <item name="seekBarPreferenceStyle">@style/SettingsSeekbarPreference</item>
+ <item name="footerPreferenceStyle">@style/Preference.Material</item>
+ </style>
+
<style name="SettingsCategoryPreference" parent="@style/Preference.Category.Material">
<item name="iconSpaceReserved">@bool/config_icon_space_reserved</item>
<item name="allowDividerAbove">@bool/config_allow_divider</item>
diff --git a/packages/SettingsLib/SettingsTheme/res/values/themes.xml b/packages/SettingsLib/SettingsTheme/res/values/themes.xml
index 36ca684..13c7523 100644
--- a/packages/SettingsLib/SettingsTheme/res/values/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values/themes.xml
@@ -21,7 +21,7 @@
<item name="android:textAppearanceListItem">@style/TextAppearance.PreferenceTitle</item>
<item name="android:listPreferredItemPaddingStart">@dimen/preference_padding_start</item>
<item name="android:listPreferredItemPaddingEnd">@dimen/preference_padding_end</item>
- <item name="preferenceTheme">@style/PreferenceTheme</item>
+ <item name="preferenceTheme">@style/SettingsPreferenceTheme</item>
</style>
<!-- Using in SubSettings page including injected settings page -->
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 46ecbd4..cb41743 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -694,6 +694,16 @@
assertThat(ap.getTitle()).isEqualTo(providerFriendlyName);
}
+ // This method doesn't copy mIsFailover, mIsAvailable and mIsRoaming because NetworkInfo
+ // doesn't expose those three set methods. But that's fine since the tests don't use those three
+ // variables.
+ private NetworkInfo copyNetworkInfo(NetworkInfo ni) {
+ final NetworkInfo copy = new NetworkInfo(ni.getType(), ni.getSubtype(), ni.getTypeName(),
+ ni.getSubtypeName());
+ copy.setDetailedState(ni.getDetailedState(), ni.getReason(), ni.getExtraInfo());
+ return copy;
+ }
+
@Test
public void testUpdateNetworkInfo_returnsTrue() {
int networkId = 123;
@@ -715,7 +725,7 @@
.setWifiInfo(wifiInfo)
.build();
- NetworkInfo newInfo = new NetworkInfo(networkInfo);
+ NetworkInfo newInfo = copyNetworkInfo(networkInfo);
newInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
}
@@ -741,7 +751,7 @@
.setWifiInfo(wifiInfo)
.build();
- NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ NetworkInfo newInfo = copyNetworkInfo(networkInfo); // same values
assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
}
@@ -766,7 +776,7 @@
.setWifiInfo(wifiInfo)
.build();
- NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ NetworkInfo newInfo = copyNetworkInfo(networkInfo); // same values
wifiInfo.setRssi(rssi + 1);
assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
}
@@ -792,7 +802,7 @@
.setWifiInfo(wifiInfo)
.build();
- NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ NetworkInfo newInfo = copyNetworkInfo(networkInfo); // same values
wifiInfo.setRssi(WifiInfo.INVALID_RSSI);
assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bcde002..a834784 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -682,7 +682,7 @@
<activity
android:name=".settings.brightness.BrightnessDialog"
android:label="@string/quick_settings_brightness_dialog_title"
- android:theme="@*android:style/Theme.DeviceDefault.SystemUI.Dialog"
+ android:theme="@style/Theme.SystemUI.QuickSettings.BrightnessDialog"
android:finishOnCloseSystemDialogs="true"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 6ecbe06..00c27bf 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -25,65 +25,30 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top">
<FrameLayout
- android:id="@+id/clock_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_alignParentTop="true">
- <TextClock
- android:id="@+id/default_clock_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:gravity="center_horizontal"
- android:paddingBottom="@dimen/title_clock_padding"
- android:letterSpacing="0.02"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:elegantTextHeight="false"
- />
- <TextClock
- android:id="@+id/default_clock_view_bold"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|center_horizontal"
- android:gravity="center_horizontal"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_title_bold"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:elegantTextHeight="false"
- android:visibility="invisible"
- />
- </FrameLayout>
- <FrameLayout
- android:id="@+id/new_lockscreen_clock_view"
+ android:id="@+id/lockscreen_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
- android:visibility="gone">
+ android:paddingStart="@dimen/clock_padding_start">
<com.android.keyguard.AnimatableClockView
android:id="@+id/animatable_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
- android:textSize="86dp"
+ android:textSize="@dimen/clock_text_size"
android:fontFamily="@font/clock"
android:typeface="monospace"
android:elegantTextHeight="false"
android:singleLine="true"
+ chargeAnimationDelay="350"
dozeWeight="200"
lockScreenWeight="400"
/>
</FrameLayout>
<FrameLayout
- android:id="@+id/new_lockscreen_clock_view_large"
+ android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/keyguard_status_area"
@@ -98,6 +63,7 @@
android:fontFamily="@font/clock"
android:typeface="monospace"
android:elegantTextHeight="false"
+ chargeAnimationDelay="200"
dozeWeight="200"
lockScreenWeight="400"
/>
@@ -106,7 +72,8 @@
android:id="@+id/keyguard_status_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/clock_view" />
+ android:layout_alignParentStart="true"
+ android:layout_below="@id/lockscreen_clock_view" />
<com.android.systemui.statusbar.phone.NotificationIconContainer
android:id="@+id/left_aligned_notification_icon_container"
@@ -114,6 +81,6 @@
android:layout_height="@dimen/notification_shelf_height"
android:layout_marginTop="@dimen/widget_vertical_padding"
android:layout_below="@id/keyguard_status_area"
- android:visibility="gone"
+ android:paddingStart="@dimen/below_clock_padding_start"
/>
</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index 9f3ca74..95eb5c1 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -25,6 +25,7 @@
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
android:orientation="vertical"
+ android:paddingStart="@dimen/below_clock_padding_start"
android:layout_centerHorizontal="true">
<TextView
android:id="@+id/title"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 10cd3cb..c5ba3d2 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -70,12 +70,5 @@
android:letterSpacing="0.05"
android:ellipsize="marquee"
android:singleLine="true" />
- <com.android.systemui.statusbar.phone.NotificationIconContainer
- android:id="@+id/clock_notification_icon_container"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_shelf_height"
- android:layout_marginTop="@dimen/widget_vertical_padding"
- android:visibility="invisible"
- />
</LinearLayout>
</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index eb7a1f7..25be37a 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -45,5 +45,6 @@
<declare-styleable name="AnimatableClockView">
<attr name="dozeWeight" format="integer" />
<attr name="lockScreenWeight" format="integer" />
+ <attr name="chargeAnimationDelay" format="integer" />
</declare-styleable>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 07bd2e6..9b8035d 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -90,4 +90,8 @@
<dimen name="num_pad_key_width">72dp</dimen>
<dimen name="num_pad_row_margin_bottom">6dp</dimen>
<dimen name="num_pad_key_margin_end">12dp</dimen>
+
+ <!-- additional offset for clock switch area items -->
+ <dimen name="clock_padding_start">28dp</dimen>
+ <dimen name="below_clock_padding_start">32dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 4b225b7..ae3d312 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,6 +15,6 @@
~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorBackgroundFloating" />
+ <solid android:color="?attr/underSurfaceColor" />
<corners android:radius="8dp" />
</shape>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
index 73b02f4..88d8f78f 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
@@ -24,7 +24,7 @@
<shape>
<size android:height="@dimen/rounded_slider_track_width" />
<corners android:radius="@dimen/rounded_slider_track_corner_radius" />
- <solid android:color="?android:attr/textColorPrimary" />
+ <solid android:color="?attr/offStateColor" />
</shape>
</inset>
</item>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index f8f455d..ceef9f9 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -16,12 +16,13 @@
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:priv-android="http://schemas.android.com/apk/prv/res/android"
android:autoMirrored="true">
<item android:id="@+id/slider_foreground"
android:height="@dimen/rounded_slider_height">
<shape>
<size android:height="@dimen/rounded_slider_height" />
- <solid android:color="?android:attr/colorControlActivated" />
+ <solid android:color="?priv-android:attr/colorAccentPrimary" />
<corners android:radius="@dimen/rounded_slider_corner_radius"/>
</shape>
</item>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 0a3afc5..30d026e 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -16,7 +16,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorBackground"/>
+ <solid android:color="?attr/underSurfaceColor"/>
<corners android:radius="@dimen/notification_corner_radius" />
</shape>
</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
index f086cec..1124a92 100644
--- a/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
+++ b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
@@ -14,4 +14,4 @@
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/qs_customize_decoration"/>
\ No newline at end of file
+ android:color="?android:attr/colorBackground"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
index c2d0841..ea0aafd 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
@@ -15,7 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorBackgroundFloating"/>
+ <solid android:color="?attr/underSurfaceColor"/>
<corners android:radius="?android:attr/dialogCornerRadius" />
</shape>
</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
index 4165830..ef950fe 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorBackgroundFloating"/>
+ <solid android:color="?attr/underSurfaceColor"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/drawable/privacy_dialog_bg.xml b/packages/SystemUI/res/drawable/qs_dialog_bg.xml
similarity index 91%
rename from packages/SystemUI/res/drawable/privacy_dialog_bg.xml
rename to packages/SystemUI/res/drawable/qs_dialog_bg.xml
index 96136c4..b307781 100644
--- a/packages/SystemUI/res/drawable/privacy_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/qs_dialog_bg.xml
@@ -18,5 +18,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?android:attr/colorBackground" />
- <corners android:radius="@dimen/ongoing_appops_dialog_bg_corner_radius" />
+ <corners android:radius="?android:attr/dialogCornerRadius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/brightness_mirror.xml b/packages/SystemUI/res/layout/brightness_mirror.xml
index 8b47ab9..b714767 100644
--- a/packages/SystemUI/res/layout/brightness_mirror.xml
+++ b/packages/SystemUI/res/layout/brightness_mirror.xml
@@ -16,6 +16,7 @@
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:theme="@style/Theme.SystemUI.QuickSettings"
android:id="@+id/brightness_mirror"
android:layout_width="@dimen/qs_panel_width"
android:layout_height="@dimen/brightness_mirror_height"
diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml
index 4d77a0d..720ae8db 100644
--- a/packages/SystemUI/res/layout/privacy_dialog.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog.xml
@@ -28,7 +28,7 @@
android:paddingRight="@dimen/ongoing_appops_dialog_side_padding"
android:paddingBottom="12dp"
android:paddingTop="8dp"
- android:background="@drawable/privacy_dialog_bg"
+ android:background="@drawable/qs_dialog_bg"
/>
<!-- 12dp padding bottom so there's 20dp total under the icon -->
<!-- 8dp padding top, as there's 4dp margin in each row -->
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/privacy_dialog_item.xml b/packages/SystemUI/res/layout/privacy_dialog_item.xml
index 91ffe22..0c8ed9f 100644
--- a/packages/SystemUI/res/layout/privacy_dialog_item.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog_item.xml
@@ -51,6 +51,7 @@
/>
<ImageView
+ android:id="@+id/chevron"
android:layout_height="24dp"
android:layout_width="24dp"
android:layout_gravity="center_vertical"
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 471f36b..d7a6103 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -47,9 +47,6 @@
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color>
<color name="notification_channel_dialog_separator">@color/GM2_grey_700</color>
- <!-- The color of the background in the bottom part of QSCustomizer -->
- <color name="qs_customize_decoration">@color/GM2_grey_900</color>
-
<!-- The color of the background in the separated list of the Global Actions menu -->
<color name="global_actions_separated_background">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index f2df4b9..302e5e4 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -40,4 +40,9 @@
<dimen name="qs_tile_margin_top">32dp</dimen>
<dimen name="qs_brightness_padding_top">6dp</dimen>
<dimen name="qs_detail_margin_top">28dp</dimen>
+
+ <!-- In split shade mode notifications should be aligned to QS header so the value should be
+ adjusted to qs header height and height of centered content inside of it:
+ (quick_qs_offset_height (48dp) - ongoing_appops_chip_height (24dp) ) / 2 -->
+ <dimen name="notifications_top_padding_split_shade">12dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 886f98e..e4bdbf3 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -126,6 +126,8 @@
<attr name="wallpaperTextColorSecondary" format="reference|color" />
<attr name="wallpaperTextColorAccent" format="reference|color" />
<attr name="backgroundProtectedStyle" format="reference" />
+ <attr name="offStateColor" format="reference|color" />
+ <attr name="underSurfaceColor" format="reference|color" />
<declare-styleable name="SmartReplyView">
<attr name="spacing" format="dimension" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bc7fcde..a807d4f 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,7 +35,6 @@
<color name="status_bar_clock_color">#FFFFFFFF</color>
<color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
- <color name="qs_customize_decoration">@color/GM2_grey_300</color>
<color name="qs_footer_action_border">#2E312C</color>
<!-- The color of the background in the separated list of the Global Actions menu -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index eb19b2e..433e1be 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -426,6 +426,11 @@
<!-- The padding between the notifications and the quick settings container -->
<dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
+ <!-- In split shade mode notifications should be aligned to QS header so the value should be
+ adjusted to qs header height and height of centered content inside of it:
+ (quick_qs_offset_height (60dp) - ongoing_appops_chip_height (24dp) ) / 2 -->
+ <dimen name="notifications_top_padding_split_shade">18dp</dimen>
+
<!-- Height of the status bar header bar when expanded -->
<dimen name="status_bar_header_height_expanded">124dp</dimen>
@@ -1086,8 +1091,9 @@
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_y_large_clock">42dp</dimen>
- <!-- Large clock maximum font size (dp is intentional, to prevent any further scaling) -->
+ <!-- Clock maximum font size (dp is intentional, to prevent any further scaling) -->
<dimen name="large_clock_text_size">150dp</dimen>
+ <dimen name="clock_text_size">86dp</dimen>
<!-- The maximum offset in either direction that icons move to prevent burn-in on AOD. -->
<dimen name="default_burn_in_prevention_offset">15dp</dimen>
@@ -1213,8 +1219,6 @@
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">16dp</dimen>
- <dimen name="ongoing_appops_dialog_bg_corner_radius">@dimen/notification_corner_radius</dimen>
-
<dimen name="ongoing_appops_dialog_side_margins">@dimen/notification_shade_content_margin_horizontal</dimen>
<dimen name="ongoing_appops_dialog_circle_size">32dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 269fdc5..d5b4f9b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -245,10 +245,14 @@
<string name="screenshot_dismiss_description">Dismiss screenshot</string>
<!-- Content description indicating that the view is a preview of the screenshot that was just taken [CHAR LIMIT=NONE] -->
<string name="screenshot_preview_description">Screenshot preview</string>
- <!-- Content description for the top boundary of the screenshot being cropped [CHAR LIMIT=NONE] -->
- <string name="screenshot_top_boundary">Top boundary</string>
- <!-- Content description for the bottom boundary of the screenshot being cropped [CHAR LIMIT=NONE] -->
- <string name="screenshot_bottom_boundary">Bottom boundary</string>
+ <!-- Content description for the top boundary of the screenshot being cropped, with the current position as a percentage. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_top_boundary_pct">Top boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
+ <!-- Content description for the bottom boundary of the screenshot being cropped, with the current position as a percentage. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_bottom_boundary_pct">Bottom boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
+ <!-- Content description for the left boundary of the screenshot being cropped, with the current position as a percentage. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_left_boundary_pct">Left boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
+ <!-- Content description for the right boundary of the screenshot being cropped, with the current position as a percentage. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_right_boundary_pct">Right boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
<string name="screenrecord_name">Screen Recorder</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ba07829..ce8c0c2 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -382,6 +382,17 @@
<item name="android:colorError">@*android:color/error_color_material_dark</item>
<item name="android:windowIsFloating">true</item>
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
+ <item name="offStateColor">@android:color/system_neutral1_800</item>
+ <item name="underSurfaceColor">@android:color/system_neutral1_1000</item>
+ <item name="android:colorBackground">@android:color/system_neutral1_900</item>
+ </style>
+
+ <style name="Theme.SystemUI.QuickSettings.BrightnessDialog" parent="@android:style/Theme.DeviceDefault.Dialog">
+ <item name="android:dialogCornerRadius">8dp</item>
+ </style>
+
+ <style name="Theme.SystemUI.QuickSettings.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog">
+ <item name="android:dialogCornerRadius">@dimen/notification_corner_radius</item>
</style>
<!-- Overridden by values-television/styles.xml with tv-specific settings -->
@@ -588,10 +599,6 @@
<item name="android:elevation">10dp</item>
</style>
- <style name="Theme.SystemUI.QuickSettings.Edit">
- <item name="android:colorBackground">?android:attr/colorSecondary</item>
- </style>
-
<style name="MediaPlayer.Button" parent="@android:style/Widget.Material.Button.Borderless.Small">
<item name="android:background">@drawable/qs_media_light_source</item>
<item name="android:tint">?android:attr/textColorPrimary</item>
@@ -628,7 +635,12 @@
</style>
<!-- Privacy dialog -->
- <style name="PrivacyDialog" parent="ScreenRecord">
+ <style name="PrivacyDialog" parent="Theme.SystemUI.QuickSettings.Dialog">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:windowCloseOnTouchOutside">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index ab219f3..60b677a 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -27,6 +27,7 @@
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.ViewController;
import java.util.Locale;
@@ -45,6 +46,7 @@
private int mLockScreenColor;
private boolean mIsDozing;
+ private boolean mIsCharging;
private float mDozeAmount;
private Locale mLocale;
@@ -56,7 +58,8 @@
public AnimatableClockController(
AnimatableClockView view,
StatusBarStateController statusBarStateController,
- BroadcastDispatcher broadcastDispatcher) {
+ BroadcastDispatcher broadcastDispatcher,
+ BatteryController batteryController) {
super(view);
mStatusBarStateController = statusBarStateController;
mIsDozing = mStatusBarStateController.isDozing();
@@ -68,6 +71,16 @@
R.dimen.keyguard_clock_line_spacing_scale_burmese);
mDefaultLineSpacing = getContext().getResources().getFloat(
R.dimen.keyguard_clock_line_spacing_scale);
+
+ batteryController.addCallback(new BatteryController.BatteryStateChangeCallback() {
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ if (!mIsCharging && charging) {
+ mView.animateCharge(mIsDozing);
+ }
+ mIsCharging = charging;
+ }
+ });
}
private BroadcastReceiver mLocaleBroadcastReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
index c918d98..0d6f64f 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
@@ -42,7 +42,9 @@
private static final CharSequence DOUBLE_LINE_FORMAT_24_HOUR = "HH\nmm";
private static final CharSequence SINGLE_LINE_FORMAT_12_HOUR = "h:mm";
private static final CharSequence SINGLE_LINE_FORMAT_24_HOUR = "H:mm";
- private static final long ANIM_DURATION = 300;
+ private static final long DOZE_ANIM_DURATION = 300;
+ private static final long CHARGE_ANIM_DURATION_PHASE_0 = 500;
+ private static final long CHARGE_ANIM_DURATION_PHASE_1 = 1000;
private final Calendar mTime = Calendar.getInstance();
@@ -53,6 +55,7 @@
private int mDozingColor;
private int mLockScreenColor;
private float mLineSpacingScale = 1f;
+ private int mChargeAnimationDelay = 0;
private TextAnimator mTextAnimator = null;
private Runnable mOnTextAnimatorInitialized;
@@ -79,6 +82,8 @@
try {
mDozingWeight = ta.getInt(R.styleable.AnimatableClockView_dozeWeight, 100);
mLockScreenWeight = ta.getInt(R.styleable.AnimatableClockView_lockScreenWeight, 300);
+ mChargeAnimationDelay = ta.getInt(
+ R.styleable.AnimatableClockView_chargeAnimationDelay, 200);
} finally {
ta.recycle();
}
@@ -150,11 +155,36 @@
mLockScreenColor = lockScreenColor;
}
+ void animateCharge(boolean isDozing) {
+ if (mTextAnimator == null || mTextAnimator.isRunning()) {
+ // Skip charge animation if dozing animation is already playing.
+ return;
+ }
+ Runnable startAnimPhase2 = () -> setTextStyle(
+ isDozing ? mDozingWeight : mLockScreenWeight/* weight */,
+ -1,
+ null,
+ true /* animate */,
+ CHARGE_ANIM_DURATION_PHASE_1,
+ 0 /* delay */,
+ null /* onAnimationEnd */);
+ setTextStyle(isDozing ? mLockScreenWeight : mDozingWeight/* weight */,
+ -1,
+ null,
+ true /* animate */,
+ CHARGE_ANIM_DURATION_PHASE_0,
+ mChargeAnimationDelay,
+ startAnimPhase2);
+ }
+
void animateDoze(boolean isDozing, boolean animate) {
setTextStyle(isDozing ? mDozingWeight : mLockScreenWeight /* weight */,
-1,
isDozing ? mDozingColor : mLockScreenColor,
- animate);
+ animate,
+ DOZE_ANIM_DURATION,
+ 0 /* delay */,
+ null /* onAnimationEnd */);
}
/**
@@ -170,15 +200,20 @@
private void setTextStyle(
@IntRange(from = 0, to = 1000) int weight,
@FloatRange(from = 0) float textSize,
- int color,
- boolean animate) {
+ Integer color,
+ boolean animate,
+ long duration,
+ long delay,
+ Runnable onAnimationEnd) {
if (mTextAnimator != null) {
- mTextAnimator.setTextStyle(weight, textSize, color, animate, ANIM_DURATION, null);
+ mTextAnimator.setTextStyle(weight, textSize, color, animate, duration, null,
+ delay, onAnimationEnd);
} else {
// when the text animator is set, update its start values
mOnTextAnimatorInitialized =
() -> mTextAnimator.setTextStyle(
- weight, textSize, color, false, ANIM_DURATION, null);
+ weight, textSize, color, false, duration, null,
+ delay, onAnimationEnd);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index d2a82cf..407146f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -4,35 +4,21 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.Style;
-import android.os.Build;
-import android.transition.Fade;
-import android.transition.Transition;
-import android.transition.TransitionListenerAdapter;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.transition.TransitionValues;
import android.util.AttributeSet;
-import android.util.Log;
-import android.util.MathUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
-import android.widget.TextClock;
-import android.widget.TextView;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.dagger.KeyguardStatusViewScope;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -47,53 +33,21 @@
private static final String TAG = "KeyguardClockSwitch";
- /**
- * Animation fraction when text is transitioned to/from bold.
- */
- private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
-
private static final long CLOCK_OUT_MILLIS = 150;
private static final long CLOCK_IN_MILLIS = 200;
/**
- * Layout transition that scales the default clock face.
- */
- private final Transition mTransition;
-
- private final ClockVisibilityTransition mClockTransition;
- private final ClockVisibilityTransition mBoldClockTransition;
-
- /**
* Optional/alternative clock injected via plugin.
*/
private ClockPlugin mClockPlugin;
/**
- * Default clock.
+ * Frame for small/large clocks
*/
- private TextClock mClockView;
-
- /**
- * Default clock, bold version.
- * Used to transition to bold when shrinking the default clock.
- */
- private TextClock mClockViewBold;
-
- /**
- * Frame for clock when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
- */
- private FrameLayout mNewLockscreenClockFrame;
- private FrameLayout mNewLockscreenLargeClockFrame;
-
- /**
- * Frame for default and custom clock.
- */
- private FrameLayout mSmallClockFrame;
-
- /**
- * Container for big custom clock.
- */
- private ViewGroup mBigClockContainer;
+ private FrameLayout mClockFrame;
+ private FrameLayout mLargeClockFrame;
+ private AnimatableClockView mClockView;
+ private AnimatableClockView mLargeClockView;
/**
* Status area (date and other stuff) shown below the clock. Plugin can decide whether or not to
@@ -117,40 +71,23 @@
/**
* If the Keyguard Slice has a header (big center-aligned text.)
*/
- private boolean mShowingHeader;
private boolean mSupportsDarkText;
private int[] mColorPalette;
- private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
private int mClockSwitchYAmount;
public KeyguardClockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mClockTransition = new ClockVisibilityTransition().setCutoff(
- 1 - TO_BOLD_TRANSITION_FRACTION);
- mClockTransition.addTarget(R.id.default_clock_view);
- mBoldClockTransition = new ClockVisibilityTransition().setCutoff(
- TO_BOLD_TRANSITION_FRACTION);
- mBoldClockTransition.addTarget(R.id.default_clock_view_bold);
- mTransition = new TransitionSet()
- .setOrdering(TransitionSet.ORDERING_TOGETHER)
- .addTransition(mClockTransition)
- .addTransition(mBoldClockTransition)
- .setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2)
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
}
/**
* Apply dp changes on font/scale change
*/
public void onDensityOrFontScaleChanged() {
- setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
- .getDimensionPixelSize(R.dimen.widget_big_font_size));
-
- ((TextView) mNewLockscreenLargeClockFrame.getChildAt(0))
- .setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
- .getDimensionPixelSize(R.dimen.large_clock_text_size));
+ mLargeClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
+ .getDimensionPixelSize(R.dimen.large_clock_text_size));
+ mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
+ .getDimensionPixelSize(R.dimen.clock_text_size));
mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_clock_switch_y_shift);
@@ -163,44 +100,14 @@
return mClockPlugin != null;
}
- /**
- * Update lock screen mode for testing different layouts
- */
- public void updateLockScreenMode(int mode) {
- mLockScreenMode = mode;
- RelativeLayout.LayoutParams statusAreaLP = (RelativeLayout.LayoutParams)
- mKeyguardStatusArea.getLayoutParams();
-
- if (mode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
- final int startEndPadding = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- 32,
- getResources().getDisplayMetrics());
- setPaddingRelative(startEndPadding, 0, startEndPadding, 0);
- mSmallClockFrame.setVisibility(GONE);
- mNewLockscreenClockFrame.setVisibility(VISIBLE);
- statusAreaLP.addRule(RelativeLayout.BELOW, R.id.new_lockscreen_clock_view);
- statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
- } else {
- setPaddingRelative(0, 0, 0, 0);
- mSmallClockFrame.setVisibility(VISIBLE);
- mNewLockscreenClockFrame.setVisibility(GONE);
-
- statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
- statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
- }
-
- requestLayout();
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mClockView = findViewById(R.id.default_clock_view);
- mClockViewBold = findViewById(R.id.default_clock_view_bold);
- mNewLockscreenClockFrame = findViewById(R.id.new_lockscreen_clock_view);
- mNewLockscreenLargeClockFrame = findViewById(R.id.new_lockscreen_clock_view_large);
- mSmallClockFrame = findViewById(R.id.clock_view);
+
+ mClockFrame = findViewById(R.id.lockscreen_clock_view);
+ mClockView = findViewById(R.id.animatable_clock_view);
+ mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large);
+ mLargeClockView = findViewById(R.id.animatable_clock_view_large);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
onDensityOrFontScaleChanged();
@@ -210,45 +117,35 @@
// Disconnect from existing plugin.
if (mClockPlugin != null) {
View smallClockView = mClockPlugin.getView();
- if (smallClockView != null && smallClockView.getParent() == mSmallClockFrame) {
- mSmallClockFrame.removeView(smallClockView);
+ if (smallClockView != null && smallClockView.getParent() == mClockFrame) {
+ mClockFrame.removeView(smallClockView);
}
- if (mBigClockContainer != null) {
- mBigClockContainer.removeAllViews();
- updateBigClockVisibility(statusBarState);
+ View bigClockView = mClockPlugin.getBigClockView();
+ if (bigClockView != null && bigClockView.getParent() == mLargeClockFrame) {
+ mLargeClockFrame.removeView(bigClockView);
}
mClockPlugin.onDestroyView();
mClockPlugin = null;
}
if (plugin == null) {
- if (mShowingHeader) {
- mClockView.setVisibility(View.GONE);
- mClockViewBold.setVisibility(View.VISIBLE);
- } else {
- mClockView.setVisibility(View.VISIBLE);
- mClockViewBold.setVisibility(View.INVISIBLE);
- }
- mKeyguardStatusArea.setVisibility(View.VISIBLE);
+ mClockView.setVisibility(View.VISIBLE);
+ mLargeClockView.setVisibility(View.VISIBLE);
return;
}
// Attach small and big clock views to hierarchy.
View smallClockView = plugin.getView();
if (smallClockView != null) {
- mSmallClockFrame.addView(smallClockView, -1,
+ mClockFrame.addView(smallClockView, -1,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
mClockView.setVisibility(View.GONE);
- mClockViewBold.setVisibility(View.GONE);
}
View bigClockView = plugin.getBigClockView();
- if (bigClockView != null && mBigClockContainer != null) {
- mBigClockContainer.addView(bigClockView);
- updateBigClockVisibility(statusBarState);
+ if (bigClockView != null) {
+ mLargeClockFrame.addView(bigClockView);
+ mLargeClockView.setVisibility(View.GONE);
}
- // Hide default clock.
- if (!plugin.shouldShowStatusArea()) {
- mKeyguardStatusArea.setVisibility(View.GONE);
- }
+
// Initialize plugin parameters.
mClockPlugin = plugin;
mClockPlugin.setStyle(getPaint().getStyle());
@@ -259,31 +156,10 @@
}
}
- float getClockTextTopPadding() {
- Paint.FontMetrics fm = mClockView.getPaint().getFontMetrics();
- return fm.ascent - fm.top;
- }
-
- /**
- * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
- */
- public void setBigClockContainer(ViewGroup container, int statusBarState) {
- if (mClockPlugin != null && container != null) {
- View bigClockView = mClockPlugin.getBigClockView();
- if (bigClockView != null) {
- container.addView(bigClockView);
- }
- }
- mBigClockContainer = container;
- updateBigClockVisibility(statusBarState);
- }
-
/**
* It will also update plugin setStyle if plugin is connected.
*/
public void setStyle(Style style) {
- mClockView.getPaint().setStyle(style);
- mClockViewBold.getPaint().setStyle(style);
if (mClockPlugin != null) {
mClockPlugin.setStyle(style);
}
@@ -293,48 +169,25 @@
* It will also update plugin setTextColor if plugin is connected.
*/
public void setTextColor(int color) {
- mClockView.setTextColor(color);
- mClockViewBold.setTextColor(color);
if (mClockPlugin != null) {
mClockPlugin.setTextColor(color);
}
}
- public void setShowCurrentUserTime(boolean showCurrentUserTime) {
- mClockView.setShowCurrentUserTime(showCurrentUserTime);
- mClockViewBold.setShowCurrentUserTime(showCurrentUserTime);
- }
-
- public void setTextSize(int unit, float size) {
- mClockView.setTextSize(unit, size);
- }
-
- public void setFormat12Hour(CharSequence format) {
- mClockView.setFormat12Hour(format);
- mClockViewBold.setFormat12Hour(format);
- }
-
- public void setFormat24Hour(CharSequence format) {
- mClockView.setFormat24Hour(format);
- mClockViewBold.setFormat24Hour(format);
- }
-
private void animateClockChange(boolean useLargeClock) {
- if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) return;
-
if (mClockInAnim != null) mClockInAnim.cancel();
if (mClockOutAnim != null) mClockOutAnim.cancel();
View in, out;
int direction = 1;
if (useLargeClock) {
- out = mNewLockscreenClockFrame;
- in = mNewLockscreenLargeClockFrame;
+ out = mClockFrame;
+ in = mLargeClockFrame;
if (indexOfChild(in) == -1) addView(in);
direction = -1;
} else {
- in = mNewLockscreenClockFrame;
- out = mNewLockscreenLargeClockFrame;
+ in = mClockFrame;
+ out = mLargeClockFrame;
// Must remove in order for notifications to appear in the proper place
removeView(out);
@@ -381,7 +234,6 @@
if (mClockPlugin != null) {
mClockPlugin.setDarkAmount(darkAmount);
}
- updateBigClockAlpha();
}
/**
@@ -394,13 +246,6 @@
animateClockChange(!hasVisibleNotifications);
mHasVisibleNotifications = hasVisibleNotifications;
- if (mDarkAmount == 0f && mBigClockContainer != null) {
- // Starting a fade transition since the visibility of the big clock will change.
- TransitionManager.beginDelayedTransition(mBigClockContainer,
- new Fade().setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2).addTarget(
- mBigClockContainer));
- }
- updateBigClockAlpha();
}
public Paint getPaint() {
@@ -433,15 +278,9 @@
* Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
*/
public void refresh() {
- mClockView.refreshTime();
- mClockViewBold.refreshTime();
if (mClockPlugin != null) {
mClockPlugin.onTimeTick();
}
- if (Build.IS_DEBUGGABLE) {
- // Log for debugging b/130888082 (sysui waking up, but clock not updating)
- Log.d(TAG, "Updating clock: " + mClockView.getText());
- }
}
/**
@@ -472,240 +311,14 @@
}
}
- void updateBigClockVisibility(int statusBarState) {
- if (mBigClockContainer == null) {
- return;
- }
- final boolean inDisplayState = statusBarState == StatusBarState.KEYGUARD
- || statusBarState == StatusBarState.SHADE_LOCKED;
- final int visibility = !mShowingHeader && inDisplayState
- && mBigClockContainer.getChildCount() != 0 ? View.VISIBLE : View.GONE;
- if (mBigClockContainer.getVisibility() != visibility) {
- mBigClockContainer.setVisibility(visibility);
- }
- }
-
- private void updateBigClockAlpha() {
- if (mBigClockContainer != null) {
- final float alpha = mHasVisibleNotifications ? mDarkAmount : 1f;
- mBigClockContainer.setAlpha(alpha);
- if (alpha == 0f) {
- mBigClockContainer.setVisibility(INVISIBLE);
- } else if (mBigClockContainer.getVisibility() == INVISIBLE) {
- mBigClockContainer.setVisibility(VISIBLE);
- }
- }
- }
-
- /**
- * Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock in
- * these cases.
- */
- void setKeyguardShowingHeader(boolean hasHeader) {
- if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- hasHeader = false;
- }
-
- if (mShowingHeader == hasHeader) {
- return;
- }
- mShowingHeader = hasHeader;
- if (hasCustomClock()) {
- return;
- }
-
- float smallFontSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.widget_small_font_size);
- float bigFontSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.widget_big_font_size);
- mClockTransition.setScale(smallFontSize / bigFontSize);
- mBoldClockTransition.setScale(bigFontSize / smallFontSize);
-
- // End any current transitions before starting a new transition so that the new transition
- // starts from a good state instead of a potentially bad intermediate state arrived at
- // during a transition animation.
- TransitionManager.endTransitions((ViewGroup) mClockView.getParent());
-
- if (hasHeader) {
- // After the transition, make the default clock GONE so that it doesn't make the
- // KeyguardStatusView appear taller in KeyguardClockPositionAlgorithm and elsewhere.
- mTransition.addListener(new TransitionListenerAdapter() {
- @Override
- public void onTransitionEnd(Transition transition) {
- super.onTransitionEnd(transition);
- // Check that header is actually showing. I saw issues where this event was
- // fired after the big clock transitioned back to visible, which causes the time
- // to completely disappear.
- if (mShowingHeader) {
- mClockView.setVisibility(View.GONE);
- }
- transition.removeListener(this);
- }
- });
- }
-
- TransitionManager.beginDelayedTransition((ViewGroup) mClockView.getParent(), mTransition);
- mClockView.setVisibility(hasHeader ? View.INVISIBLE : View.VISIBLE);
- mClockViewBold.setVisibility(hasHeader ? View.VISIBLE : View.INVISIBLE);
- int paddingBottom = mContext.getResources().getDimensionPixelSize(hasHeader
- ? R.dimen.widget_vertical_padding_clock : R.dimen.title_clock_padding);
- mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(),
- mClockView.getPaddingRight(), paddingBottom);
- mClockViewBold.setPadding(mClockViewBold.getPaddingLeft(), mClockViewBold.getPaddingTop(),
- mClockViewBold.getPaddingRight(), paddingBottom);
- }
-
- /**
- * Hide big clock if the keyguard slice is showing a header, need to reduce visual clutter in
- * these cases.
- */
- public void setKeyguardHidingBigClock(boolean hasHeader) {
- if (mBigClockContainer != null) {
- mBigClockContainer.setVisibility(hasHeader ? View.GONE : View.VISIBLE);
- }
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardClockSwitch:");
pw.println(" mClockPlugin: " + mClockPlugin);
- pw.println(" mClockView: " + mClockView);
- pw.println(" mClockViewBold: " + mClockViewBold);
- pw.println(" mSmallClockFrame: " + mSmallClockFrame);
- pw.println(" mBigClockContainer: " + mBigClockContainer);
+ pw.println(" mClockFrame: " + mClockFrame);
+ pw.println(" mLargeClockFrame: " + mLargeClockFrame);
pw.println(" mKeyguardStatusArea: " + mKeyguardStatusArea);
pw.println(" mDarkAmount: " + mDarkAmount);
- pw.println(" mShowingHeader: " + mShowingHeader);
pw.println(" mSupportsDarkText: " + mSupportsDarkText);
pw.println(" mColorPalette: " + Arrays.toString(mColorPalette));
}
-
- /**
- * {@link Visibility} transformation that scales the view while it is disappearing/appearing and
- * transitions suddenly at a cutoff fraction during the animation.
- */
- private class ClockVisibilityTransition extends android.transition.Visibility {
-
- private static final String PROPNAME_VISIBILITY = "systemui:keyguard:visibility";
-
- private float mCutoff;
- private float mScale;
-
- /**
- * Constructs a transition that switches between visible/invisible at a cutoff and scales in
- * size while appearing/disappearing.
- */
- ClockVisibilityTransition() {
- setCutoff(1f);
- setScale(1f);
- }
-
- /**
- * Sets the transition point between visible/invisible.
- *
- * @param cutoff The fraction in [0, 1] when the view switches between visible/invisible.
- * @return This transition object
- */
- public ClockVisibilityTransition setCutoff(float cutoff) {
- mCutoff = cutoff;
- return this;
- }
-
- /**
- * Sets the scale factor applied while appearing/disappearing.
- *
- * @param scale Scale factor applied while appearing/disappearing. When factor is less than
- * one, the view will shrink while disappearing. When it is greater than one,
- * the view will expand while disappearing.
- * @return This transition object
- */
- public ClockVisibilityTransition setScale(float scale) {
- mScale = scale;
- return this;
- }
-
- @Override
- public void captureStartValues(TransitionValues transitionValues) {
- super.captureStartValues(transitionValues);
- captureVisibility(transitionValues);
- }
-
- @Override
- public void captureEndValues(TransitionValues transitionValues) {
- super.captureStartValues(transitionValues);
- captureVisibility(transitionValues);
- }
-
- private void captureVisibility(TransitionValues transitionValues) {
- transitionValues.values.put(PROPNAME_VISIBILITY,
- transitionValues.view.getVisibility());
- }
-
- @Override
- public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
- TransitionValues endValues) {
- if (!sceneRoot.isShown()) {
- return null;
- }
- final float cutoff = mCutoff;
- final int startVisibility = View.INVISIBLE;
- final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
- final float startScale = mScale;
- final float endScale = 1f;
- return createAnimator(view, cutoff, startVisibility, endVisibility, startScale,
- endScale);
- }
-
- @Override
- public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
- TransitionValues endValues) {
- if (!sceneRoot.isShown()) {
- return null;
- }
- final float cutoff = 1f - mCutoff;
- final int startVisibility = View.VISIBLE;
- final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
- final float startScale = 1f;
- final float endScale = mScale;
- return createAnimator(view, cutoff, startVisibility, endVisibility, startScale,
- endScale);
- }
-
- private Animator createAnimator(View view, float cutoff, int startVisibility,
- int endVisibility, float startScale, float endScale) {
- view.setPivotY(view.getHeight() - view.getPaddingBottom());
- ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
- animator.addUpdateListener(animation -> {
- final float fraction = animation.getAnimatedFraction();
- if (fraction > cutoff) {
- view.setVisibility(endVisibility);
- }
- final float scale = MathUtils.lerp(startScale, endScale, fraction);
- view.setScaleX(scale);
- view.setScaleY(scale);
- });
- animator.addListener(new KeepAwakeAnimationListener(getContext()) {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- view.setVisibility(startVisibility);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- animation.removeListener(this);
- }
- });
- addListener(new TransitionListenerAdapter() {
- @Override
- public void onTransitionEnd(Transition transition) {
- view.setVisibility(endVisibility);
- view.setScaleX(1f);
- view.setScaleY(1f);
- transition.removeListener(this);
- }
- });
- return animator;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 24b7cd1..032ed7d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -26,11 +26,9 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
-import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
@@ -51,6 +49,7 @@
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.ViewController;
import java.util.Locale;
@@ -72,14 +71,15 @@
private final KeyguardSliceViewController mKeyguardSliceViewController;
private final NotificationIconAreaController mNotificationIconAreaController;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final BatteryController mBatteryController;
/**
- * Gradient clock for usage when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
+ * Clock for both small and large sizes
*/
- private AnimatableClockController mNewLockScreenClockViewController;
- private FrameLayout mNewLockScreenClockFrame;
- private AnimatableClockController mNewLockScreenLargeClockViewController;
- private FrameLayout mNewLockScreenLargeClockFrame;
+ private AnimatableClockController mClockViewController;
+ private FrameLayout mClockFrame;
+ private AnimatableClockController mLargeClockViewController;
+ private FrameLayout mLargeClockFrame;
private PluginManager mPluginManager;
private boolean mIsSmartspaceEnabled;
@@ -88,16 +88,6 @@
private SmartspaceSession mSmartspaceSession;
private SmartspaceSession.Callback mSmartspaceCallback;
- private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
-
- private final StatusBarStateController.StateListener mStateListener =
- new StatusBarStateController.StateListener() {
- @Override
- public void onStateChanged(int newState) {
- mView.updateBigClockVisibility(newState);
- }
- };
-
/**
* Listener for changes to the color palette.
*
@@ -114,7 +104,6 @@
};
private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
- private String mTimeFormat;
// If set, will replace keyguard_status_area
private BcSmartspaceDataPlugin.SmartspaceView mSmartspaceView;
@@ -131,7 +120,8 @@
BroadcastDispatcher broadcastDispatcher,
PluginManager pluginManager,
FeatureFlags featureFlags,
- @Main Executor uiExecutor) {
+ @Main Executor uiExecutor,
+ BatteryController batteryController) {
super(keyguardClockSwitch);
mResources = resources;
mStatusBarStateController = statusBarStateController;
@@ -140,10 +130,10 @@
mKeyguardSliceViewController = keyguardSliceViewController;
mNotificationIconAreaController = notificationIconAreaController;
mBroadcastDispatcher = broadcastDispatcher;
- mTimeFormat = Settings.System.getString(contentResolver, Settings.System.TIME_12_24);
mPluginManager = pluginManager;
mIsSmartspaceEnabled = featureFlags.isSmartspaceEnabled();
mUiExecutor = uiExecutor;
+ mBatteryController = batteryController;
}
/**
@@ -159,13 +149,28 @@
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.addOnClockChangedListener(mClockChangedListener);
}
- refreshFormat();
- mStatusBarStateController.addCallback(mStateListener);
mColorExtractor.addOnColorsChangedListener(mColorsListener);
mView.updateColors(getGradientColors());
updateAodIcons();
- mNewLockScreenClockFrame = mView.findViewById(R.id.new_lockscreen_clock_view);
- mNewLockScreenLargeClockFrame = mView.findViewById(R.id.new_lockscreen_clock_view_large);
+
+ mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
+ mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
+
+ mClockViewController =
+ new AnimatableClockController(
+ mView.findViewById(R.id.animatable_clock_view),
+ mStatusBarStateController,
+ mBroadcastDispatcher,
+ mBatteryController);
+ mClockViewController.init();
+
+ mLargeClockViewController =
+ new AnimatableClockController(
+ mView.findViewById(R.id.animatable_clock_view_large),
+ mStatusBarStateController,
+ mBroadcastDispatcher,
+ mBatteryController);
+ mLargeClockViewController.init();
// If a smartspace plugin is detected, replace the existing smartspace
// (keyguard_status_area), and initialize a new session
@@ -181,16 +186,21 @@
mSmartspaceView = plugin.getView(mView);
mSmartspaceView.registerDataProvider(plugin);
+ View asView = (View) mSmartspaceView;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
MATCH_PARENT, WRAP_CONTENT);
- lp.addRule(RelativeLayout.BELOW, R.id.new_lockscreen_clock_view);
- mView.addView((View) mSmartspaceView, ksaIndex, lp);
+ lp.addRule(RelativeLayout.BELOW, R.id.lockscreen_clock_view);
+
+ mView.addView(asView, ksaIndex, lp);
+ int padding = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.below_clock_padding_start);
+ asView.setPadding(padding, 0, padding, 0);
View nic = mView.findViewById(
com.android.systemui.R.id.left_aligned_notification_icon_container);
lp = (RelativeLayout.LayoutParams) nic.getLayoutParams();
- lp.addRule(RelativeLayout.BELOW, ((View) mSmartspaceView).getId());
+ lp.addRule(RelativeLayout.BELOW, asView.getId());
nic.setLayoutParams(lp);
createSmartspaceSession(plugin);
@@ -230,7 +240,6 @@
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.removeOnClockChangedListener(mClockChangedListener);
}
- mStatusBarStateController.removeCallback(mStateListener);
mColorExtractor.removeOnColorsChangedListener(mColorsListener);
mView.setClockPlugin(null, mStatusBarStateController.getState());
@@ -250,13 +259,6 @@
}
/**
- * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
- */
- public void setBigClockContainer(ViewGroup bigClockContainer) {
- mView.setBigClockContainer(bigClockContainer, mStatusBarStateController.getState());
- }
-
- /**
* Set whether or not the lock screen is showing notifications.
*/
public void setHasVisibleNotifications(boolean hasVisibleNotifications) {
@@ -291,9 +293,9 @@
* Refresh clock. Called in response to TIME_TICK broadcasts.
*/
void refresh() {
- if (mNewLockScreenClockViewController != null) {
- mNewLockScreenClockViewController.refreshTime();
- mNewLockScreenLargeClockViewController.refreshTime();
+ if (mClockViewController != null) {
+ mClockViewController.refreshTime();
+ mLargeClockViewController.refreshTime();
}
mView.refresh();
@@ -307,86 +309,45 @@
*/
void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
- if (mNewLockScreenClockFrame != null) {
- PropertyAnimator.setProperty(mNewLockScreenClockFrame, AnimatableProperty.TRANSLATION_X,
- x, props, animate);
- PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_X,
- scale, props, animate);
- PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_Y,
- scale, props, animate);
- }
+
+ PropertyAnimator.setProperty(mClockFrame, AnimatableProperty.TRANSLATION_X,
+ x, props, animate);
+ PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X,
+ scale, props, animate);
+ PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_Y,
+ scale, props, animate);
if (mSmartspaceView != null) {
PropertyAnimator.setProperty((View) mSmartspaceView, AnimatableProperty.TRANSLATION_X,
x, props, animate);
}
+
mKeyguardSliceViewController.updatePosition(x, props, animate);
mNotificationIconAreaController.updatePosition(x, props, animate);
}
- /**
- * Update lockscreen mode that may change clock display.
- */
- void updateLockScreenMode(int mode) {
- mLockScreenMode = mode;
- if (mode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
- if (mNewLockScreenClockViewController == null) {
- mNewLockScreenClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view),
- mStatusBarStateController,
- mBroadcastDispatcher);
- mNewLockScreenClockViewController.init();
- mNewLockScreenLargeClockViewController =
- new AnimatableClockController(
- mView.findViewById(R.id.animatable_clock_view_large),
- mStatusBarStateController,
- mBroadcastDispatcher);
- mNewLockScreenLargeClockViewController.init();
- }
- } else {
- mNewLockScreenClockViewController = null;
- mNewLockScreenLargeClockViewController = null;
- }
- mView.updateLockScreenMode(mLockScreenMode);
- updateAodIcons();
- }
-
void updateTimeZone(TimeZone timeZone) {
mView.onTimeZoneChanged(timeZone);
- if (mNewLockScreenClockViewController != null) {
- mNewLockScreenClockViewController.onTimeZoneChanged(timeZone);
- mNewLockScreenLargeClockViewController.onTimeZoneChanged(timeZone);
+ if (mClockViewController != null) {
+ mClockViewController.onTimeZoneChanged(timeZone);
+ mLargeClockViewController.onTimeZoneChanged(timeZone);
}
}
void refreshFormat(String timeFormat) {
- mTimeFormat = timeFormat;
- Patterns.update(mResources);
- mView.setFormat12Hour(Patterns.sClockView12);
- mView.setFormat24Hour(Patterns.sClockView24);
- mView.onTimeFormatChanged(mTimeFormat);
- if (mNewLockScreenClockViewController != null) {
- mNewLockScreenClockViewController.refreshFormat();
- mNewLockScreenLargeClockViewController.refreshFormat();
+ if (mClockViewController != null) {
+ mClockViewController.refreshFormat();
+ mLargeClockViewController.refreshFormat();
}
}
- void refreshFormat() {
- refreshFormat(mTimeFormat);
- }
-
private void updateAodIcons() {
NotificationIconContainer nic = (NotificationIconContainer)
mView.findViewById(
com.android.systemui.R.id.left_aligned_notification_icon_container);
- if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
- // alt icon area is set in KeyguardClockSwitchController
- mNotificationIconAreaController.setupAodIcons(nic, mLockScreenMode);
- } else {
- nic.setVisibility(View.GONE);
- }
+ // alt icon area is set in KeyguardClockSwitchController
+ mNotificationIconAreaController.setupAodIcons(nic);
}
private void setClockPlugin(ClockPlugin plugin) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 5db4f9e..9df7734 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -44,7 +44,6 @@
* - keyguard clock
* - logout button (on certain managed devices)
* - owner information (if set)
- * - notification icons (shown on AOD)
*/
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -59,7 +58,6 @@
private TextView mOwnerInfo;
private boolean mCanShowOwnerInfo = true; // by default, try to show the owner information here
private KeyguardSliceView mKeyguardSlice;
- private View mNotificationIcons;
private Runnable mPendingMarqueeStart;
private Handler mHandler;
@@ -132,13 +130,11 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLogoutView = findViewById(R.id.logout);
- mNotificationIcons = findViewById(R.id.clock_notification_icon_container);
if (mLogoutView != null) {
mLogoutView.setOnClickListener(this::onLogoutClicked);
}
mClockView = findViewById(R.id.keyguard_clock_container);
- mClockView.setShowCurrentUserTime(true);
if (KeyguardClockAccessibilityDelegate.isNeeded(mContext)) {
mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
}
@@ -161,22 +157,10 @@
*/
private void onSliceContentChanged() {
final boolean hasHeader = mKeyguardSlice.hasHeader();
- mClockView.setKeyguardShowingHeader(hasHeader);
if (mShowingHeader == hasHeader) {
return;
}
mShowingHeader = hasHeader;
- if (mNotificationIcons != null) {
- // Update top margin since header has appeared/disappeared.
- MarginLayoutParams params = (MarginLayoutParams) mNotificationIcons.getLayoutParams();
- params.setMargins(params.leftMargin,
- hasHeader ? mIconTopMarginWithHeader : mIconTopMargin,
- params.rightMargin,
- params.bottomMargin);
- mNotificationIcons.setLayoutParams(params);
- }
-
- mClockView.setKeyguardHidingBigClock(hasHeader);
}
@Override
@@ -293,13 +277,6 @@
int expanded = mOwnerInfo.getBottom() + mOwnerInfo.getPaddingBottom();
int toRemove = (int) ((expanded - collapsed) * ratio);
setBottom(getMeasuredHeight() - toRemove);
- if (mNotificationIcons != null) {
- // We're using scrolling in order not to overload the translation which is used
- // when appearing the icons
- mNotificationIcons.setScrollY(toRemove);
- }
- } else if (mNotificationIcons != null){
- mNotificationIcons.setScrollY(0);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 31ec003..fc80dbe 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -18,15 +18,12 @@
import android.os.UserHandle;
import android.util.Slog;
-import android.view.View;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
@@ -49,7 +46,6 @@
private final KeyguardClockSwitchController mKeyguardClockSwitchController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ConfigurationController mConfigurationController;
- private final NotificationIconAreaController mNotificationIconAreaController;
private final DozeParameters mDozeParameters;
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
@@ -63,14 +59,12 @@
KeyguardStateController keyguardStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
ConfigurationController configurationController,
- NotificationIconAreaController notificationIconAreaController,
DozeParameters dozeParameters) {
super(keyguardStatusView);
mKeyguardSliceViewController = keyguardSliceViewController;
mKeyguardClockSwitchController = keyguardClockSwitchController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mConfigurationController = configurationController;
- mNotificationIconAreaController = notificationIconAreaController;
mDozeParameters = dozeParameters;
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
dozeParameters);
@@ -87,7 +81,6 @@
protected void onViewAttached() {
mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
mConfigurationController.addCallback(mConfigurationListener);
- updateAodIcons();
}
@Override
@@ -237,17 +230,6 @@
mKeyguardClockSwitchController.refresh();
}
- private void updateAodIcons() {
- NotificationIconContainer nic = (NotificationIconContainer)
- mView.findViewById(com.android.systemui.R.id.clock_notification_icon_container);
- if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
- // alternate icon area is set in KeyguardClockSwitchController
- mNotificationIconAreaController.setupAodIcons(nic, mLockScreenMode);
- } else {
- nic.setVisibility(View.GONE);
- }
- }
-
private boolean shouldShowLogout() {
return mKeyguardUpdateMonitor.isLogoutEnabled()
&& KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
@@ -271,16 +253,9 @@
@Override
public void onLockScreenModeChanged(int mode) {
mLockScreenMode = mode;
- mKeyguardClockSwitchController.updateLockScreenMode(mode);
mKeyguardSliceViewController.updateLockScreenMode(mode);
- if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
- mView.setCanShowOwnerInfo(false);
- mView.updateLogoutView(false);
- } else {
- mView.setCanShowOwnerInfo(true);
- mView.updateLogoutView(false);
- }
- updateAodIcons();
+ mView.setCanShowOwnerInfo(false);
+ mView.updateLogoutView(false);
}
@Override
@@ -294,11 +269,6 @@
}
@Override
- public void onTimeFormatChanged(String timeFormat) {
- mKeyguardClockSwitchController.refreshFormat(timeFormat);
- }
-
- @Override
public void onKeyguardVisibilityChanged(boolean showing) {
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
@@ -320,7 +290,6 @@
@Override
public void onUserSwitchComplete(int userId) {
- mKeyguardClockSwitchController.refreshFormat();
mView.updateOwnerInfo();
mView.updateLogoutView(shouldShowLogout());
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 7329071..66ea2ad 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -199,14 +199,14 @@
}
private void updateVisibility() {
- if (!mIsKeyguardShowing) {
+ if (!mIsKeyguardShowing || (!mUdfpsEnrolled && !mFaceAuthEnrolled)) {
mView.setVisibility(View.INVISIBLE);
return;
}
// these three states are mutually exclusive:
mShowButton = mUdfpsEnrolled && !mCanDismissLockScreen && !mRunningFPS && isLockScreen();
- mShowUnlockIcon = mCanDismissLockScreen && isLockScreen();
+ mShowUnlockIcon = mFaceAuthEnrolled & mCanDismissLockScreen && isLockScreen();
mShowLockIcon = !mUdfpsEnrolled && !mCanDismissLockScreen && isLockScreen()
&& mFaceAuthEnrolled;
diff --git a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
index 5735a4f..cdb39ef 100644
--- a/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/TextAnimator.kt
@@ -65,7 +65,9 @@
invalidateCallback()
}
addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) = textInterpolator.rebase()
+ override fun onAnimationEnd(animation: Animator?) {
+ textInterpolator.rebase()
+ }
override fun onAnimationCancel(animation: Animator?) = textInterpolator.rebase()
})
}
@@ -74,6 +76,10 @@
textInterpolator.layout = layout
}
+ fun isRunning(): Boolean {
+ return animator.isRunning
+ }
+
fun draw(c: Canvas) = textInterpolator.draw(c)
/**
@@ -101,7 +107,9 @@
color: Int? = null,
animate: Boolean = true,
duration: Long = -1L,
- interpolator: TimeInterpolator? = null
+ interpolator: TimeInterpolator? = null,
+ delay: Long = 0,
+ onAnimationEnd: Runnable? = null
) {
if (animate) {
animator.cancel()
@@ -120,12 +128,25 @@
textInterpolator.onTargetPaintModified()
if (animate) {
+ animator.startDelay = delay
animator.duration = if (duration == -1L) {
DEFAULT_ANIMATION_DURATION
} else {
duration
}
interpolator?.let { animator.interpolator = it }
+ if (onAnimationEnd != null) {
+ val listener = object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ onAnimationEnd.run()
+ animator.removeListener(this)
+ }
+ override fun onAnimationCancel(animation: Animator?) {
+ animator.removeListener(this)
+ }
+ }
+ animator.addListener(listener)
+ }
animator.start()
} else {
// No animation is requested, thus set base and target state to the same state.
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
index 8ec9b68..dc22dc1 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
@@ -128,9 +128,14 @@
)
} ?: firstLine
newView.requireViewById<TextView>(R.id.text).text = finalText
+ if (element.phoneCall) {
+ newView.requireViewById<View>(R.id.chevron).visibility = View.GONE
+ }
newView.apply {
setTag(element)
- setOnClickListener(clickListener)
+ if (!element.phoneCall) {
+ setOnClickListener(clickListener)
+ }
}
return newView
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 2c5dbcd..670475f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -36,7 +36,6 @@
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -89,7 +88,7 @@
private Drawable mPrimaryFooterIconDrawable;
@Inject
- QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView, Context context,
+ QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView,
UserTracker userTracker, @Main Handler mainHandler, ActivityStarter activityStarter,
SecurityController securityController, @Background Looper bgLooper) {
mRootView = rootView;
@@ -98,7 +97,7 @@
mFooterIcon = mRootView.findViewById(R.id.footer_icon);
mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon);
mFooterIconId = R.drawable.ic_info_outline;
- mContext = context;
+ mContext = rootView.getContext();
mMainHandler = mainHandler;
mActivityStarter = activityStarter;
mSecurityController = securityController;
@@ -308,7 +307,7 @@
}
private void createDialog() {
- mDialog = new SystemUIDialog(mContext);
+ mDialog = new SystemUIDialog(mContext, 0); // Use mContext theme
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getNegativeButton(), this);
@@ -344,8 +343,7 @@
final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
- View dialogView = LayoutInflater.from(
- new ContextThemeWrapper(mContext, R.style.Theme_SystemUI_Dialog))
+ View dialogView = LayoutInflater.from(mContext)
.inflate(R.layout.quick_settings_footer_dialog, null, false);
// device management section
@@ -420,8 +418,7 @@
}
private View createParentalControlsDialogView() {
- View dialogView = LayoutInflater.from(
- new ContextThemeWrapper(mContext, R.style.Theme_SystemUI_Dialog))
+ View dialogView = LayoutInflater.from(mContext)
.inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);
DeviceAdminInfo info = mSecurityController.getDeviceAdminInfo();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 6f789d3..30a08c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -22,7 +22,6 @@
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
@@ -63,7 +62,7 @@
private boolean mIsShowingNavBackdrop;
public QSCustomizer(Context context, AttributeSet attrs) {
- super(new ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Edit), attrs);
+ super(context, attrs);
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
mClipper = new QSDetailClipper(findViewById(R.id.customize_container));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 08aa599..006b230 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -52,6 +52,7 @@
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.qs.dagger.QSThemedContext;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSIconViewImpl;
import com.android.systemui.qs.tileimpl.QSTileView;
@@ -89,7 +90,7 @@
private final Handler mHandler = new Handler();
private final List<TileInfo> mTiles = new ArrayList<>();
private final ItemTouchHelper mItemTouchHelper;
- private final ItemDecoration mDecoration;
+ private ItemDecoration mDecoration;
private final MarginTileDecoration mMarginDecoration;
private final int mMinNumTiles;
private final QSTileHost mHost;
@@ -112,8 +113,12 @@
private final boolean mUseHorizontalTiles;
@Inject
- public TileAdapter(Context context, QSTileHost qsHost, UiEventLogger uiEventLogger,
- @Named(QS_LABELS_FLAG) boolean useHorizontalTiles) {
+ public TileAdapter(
+ @QSThemedContext Context context,
+ QSTileHost qsHost,
+ UiEventLogger uiEventLogger,
+ @Named(QS_LABELS_FLAG) boolean useHorizontalTiles
+ ) {
mContext = context;
mHost = qsHost;
mUiEventLogger = uiEventLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 2363aa4..3a5adce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -49,6 +49,22 @@
String QS_SECURITY_FOOTER_VIEW = "qs_security_footer";
String QS_USING_MEDIA_PLAYER = "qs_using_media_player";
+ /**
+ * Provide a context themed using the QS theme
+ */
+ @Provides
+ @QSThemedContext
+ static Context provideThemedContext(@RootView View view) {
+ return view.getContext();
+ }
+
+ /** */
+ @Provides
+ @QSThemedContext
+ static LayoutInflater provideThemedLayoutInflater(@QSThemedContext Context context) {
+ return LayoutInflater.from(context);
+ }
+
/** */
@Provides
@RootView
@@ -109,7 +125,10 @@
@Provides
@QSScope
@Named(QS_SECURITY_FOOTER_VIEW)
- static View providesQSSecurityFooterView(LayoutInflater layoutInflater, QSPanel qsPanel) {
+ static View providesQSSecurityFooterView(
+ @QSThemedContext LayoutInflater layoutInflater,
+ QSPanel qsPanel
+ ) {
return layoutInflater.inflate(R.layout.quick_settings_footer, qsPanel, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSThemedContext.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSThemedContext.java
new file mode 100644
index 0000000..a878d4c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSThemedContext.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/**
+ * Annotation for themed context in QS
+ */
+@Documented
+@Retention(RUNTIME)
+@Qualifier
+public @interface QSThemedContext {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index abe3219..7e72f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -72,7 +72,6 @@
protected final ImageView mBg;
private final int mColorActive;
private final int mColorInactive;
- private final int mColorDisabled;
private int mCircleColor;
private int mBgSize;
@@ -131,10 +130,9 @@
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
setBackground(mTileBackground);
- mColorActive = Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent);
- mColorDisabled = Utils.getDisabled(context,
- Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlActivated));
- mColorInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary);
+ mColorActive = Utils.getColorAttrDefaultColor(context,
+ com.android.internal.R.attr.colorAccentPrimary);
+ mColorInactive = Utils.getColorAttrDefaultColor(context, R.attr.offStateColor);
setPadding(0, 0, 0, 0);
setClipChildren(false);
@@ -324,7 +322,7 @@
return mColorActive;
case Tile.STATE_INACTIVE:
case Tile.STATE_UNAVAILABLE:
- return mColorDisabled;
+ return mColorInactive;
default:
Log.e(TAG, "Invalid state " + state);
return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
index 78ee896..9e11451 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
@@ -28,21 +28,26 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
-import android.util.IntArray;
import android.util.Log;
import android.util.MathUtils;
import android.util.Range;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.SeekBar;
import androidx.annotation.Nullable;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
+import androidx.customview.widget.ExploreByTouchHelper;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
-import com.android.internal.widget.ExploreByTouchHelper;
import com.android.systemui.R;
+import java.util.List;
+
/**
* CropView has top and bottom draggable crop handles, with a scrim to darken the areas being
* cropped out.
@@ -66,6 +71,7 @@
private int mImageWidth;
private CropBoundary mCurrentDraggingBoundary = CropBoundary.NONE;
+ private int mActivePointerId;
// The starting value of mCurrentDraggingBoundary's crop, used to compute touch deltas.
private float mMovementStartValue;
private float mStartingY; // y coordinate of ACTION_DOWN
@@ -74,6 +80,7 @@
private Range<Float> mMotionRange;
private CropInteractionListener mCropInteractionListener;
+ private final ExploreByTouchHelper mExploreByTouchHelper;
public CropView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
@@ -94,7 +101,8 @@
// 48 dp touchable region around each handle.
mCropTouchMargin = 24 * getResources().getDisplayMetrics().density;
- setAccessibilityDelegate(new AccessibilityHelper());
+ mExploreByTouchHelper = new AccessibilityHelper();
+ ViewCompat.setAccessibilityDelegate(this, mExploreByTouchHelper);
}
@Override
@@ -131,64 +139,88 @@
public boolean onTouchEvent(MotionEvent event) {
int topPx = fractionToVerticalPixels(mCrop.top);
int bottomPx = fractionToVerticalPixels(mCrop.bottom);
- switch (event.getAction()) {
+ switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mCurrentDraggingBoundary = nearestBoundary(event, topPx, bottomPx,
fractionToHorizontalPixels(mCrop.left),
fractionToHorizontalPixels(mCrop.right));
if (mCurrentDraggingBoundary != CropBoundary.NONE) {
+ mActivePointerId = event.getPointerId(0);
mStartingY = event.getY();
mStartingX = event.getX();
mMovementStartValue = getBoundaryPosition(mCurrentDraggingBoundary);
- updateListener(event);
- switch (mCurrentDraggingBoundary) {
- case TOP:
- mMotionRange = new Range<>(0f,
- mCrop.bottom - pixelDistanceToFraction(mCropTouchMargin,
- CropBoundary.BOTTOM));
- break;
- case BOTTOM:
- mMotionRange = new Range<>(
- mCrop.top + pixelDistanceToFraction(mCropTouchMargin,
- CropBoundary.TOP), 1f);
- break;
- case LEFT:
- mMotionRange = new Range<>(0f,
- mCrop.right - pixelDistanceToFraction(mCropTouchMargin,
- CropBoundary.RIGHT));
- break;
- case RIGHT:
- mMotionRange = new Range<>(
- mCrop.left + pixelDistanceToFraction(mCropTouchMargin,
- CropBoundary.LEFT), 1f);
- break;
- }
+ updateListener(MotionEvent.ACTION_DOWN, event.getX());
+ mMotionRange = getAllowedValues(mCurrentDraggingBoundary);
}
return true;
case MotionEvent.ACTION_MOVE:
if (mCurrentDraggingBoundary != CropBoundary.NONE) {
- float deltaPx = isVertical(mCurrentDraggingBoundary) ? event.getY() - mStartingY
- : event.getX() - mStartingX;
- float delta = pixelDistanceToFraction((int) deltaPx, mCurrentDraggingBoundary);
- setBoundaryPosition(mCurrentDraggingBoundary,
- mMotionRange.clamp(mMovementStartValue + delta));
- updateListener(event);
- invalidate();
+ int pointerIndex = event.findPointerIndex(mActivePointerId);
+ if (pointerIndex >= 0) {
+ // Original pointer still active, do the move.
+ float deltaPx = isVertical(mCurrentDraggingBoundary)
+ ? event.getY(pointerIndex) - mStartingY
+ : event.getX(pointerIndex) - mStartingX;
+ float delta = pixelDistanceToFraction((int) deltaPx,
+ mCurrentDraggingBoundary);
+ setBoundaryPosition(mCurrentDraggingBoundary,
+ mMotionRange.clamp(mMovementStartValue + delta));
+ updateListener(MotionEvent.ACTION_MOVE, event.getX(pointerIndex));
+ invalidate();
+ }
return true;
}
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mActivePointerId == event.getPointerId(event.getActionIndex())
+ && mCurrentDraggingBoundary != CropBoundary.NONE) {
+ updateListener(MotionEvent.ACTION_DOWN, event.getX(event.getActionIndex()));
+ return true;
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ if (mActivePointerId == event.getPointerId(event.getActionIndex())
+ && mCurrentDraggingBoundary != CropBoundary.NONE) {
+ updateListener(MotionEvent.ACTION_UP, event.getX(event.getActionIndex()));
+ return true;
+ }
+ break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- if (mCurrentDraggingBoundary != CropBoundary.NONE) {
- updateListener(event);
+ if (mCurrentDraggingBoundary != CropBoundary.NONE
+ && mActivePointerId == event.getPointerId(mActivePointerId)) {
+ updateListener(MotionEvent.ACTION_UP, event.getX(0));
+ return true;
}
+ break;
}
return super.onTouchEvent(event);
}
+ @Override
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ return mExploreByTouchHelper.dispatchHoverEvent(event)
+ || super.dispatchHoverEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return mExploreByTouchHelper.dispatchKeyEvent(event)
+ || super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public void onFocusChanged(boolean gainFocus, int direction,
+ Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ mExploreByTouchHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+
/**
* Set the given boundary to the given value without animation.
*/
public void setBoundaryPosition(CropBoundary boundary, float position) {
+ position = (float) getAllowedValues(boundary).clamp(position);
switch (boundary) {
case TOP:
mCrop.top = position;
@@ -280,12 +312,51 @@
mCropInteractionListener = listener;
}
- private void updateListener(MotionEvent event) {
- if (mCropInteractionListener != null && (isVertical(mCurrentDraggingBoundary))) {
+ private Range getAllowedValues(CropBoundary boundary) {
+ switch (boundary) {
+ case TOP:
+ return new Range<>(0f,
+ mCrop.bottom - pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.BOTTOM));
+ case BOTTOM:
+ return new Range<>(
+ mCrop.top + pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.TOP), 1f);
+ case LEFT:
+ return new Range<>(0f,
+ mCrop.right - pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.RIGHT));
+ case RIGHT:
+ return new Range<>(
+ mCrop.left + pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.LEFT), 1f);
+ }
+ return null;
+ }
+
+ /**
+ * @param action either ACTION_DOWN, ACTION_UP or ACTION_MOVE.
+ * @param x coordinate of the relevant pointer.
+ */
+ private void updateListener(int action, float x) {
+ if (mCropInteractionListener != null && isVertical(mCurrentDraggingBoundary)) {
float boundaryPosition = getBoundaryPosition(mCurrentDraggingBoundary);
- mCropInteractionListener.onCropMotionEvent(event, mCurrentDraggingBoundary,
- boundaryPosition, fractionToVerticalPixels(boundaryPosition),
- (mCrop.left + mCrop.right) / 2);
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mCropInteractionListener.onCropDragStarted(mCurrentDraggingBoundary,
+ boundaryPosition, fractionToVerticalPixels(boundaryPosition),
+ (mCrop.left + mCrop.right) / 2, x);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mCropInteractionListener.onCropDragMoved(mCurrentDraggingBoundary,
+ boundaryPosition, fractionToVerticalPixels(boundaryPosition),
+ (mCrop.left + mCrop.right) / 2, x);
+ break;
+ case MotionEvent.ACTION_UP:
+ mCropInteractionListener.onCropDragComplete();
+ break;
+
+ }
}
}
@@ -371,6 +442,8 @@
private static final int TOP_HANDLE_ID = 1;
private static final int BOTTOM_HANDLE_ID = 2;
+ private static final int LEFT_HANDLE_ID = 3;
+ private static final int RIGHT_HANDLE_ID = 4;
AccessibilityHelper() {
super(CropView.this);
@@ -384,62 +457,125 @@
if (Math.abs(y - fractionToVerticalPixels(mCrop.bottom)) < mCropTouchMargin) {
return BOTTOM_HANDLE_ID;
}
- return ExploreByTouchHelper.INVALID_ID;
+ if (y > fractionToVerticalPixels(mCrop.top)
+ && y < fractionToVerticalPixels(mCrop.bottom)) {
+ if (Math.abs(x - fractionToHorizontalPixels(mCrop.left)) < mCropTouchMargin) {
+ return LEFT_HANDLE_ID;
+ }
+ if (Math.abs(x - fractionToHorizontalPixels(mCrop.right)) < mCropTouchMargin) {
+ return RIGHT_HANDLE_ID;
+ }
+ }
+
+ return ExploreByTouchHelper.HOST_ID;
}
@Override
- protected void getVisibleVirtualViews(IntArray virtualViewIds) {
+ protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+ // Add views in traversal order
virtualViewIds.add(TOP_HANDLE_ID);
+ virtualViewIds.add(LEFT_HANDLE_ID);
+ virtualViewIds.add(RIGHT_HANDLE_ID);
virtualViewIds.add(BOTTOM_HANDLE_ID);
}
@Override
protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
- switch (virtualViewId) {
- case TOP_HANDLE_ID:
- event.setContentDescription(
- getResources().getString(R.string.screenshot_top_boundary));
- break;
- case BOTTOM_HANDLE_ID:
- event.setContentDescription(
- getResources().getString(R.string.screenshot_bottom_boundary));
- break;
- }
+ CropBoundary boundary = viewIdToBoundary(virtualViewId);
+ event.setContentDescription(getBoundaryContentDescription(boundary));
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId,
- AccessibilityNodeInfo node) {
- switch (virtualViewId) {
- case TOP_HANDLE_ID:
- node.setContentDescription(
- getResources().getString(R.string.screenshot_top_boundary));
- setNodePositions(mCrop.top, node);
- break;
- case BOTTOM_HANDLE_ID:
- node.setContentDescription(
- getResources().getString(R.string.screenshot_bottom_boundary));
- setNodePositions(mCrop.bottom, node);
- break;
- }
+ AccessibilityNodeInfoCompat node) {
+ CropBoundary boundary = viewIdToBoundary(virtualViewId);
+ node.setContentDescription(getBoundaryContentDescription(boundary));
+ setNodePosition(getNodeRect(boundary), node);
- // TODO: need to figure out the full set of actions to support here.
- node.addAction(
- AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
- node.setClickable(true);
- node.setFocusable(true);
+ // Intentionally set the class name to SeekBar so that TalkBack uses volume control to
+ // scroll.
+ node.setClassName(SeekBar.class.getName());
+ node.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD);
+ node.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD);
}
@Override
protected boolean onPerformActionForVirtualView(
int virtualViewId, int action, Bundle arguments) {
- return false;
+ if (action != AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
+ && action != AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
+ return false;
+ }
+ CropBoundary boundary = viewIdToBoundary(virtualViewId);
+ float delta = pixelDistanceToFraction(mCropTouchMargin, boundary);
+ if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
+ delta = -delta;
+ }
+ setBoundaryPosition(boundary, delta + getBoundaryPosition(boundary));
+ invalidateVirtualView(virtualViewId);
+ sendEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_SELECTED);
+ return true;
}
- private void setNodePositions(float fraction, AccessibilityNodeInfo node) {
- int pixels = fractionToVerticalPixels(fraction);
- Rect rect = new Rect(0, (int) (pixels - mCropTouchMargin),
- getWidth(), (int) (pixels + mCropTouchMargin));
+ private CharSequence getBoundaryContentDescription(CropBoundary boundary) {
+ int template;
+ switch (boundary) {
+ case TOP:
+ template = R.string.screenshot_top_boundary_pct;
+ break;
+ case BOTTOM:
+ template = R.string.screenshot_bottom_boundary_pct;
+ break;
+ case LEFT:
+ template = R.string.screenshot_left_boundary_pct;
+ break;
+ case RIGHT:
+ template = R.string.screenshot_right_boundary_pct;
+ break;
+ default:
+ return "";
+ }
+
+ return getResources().getString(template,
+ Math.round(getBoundaryPosition(boundary) * 100));
+ }
+
+ private CropBoundary viewIdToBoundary(int viewId) {
+ switch (viewId) {
+ case TOP_HANDLE_ID:
+ return CropBoundary.TOP;
+ case BOTTOM_HANDLE_ID:
+ return CropBoundary.BOTTOM;
+ case LEFT_HANDLE_ID:
+ return CropBoundary.LEFT;
+ case RIGHT_HANDLE_ID:
+ return CropBoundary.RIGHT;
+ }
+ return CropBoundary.NONE;
+ }
+
+ private Rect getNodeRect(CropBoundary boundary) {
+ Rect rect;
+ if (isVertical(boundary)) {
+ int pixels = fractionToVerticalPixels(getBoundaryPosition(boundary));
+ rect = new Rect(0, (int) (pixels - mCropTouchMargin),
+ getWidth(), (int) (pixels + mCropTouchMargin));
+ // Top boundary can sometimes go beyond the view, shift it down to compensate so
+ // the area is big enough.
+ if (rect.top < 0) {
+ rect.offset(0, -rect.top);
+ }
+ } else {
+ int pixels = fractionToHorizontalPixels(getBoundaryPosition(boundary));
+ rect = new Rect((int) (pixels - mCropTouchMargin),
+ (int) (fractionToVerticalPixels(mCrop.top) + mCropTouchMargin),
+ (int) (pixels + mCropTouchMargin),
+ (int) (fractionToVerticalPixels(mCrop.bottom) - mCropTouchMargin));
+ }
+ return rect;
+ }
+
+ private void setNodePosition(Rect rect, AccessibilityNodeInfoCompat node) {
node.setBoundsInParent(rect);
int[] pos = new int[2];
getLocationOnScreen(pos);
@@ -452,12 +588,11 @@
* Listen for crop motion events and state.
*/
public interface CropInteractionListener {
- /**
- * Called whenever CropView has a MotionEvent that can impact the position of the crop
- * boundaries.
- */
- void onCropMotionEvent(MotionEvent event, CropBoundary boundary, float boundaryPosition,
- int boundaryPositionPx, float horizontalCenter);
+ void onCropDragStarted(CropBoundary boundary, float boundaryPosition,
+ int boundaryPositionPx, float horizontalCenter, float x);
+ void onCropDragMoved(CropBoundary boundary, float boundaryPosition,
+ int boundaryPositionPx, float horizontalCenter, float x);
+ void onCropDragComplete();
}
static class SavedState extends BaseSavedState {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
index 08cd91c..34b40f7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
@@ -28,7 +28,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewPropertyAnimator;
@@ -148,49 +147,51 @@
}
@Override
- public void onCropMotionEvent(MotionEvent event, CropView.CropBoundary boundary,
- float cropPosition, int cropPositionPx, float horizontalCenter) {
+ public void onCropDragStarted(CropView.CropBoundary boundary, float boundaryPosition,
+ int boundaryPositionPx, float horizontalCenter, float x) {
mCropBoundary = boundary;
mLastCenter = horizontalCenter;
- boolean touchOnRight = event.getX() > getParentWidth() / 2;
+ boolean touchOnRight = x > getParentWidth() / 2;
float translateXTarget = touchOnRight ? 0 : getParentWidth() - getWidth();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mLastCropPosition = cropPosition;
- setTranslationY(cropPositionPx - getHeight() / 2);
- setPivotX(getWidth() / 2);
- setPivotY(getHeight() / 2);
- setScaleX(0.2f);
- setScaleY(0.2f);
- setAlpha(0f);
- setTranslationX((getParentWidth() - getWidth()) / 2);
- setVisibility(View.VISIBLE);
- mTranslationAnimator =
- animate().alpha(1f).translationX(translateXTarget).scaleX(1f).scaleY(1f);
- mTranslationAnimator.setListener(mTranslationAnimatorListener);
- mTranslationAnimator.start();
- break;
- case MotionEvent.ACTION_MOVE:
- // The touch is near the middle if it's within 10% of the center point.
- // We don't want to animate horizontally if the touch is near the middle.
- boolean nearMiddle = Math.abs(event.getX() - getParentWidth() / 2)
- < getParentWidth() / 10f;
- boolean viewOnLeft = getTranslationX() < (getParentWidth() - getWidth()) / 2;
- if (!nearMiddle && viewOnLeft != touchOnRight && mTranslationAnimator == null) {
- mTranslationAnimator = animate().translationX(translateXTarget);
- mTranslationAnimator.setListener(mTranslationAnimatorListener);
- mTranslationAnimator.start();
- }
- mLastCropPosition = cropPosition;
- setTranslationY(cropPositionPx - getHeight() / 2);
- invalidate();
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- animate().alpha(0).translationX((getParentWidth() - getWidth()) / 2).scaleX(0.2f)
- .scaleY(0.2f).withEndAction(() -> setVisibility(View.INVISIBLE)).start();
- break;
+ mLastCropPosition = boundaryPosition;
+ setTranslationY(boundaryPositionPx - getHeight() / 2);
+ setPivotX(getWidth() / 2);
+ setPivotY(getHeight() / 2);
+ setScaleX(0.2f);
+ setScaleY(0.2f);
+ setAlpha(0f);
+ setTranslationX((getParentWidth() - getWidth()) / 2);
+ setVisibility(View.VISIBLE);
+ mTranslationAnimator =
+ animate().alpha(1f).translationX(translateXTarget).scaleX(1f).scaleY(1f);
+ mTranslationAnimator.setListener(mTranslationAnimatorListener);
+ mTranslationAnimator.start();
+ }
+
+ @Override
+ public void onCropDragMoved(CropView.CropBoundary boundary, float boundaryPosition,
+ int boundaryPositionPx, float horizontalCenter, float x) {
+ boolean touchOnRight = x > getParentWidth() / 2;
+ float translateXTarget = touchOnRight ? 0 : getParentWidth() - getWidth();
+ // The touch is near the middle if it's within 10% of the center point.
+ // We don't want to animate horizontally if the touch is near the middle.
+ boolean nearMiddle = Math.abs(x - getParentWidth() / 2)
+ < getParentWidth() / 10f;
+ boolean viewOnLeft = getTranslationX() < (getParentWidth() - getWidth()) / 2;
+ if (!nearMiddle && viewOnLeft != touchOnRight && mTranslationAnimator == null) {
+ mTranslationAnimator = animate().translationX(translateXTarget);
+ mTranslationAnimator.setListener(mTranslationAnimatorListener);
+ mTranslationAnimator.start();
}
+ mLastCropPosition = boundaryPosition;
+ setTranslationY(boundaryPositionPx - getHeight() / 2);
+ invalidate();
+ }
+
+ @Override
+ public void onCropDragComplete() {
+ animate().alpha(0).translationX((getParentWidth() - getWidth()) / 2).scaleX(0.2f)
+ .scaleY(0.2f).withEndAction(() -> setVisibility(View.INVISIBLE)).start();
}
private Path generateCheckerboard() {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 1961bfc..3ba4646 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -25,6 +25,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import javax.inject.Inject;
@@ -61,10 +62,10 @@
window.setLayout(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
-
BrightnessSlider controller = mToggleSliderFactory.create(this, null);
controller.init();
setContentView(controller.getRootView());
+ controller.getRootView().setBackgroundResource(R.drawable.brightness_mirror_background);
mBrightnessController = new BrightnessController(this, controller, mBroadcastDispatcher);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 019f7e0..6b864c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -161,15 +161,14 @@
/**
* Called by the Keyguard*ViewController whose view contains the aod icons.
*/
- public void setupAodIcons(@NonNull NotificationIconContainer aodIcons,
- int lockScreenMode) {
+ public void setupAodIcons(@NonNull NotificationIconContainer aodIcons) {
boolean changed = mAodIcons != null;
if (changed) {
mAodIcons.setAnimationsEnabled(false);
mAodIcons.removeAllViews();
}
mAodIcons = aodIcons;
- mAodIcons.setOnLockScreen(true, lockScreenMode);
+ mAodIcons.setOnLockScreen(true);
updateAodIconsVisibility(false /* animate */);
updateAnimations();
if (changed) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 52f656f..c09c485 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -35,7 +35,6 @@
import androidx.collection.ArrayMap;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -151,7 +150,6 @@
private float mActualPaddingStart = NO_VALUE;
private boolean mDozing;
private boolean mOnLockScreen;
- private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
private boolean mInNotificationIconShelf;
private boolean mChangingViewPositions;
private int mAddAnimationStartIndex = -1;
@@ -464,33 +462,6 @@
mFirstVisibleIconState = mIconStates.get(getChildAt(0));
}
- boolean center = mOnLockScreen
- && mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
- if (center && translationX < getLayoutEnd()) {
- float initialTranslation =
- mFirstVisibleIconState == null ? 0 : mFirstVisibleIconState.xTranslation;
-
- float contentWidth = 0;
- if (mLastVisibleIconState != null) {
- contentWidth = mLastVisibleIconState.xTranslation + mIconSize;
- contentWidth = Math.min(getWidth(), contentWidth) - initialTranslation;
- }
- float availableSpace = getLayoutEnd() - getActualPaddingStart();
- float delta = (availableSpace - contentWidth) / 2;
-
- if (firstOverflowIndex != -1) {
- // If we have an overflow, only count those half for centering because the dots
- // don't have a lot of visual weight.
- float deltaIgnoringOverflow = (getLayoutEnd() - mVisualOverflowStart) / 2;
- delta = (deltaIgnoringOverflow + delta) / 2;
- }
- for (int i = 0; i < childCount; i++) {
- View view = getChildAt(i);
- IconState iconState = mIconStates.get(view);
- iconState.xTranslation += delta;
- }
- }
-
if (isLayoutRtl()) {
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
@@ -698,9 +669,8 @@
* Set whether the device is on the lockscreen and which lockscreen mode the device is
* configured to. Depending on these values, the layout of the AOD icons change.
*/
- public void setOnLockScreen(boolean onLockScreen, int lockScreenMode) {
+ public void setOnLockScreen(boolean onLockScreen) {
mOnLockScreen = onLockScreen;
- mLockScreenMode = lockScreenMode;
}
public void setInNotificationIconShelf(boolean inShelf) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 6af2990..7032aef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -76,7 +76,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -363,6 +362,7 @@
private float mDownX;
private float mDownY;
private int mDisplayCutoutTopInset = 0; // in pixels
+ private int mSplitShadeNotificationsTopPadding;
private final KeyguardClockPositionAlgorithm
mClockPositionAlgorithm =
@@ -798,11 +798,6 @@
statusBarViewComponent.getKeyguardStatusBarViewController();
mKeyguarStatusBarViewController.init();
- // Re-associate the clock container with the keyguard clock switch.
- KeyguardClockSwitchController keyguardClockSwitchController =
- statusViewComponent.getKeyguardClockSwitchController();
- keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
-
if (mKeyguardUserSwitcherController != null) {
// Try to close the switcher so that callbacks are triggered if necessary.
// Otherwise, NPV can get into a state where some of the views are still hidden
@@ -847,6 +842,8 @@
}
public void updateResources() {
+ mSplitShadeNotificationsTopPadding =
+ mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade);
int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
mShouldUseSplitNotificationShade =
@@ -2019,10 +2016,9 @@
}
}
- private float calculateQsTopPadding() {
- // in split shade mode we want notifications to be directly below status bar
+ private float calculateNotificationsTopPadding() {
if (mShouldUseSplitNotificationShade && !mKeyguardShowing) {
- return 0f;
+ return mSplitShadeNotificationsTopPadding;
}
if (mKeyguardShowing && (mQsExpandImmediate
|| mIsExpanding && mQsExpandedWhenExpandingStarted)) {
@@ -2076,7 +2072,8 @@
protected void requestScrollerTopPaddingUpdate(boolean animate) {
- mNotificationStackScrollLayoutController.updateTopPadding(calculateQsTopPadding(), animate);
+ mNotificationStackScrollLayoutController.updateTopPadding(
+ calculateNotificationsTopPadding(), animate);
if (mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()) {
// update the position of the header
updateQsExpansion();
@@ -4056,7 +4053,8 @@
calculatePanelHeightShade(), p);
p.setColor(Color.MAGENTA);
canvas.drawLine(
- 0, calculateQsTopPadding(), mView.getWidth(), calculateQsTopPadding(), p);
+ 0, calculateNotificationsTopPadding(), mView.getWidth(),
+ calculateNotificationsTopPadding(), p);
p.setColor(Color.CYAN);
canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
mNotificationStackScrollLayoutController.getTopPadding(), p);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index adde4d8..58488ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -497,7 +497,7 @@
return;
}
shiftNotificationsScrim(qsPanelBottomY);
- updateNotificationsScrimAlpha(qsPanelBottomY);
+ updateNotificationsScrimAlpha(expansionFraction, qsPanelBottomY);
if (mQsExpansion != expansionFraction) {
mQsExpansion = expansionFraction;
boolean relevantState = (mState == ScrimState.SHADE_LOCKED
@@ -519,14 +519,14 @@
}
}
- private void updateNotificationsScrimAlpha(int qsPanelBottomY) {
+ private void updateNotificationsScrimAlpha(float qsExpansion, int qsPanelBottomY) {
float newAlpha = 0;
if (qsPanelBottomY > 0) {
float interpolator = 0;
if (mState == ScrimState.UNLOCKED || mState == ScrimState.SHADE_LOCKED) {
interpolator = getInterpolatedFraction();
} else {
- interpolator = mQsExpansion;
+ interpolator = qsExpansion;
}
newAlpha = MathUtils.lerp(0, 1, interpolator);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index afeda967..55b80dd 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -38,7 +38,6 @@
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Configuration;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -85,16 +84,13 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
-import java.util.function.Supplier;
/**
* The SysUi side bubbles manager which communicate with other SysUi components.
@@ -252,6 +248,13 @@
mSysuiProxy = new Bubbles.SysuiProxy() {
@Override
+ public void isNotificationShadeExpand(Consumer<Boolean> callback) {
+ sysuiMainExecutor.execute(() -> {
+ callback.accept(mNotificationShadeWindowController.getPanelExpanded());
+ });
+ }
+
+ @Override
public void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback) {
sysuiMainExecutor.execute(() -> {
NotificationEntry entry =
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 45b0b59..98833eb 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -186,14 +186,15 @@
WindowManager windowManager,
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps,
+ TaskStackListenerImpl taskStackListener,
UiEventLogger uiEventLogger,
ShellTaskOrganizer organizer,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler) {
return Optional.of(BubbleController.create(context, null /* synchronizer */,
floatingContentCoordinator, statusBarService, windowManager,
- windowManagerShellWrapper, launcherApps, uiEventLogger, organizer,
- mainExecutor, mainHandler));
+ windowManagerShellWrapper, launcherApps, taskStackListener,
+ uiEventLogger, organizer, mainExecutor, mainHandler));
}
//
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 0fcd79b..9017dd2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -31,8 +31,6 @@
import android.testing.AndroidTestingRunner;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.android.internal.colorextraction.ColorExtractor;
@@ -49,6 +47,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.statusbar.policy.BatteryController;
import org.junit.Before;
import org.junit.Test;
@@ -94,6 +93,12 @@
private FeatureFlags mFeatureFlags;
@Mock
private Executor mExecutor;
+ @Mock
+ private AnimatableClockView mClockView;
+ @Mock
+ private AnimatableClockView mLargeClockView;
+ @Mock
+ BatteryController mBatteryController;
private KeyguardClockSwitchController mController;
@@ -101,9 +106,15 @@
public void setup() {
MockitoAnnotations.initMocks(this);
- when(mView.findViewById(com.android.systemui.R.id.left_aligned_notification_icon_container))
+ when(mView.findViewById(R.id.left_aligned_notification_icon_container))
.thenReturn(mNotificationIcons);
when(mView.getContext()).thenReturn(getContext());
+
+ when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
+ when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
+ when(mClockView.getContext()).thenReturn(getContext());
+ when(mLargeClockView.getContext()).thenReturn(getContext());
+
when(mFeatureFlags.isSmartspaceEnabled()).thenReturn(true);
when(mView.isAttachedToWindow()).thenReturn(true);
when(mResources.getString(anyInt())).thenReturn("h:mm");
@@ -119,7 +130,8 @@
mBroadcastDispatcher,
mPluginManager,
mFeatureFlags,
- mExecutor);
+ mExecutor,
+ mBatteryController);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
@@ -165,33 +177,11 @@
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mStatusBarStateController).removeCallback(
- any(StatusBarStateController.StateListener.class));
verify(mColorExtractor).removeOnColorsChangedListener(
any(ColorExtractor.OnColorsChangedListener.class));
}
@Test
- public void testBigClockPassesStatusBarState() {
- ViewGroup testView = new FrameLayout(mContext);
-
- mController.init();
- when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
- mController.setBigClockContainer(testView);
- verify(mView).setBigClockContainer(testView, StatusBarState.SHADE);
-
-
- when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
- mController.setBigClockContainer(testView);
- verify(mView).setBigClockContainer(testView, StatusBarState.KEYGUARD);
-
-
- when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
- mController.setBigClockContainer(testView);
- verify(mView).setBigClockContainer(testView, StatusBarState.SHADE_LOCKED);
- }
-
- @Test
public void testPluginPassesStatusBarState() {
ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
@@ -245,8 +235,6 @@
private void verifyAttachment(VerificationMode times) {
verify(mClockManager, times).addOnClockChangedListener(
any(ClockManager.ClockChangedListener.class));
- verify(mStatusBarStateController, times).addCallback(
- any(StatusBarStateController.StateListener.class));
verify(mColorExtractor, times).addOnColorsChangedListener(
any(ColorExtractor.OnColorsChangedListener.class));
verify(mView, times).updateColors(mGradientColors);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index e793079..10ed1d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -21,9 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -33,7 +31,6 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -48,8 +45,6 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@@ -59,14 +54,13 @@
// the keyguard_clcok_switch layout is inflated.
@RunWithLooper(setAsMainLooper = true)
public class KeyguardClockSwitchTest extends SysuiTestCase {
- private FrameLayout mClockContainer;
- private FrameLayout mBigClockContainer;
+ private FrameLayout mClockFrame;
+ private FrameLayout mLargeClockFrame;
private TextClock mBigClock;
- @Mock
- TextClock mClockView;
+ private AnimatableClockView mClockView;
+ private AnimatableClockView mLargeClockView;
View mMockKeyguardSliceView;
- @InjectMocks
KeyguardClockSwitch mKeyguardClockSwitch;
@Before
@@ -95,11 +89,12 @@
});
mKeyguardClockSwitch =
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
- mClockContainer = mKeyguardClockSwitch.findViewById(R.id.clock_view);
- mBigClockContainer = new FrameLayout(getContext());
+ mClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
+ mClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view);
+ mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large);
+ mLargeClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view_large);
mBigClock = new TextClock(getContext());
MockitoAnnotations.initMocks(this);
- when(mClockView.getPaint()).thenReturn(mock(TextPaint.class));
}
@Test
@@ -110,33 +105,28 @@
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- verify(mClockView).setVisibility(GONE);
- assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
+ assertThat(mClockView.getVisibility()).isEqualTo(GONE);
+ assertThat(plugin.getView().getParent()).isEqualTo(mClockFrame);
}
@Test
public void onPluginConnected_showPluginBigClock() {
- // GIVEN that the container for the big clock has visibility GONE
- mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // AND the plugin returns a view for the big clock
+ // GIVEN the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// THEN the big clock container is visible and it is the parent of the
// big clock view.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mBigClock.getParent()).isEqualTo(mBigClockContainer);
+ assertThat(mLargeClockView.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBigClock.getParent()).isEqualTo(mLargeClockFrame);
}
@Test
public void onPluginConnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- verify(mClockView, never()).setVisibility(GONE);
+ assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
}
@Test
@@ -150,7 +140,7 @@
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
- assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
+ assertThat(plugin2.getView().getParent()).isEqualTo(mClockFrame);
assertThat(plugin1.getView().getParent()).isNull();
}
@@ -170,33 +160,28 @@
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
- mClockView.setVisibility(GONE);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
+ assertThat(mClockView.getVisibility()).isEqualTo(GONE);
- verify(mClockView).setVisibility(VISIBLE);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
+ assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
+
assertThat(plugin.getView().getParent()).isNull();
}
@Test
public void onPluginDisconnected_hidePluginBigClock() {
- // GIVEN that the big clock container is visible
- FrameLayout bigClockContainer = new FrameLayout(getContext());
- bigClockContainer.setVisibility(VISIBLE);
- mKeyguardClockSwitch.setBigClockContainer(bigClockContainer, StatusBarState.KEYGUARD);
- // AND the plugin returns a view for the big clock
+ // GIVEN the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getBigClockView()).thenReturn(pluginView);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected and then disconnected
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the big lock container is GONE and the big clock view doesn't have
// a parent.
- assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
+ assertThat(mLargeClockView.getVisibility()).isEqualTo(VISIBLE);
assertThat(pluginView.getParent()).isNull();
}
@@ -205,7 +190,7 @@
ClockPlugin plugin = mock(ClockPlugin.class);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
- verify(mClockView, never()).setVisibility(GONE);
+ assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
}
@Test
@@ -220,7 +205,7 @@
// WHEN the second plugin is disconnected
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the default clock should be shown.
- verify(mClockView).setVisibility(VISIBLE);
+ assertThat(mClockView.getVisibility()).isEqualTo(VISIBLE);
assertThat(plugin1.getView().getParent()).isNull();
assertThat(plugin2.getView().getParent()).isNull();
}
@@ -238,13 +223,6 @@
}
@Test
- public void setTextColor_defaultClockSetTextColor() {
- mKeyguardClockSwitch.setTextColor(Color.YELLOW);
-
- verify(mClockView).setTextColor(Color.YELLOW);
- }
-
- @Test
public void setTextColor_pluginClockSetTextColor() {
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
@@ -256,16 +234,6 @@
verify(plugin).setTextColor(Color.WHITE);
}
- @Test
- public void setStyle_defaultClockSetStyle() {
- TextPaint paint = mock(TextPaint.class);
- Style style = mock(Style.class);
- doReturn(paint).when(mClockView).getPaint();
-
- mKeyguardClockSwitch.setStyle(style);
-
- verify(paint).setStyle(style);
- }
@Test
public void setStyle_pluginClockSetStyle() {
@@ -279,98 +247,4 @@
verify(plugin).setStyle(style);
}
-
- @Test
- public void onStateChanged_GoneInShade() {
- // GIVEN that the big clock container is visible
- mBigClockContainer.setVisibility(View.VISIBLE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // WHEN transitioned to SHADE state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.SHADE);
- // THEN the container is gone.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
- }
-
- @Test
- public void onStateChanged_VisibleInKeyguard() {
- // GIVEN that the big clock container is gone
- mBigClockContainer.setVisibility(View.GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // AND GIVEN that a plugin is active.
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // WHEN transitioned to KEYGUARD state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
- // THEN the container is visible.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void setBigClockContainer_visible() {
- // GIVEN that the big clock container is visible
- mBigClockContainer.setVisibility(View.VISIBLE);
- // AND GIVEN that a plugin is active.
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
- // WHEN the container is associated with the clock switch
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // THEN the container remains visible.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void setBigClockContainer_gone() {
- // GIVEN that the big clock container is gone
- mBigClockContainer.setVisibility(View.GONE);
- // AND GIVEN that a plugin is active.
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
- // WHEN the container is associated with the clock switch
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // THEN the container is made visible.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void setKeyguardHidingBigClock_gone() {
- // GIVEN that the container for the big clock has visibility GONE
- mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // AND the plugin returns a view for the big clock
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
- // WHEN the plugin is connected
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // WHEN the container set hiding clock as true
- mKeyguardClockSwitch.setKeyguardHidingBigClock(true);
- // THEN the container is gone.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
- }
-
- @Test
- public void setKeyguardHidingBigClock_visible() {
- // GIVEN that the container for the big clock has visibility GONE
- mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
- // AND the plugin returns a view for the big clock
- ClockPlugin plugin = mock(ClockPlugin.class);
- when(plugin.getBigClockView()).thenReturn(mBigClock);
- // AND in the keyguard state
- mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
- // WHEN the plugin is connected
- mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
- // WHEN the container set hiding clock as false
- mKeyguardClockSwitch.setKeyguardHidingBigClock(false);
- // THEN the container is made visible.
- assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 0074dbe..49f1655 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -23,7 +23,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -50,8 +49,6 @@
@Mock
ConfigurationController mConfigurationController;
@Mock
- NotificationIconAreaController mNotificationIconAreaController;
- @Mock
DozeParameters mDozeParameters;
private KeyguardStatusViewController mController;
@@ -67,7 +64,6 @@
mKeyguardStateController,
mKeyguardUpdateMonitor,
mConfigurationController,
- mNotificationIconAreaController,
mDozeParameters);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
index 7b4f14d..ad7f0cb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/TextAnimatorTest.kt
@@ -16,6 +16,7 @@
package com.android.keyguard
+import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.testing.AndroidTestingRunner
import android.text.Layout
@@ -25,7 +26,9 @@
import com.android.systemui.SysuiTestCase
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.eq
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -107,4 +110,34 @@
// Then, animation start should not be called.
verify(valueAnimator, never()).start()
}
+
+ @Test
+ fun testAnimationEnded() {
+ val layout = makeLayout("Hello, World", PAINT)
+ val valueAnimator = mock(ValueAnimator::class.java)
+ val textInterpolator = mock(TextInterpolator::class.java)
+ val paint = mock(TextPaint::class.java)
+ `when`(textInterpolator.targetPaint).thenReturn(paint)
+ val animationEndCallback = mock(Runnable::class.java)
+
+ val textAnimator = TextAnimator(layout, {}).apply {
+ this.textInterpolator = textInterpolator
+ this.animator = valueAnimator
+ }
+
+ textAnimator.setTextStyle(
+ weight = 400,
+ animate = true,
+ onAnimationEnd = animationEndCallback
+ )
+
+ // Verify animationEnd callback has been added.
+ val captor = ArgumentCaptor.forClass(AnimatorListenerAdapter::class.java)
+ verify(valueAnimator).addListener(captor.capture())
+ captor.value.onAnimationEnd(valueAnimator)
+
+ // Verify animationEnd callback has been invoked and removed.
+ verify(animationEndCallback).run()
+ verify(valueAnimator).removeListener(eq(captor.value))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
index 28b44d9..1baaf6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
@@ -234,6 +234,27 @@
}
@Test
+ fun testPhoneCallNotClickable() {
+ val element = PrivacyDialog.PrivacyElement(
+ PrivacyType.TYPE_MICROPHONE,
+ TEST_PACKAGE_NAME,
+ TEST_USER_ID,
+ "App",
+ null,
+ 0L,
+ false,
+ false,
+ true
+ )
+
+ val list = listOf(element)
+ dialog = PrivacyDialog(context, list, starter)
+ dialog.show()
+ assertThat(dialog.requireViewById<View>(R.id.privacy_item).isClickable).isFalse()
+ assertThat(dialog.requireViewById<View>(R.id.chevron).visibility).isEqualTo(View.GONE)
+ }
+
+ @Test
fun testAttribution() {
val element = PrivacyDialog.PrivacyElement(
PrivacyType.TYPE_MICROPHONE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index e4b95af..4ee639b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -102,7 +102,7 @@
mRootView = (ViewGroup) new LayoutInflaterBuilder(mContext)
.replace("ImageView", TestableImageView.class)
.build().inflate(R.layout.quick_settings_footer, null, false);
- mFooter = new QSSecurityFooter(mRootView, mContext, mUserTracker, new Handler(looper),
+ mFooter = new QSSecurityFooter(mRootView, mUserTracker, new Handler(looper),
mActivityStarter, mSecurityController, looper);
mFooterText = mRootView.findViewById(R.id.footer_text);
mFooterIcon = mRootView.findViewById(R.id.footer_icon);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 858227f..5f8eb9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -25,7 +25,6 @@
import androidx.test.filters.SmallTest;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -107,9 +106,7 @@
@Test
public void testAppearResetsTranslation() {
- mController.setupAodIcons(
- mAodIcons,
- KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL);
+ mController.setupAodIcons(mAodIcons);
when(mDozeParameters.shouldControlScreenOff()).thenReturn(false);
mController.appearAodIcons();
verify(mAodIcons).setTranslationY(0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 123e4ef..8633eb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -70,6 +70,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Map;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -245,13 +246,14 @@
mScrimController.transitionTo(ScrimState.KEYGUARD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false));
}
@Test
@@ -259,13 +261,15 @@
mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
- assertScrimTint(false /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -273,13 +277,15 @@
mScrimController.transitionTo(ScrimState.OFF);
finishAnimationsImmediately();
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, OPAQUE));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -287,13 +293,16 @@
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE,
+ mNotificationsScrim, TRANSPARENT));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -302,17 +311,17 @@
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
// Pulsing notification should conserve AOD wallpaper.
mScrimController.transitionTo(ScrimState.PULSING);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
}
@Test
@@ -322,13 +331,15 @@
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -339,13 +350,15 @@
mScrimController.setHasBackdrop(true);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -355,31 +368,31 @@
mScrimController.setAodFrontScrimAlpha(0.5f);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
// ... but that it does take effect once we enter the AOD state.
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, SEMI_TRANSPARENT,
+ mScrimBehind, OPAQUE));
// ... and that if we set it while we're in AOD, it does take immediate effect.
mScrimController.setAodFrontScrimAlpha(1f);
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, OPAQUE));
// ... and make sure we recall the previous front scrim alpha even if we transition away
// for a bit.
mScrimController.transitionTo(ScrimState.UNLOCKED);
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, OPAQUE));
// ... and alpha updates should be completely ignored if always_on is off.
// Passing it forward would mess up the wake-up transition.
@@ -402,17 +415,17 @@
mScrimController.setAodFrontScrimAlpha(0.5f);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
// ... and doesn't take effect when disabled always_on
mAlwaysOnEnabled = false;
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, OPAQUE));
// ... but will take effect after docked
when(mDockManager.isDocked()).thenReturn(true);
@@ -420,15 +433,15 @@
mScrimController.setAodFrontScrimAlpha(0.5f);
mScrimController.transitionTo(ScrimState.AOD);
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, SEMI_TRANSPARENT,
+ mScrimBehind, OPAQUE));
// ... and that if we set it while we're in AOD, it does take immediate effect after docked.
mScrimController.setAodFrontScrimAlpha(1f);
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, OPAQUE));
// Reset value since enums are static.
mScrimController.setAodFrontScrimAlpha(0f);
@@ -442,36 +455,38 @@
mScrimController.setWallpaperSupportsAmbientMode(false);
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
mScrimController.transitionTo(ScrimState.PULSING);
finishAnimationsImmediately();
// Front scrim should be transparent, but tinted
// Back scrim should be semi-transparent so the user can see the wallpaper
// Pulse callback should have been invoked
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
// ... and when ambient goes dark, front scrim should be semi-transparent
mScrimController.setAodFrontScrimAlpha(0.5f);
finishAnimationsImmediately();
// Front scrim should be semi-transparent
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, SEMI_TRANSPARENT,
+ mScrimBehind, OPAQUE));
mScrimController.setWakeLockScreenSensorActive(true);
finishAnimationsImmediately();
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, SEMI_TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
// Reset value since enums are static.
mScrimController.setAodFrontScrimAlpha(0f);
@@ -483,27 +498,29 @@
finishAnimationsImmediately();
// Front scrim should be transparent
// Back scrim should be visible without tint
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, false,
+ mScrimForBubble, false
+ ));
}
@Test
public void transitionToBouncer() {
mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
finishAnimationsImmediately();
- // Front scrim should be transparent
- // Back scrim should be visible without tint
- assertScrimAlpha(OPAQUE /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, OPAQUE,
+ mScrimBehind, TRANSPARENT));
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, false,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -511,19 +528,21 @@
mScrimController.setPanelExpansion(0f);
mScrimController.transitionTo(ScrimState.UNLOCKED);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
- assertScrimTint(false /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
// Back scrim should be visible after start dragging
mScrimController.setPanelExpansion(0.5f);
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, SEMI_TRANSPARENT));
}
@Test
@@ -531,9 +550,11 @@
mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
finishAnimationsImmediately();
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, false,
+ mScrimForBubble, false
+ ));
// Front scrim should be transparent
Assert.assertEquals(ScrimController.TRANSPARENT,
@@ -589,7 +610,10 @@
mScrimController.setQsPosition(1f, 999 /* value doesn't matter */);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT, OPAQUE, TRANSPARENT);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE,
+ mNotificationsScrim, OPAQUE));
}
@Test
@@ -623,21 +647,26 @@
mScrimController.transitionTo(ScrimState.UNLOCKED);
// Immediately tinted black after the transition starts
- assertScrimTint(true /* front */,
- true /* behind */,
- true /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, true
+ ));
finishAnimationsImmediately();
// All scrims should be transparent at the end of fade transition.
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, TRANSPARENT,
+ mScrimForBubble, TRANSPARENT));
// Make sure at the very end of the animation, we're reset to transparent
- assertScrimTint(false /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, false,
+ mScrimBehind, true,
+ mScrimForBubble, false
+ ));
}
@Test
@@ -652,9 +681,11 @@
// Front scrim should be black in the middle of the transition
Assert.assertTrue("Scrim should be visible during transition. Alpha: "
+ mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
- assertScrimTint(true /* front */,
- true /* behind */,
- true /* bubble */);
+ assertScrimTinted(Map.of(
+ mScrimInFront, true,
+ mScrimBehind, true,
+ mScrimForBubble, true
+ ));
Assert.assertSame("Scrim should be visible during transition.",
mScrimVisibility, OPAQUE);
}
@@ -843,15 +874,15 @@
mScrimController.setKeyguardOccluded(true);
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
mScrimController.transitionTo(ScrimState.PULSING);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
}
@Test
@@ -859,15 +890,15 @@
mScrimController.setWallpaperSupportsAmbientMode(true);
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, TRANSPARENT));
mScrimController.setKeyguardOccluded(true);
finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mScrimBehind, OPAQUE));
}
@Test
@@ -926,21 +957,67 @@
}
}
- private void assertScrimTint(boolean front, boolean behind, boolean bubble) {
- Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimInFront) + " and tint: "
- + Integer.toHexString(mScrimInFront.getTint()),
- front, mScrimInFront.getTint() != Color.TRANSPARENT);
+ @Test
+ public void testScrimsOpaque_whenShadeFullyExpanded() {
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ mScrimController.setPanelExpansion(1);
+ // notifications scrim alpha change require calling setQsPosition
+ mScrimController.setQsPosition(0, 300);
+ finishAnimationsImmediately();
- Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimBehind) + " and tint: "
- + Integer.toHexString(mScrimBehind.getTint()),
- behind, mScrimBehind.getTint() != Color.TRANSPARENT);
+ Assert.assertEquals("Behind scrim should be opaque",
+ mScrimBehind.getViewAlpha(), 1, 0.0);
+ Assert.assertEquals("Notifications scrim should be opaque",
+ mNotificationsScrim.getViewAlpha(), 1, 0.0);
+ }
- Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimForBubble) + " and tint: "
- + Integer.toHexString(mScrimForBubble.getTint()),
- bubble, mScrimForBubble.getTint() != Color.TRANSPARENT);
+ @Test
+ public void testScrimsVisible_whenShadeVisible() {
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+ mScrimController.setPanelExpansion(0.5f);
+ // notifications scrim alpha change require calling setQsPosition
+ mScrimController.setQsPosition(0, 300);
+
+ assertScrimAlpha(Map.of(
+ mScrimBehind, SEMI_TRANSPARENT,
+ mNotificationsScrim, SEMI_TRANSPARENT,
+ mScrimInFront, TRANSPARENT));
+ }
+
+ @Test
+ public void testScrimsVisible_whenShadeVisibleOnLockscreen() {
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.setQsPosition(0.5f, 300);
+
+ assertScrimAlpha(Map.of(
+ mScrimBehind, SEMI_TRANSPARENT,
+ mNotificationsScrim, SEMI_TRANSPARENT,
+ mScrimInFront, TRANSPARENT));
+ }
+
+ @Test
+ public void testNotificationScrimTransparent_whenOnLockscreen() {
+ mScrimController.transitionTo(ScrimState.KEYGUARD);
+ // even if shade is not pulled down, panel has expansion of 1 on the lockscreen
+ mScrimController.setPanelExpansion(1);
+ mScrimController.setQsPosition(0f, /*qs panel bottom*/ 0);
+
+ assertScrimAlpha(Map.of(
+ mScrimBehind, SEMI_TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT));
+ }
+
+ private void assertScrimTinted(Map<ScrimView, Boolean> scrimToTint) {
+ // notifications scrim should have always transparent tint
+ assertScrimTint(mNotificationsScrim, false);
+ scrimToTint.forEach((scrim, hasTint) -> assertScrimTint(scrim, hasTint));
+ }
+
+ private void assertScrimTint(ScrimView scrim, boolean hasTint) {
+ String message = "Tint test failed at state " + mScrimController.getState()
+ + " with scrim: " + getScrimName(scrim) + " and tint: "
+ + Integer.toHexString(scrim.getTint());
+ Assert.assertEquals(message, hasTint, scrim.getTint() != Color.TRANSPARENT);
}
private String getScrimName(ScrimView scrim) {
@@ -956,29 +1033,25 @@
return "unknown_scrim";
}
- private void assertScrimAlpha(int front, int behind, int bubble) {
+ /**
+ * If {@link #mScrimForBubble} or {@link #mNotificationsScrim} is not passed in the map
+ * we assume it must be transparent
+ */
+ private void assertScrimAlpha(Map<ScrimView, Integer> scrimToAlpha) {
// Check single scrim visibility.
- Assert.assertEquals("Unexpected front scrim alpha: "
- + mScrimInFront.getViewAlpha(),
- front != TRANSPARENT /* expected */,
- mScrimInFront.getViewAlpha() > TRANSPARENT /* actual */);
-
- Assert.assertEquals("Unexpected back scrim alpha: "
- + mScrimBehind.getViewAlpha(),
- behind != TRANSPARENT /* expected */,
- mScrimBehind.getViewAlpha() > TRANSPARENT /* actual */);
-
- Assert.assertEquals(
- "Unexpected bubble scrim alpha: "
- + mScrimForBubble.getViewAlpha(), /* message */
- bubble != TRANSPARENT /* expected */,
- mScrimForBubble.getViewAlpha() > TRANSPARENT /* actual */);
+ if (!scrimToAlpha.containsKey(mScrimForBubble)) {
+ assertScrimAlpha(mScrimForBubble, TRANSPARENT);
+ }
+ if (!scrimToAlpha.containsKey(mNotificationsScrim)) {
+ assertScrimAlpha(mNotificationsScrim, TRANSPARENT);
+ }
+ scrimToAlpha.forEach((scrimView, alpha) -> assertScrimAlpha(scrimView, alpha));
// Check combined scrim visibility.
final int visibility;
- if (front == OPAQUE || behind == OPAQUE || bubble == OPAQUE) {
+ if (scrimToAlpha.values().contains(OPAQUE)) {
visibility = OPAQUE;
- } else if (front > TRANSPARENT || behind > TRANSPARENT || bubble > TRANSPARENT) {
+ } else if (scrimToAlpha.values().contains(SEMI_TRANSPARENT)) {
visibility = SEMI_TRANSPARENT;
} else {
visibility = TRANSPARENT;
@@ -987,4 +1060,11 @@
visibility /* expected */,
mScrimVisibility);
}
+
+ private void assertScrimAlpha(ScrimView scrim, int expectedAlpha) {
+ Assert.assertEquals("Unexpected " + getScrimName(scrim) + " scrim alpha: "
+ + scrim.getViewAlpha(),
+ expectedAlpha != TRANSPARENT /* expected */,
+ scrim.getViewAlpha() > TRANSPARENT /* actual */);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 9b9937b..abc8da2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -101,6 +101,7 @@
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.google.common.collect.ImmutableList;
@@ -206,6 +207,8 @@
@Mock
private BubbleLogger mBubbleLogger;
@Mock
+ private TaskStackListenerImpl mTaskStackListener;
+ @Mock
private ShellTaskOrganizer mShellTaskOrganizer;
private TestableBubblePositioner mPositioner;
@@ -287,6 +290,7 @@
mWindowManagerShellWrapper,
mLauncherApps,
mBubbleLogger,
+ mTaskStackListener,
mShellTaskOrganizer,
mPositioner,
syncExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index b0ec628..1ba7f8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -94,6 +94,7 @@
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import org.junit.Before;
import org.junit.Ignore;
@@ -187,6 +188,8 @@
@Mock
private BubbleLogger mBubbleLogger;
@Mock
+ private TaskStackListenerImpl mTaskStackListener;
+ @Mock
private ShellTaskOrganizer mShellTaskOrganizer;
private TestableBubblePositioner mPositioner;
@@ -253,6 +256,7 @@
mWindowManagerShellWrapper,
mLauncherApps,
mBubbleLogger,
+ mTaskStackListener,
mShellTaskOrganizer,
mPositioner,
syncExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index a1adb2c..a9a558d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -31,6 +31,7 @@
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerImpl;
/**
* Testable BubbleController subclass that immediately synchronizes surfaces.
@@ -47,13 +48,15 @@
WindowManagerShellWrapper windowManagerShellWrapper,
LauncherApps launcherApps,
BubbleLogger bubbleLogger,
+ TaskStackListenerImpl taskStackListener,
ShellTaskOrganizer shellTaskOrganizer,
BubblePositioner positioner,
ShellExecutor shellMainExecutor,
Handler shellMainHandler) {
super(context, data, Runnable::run, floatingContentCoordinator, dataRepository,
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
- bubbleLogger, shellTaskOrganizer, positioner, shellMainExecutor, shellMainHandler);
+ bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, shellMainExecutor,
+ shellMainHandler);
setInflateSynchronously(true);
initialize();
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 09687d3..8246ca3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2279,7 +2279,9 @@
netId = nai.network.getNetId();
}
boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
- if (DBG) log("requestRouteToHostAddress ok=" + ok);
+ if (DBG) {
+ log("requestRouteToHostAddress " + addr + nai.toShortString() + " ok=" + ok);
+ }
return ok;
} finally {
Binder.restoreCallingIdentity(token);
@@ -4229,7 +4231,7 @@
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
nai.networkAgentConfig.acceptPartialConnectivity = accept;
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
@@ -4297,6 +4299,7 @@
}
if (!nai.avoidUnvalidated) {
nai.avoidUnvalidated = true;
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
}
@@ -4404,7 +4407,7 @@
private void updateAvoidBadWifi() {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
}
rematchAllNetworksAndRequests();
}
@@ -7170,6 +7173,7 @@
final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
updateUids(nai, prevNc, newNc);
+ nai.updateScoreForNetworkAgentUpdate();
if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/services/core/java/com/android/server/connectivity/FullScore.java
index a8a83fc..52da566 100644
--- a/services/core/java/com/android/server/connectivity/FullScore.java
+++ b/services/core/java/com/android/server/connectivity/FullScore.java
@@ -91,17 +91,26 @@
/** @hide */
public static final int POLICY_IS_INVINCIBLE = 58;
+ // This network has been validated at least once since it was connected, but not explicitly
+ // avoided in UI.
+ // TODO : remove setAvoidUnvalidated and instead disconnect the network when the user
+ // chooses to move away from this network, and remove this flag.
+ /** @hide */
+ public static final int POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD = 57;
+
// To help iterate when printing
@VisibleForTesting
- static final int MIN_CS_MANAGED_POLICY = POLICY_IS_INVINCIBLE;
+ static final int MIN_CS_MANAGED_POLICY = POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
@VisibleForTesting
static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;
// Mask for policies in NetworkScore. This should have all bits managed by NetworkScore set
// and all bits managed by FullScore unset. As bits are handled from 0 up in NetworkScore and
- // from 63 down in FullScore, cut at the 32rd bit for simplicity, but change this if some day
+ // from 63 down in FullScore, cut at the 32nd bit for simplicity, but change this if some day
// there are more than 32 bits handled on either side.
- private static final int EXTERNAL_POLICIES_MASK = 0x0000FFFF;
+ // YIELD_TO_BAD_WIFI is temporarily handled by ConnectivityService.
+ private static final long EXTERNAL_POLICIES_MASK =
+ 0x00000000FFFFFFFFL & ~(1L << POLICY_YIELD_TO_BAD_WIFI);
@VisibleForTesting
static @NonNull String policyNameOf(final int policy) {
@@ -115,6 +124,7 @@
case POLICY_TRANSPORT_PRIMARY: return "TRANSPORT_PRIMARY";
case POLICY_EXITING: return "EXITING";
case POLICY_IS_INVINCIBLE: return "INVINCIBLE";
+ case POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD: return "EVER_VALIDATED";
}
throw new IllegalArgumentException("Unknown policy : " + policy);
}
@@ -137,6 +147,7 @@
* @param score the score supplied by the agent
* @param caps the NetworkCapabilities of the network
* @param config the NetworkAgentConfig of the network
+ * @param everValidated whether this network has ever validated
* @param yieldToBadWiFi whether this network yields to a previously validated wifi gone bad
* @return a FullScore that is appropriate to use for ranking.
*/
@@ -145,12 +156,13 @@
// connectivity for backward compatibility.
public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
@NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config,
- final boolean yieldToBadWiFi) {
+ final boolean everValidated, final boolean yieldToBadWiFi) {
return withPolicies(score.getLegacyInt(), score.getPolicies(),
score.getKeepConnectedReason(),
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWiFi,
@@ -179,6 +191,8 @@
// Prospective scores are always unmetered, because unmetered networks are stronger
// than metered networks, and it's not known in advance whether the network is metered.
final boolean unmetered = true;
+ // If the offer may validate, then it should be considered to have validated at some point
+ final boolean everValidated = mayValidate;
// The network hasn't been chosen by the user (yet, at least).
final boolean everUserSelected = false;
// Don't assume the user will accept unvalidated connectivity.
@@ -189,8 +203,8 @@
// score.
final boolean invincible = score.getLegacyInt() > NetworkRanker.LEGACY_INT_MAX;
return withPolicies(score.getLegacyInt(), score.getPolicies(), KEEP_CONNECTED_NONE,
- mayValidate, vpn, unmetered, everUserSelected, acceptUnvalidated, yieldToBadWiFi,
- invincible);
+ mayValidate, vpn, unmetered, everValidated, everUserSelected, acceptUnvalidated,
+ yieldToBadWiFi, invincible);
}
/**
@@ -204,11 +218,14 @@
// telephony factory, so that it depends on the carrier. For now this is handled by
// connectivity for backward compatibility.
public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
- @NonNull final NetworkAgentConfig config, final boolean yieldToBadWifi) {
+ @NonNull final NetworkAgentConfig config,
+ final boolean everValidated,
+ final boolean yieldToBadWifi) {
return withPolicies(mLegacyInt, mPolicies, mKeepConnectedReason,
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWifi,
@@ -224,6 +241,7 @@
final boolean isValidated,
final boolean isVpn,
final boolean isUnmetered,
+ final boolean everValidated,
final boolean everUserSelected,
final boolean acceptUnvalidated,
final boolean yieldToBadWiFi,
@@ -232,6 +250,7 @@
| (isValidated ? 1L << POLICY_IS_VALIDATED : 0)
| (isVpn ? 1L << POLICY_IS_VPN : 0)
| (isUnmetered ? 1L << POLICY_IS_UNMETERED : 0)
+ | (everValidated ? 1L << POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD : 0)
| (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0)
| (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0)
| (yieldToBadWiFi ? 1L << POLICY_YIELD_TO_BAD_WIFI : 0)
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 5d793fd..4d310cb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -707,7 +707,8 @@
@NonNull final NetworkCapabilities nc) {
final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, everValidatedForYield(),
+ yieldToBadWiFi());
final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
nm.notifyNetworkCapabilitiesChanged(nc);
@@ -893,7 +894,7 @@
// Caller must not mutate. This method is called frequently and making a defensive copy
// would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared
// against other scoreables.
- @Override public NetworkCapabilities getCaps() {
+ @Override public NetworkCapabilities getCapsNoCopy() {
return networkCapabilities;
}
@@ -919,7 +920,7 @@
*/
public void setScore(final NetworkScore score) {
mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
- yieldToBadWiFi());
+ everValidatedForYield(), yieldToBadWiFi());
}
/**
@@ -927,8 +928,13 @@
*
* Call this after updating the network agent config.
*/
- public void updateScoreForNetworkAgentConfigUpdate() {
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ public void updateScoreForNetworkAgentUpdate() {
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig,
+ everValidatedForYield(), yieldToBadWiFi());
+ }
+
+ private boolean everValidatedForYield() {
+ return everValidated && !avoidUnvalidated;
}
/**
diff --git a/services/core/java/com/android/server/connectivity/NetworkOffer.java b/services/core/java/com/android/server/connectivity/NetworkOffer.java
index 5336593..2bad596 100644
--- a/services/core/java/com/android/server/connectivity/NetworkOffer.java
+++ b/services/core/java/com/android/server/connectivity/NetworkOffer.java
@@ -76,7 +76,7 @@
/**
* Get the capabilities filter of this offer
*/
- @Override @NonNull public NetworkCapabilities getCaps() {
+ @Override @NonNull public NetworkCapabilities getCapsNoCopy() {
return caps;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java
index 3aaff59..c123ea7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkRanker.java
+++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java
@@ -26,6 +26,7 @@
import static com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED;
+import static com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
import static com.android.server.connectivity.FullScore.POLICY_IS_INVINCIBLE;
import static com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_IS_VPN;
@@ -58,7 +59,7 @@
/** Get score of this scoreable */
FullScore getScore();
/** Get capabilities of this scoreable */
- NetworkCapabilities getCaps();
+ NetworkCapabilities getCapsNoCopy();
}
private static final boolean USE_POLICY_RANKING = false;
@@ -158,11 +159,12 @@
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
- // Yield to bad wifi policy : if any wifi has ever been validated, keep only networks
- // that don't yield to such a wifi network.
+ // Yield to bad wifi policy : if any wifi has ever been validated (even if it's now
+ // unvalidated), and unless it's been explicitly avoided when bad in UI, then keep only
+ // networks that don't yield to such a wifi network.
final boolean anyWiFiEverValidated = CollectionUtils.any(candidates,
- nai -> nai.getScore().hasPolicy(POLICY_EVER_USER_SELECTED)
- && nai.getCaps().hasTransport(TRANSPORT_WIFI));
+ nai -> nai.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD)
+ && nai.getCapsNoCopy().hasTransport(TRANSPORT_WIFI));
if (anyWiFiEverValidated) {
partitionInto(candidates, nai -> !nai.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI),
accepted, rejected);
@@ -206,18 +208,18 @@
for (final Scoreable defaultSubNai : accepted) {
// Remove all networks without the DEFAULT_SUBSCRIPTION policy and the same transports
// as a network that has it.
- final int[] transports = defaultSubNai.getCaps().getTransportTypes();
+ final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes();
candidates.removeIf(nai -> !nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY)
- && Arrays.equals(transports, nai.getCaps().getTransportTypes()));
+ && Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes()));
}
if (1 == candidates.size()) return candidates.get(0);
- // It's guaranteed candidates.size() > 0 because there is at least one with DEFAULT_SUB
- // policy and only those without it were removed.
+ // It's guaranteed candidates.size() > 0 because there is at least one with the
+ // TRANSPORT_PRIMARY policy and only those without it were removed.
// If some of the networks have a better transport than others, keep only the ones with
// the best transports.
for (final int transport : PREFERRED_TRANSPORTS_ORDER) {
- partitionInto(candidates, nai -> nai.getCaps().hasTransport(transport),
+ partitionInto(candidates, nai -> nai.getCapsNoCopy().hasTransport(transport),
accepted, rejected);
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index cb8541e..5cd0534 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -140,6 +140,7 @@
private static final int RAMP_STATE_SKIP_INITIAL = 1;
private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
+ private static final int REPORTED_TO_POLICY_UNREPORTED = -1;
private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -311,8 +312,8 @@
private long mScreenOnBlockStartRealTime;
private long mScreenOffBlockStartRealTime;
- // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
- private int mReportedScreenStateToPolicy;
+ // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_* fields.
+ private int mReportedScreenStateToPolicy = REPORTED_TO_POLICY_UNREPORTED;
// If the last recorded screen state was dozing or not.
private boolean mDozing;
@@ -1440,12 +1441,14 @@
private boolean setScreenState(int state, boolean reportOnly) {
final boolean isOff = (state == Display.STATE_OFF);
- if (mPowerState.getScreenState() != state) {
+ if (mPowerState.getScreenState() != state
+ || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
// If we are trying to turn screen off, give policy a chance to do something before we
// actually turn the screen off.
if (isOff && !mScreenOffBecauseOfProximity) {
- if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
+ if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON
+ || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
blockScreenOff();
mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
@@ -1456,7 +1459,7 @@
}
}
- if (!reportOnly) {
+ if (!reportOnly && mPowerState.getScreenState() != state) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -1486,7 +1489,9 @@
mWindowManagerPolicy.screenTurnedOff(mDisplayId);
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
}
- if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
+ if (!isOff
+ && (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
+ || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn();
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 27e0ffc..91a66ac 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -978,7 +978,6 @@
// Flag for bubble to make behaviour match documentLaunchMode=always.
intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
- intents[0].putExtra(Intent.EXTRA_IS_BUBBLED, true);
}
intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c7789ee..45e6cdc 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -405,6 +405,7 @@
private boolean mEnableCarDockHomeCapture = true;
boolean mBootMessageNeedsHiding;
+ volatile boolean mBootAnimationDismissable;
private KeyguardServiceDelegate mKeyguardDelegate;
private boolean mKeyguardBound;
final Runnable mWindowManagerDrawCallback = new Runnable() {
@@ -4305,6 +4306,7 @@
0 /* cookie */);
updateScreenOffSleepToken(false);
mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
+ mBootAnimationDismissable = false;
synchronized (mLock) {
if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
@@ -4379,6 +4381,10 @@
}
Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */);
+ enableScreen(listener, true /* report */);
+ }
+
+ private void enableScreen(ScreenOnListener listener, boolean report) {
final boolean enableScreen;
final boolean awake = mDefaultDisplayPolicy.isAwake();
synchronized (mLock) {
@@ -4396,17 +4402,19 @@
}
}
- if (listener != null) {
- listener.onScreenOn();
- }
-
- for (int i = mScreenOnListeners.size() - 1; i >= 0; i--) {
- final ScreenOnListener screenOnListener = mScreenOnListeners.valueAt(i);
- if (screenOnListener != null) {
- screenOnListener.onScreenOn();
+ if (report) {
+ if (listener != null) {
+ listener.onScreenOn();
}
+
+ for (int i = mScreenOnListeners.size() - 1; i >= 0; i--) {
+ final ScreenOnListener screenOnListener = mScreenOnListeners.valueAt(i);
+ if (screenOnListener != null) {
+ screenOnListener.onScreenOn();
+ }
+ }
+ mScreenOnListeners.clear();
}
- mScreenOnListeners.clear();
if (enableScreen) {
try {
@@ -4614,13 +4622,28 @@
}
startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
- screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
- screenTurnedOn(DEFAULT_DISPLAY);
+
+ int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
+ boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
+ boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
+ if (defaultDisplayOn || defaultScreenTurningOn) {
+ // Now that system is booted, wait for keyguard and windows to be drawn before
+ // updating the orientation listener, stopping the boot animation and enabling screen.
+ screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
+ screenTurnedOn(DEFAULT_DISPLAY);
+ } else {
+ // We're not turning the screen on, so don't wait for keyguard to be drawn
+ // to dismiss the boot animation and finish booting
+ mBootAnimationDismissable = true;
+ enableScreen(null, false /* report */);
+ }
}
@Override
public boolean canDismissBootAnimation() {
- return mDefaultDisplayPolicy.isKeyguardDrawComplete();
+ // Allow to dismiss the boot animation if the keyguard has finished drawing,
+ // or mBootAnimationDismissable has been set
+ return mDefaultDisplayPolicy.isKeyguardDrawComplete() || mBootAnimationDismissable;
}
ProgressDialog mBootMsgDialog = null;
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index df85e26..b4a95c4 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -255,9 +255,6 @@
@Nullable
private SingleVibratorStep nextVibrateStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int segmentIndex, long vibratorOffTimeout) {
- // Some steps should only start after the vibrator has finished the previous vibration, so
- // make sure we take the latest between both timings.
- long latestStartTime = Math.max(startTime, vibratorOffTimeout);
if (segmentIndex >= effect.getSegments().size()) {
segmentIndex = effect.getRepeatIndex();
}
@@ -272,15 +269,14 @@
VibrationEffectSegment segment = effect.getSegments().get(segmentIndex);
if (segment instanceof PrebakedSegment) {
- return new PerformStep(latestStartTime, controller, effect, segmentIndex,
- vibratorOffTimeout);
+ return new PerformStep(startTime, controller, effect, segmentIndex, vibratorOffTimeout);
}
if (segment instanceof PrimitiveSegment) {
- return new ComposePrimitivesStep(latestStartTime, controller, effect, segmentIndex,
+ return new ComposePrimitivesStep(startTime, controller, effect, segmentIndex,
vibratorOffTimeout);
}
if (segment instanceof RampSegment) {
- return new ComposePwleStep(latestStartTime, controller, effect, segmentIndex,
+ return new ComposePwleStep(startTime, controller, effect, segmentIndex,
vibratorOffTimeout);
}
return new AmplitudeStep(startTime, controller, effect, segmentIndex, vibratorOffTimeout);
@@ -572,7 +568,7 @@
private long startVibrating(SingleVibratorStep step, List<Step> nextSteps) {
nextSteps.addAll(step.play());
- long stepDuration = step.getOnResult();
+ long stepDuration = step.getVibratorOnDuration();
if (stepDuration < 0) {
// Step failed, so return negative duration to propagate failure.
return stepDuration;
@@ -649,14 +645,13 @@
}
/**
- * Return the result a call to {@link VibratorController#on} method triggered by
- * {@link #play()}.
+ * Return the duration the vibrator was turned on when this step was played.
*
* @return A positive duration that the vibrator was turned on for by this step;
- * Zero if the segment is not supported or vibrator was never turned on;
- * A negative value if the vibrator call has failed.
+ * Zero if the segment is not supported, the step was not played yet or vibrator was never
+ * turned on by this step; A negative value if the vibrator call has failed.
*/
- public long getOnResult() {
+ public long getVibratorOnDuration() {
return mVibratorOnResult;
}
@@ -690,7 +685,7 @@
/**
* Return the {@link #nextVibrateStep} with same start and off timings calculated from
- * {@link #getOnResult()}, jumping all played segments.
+ * {@link #getVibratorOnDuration()}, jumping all played segments.
*
* <p>This method has same behavior as {@link #skipToNextSteps(int)} when the vibrator
* result is non-positive, meaning the vibrator has either ignored or failed to turn on.
@@ -730,7 +725,10 @@
PerformStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int index, long vibratorOffTimeout) {
- super(startTime, controller, effect, index, vibratorOffTimeout);
+ // This step should wait for the last vibration to finish (with the timeout) and for the
+ // intended step start time (to respect the effect delays).
+ super(Math.max(startTime, vibratorOffTimeout), controller, effect, index,
+ vibratorOffTimeout);
}
@Override
@@ -765,7 +763,7 @@
List<Step> fallbackResult = fallbackStep.play();
// Update the result with the fallback result so this step is seamlessly
// replaced by the fallback to any outer application of this.
- mVibratorOnResult = fallbackStep.getOnResult();
+ mVibratorOnResult = fallbackStep.getVibratorOnDuration();
return fallbackResult;
}
@@ -802,7 +800,10 @@
ComposePrimitivesStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int index, long vibratorOffTimeout) {
- super(startTime, controller, effect, index, vibratorOffTimeout);
+ // This step should wait for the last vibration to finish (with the timeout) and for the
+ // intended step start time (to respect the effect delays).
+ super(Math.max(startTime, vibratorOffTimeout), controller, effect, index,
+ vibratorOffTimeout);
}
@Override
@@ -851,7 +852,10 @@
ComposePwleStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int index, long vibratorOffTimeout) {
- super(startTime, controller, effect, index, vibratorOffTimeout);
+ // This step should wait for the last vibration to finish (with the timeout) and for the
+ // intended step start time (to respect the effect delays).
+ super(Math.max(startTime, vibratorOffTimeout), controller, effect, index,
+ vibratorOffTimeout);
}
@Override
@@ -924,6 +928,7 @@
AmplitudeStep(long startTime, VibratorController controller,
VibrationEffect.Composed effect, int index, long vibratorOffTimeout) {
+ // This step has a fixed startTime coming from the timings of the waveform it's playing.
super(startTime, controller, effect, index, vibratorOffTimeout);
mNextOffTime = vibratorOffTimeout;
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index b1d6050..6bd7198 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -603,11 +603,20 @@
// Repeating vibrations always take precedence.
return null;
}
- if (mCurrentVibration != null && mCurrentVibration.getVibration().isRepeating()) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring incoming vibration in favor of previous alarm vibration");
+ if (mCurrentVibration != null) {
+ if (mCurrentVibration.getVibration().attrs.getUsage()
+ == VibrationAttributes.USAGE_ALARM) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration");
+ }
+ return Vibration.Status.IGNORED_FOR_ALARM;
}
- return Vibration.Status.IGNORED_FOR_ALARM;
+ if (mCurrentVibration.getVibration().isRepeating()) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring incoming vibration in favor of repeating vibration");
+ }
+ return Vibration.Status.IGNORED_FOR_ONGOING;
+ }
}
return null;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 631d866..e0724fd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -561,6 +561,9 @@
// The locusId associated with this activity, if set.
private LocusId mLocusId;
+ // Whether the activity was launched from a bubble.
+ private boolean mLaunchedFromBubble;
+
private SizeConfigurationBuckets mSizeConfigurations;
/**
@@ -4218,7 +4221,12 @@
}
}
+ boolean getLaunchedFromBubble() {
+ return mLaunchedFromBubble;
+ }
+
private void setOptions(@NonNull ActivityOptions options) {
+ mLaunchedFromBubble = options.getLaunchedFromBubble();
mPendingOptions = options;
if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) {
mPendingRemoteAnimation = options.getRemoteAnimationAdapter();
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index aa1f42e..75a188e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2633,6 +2633,12 @@
mOptions = null;
}
}
+
+ if (mPreferredWindowingMode != WINDOWING_MODE_UNDEFINED
+ && intentTask.getWindowingMode() != mPreferredWindowingMode) {
+ intentTask.setWindowingMode(mPreferredWindowingMode);
+ }
+
// Need to update mTargetRootTask because if task was moved out of it, the original root
// task may be destroyed.
mTargetRootTask = intentActivity.getRootTask();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index bfbc10a..bdde369 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -826,7 +826,8 @@
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
r.takeOptions(), dc.isNextTransitionForward(),
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
- r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken));
+ r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
+ r.getLaunchedFromBubble()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 0732314..7daebff 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -84,6 +84,7 @@
private TriConsumer<DisplayFrames, WindowState, Rect> mImeFrameProvider;
private final Rect mImeOverrideFrame = new Rect();
private boolean mIsLeashReadyForDispatching;
+ private final Rect mLastSourceFrame = new Rect();
private final Consumer<Transaction> mSetLeashPositionConsumer = t -> {
if (mControl != null) {
@@ -268,11 +269,14 @@
mSetLeashPositionConsumer.accept(mWin.getPendingTransaction());
}
}
- final Insets insetsHint = mSource.calculateInsets(
- mWin.getBounds(), true /* ignoreVisibility */);
- if (!insetsHint.equals(mControl.getInsetsHint())) {
- changed = true;
- mControl.setInsetsHint(insetsHint);
+ if (mServerVisible && !mLastSourceFrame.equals(mSource.getFrame())) {
+ final Insets insetsHint = mSource.calculateInsets(
+ mWin.getBounds(), true /* ignoreVisibility */);
+ if (!insetsHint.equals(mControl.getInsetsHint())) {
+ changed = true;
+ mControl.setInsetsHint(insetsHint);
+ }
+ mLastSourceFrame.set(mSource.getFrame());
}
if (changed) {
mStateController.notifyControlChanged(mControlTarget);
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 6567195..c9d5fa4 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.STATUS_BAR_SERVICE;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -278,6 +279,19 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
+
+ // If launched from bubble is specified, then ensure that the caller is system or sysui.
+ if (options.getLaunchedFromBubble() && callingUid != Process.SYSTEM_UID) {
+ final int statusBarPerm = ActivityTaskManagerService.checkPermission(
+ STATUS_BAR_SERVICE, callingPid, callingUid);
+ if (statusBarPerm == PERMISSION_DENIED) {
+ final String msg = "Permission Denial: starting " + getIntentString(intent)
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with launchedFromBubble=true";
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
}
private String getIntentString(Intent intent) {
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index cf64a68..b7fa796 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -199,7 +199,7 @@
ALOGE("vibratorIsAvailable failed because native wrapper was not initialized");
return JNI_FALSE;
}
- auto pingFn = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->ping(); };
+ auto pingFn = [](vibrator::HalWrapper* hal) { return hal->ping(); };
return wrapper->halCall<void>(pingFn, "ping").isOk() ? JNI_TRUE : JNI_FALSE;
}
@@ -211,7 +211,7 @@
return -1;
}
auto callback = wrapper->createCallback(vibrationId);
- auto onFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
return hal->on(std::chrono::milliseconds(timeoutMs), callback);
};
auto result = wrapper->halCall<void>(onFn, "on");
@@ -224,7 +224,7 @@
ALOGE("vibratorOff failed because native wrapper was not initialized");
return;
}
- auto offFn = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->off(); };
+ auto offFn = [](vibrator::HalWrapper* hal) { return hal->off(); };
wrapper->halCall<void>(offFn, "off");
}
@@ -234,7 +234,7 @@
ALOGE("vibratorSetAmplitude failed because native wrapper was not initialized");
return;
}
- auto setAmplitudeFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto setAmplitudeFn = [amplitude](vibrator::HalWrapper* hal) {
return hal->setAmplitude(static_cast<float>(amplitude));
};
wrapper->halCall<void>(setAmplitudeFn, "setAmplitude");
@@ -247,7 +247,7 @@
ALOGE("vibratorSetExternalControl failed because native wrapper was not initialized");
return;
}
- auto setExternalControlFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto setExternalControlFn = [enabled](vibrator::HalWrapper* hal) {
return hal->setExternalControl(enabled);
};
wrapper->halCall<void>(setExternalControlFn, "setExternalControl");
@@ -263,7 +263,7 @@
aidl::Effect effectType = static_cast<aidl::Effect>(effect);
aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength);
auto callback = wrapper->createCallback(vibrationId);
- auto performEffectFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto performEffectFn = [effectType, effectStrength, &callback](vibrator::HalWrapper* hal) {
return hal->performEffect(effectType, effectStrength, callback);
};
auto result = wrapper->halCall<std::chrono::milliseconds>(performEffectFn, "performEffect");
@@ -284,7 +284,7 @@
effects.push_back(effectFromJavaPrimitive(env, element));
}
auto callback = wrapper->createCallback(vibrationId);
- auto performComposedEffectFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto performComposedEffectFn = [&effects, &callback](vibrator::HalWrapper* hal) {
return hal->performComposedEffect(effects, callback);
};
auto result = wrapper->halCall<std::chrono::milliseconds>(performComposedEffectFn,
@@ -319,7 +319,7 @@
}
auto callback = wrapper->createCallback(vibrationId);
- auto performPwleEffectFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto performPwleEffectFn = [&primitives, &callback](vibrator::HalWrapper* hal) {
return hal->performPwleEffect(primitives, callback);
};
auto result = wrapper->halCall<void>(performPwleEffectFn, "performPwleEffect");
@@ -333,7 +333,7 @@
ALOGE("vibratorAlwaysOnEnable failed because native wrapper was not initialized");
return;
}
- auto alwaysOnEnableFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto alwaysOnEnableFn = [id, effect, strength](vibrator::HalWrapper* hal) {
return hal->alwaysOnEnable(static_cast<int32_t>(id), static_cast<aidl::Effect>(effect),
static_cast<aidl::EffectStrength>(strength));
};
@@ -346,7 +346,7 @@
ALOGE("vibratorAlwaysOnDisable failed because native wrapper was not initialized");
return;
}
- auto alwaysOnDisableFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) {
+ auto alwaysOnDisableFn = [id](vibrator::HalWrapper* hal) {
return hal->alwaysOnDisable(static_cast<int32_t>(id));
};
wrapper->halCall<void>(alwaysOnDisableFn, "alwaysOnDisable");
@@ -446,11 +446,11 @@
sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I");
jclass frequencyMappingClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyMapping");
- sFrequencyMappingClass = (jclass)env->NewGlobalRef(frequencyMappingClass);
+ sFrequencyMappingClass = static_cast<jclass>(env->NewGlobalRef(frequencyMappingClass));
sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "<init>", "(FFFF[F)V");
jclass vibratorInfoClass = FindClassOrDie(env, "android/os/VibratorInfo");
- sVibratorInfoClass = (jclass)env->NewGlobalRef(vibratorInfoClass);
+ sVibratorInfoClass = static_cast<jclass>(env->NewGlobalRef(vibratorInfoClass));
sVibratorInfoCtor = GetMethodIDOrDie(env, sVibratorInfoClass, "<init>",
"(IJ[I[I[IFLandroid/os/VibratorInfo$FrequencyMapping;)V");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index fb0265e..ff7514a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -144,13 +144,13 @@
private static final String TAG_ENROLLMENT_SPECIFIC_ID = "enrollment-specific-id";
private static final String TAG_ADMIN_CAN_GRANT_SENSORS_PERMISSIONS =
"admin-can-grant-sensors-permissions";
- private static final String TAG_ENTERPRISE_NETWORK_PREFERENCE_ENABLED =
- "enterprise-network-preference-enabled";
+ private static final String TAG_PREFERENTIAL_NETWORK_SERVICE_ENABLED =
+ "preferential-network-service-enabled";
private static final String TAG_USB_DATA_SIGNALING = "usb-data-signaling";
private static final String ATTR_VALUE = "value";
private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
- private static final boolean ENTERPRISE_NETWORK_PREFERENCE_ENABLED_DEFAULT = true;
+ private static final boolean PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT = true;
DeviceAdminInfo info;
@@ -296,8 +296,8 @@
public String mOrganizationId;
public String mEnrollmentSpecificId;
public boolean mAdminCanGrantSensorsPermissions;
- public boolean mEnterpriseNetworkPreferenceEnabled =
- ENTERPRISE_NETWORK_PREFERENCE_ENABLED_DEFAULT;
+ public boolean mPreferentialNetworkServiceEnabled =
+ PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT;
private static final boolean USB_DATA_SIGNALING_ENABLED_DEFAULT = true;
boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT;
@@ -576,9 +576,9 @@
}
writeAttributeValueToXml(out, TAG_ADMIN_CAN_GRANT_SENSORS_PERMISSIONS,
mAdminCanGrantSensorsPermissions);
- if (mEnterpriseNetworkPreferenceEnabled != ENTERPRISE_NETWORK_PREFERENCE_ENABLED_DEFAULT) {
- writeAttributeValueToXml(out, TAG_ENTERPRISE_NETWORK_PREFERENCE_ENABLED,
- mEnterpriseNetworkPreferenceEnabled);
+ if (mPreferentialNetworkServiceEnabled != PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT) {
+ writeAttributeValueToXml(out, TAG_PREFERENTIAL_NETWORK_SERVICE_ENABLED,
+ mPreferentialNetworkServiceEnabled);
}
if (mUsbDataSignalingEnabled != USB_DATA_SIGNALING_ENABLED_DEFAULT) {
writeAttributeValueToXml(out, TAG_USB_DATA_SIGNALING, mUsbDataSignalingEnabled);
@@ -806,9 +806,9 @@
mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
} else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
mAlwaysOnVpnLockdown = parser.getAttributeBoolean(null, ATTR_VALUE, false);
- } else if (TAG_ENTERPRISE_NETWORK_PREFERENCE_ENABLED.equals(tag)) {
- mEnterpriseNetworkPreferenceEnabled = parser.getAttributeBoolean(
- null, ATTR_VALUE, ENTERPRISE_NETWORK_PREFERENCE_ENABLED_DEFAULT);
+ } else if (TAG_PREFERENTIAL_NETWORK_SERVICE_ENABLED.equals(tag)) {
+ mPreferentialNetworkServiceEnabled = parser.getAttributeBoolean(
+ null, ATTR_VALUE, PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT);
} else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
} else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
@@ -1168,8 +1168,8 @@
pw.print("mAlwaysOnVpnLockdown=");
pw.println(mAlwaysOnVpnLockdown);
- pw.print("mEnterpriseNetworkPreferenceEnabled=");
- pw.println(mEnterpriseNetworkPreferenceEnabled);
+ pw.print("mPreferentialNetworkServiceEnabled=");
+ pw.println(mPreferentialNetworkServiceEnabled);
pw.print("mCommonCriteriaMode=");
pw.println(mCommonCriteriaMode);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 20a88af..66e640d6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3123,13 +3123,13 @@
updatePermissionPolicyCache(userId);
updateAdminCanGrantSensorsPermissionCache(userId);
- boolean enableEnterpriseNetworkPreferenceEnabled = true;
+ boolean preferentialNetworkServiceEnabled = true;
synchronized (getLockObject()) {
ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
- enableEnterpriseNetworkPreferenceEnabled = owner != null
- ? owner.mEnterpriseNetworkPreferenceEnabled : true;
+ preferentialNetworkServiceEnabled = owner != null
+ ? owner.mPreferentialNetworkServiceEnabled : true;
}
- updateNetworkPreferenceForUser(userId, enableEnterpriseNetworkPreferenceEnabled);
+ updateNetworkPreferenceForUser(userId, preferentialNetworkServiceEnabled);
startOwnerService(userId, "start-user");
}
@@ -11616,32 +11616,32 @@
}
@Override
- public void setEnterpriseNetworkPreferenceEnabled(boolean enabled) {
+ public void setPreferentialNetworkServiceEnabled(boolean enabled) {
if (!mHasFeature) {
return;
}
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(isProfileOwner(caller),
"Caller is not profile owner;"
- + " only profile owner may control the enterprise network preference");
+ + " only profile owner may control the preferntial network service");
synchronized (getLockObject()) {
final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(
caller.getUserId());
if (requiredAdmin != null
- && requiredAdmin.mEnterpriseNetworkPreferenceEnabled != enabled) {
- requiredAdmin.mEnterpriseNetworkPreferenceEnabled = enabled;
+ && requiredAdmin.mPreferentialNetworkServiceEnabled != enabled) {
+ requiredAdmin.mPreferentialNetworkServiceEnabled = enabled;
saveSettingsLocked(caller.getUserId());
}
}
updateNetworkPreferenceForUser(caller.getUserId(), enabled);
DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.SET_ENTERPRISE_NETWORK_PREFERENCE_ENABLED)
+ .createEvent(DevicePolicyEnums.SET_PREFERENTIAL_NETWORK_SERVICE_ENABLED)
.setBoolean(enabled)
.write();
}
@Override
- public boolean isEnterpriseNetworkPreferenceEnabled(int userHandle) {
+ public boolean isPreferentialNetworkServiceEnabled(int userHandle) {
if (!mHasFeature) {
return false;
}
@@ -11652,7 +11652,7 @@
synchronized (getLockObject()) {
final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(userHandle);
if (requiredAdmin != null) {
- return requiredAdmin.mEnterpriseNetworkPreferenceEnabled;
+ return requiredAdmin.mPreferentialNetworkServiceEnabled;
} else {
return false;
}
@@ -17227,11 +17227,11 @@
}
private void updateNetworkPreferenceForUser(int userId,
- boolean enableEnterpriseNetworkPreferenceEnabled) {
+ boolean preferentialNetworkServiceEnabled) {
if (!isManagedProfile(userId)) {
return;
}
- int networkPreference = enableEnterpriseNetworkPreferenceEnabled
+ int networkPreference = preferentialNetworkServiceEnabled
? PROFILE_NETWORK_PREFERENCE_ENTERPRISE : PROFILE_NETWORK_PREFERENCE_DEFAULT;
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.getConnectivityManager().setProfileNetworkPreference(
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 486d2b3..78e2dee 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4032,20 +4032,20 @@
}
@Test
- public void testGetSetEnterpriseNetworkPreference() throws Exception {
+ public void testGetSetPreferentialNetworkService() throws Exception {
assertExpectException(SecurityException.class, null,
- () -> dpm.setEnterpriseNetworkPreferenceEnabled(false));
+ () -> dpm.setPreferentialNetworkServiceEnabled(false));
assertExpectException(SecurityException.class, null,
- () -> dpm.isEnterpriseNetworkPreferenceEnabled());
+ () -> dpm.isPreferentialNetworkServiceEnabled());
final int managedProfileUserId = 15;
final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
addManagedProfile(admin1, managedProfileAdminUid, admin1);
mContext.binder.callingUid = managedProfileAdminUid;
- dpm.setEnterpriseNetworkPreferenceEnabled(false);
- assertThat(dpm.isEnterpriseNetworkPreferenceEnabled()).isFalse();
+ dpm.setPreferentialNetworkServiceEnabled(false);
+ assertThat(dpm.isPreferentialNetworkServiceEnabled()).isFalse();
verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
eq(UserHandle.of(managedProfileUserId)),
eq(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT),
@@ -4053,8 +4053,8 @@
any()
);
- dpm.setEnterpriseNetworkPreferenceEnabled(true);
- assertThat(dpm.isEnterpriseNetworkPreferenceEnabled()).isTrue();
+ dpm.setPreferentialNetworkServiceEnabled(true);
+ assertThat(dpm.isPreferentialNetworkServiceEnabled()).isTrue();
verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
eq(UserHandle.of(managedProfileUserId)),
eq(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE),
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 12ced38..b0e8ef0b 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -566,6 +566,54 @@
}
@Test
+ public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect, new VibrationAttributes.Builder().setUsage(
+ VibrationAttributes.USAGE_UNKNOWN).build());
+
+ // VibrationThread will start this vibration async, so wait before checking it started.
+ assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(),
+ service, TEST_TIMEOUT_MILLIS));
+
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ new VibrationAttributes.Builder().setUsage(
+ VibrationAttributes.USAGE_TOUCH).build());
+
+ // Wait before checking it never played a second effect.
+ assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1,
+ service, /* timeout= */ 50));
+ }
+
+ @Test
+ public void vibrate_withOngoingAlarmVibration_ignoresEffect() throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect alarmEffect = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, -1);
+ vibrate(service, alarmEffect, new VibrationAttributes.Builder().setUsage(
+ VibrationAttributes.USAGE_ALARM).build());
+
+ // VibrationThread will start this vibration async, so wait before checking it started.
+ assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getEffectSegments().isEmpty(),
+ service, TEST_TIMEOUT_MILLIS));
+
+ vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ new VibrationAttributes.Builder().setUsage(
+ VibrationAttributes.USAGE_TOUCH).build());
+
+ // Wait before checking it never played a second effect.
+ assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1,
+ service, /* timeout= */ 50));
+ }
+
+ @Test
public void vibrate_withInputDevices_vibratesInputDevices() throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
@@ -761,22 +809,22 @@
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
VibratorManagerService service = createSystemReadyService();
- vibrate(service, CombinedVibrationEffect.startSynced()
- .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
- .combine(), ALARM_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
- service, TEST_TIMEOUT_MILLIS));
-
vibrate(service, CombinedVibrationEffect.startSequential()
.addNext(1, VibrationEffect.createOneShot(20, 100))
.combine(), NOTIFICATION_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
+ assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
service, TEST_TIMEOUT_MILLIS));
vibrate(service, VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.compose(), HAPTIC_FEEDBACK_ATTRS);
+ assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3,
+ service, TEST_TIMEOUT_MILLIS));
+
+ vibrate(service, CombinedVibrationEffect.startSynced()
+ .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .combine(), ALARM_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 4,
service, TEST_TIMEOUT_MILLIS));
@@ -785,17 +833,17 @@
assertEquals(4, fakeVibrator.getEffectSegments().size());
assertEquals(1, fakeVibrator.getAmplitudes().size());
- // Alarm vibration is always VIBRATION_INTENSITY_HIGH.
- PrebakedSegment expected = new PrebakedSegment(
- VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
- assertEquals(expected, fakeVibrator.getEffectSegments().get(0));
-
// Notification vibrations will be scaled with SCALE_VERY_HIGH.
assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0));
// Haptic feedback vibrations will be scaled with SCALE_LOW.
- assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale());
- assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(3)).getScale());
+ assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale());
+ assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale());
+
+ // Alarm vibration is always VIBRATION_INTENSITY_HIGH.
+ PrebakedSegment expected = new PrebakedSegment(
+ VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
+ assertEquals(expected, fakeVibrator.getEffectSegments().get(3));
// Ring vibrations have intensity OFF and are not played.
}
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
index 1e54093..db939f9 100644
--- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -63,8 +63,8 @@
setPartialConnectivityAcceptable(false)
setUnvalidatedConnectivityAcceptable(true)
setLegacyTypeName("TEST_NETWORK")
- disableNat64Detection()
- disableProvisioningNotification()
+ setNat64DetectionEnabled(false)
+ setProvisioningNotificationEnabled(false)
}.build()
assertTrue(config.isExplicitlySelected())
diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
index f0d7d86..45b575a 100644
--- a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
+++ b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
@@ -56,7 +56,7 @@
if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}.build()
- return mixInScore(nc, nac, false /* avoidBadWifi */)
+ return mixInScore(nc, nac, validated, false /* yieldToBadWifi */)
}
@Test