diff options
94 files changed, 1308 insertions, 1099 deletions
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java index 95892aa7af81..b06d076fe08e 100644 --- a/core/java/android/hardware/devicestate/DeviceStateManager.java +++ b/core/java/android/hardware/devicestate/DeviceStateManager.java @@ -96,7 +96,7 @@ public final class DeviceStateManager { public void requestState(@NonNull DeviceStateRequest request, @Nullable @CallbackExecutor Executor executor, @Nullable DeviceStateRequest.Callback callback) { - mGlobal.requestState(request, callback, executor); + mGlobal.requestState(request, executor, callback); } /** diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java index 904a54b00fa3..85e70b0fb3e9 100644 --- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java +++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java @@ -117,7 +117,7 @@ public final class DeviceStateManagerGlobal { * @see DeviceStateRequest */ public void requestState(@NonNull DeviceStateRequest request, - @Nullable DeviceStateRequest.Callback callback, @Nullable Executor executor) { + @Nullable Executor executor, @Nullable DeviceStateRequest.Callback callback) { if (callback == null && executor != null) { throw new IllegalArgumentException("Callback must be supplied with executor."); } else if (executor == null && callback != null) { @@ -149,7 +149,7 @@ public final class DeviceStateManagerGlobal { /** * Cancels a {@link DeviceStateRequest request} previously submitted with a call to - * {@link #requestState(DeviceStateRequest, DeviceStateRequest.Callback, Executor)}. + * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}. * * @see DeviceStateManager#cancelRequest(DeviceStateRequest) */ @@ -408,7 +408,7 @@ public final class DeviceStateManagerGlobal { return; } - mExecutor.execute(() -> mCallback.onRequestSuspended(mRequest)); + mExecutor.execute(() -> mCallback.onRequestCanceled(mRequest)); } } } diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index fee2e2b27457..798a0015925e 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -764,8 +764,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * <p> @@ -780,8 +780,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * @@ -793,7 +793,12 @@ public class NetworkTemplate implements Parcelable { * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { - if (!template.isMatchRuleMobile()) return template; + // Now there are several types of network which uses SubscriberId to store network + // information. For instances: + // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. + // The TYPE_CARRIER means that the network associate to specific carrier network. + + if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index 63bcc9c89ca9..c64aa4db561a 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -159,8 +159,6 @@ public final class PermissionManager { mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow( "permissionmgr")); mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class); - //TODO ntmyren: there should be a way to only enable the watcher when requested - mUsageHelper = new PermissionUsageHelper(context); } /** @@ -872,6 +870,29 @@ public final class PermissionManager { } /** + * Initialize the PermissionUsageHelper, which will register active app op listeners + * + * @hide + */ + public void initializeUsageHelper() { + if (mUsageHelper == null) { + mUsageHelper = new PermissionUsageHelper(mContext); + } + } + + /** + * Teardown the PermissionUsageHelper, removing listeners + * + * @hide + */ + public void tearDownUsageHelper() { + if (mUsageHelper != null) { + mUsageHelper.tearDown(); + mUsageHelper = null; + } + } + + /** * @return A list of permission groups currently or recently used by all apps by all users in * the current profile group. * @@ -881,7 +902,7 @@ public final class PermissionManager { @NonNull @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) public List<PermGroupUsage> getIndicatorAppOpUsageData() { - return mUsageHelper.getOpUsageData(new AudioManager().isMicrophoneMute()); + return getIndicatorAppOpUsageData(new AudioManager().isMicrophoneMute()); } /** @@ -896,9 +917,7 @@ public final class PermissionManager { @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS) public List<PermGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) { // Lazily initialize the usage helper - if (mUsageHelper == null) { - mUsageHelper = new PermissionUsageHelper(mContext); - } + initializeUsageHelper(); return mUsageHelper.getOpUsageData(micMuted); } diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index 19f204b377c8..20f6c10f929e 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -176,6 +176,11 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis return mUserContexts.get(user); } + public void tearDown() { + mAppOpsManager.stopWatchingActive(this); + mAppOpsManager.stopWatchingStarted(this); + } + @Override public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName, boolean active) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1b6a03c7a736..50155f992aaf 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9604,6 +9604,14 @@ public final class Settings { public static final String LOCKSCREEN_SHOW_WALLET = "lockscreen_show_wallet"; /** + * Whether to use the lockscreen double-line clock + * + * @hide + */ + public static final String LOCKSCREEN_USE_DOUBLE_LINE_CLOCK = + "lockscreen_use_double_line_clock"; + + /** * Specifies whether the web action API is enabled. * * @hide diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b0b5bb8870c6..cdfd7bea1a82 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -208,13 +208,13 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.function.Consumer; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Queue; import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; /** * The top of a view hierarchy, implementing the needed protocol between View @@ -10518,7 +10518,7 @@ public final class ViewRootImpl implements ViewParent, @Override public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) { - if (mRemoved) { + if (mRemoved || !isHardwareEnabled()) { t.apply(); } else { registerRtFrameCallback(frame -> mergeWithNextTransaction(t, frame)); diff --git a/core/java/android/window/TaskSnapshot.java b/core/java/android/window/TaskSnapshot.java index f1e5fb95ea54..b7bb6082296e 100644 --- a/core/java/android/window/TaskSnapshot.java +++ b/core/java/android/window/TaskSnapshot.java @@ -50,6 +50,7 @@ public class TaskSnapshot implements Parcelable { /** The size of the snapshot before scaling */ private final Point mTaskSize; private final Rect mContentInsets; + private final Rect mLetterboxInsets; // Whether this snapshot is a down-sampled version of the high resolution snapshot, used // mainly for loading snapshots quickly from disk when user is flinging fast private final boolean mIsLowResolution; @@ -67,9 +68,10 @@ public class TaskSnapshot implements Parcelable { public TaskSnapshot(long id, @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot, @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, - Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot, - int windowingMode, @WindowInsetsController.Appearance int appearance, - boolean isTranslucent, boolean hasImeSurface) { + Rect contentInsets, Rect letterboxInsets, boolean isLowResolution, + boolean isRealSnapshot, int windowingMode, + @WindowInsetsController.Appearance int appearance, boolean isTranslucent, + boolean hasImeSurface) { mId = id; mTopActivityComponent = topActivityComponent; mSnapshot = snapshot; @@ -79,6 +81,7 @@ public class TaskSnapshot implements Parcelable { mRotation = rotation; mTaskSize = new Point(taskSize); mContentInsets = new Rect(contentInsets); + mLetterboxInsets = new Rect(letterboxInsets); mIsLowResolution = isLowResolution; mIsRealSnapshot = isRealSnapshot; mWindowingMode = windowingMode; @@ -99,6 +102,7 @@ public class TaskSnapshot implements Parcelable { mRotation = source.readInt(); mTaskSize = source.readTypedObject(Point.CREATOR); mContentInsets = source.readTypedObject(Rect.CREATOR); + mLetterboxInsets = source.readTypedObject(Rect.CREATOR); mIsLowResolution = source.readBoolean(); mIsRealSnapshot = source.readBoolean(); mWindowingMode = source.readInt(); @@ -179,6 +183,14 @@ public class TaskSnapshot implements Parcelable { } /** + * @return The letterbox insets on the snapshot. These can be clipped off in order to + * remove any letterbox areas in the snapshot. + */ + public Rect getLetterboxInsets() { + return mLetterboxInsets; + } + + /** * @return Whether this snapshot is a down-sampled version of the full resolution. */ @UnsupportedAppUsage @@ -241,6 +253,7 @@ public class TaskSnapshot implements Parcelable { dest.writeInt(mRotation); dest.writeTypedObject(mTaskSize, 0); dest.writeTypedObject(mContentInsets, 0); + dest.writeTypedObject(mLetterboxInsets, 0); dest.writeBoolean(mIsLowResolution); dest.writeBoolean(mIsRealSnapshot); dest.writeInt(mWindowingMode); @@ -262,6 +275,7 @@ public class TaskSnapshot implements Parcelable { + " mRotation=" + mRotation + " mTaskSize=" + mTaskSize.toString() + " mContentInsets=" + mContentInsets.toShortString() + + " mLetterboxInsets=" + mLetterboxInsets.toShortString() + " mIsLowResolution=" + mIsLowResolution + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode @@ -289,6 +303,7 @@ public class TaskSnapshot implements Parcelable { private int mRotation; private Point mTaskSize; private Rect mContentInsets; + private Rect mLetterboxInsets; private boolean mIsRealSnapshot; private int mWindowingMode; private @WindowInsetsController.Appearance @@ -340,6 +355,11 @@ public class TaskSnapshot implements Parcelable { return this; } + public Builder setLetterboxInsets(Rect letterboxInsets) { + mLetterboxInsets = letterboxInsets; + return this; + } + public Builder setIsRealSnapshot(boolean realSnapshot) { mIsRealSnapshot = realSnapshot; return this; @@ -387,6 +407,7 @@ public class TaskSnapshot implements Parcelable { mRotation, mTaskSize, mContentInsets, + mLetterboxInsets, // When building a TaskSnapshot with the Builder class, isLowResolution // is always false. Low-res snapshots are only created when loading from // disk. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 8cb727827009..5aff0e0cf38a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1388,6 +1388,12 @@ <integer name="config_screenBrightnessDim">10</integer> <item name="config_screenBrightnessDimFloat" format="float" type="dimen">0.05</item> + <!-- If the screen brightness is already set at or below config_screenBrightnessDim, and the + user activity timeout expires, we still want to dim the screen slightly to indicate that + the device is about to go to sleep. The screen will dim by this amount in that case. + --> + <item name="config_screenBrightnessMinimumDimAmountFloat" format="float" type="dimen">0.04</item> + <!-- Minimum allowable screen brightness to use in a very dark room. This value sets the floor for the darkest possible auto-brightness adjustment. It is expected to be somewhat less than the first entry in diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9bb92e6c93cc..6797eaffe134 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2040,6 +2040,7 @@ <java-symbol type="dimen" name="config_screenBrightnessSettingDefaultFloat" /> <java-symbol type="dimen" name="config_screenBrightnessDozeFloat" /> <java-symbol type="dimen" name="config_screenBrightnessDimFloat" /> + <java-symbol type="dimen" name="config_screenBrightnessMinimumDimAmountFloat" /> <java-symbol type="integer" name="config_screenBrightnessDark" /> <java-symbol type="integer" name="config_screenBrightnessDim" /> <java-symbol type="integer" name="config_screenBrightnessDoze" /> diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 6f17ea994699..4a7c50d8b934 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -304,18 +304,22 @@ public class ActivityThreadTest { final int numOfConfig = activity.mNumOfConfigChanges; final Configuration processConfigLandscape = new Configuration(); + processConfigLandscape.orientation = ORIENTATION_LANDSCAPE; processConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 60)); processConfigLandscape.seq = BASE_SEQ + 1; final Configuration activityConfigLandscape = new Configuration(); + activityConfigLandscape.orientation = ORIENTATION_LANDSCAPE; activityConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 50)); activityConfigLandscape.seq = BASE_SEQ + 2; final Configuration processConfigPortrait = new Configuration(); + processConfigPortrait.orientation = ORIENTATION_PORTRAIT; processConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 60, 100)); processConfigPortrait.seq = BASE_SEQ + 3; final Configuration activityConfigPortrait = new Configuration(); + activityConfigPortrait.orientation = ORIENTATION_PORTRAIT; activityConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 50, 100)); activityConfigPortrait.seq = BASE_SEQ + 4; @@ -343,7 +347,8 @@ public class ActivityThreadTest { assertEquals(activityConfigPortrait.windowConfiguration.getBounds(), bounds); // Ensure that Activity#onConfigurationChanged() not be called because the changes in - // WindowConfiguration shouldn't be reported. + // WindowConfiguration shouldn't be reported, and we only apply the latest Configuration + // update in transaction. assertEquals(numOfConfig, activity.mNumOfConfigChanges); } diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java index 055fc7171fa0..db63e6e0b187 100644 --- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java +++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java @@ -160,6 +160,34 @@ public final class DeviceStateManagerGlobalTest { verify(callback).onStateChanged(eq(mService.getBaseState())); } + @Test + public void verifyDeviceStateRequestCallbacksCalled() { + DeviceStateRequest.Callback callback = mock(TestDeviceStateRequestCallback.class); + + DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build(); + mDeviceStateManagerGlobal.requestState(request, + ConcurrentUtils.DIRECT_EXECUTOR /* executor */, + callback /* callback */); + + verify(callback).onRequestActivated(eq(request)); + Mockito.reset(callback); + + mDeviceStateManagerGlobal.cancelRequest(request); + + verify(callback).onRequestCanceled(eq(request)); + } + + public static class TestDeviceStateRequestCallback implements DeviceStateRequest.Callback { + @Override + public void onRequestActivated(DeviceStateRequest request) { } + + @Override + public void onRequestCanceled(DeviceStateRequest request) { } + + @Override + public void onRequestSuspended(DeviceStateRequest request) { } + } + private static final class TestDeviceStateManagerService extends IDeviceStateManager.Stub { public static final class Request { public final IBinder token; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index 194b6330d92c..89d7a407e459 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -39,6 +39,8 @@ class TaskFragmentAnimationAdapter { final Transformation mTransformation = new Transformation(); final float[] mMatrix = new float[9]; + final float[] mVecs = new float[4]; + final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; TaskFragmentAnimationAdapter(@NonNull Animation animation, @@ -76,6 +78,22 @@ class TaskFragmentAnimationAdapter { mTarget.localBounds.left, mTarget.localBounds.top); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); + + // Open/close animation may scale up the surface. Apply an inverse scale to the window crop + // so that it will not be covering other windows. + mVecs[1] = mVecs[2] = 0; + mVecs[0] = mVecs[3] = 1; + mTransformation.getMatrix().mapVectors(mVecs); + mVecs[0] = 1.f / mVecs[0]; + mVecs[3] = 1.f / mVecs[3]; + final Rect clipRect = mTarget.localBounds; + mRect.left = (int) (clipRect.left * mVecs[0] + 0.5f); + mRect.right = (int) (clipRect.right * mVecs[0] + 0.5f); + mRect.top = (int) (clipRect.top * mVecs[3] + 0.5f); + mRect.bottom = (int) (clipRect.bottom * mVecs[3] + 0.5f); + mRect.offsetTo(Math.round(mTarget.localBounds.width() * (1 - mVecs[0]) / 2.f), + Math.round(mTarget.localBounds.height() * (1 - mVecs[3]) / 2.f)); + t.setWindowCrop(mLeash, mRect); } /** Called after animation finished. */ @@ -157,8 +175,6 @@ class TaskFragmentAnimationAdapter { * Should be used for the animation of the {@link RemoteAnimationTarget} that has size change. */ static class BoundsChangeAdapter extends TaskFragmentAnimationAdapter { - private final float[] mVecs = new float[4]; - private final Rect mRect = new Rect(); BoundsChangeAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { super(animation, target); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index 32d447ef1586..fe9ce971d4d9 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -18,9 +18,12 @@ package androidx.window.extensions.layout; import static android.view.Display.DEFAULT_DISPLAY; +import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT; +import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED; import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; +import android.annotation.Nullable; import android.app.Activity; import android.content.Context; import android.graphics.Rect; @@ -119,22 +122,45 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return !mWindowLayoutChangeListeners.isEmpty(); } - private int getFeatureState(DisplayFeature feature) { + /** + * Calculate the {@link DisplayFeature.State} from the feature or the device posture producer. + * If the given {@link DisplayFeature.State} is not valid then {@code null} will be returned. + * The {@link FoldingFeature} should be ignored in the case of an invalid + * {@link DisplayFeature.State}. + * + * @param feature a {@link DisplayFeature} to provide the feature state if present. + * @return {@link DisplayFeature.State} of the hinge if present or the state from the posture + * produce if present. + */ + @Nullable + private Integer getFeatureState(DisplayFeature feature) { Integer featureState = feature.getState(); Optional<Integer> posture = mDevicePostureProducer.getData(); - int fallbackPosture = posture.orElse(DisplayFeature.COMMON_STATE_FLAT); - int displayFeatureState = featureState == null ? fallbackPosture : featureState; - return convertToExtensionState(displayFeatureState); + Integer state = featureState == null ? posture.orElse(null) : featureState; + return convertToExtensionState(state); } - private int convertToExtensionState(int state) { - switch (state) { - case DisplayFeature.COMMON_STATE_FLAT: - return FoldingFeature.STATE_FLAT; - case DisplayFeature.COMMON_STATE_HALF_OPENED: - return FoldingFeature.STATE_HALF_OPENED; + /** + * A convenience method to translate from the common feature state to the extensions feature + * state. More specifically, translates from {@link DisplayFeature.State} to + * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not + * possible to translate, then we will return a {@code null} value. + * + * @param state if it matches a value in {@link DisplayFeature.State}, {@code null} otherwise. + * @return a {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED} if + * the given state matches a value in {@link DisplayFeature.State} and {@code null} otherwise. + */ + @Nullable + private Integer convertToExtensionState(@Nullable Integer state) { + if (state == null) { // The null check avoids a NullPointerException. + return null; + } else if (state == COMMON_STATE_FLAT) { + return FoldingFeature.STATE_FLAT; + } else if (state == COMMON_STATE_HALF_OPENED) { + return FoldingFeature.STATE_HALF_OPENED; + } else { + return null; } - return FoldingFeature.STATE_FLAT; } private void onDisplayFeaturesChanged() { @@ -151,6 +177,25 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return new WindowLayoutInfo(displayFeatures); } + /** + * Translate from the {@link DisplayFeature} to + * {@link androidx.window.extensions.layout.DisplayFeature} for a given {@link Activity}. If a + * {@link DisplayFeature} is not valid then it will be omitted. + * + * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window + * coordinate space and the state is calculated either from {@link DisplayFeature#getState()} or + * {@link #mDisplayFeatureProducer}. The state from {@link #mDisplayFeatureProducer} may not be + * valid since {@link #mDisplayFeatureProducer} is a general state controller. If the state is + * not valid, the {@link FoldingFeature} is omitted from the {@link List} of + * {@link androidx.window.extensions.layout.DisplayFeature}. If the bounds are not valid, + * constructing a {@link FoldingFeature} will throw an {@link IllegalArgumentException} since + * this can cause negative UI effects down stream. + * + * @param activity a proxy for the {@link android.view.Window} that contains the + * {@link androidx.window.extensions.layout.DisplayFeature}. + * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that + * are within the {@link android.view.Window} of the {@link Activity} + */ private List<androidx.window.extensions.layout.DisplayFeature> getDisplayFeatures( @NonNull Activity activity) { List<androidx.window.extensions.layout.DisplayFeature> features = new ArrayList<>(); @@ -170,6 +215,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { if (storedFeatures.isPresent()) { for (DisplayFeature baseFeature : storedFeatures.get()) { + Integer state = getFeatureState(baseFeature); + if (state == null) { + continue; + } Rect featureRect = baseFeature.getRect(); rotateRectToDisplayRotation(displayId, featureRect); transformToWindowSpaceRect(activity, featureRect); 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 caa532761f1c..ec59fad3e95b 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 @@ -111,8 +111,7 @@ public class BubbleController { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; - // TODO(b/173386799) keep in sync with Launcher3 and also don't do a broadcast - public static final String TASKBAR_CHANGED_BROADCAST = "taskbarChanged"; + // TODO(b/173386799) keep in sync with Launcher3, not hooked up to anything public static final String EXTRA_TASKBAR_CREATED = "taskbarCreated"; public static final String EXTRA_BUBBLE_OVERFLOW_OPENED = "bubbleOverflowOpened"; public static final String EXTRA_TASKBAR_VISIBLE = "taskbarVisible"; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 0c12d6c7bca2..d2b4711d30af 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -19,6 +19,7 @@ package com.android.wm.shell.draganddrop; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DragEvent.ACTION_DRAG_ENDED; import static android.view.DragEvent.ACTION_DRAG_ENTERED; import static android.view.DragEvent.ACTION_DRAG_EXITED; @@ -34,13 +35,13 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; -import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.util.Slog; import android.util.SparseArray; +import android.view.Display; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.SurfaceControl; @@ -55,7 +56,6 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.protolog.ShellProtoLogGroup; -import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.Optional; @@ -91,6 +91,11 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange @Override public void onDisplayAdded(int displayId) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display added: %d", displayId); + if (displayId != DEFAULT_DISPLAY) { + // Ignore non-default displays for now + return; + } + final Context context = mDisplayController.getDisplayContext(displayId) .createWindowContext(TYPE_APPLICATION_OVERLAY, null); final WindowManager wm = context.getSystemService(WindowManager.class); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java index 80ab166d0649..67e487de0993 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java @@ -172,6 +172,14 @@ public class LegacySplitScreenController implements DisplayController.OnDisplays }; mWindowManager = new DividerWindowManager(mSystemWindows); + + // No need to listen to display window container or create root tasks if the device is not + // using legacy split screen. + if (!context.getResources().getBoolean(com.android.internal.R.bool.config_useLegacySplit)) { + return; + } + + mDisplayController.addDisplayWindowListener(this); // Don't initialize the divider or anything until we get the default display. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 6ce43a041299..7cfba148a907 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -491,25 +491,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb if (mPipTaskOrganizer.isInPip() && saveRestoreSnapFraction) { // Calculate the snap fraction of the current stack along the old movement bounds final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm(); - final float snapFraction = pipSnapAlgorithm.getSnapFraction(mPipBoundsState.getBounds(), - mPipBoundsAlgorithm.getMovementBounds(mPipBoundsState.getBounds()), + final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds()); + final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeStackBounds, + mPipBoundsAlgorithm.getMovementBounds(postChangeStackBounds), mPipBoundsState.getStashedState()); updateDisplayLayout.run(); - final Rect postChangeStackBounds; - if (mPipBoundsState.getBounds() != null - && (mPipBoundsState.getBounds().width() > mPipBoundsState.getMaxSize().x - || mPipBoundsState.getBounds().height() > mPipBoundsState.getMaxSize().y)) { - postChangeStackBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x, - mPipBoundsState.getMaxSize().y); - } else if (mPipBoundsState.getBounds() != null - && (mPipBoundsState.getBounds().width() < mPipBoundsState.getMinSize().x - || mPipBoundsState.getBounds().height() < mPipBoundsState.getMinSize().y)) { - postChangeStackBounds = new Rect(0, 0, mPipBoundsState.getMinSize().x, - mPipBoundsState.getMinSize().y); - } else { - postChangeStackBounds = new Rect(mPipBoundsState.getBounds()); - } // Calculate the stack bounds in the new orientation based on same fraction along the // rotated movement bounds. @@ -521,7 +508,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb mPipBoundsState.getDisplayBounds(), mPipBoundsState.getDisplayLayout().stableInsets()); - mTouchHandler.getMotionHelper().animateResizedBounds(postChangeStackBounds); + mTouchHandler.getMotionHelper().movePip(postChangeStackBounds); } else { updateDisplayLayout.run(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java index c634b7f220b0..96fd59f0c911 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java @@ -69,7 +69,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private static final int UNSTASH_DURATION = 250; private static final int LEAVE_PIP_DURATION = 300; private static final int SHIFT_DURATION = 300; - private static final int ANIMATE_PIP_RESIZE_ANIMATION = 250; /** Friction to use for PIP when it moves via physics fling animations. */ private static final float DEFAULT_FRICTION = 1.9f; @@ -549,14 +548,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } /** - * Animates the PiP from an old bound to a new bound. This is mostly used when display - * has changed and PiP bounds needs to be changed. - */ - void animateResizedBounds(Rect newBounds) { - resizeAndAnimatePipUnchecked(newBounds, ANIMATE_PIP_RESIZE_ANIMATION); - } - - /** * Animates the PiP to offset it from the IME or shelf. */ void animateToOffset(Rect originalBounds, int offset) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 050d255bfd2d..d4941916850d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -78,7 +78,6 @@ import android.window.TransitionRequestInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.internal.protolog.common.ProtoLog; @@ -157,10 +156,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private boolean mExitSplitScreenOnHide; private boolean mKeyguardOccluded; - // TODO(b/187041611): remove this flag after totally deprecated legacy split - /** Whether the device is supporting legacy split or not. */ - private boolean mUseLegacySplit; - @SplitScreen.StageType private int mDismissTop = NO_DISMISS; @@ -735,17 +730,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void onStageRootTaskAppeared(StageListenerImpl stageListener) { if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) { - mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit); final WindowContainerTransaction wct = new WindowContainerTransaction(); // Make the stages adjacent to each other so they occlude what's behind them. wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); - - // Only sets side stage as launch-adjacent-flag-root when the device is not using legacy - // split to prevent new split behavior confusing users. - if (!mUseLegacySplit) { - wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token); - } - mTaskOrganizer.applyTransaction(wct); } } @@ -755,11 +742,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, final WindowContainerTransaction wct = new WindowContainerTransaction(); // Deactivate the main stage if it no longer has a root task. mMainStage.deactivate(wct); - - if (!mUseLegacySplit) { - wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token); - } - mTaskOrganizer.applyTransaction(wct); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 190006ec0d9b..62b8638a2582 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -37,6 +37,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; +import com.android.internal.R; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.SurfaceUtils; @@ -102,7 +103,12 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { mSurfaceSession = surfaceSession; mIconProvider = iconProvider; mStageTaskUnfoldController = stageTaskUnfoldController; - taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this); + + // No need to create root task if the device is using legacy split screen. + // TODO(b/199236198): Remove this check after totally deprecated legacy split. + if (!context.getResources().getBoolean(R.bool.config_useLegacySplit)) { + taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this); + } } int getChildCount() { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java new file mode 100644 index 000000000000..bfa2c92f6679 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.draganddrop; + +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import android.content.Context; +import android.os.RemoteException; +import android.view.Display; +import android.view.DragEvent; +import android.view.View; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.internal.logging.UiEventLogger; +import com.android.wm.shell.common.DisplayController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for the drag and drop controller. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DragAndDropControllerTest { + + @Mock + private Context mContext; + + @Mock + private DisplayController mDisplayController; + + @Mock + private UiEventLogger mUiEventLogger; + + private DragAndDropController mController; + + @Before + public void setUp() throws RemoteException { + MockitoAnnotations.initMocks(this); + + mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger); + } + + @Test + public void testIgnoreNonDefaultDisplays() { + final int nonDefaultDisplayId = 12345; + final View dragLayout = mock(View.class); + final Display display = mock(Display.class); + doReturn(nonDefaultDisplayId).when(display).getDisplayId(); + doReturn(display).when(dragLayout).getDisplay(); + + // Expect no per-display layout to be added + mController.onDisplayAdded(nonDefaultDisplayId); + assertFalse(mController.onDrag(dragLayout, mock(DragEvent.class))); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index c2f58b8b6266..935f6695538d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -191,7 +191,7 @@ public class PipControllerTest extends ShellTestCase { mPipController.mDisplaysChangedListener.onDisplayConfigurationChanged( displayId, new Configuration()); - verify(mMockPipMotionHelper).animateResizedBounds(any(Rect.class)); + verify(mMockPipMotionHelper).movePip(any(Rect.class)); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index b866bf9d4192..70b7c6793492 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -301,8 +301,8 @@ public class StartingSurfaceDrawerTests { System.currentTimeMillis(), new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, - Surface.ROTATION_0, taskSize, contentInsets, false, - true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, + Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */, + false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */, hasImeSurface /* hasImeSurface */); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java index aad9528bd527..78e27c956807 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java @@ -94,8 +94,8 @@ public class TaskSnapshotWindowTest { System.currentTimeMillis(), new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, - Surface.ROTATION_0, taskSize, contentInsets, false, - true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, + Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */, + false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */); } diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java index 14a7cfa568d8..5e91a147318e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java @@ -113,6 +113,8 @@ public class MobileMappings { TelephonyIcons.UNKNOWN); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), TelephonyIcons.E); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_GPRS), + TelephonyIcons.G); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), TelephonyIcons.ONE_X); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), @@ -122,6 +124,8 @@ public class MobileMappings { TelephonyIcons.THREE_G); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_GPRS), + TelephonyIcons.THREE_G); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), TelephonyIcons.THREE_G); networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 96f127b6a611..77fff0f08d4c 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -191,5 +191,6 @@ public class SecureSettings { Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED, Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, Settings.Secure.LOCKSCREEN_SHOW_WALLET, + Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 7aeacdc0cf71..9f883960981b 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -150,6 +150,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.POWER_MENU_LOCKED_SHOW_CONTENT, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.LOCKSCREEN_SHOW_CONTROLS, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.LOCKSCREEN_SHOW_WALLET, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR); diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java index b83ea4acd26f..d5f858c4df94 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java @@ -34,7 +34,7 @@ public interface QS extends FragmentBase { String ACTION = "com.android.systemui.action.PLUGIN_QS"; - int VERSION = 11; + int VERSION = 12; String TAG = "QS"; @@ -46,6 +46,8 @@ public interface QS extends FragmentBase { void setHeightOverride(int desiredHeight); void setHeaderClickable(boolean qsExpansionEnabled); boolean isCustomizing(); + /** Close the QS customizer, if it is open. */ + void closeCustomizer(); void setOverscrolling(boolean overscrolling); void setExpanded(boolean qsExpanded); void setListening(boolean listening); diff --git a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml deleted file mode 100644 index 52ed76dd236f..000000000000 --- a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2014 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 - --> - -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <gradient - android:type="linear" - android:angle="90" - android:startColor="#33000000" - android:endColor="#00000000" /> -</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/assist_orb_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_scrim.xml deleted file mode 100644 index bbb2617db4a0..000000000000 --- a/packages/SystemUI/res/drawable/assist_orb_scrim.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2014 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 - --> - -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <gradient - android:type="linear" - android:angle="90" - android:startColor="#55000000" - android:endColor="#00000000" /> -</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/assist_orb.xml b/packages/SystemUI/res/layout/assist_orb.xml deleted file mode 100644 index 0036ed6abaf1..000000000000 --- a/packages/SystemUI/res/layout/assist_orb.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** Copyright 2012, 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. -*/ ---> - -<!-- Extends FrameLayout --> -<com.android.systemui.assist.AssistOrbContainer - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <com.android.systemui.statusbar.AlphaOptimizedView - android:layout_width="match_parent" - android:layout_height="@dimen/assist_orb_scrim_height" - android:layout_gravity="bottom" - android:id="@+id/assist_orb_scrim" - android:background="@drawable/assist_orb_scrim"/> - - <com.android.systemui.assist.AssistOrbView - android:id="@+id/assist_orb" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/search_logo"/> - </com.android.systemui.assist.AssistOrbView> - - <com.android.systemui.statusbar.AlphaOptimizedView - android:id="@+id/assist_orb_navbar_scrim" - android:layout_height="@dimen/assist_orb_navbar_scrim_height" - android:layout_width="match_parent" - android:layout_gravity="bottom" - android:elevation="50dp" - android:outlineProvider="none" - android:background="@drawable/assist_orb_navbar_scrim"/> - -</com.android.systemui.assist.AssistOrbContainer>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 141b97977dab..8a3bacae9243 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -87,8 +87,6 @@ <color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color> - <color name="assist_orb_color">#ffffff</color> - <color name="keyguard_user_switcher_background_gradient_color">#77000000</color> <!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 38be0932070f..2afbe8c648be 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -678,25 +678,6 @@ from Keyguard. --> <dimen name="go_to_full_shade_appearing_translation">200dp</dimen> - <!-- The diameter of the search panel circle. --> - <dimen name="assist_orb_size">144dp</dimen> - - <!-- The margin to the edge of the screen from where the orb starts to appear --> - <dimen name="assist_orb_base_margin">22dp</dimen> - - <!-- The amount the orb translates when appearing --> - <dimen name="assist_orb_travel_distance">26dp</dimen> - - <!-- The elevation of the orb --> - <dimen name="assist_orb_elevation">12dp</dimen> - - <!-- The height of the scrim behind the orb. --> - <dimen name="assist_orb_scrim_height">250dp</dimen> - - <!-- The height of the scrim behind the search panel circle. Should be navigation_bar_height - + 8dp. --> - <dimen name="assist_orb_navbar_scrim_height">56dp</dimen> - <!-- The width/height of the keyguard bottom area icon view on keyguard. --> <dimen name="keyguard_affordance_height">48dp</dimen> <dimen name="keyguard_affordance_width">48dp</dimen> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java index 2f2876d2e9f3..1142e05f4649 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java @@ -42,6 +42,7 @@ public class ThumbnailData { public int orientation; public int rotation; public Rect insets; + public Rect letterboxInsets; public boolean reducedResolution; public boolean isRealSnapshot; public boolean isTranslucent; @@ -55,6 +56,7 @@ public class ThumbnailData { orientation = ORIENTATION_UNDEFINED; rotation = ROTATION_UNDEFINED; insets = new Rect(); + letterboxInsets = new Rect(); reducedResolution = false; scale = 1f; isRealSnapshot = true; @@ -97,6 +99,7 @@ public class ThumbnailData { public ThumbnailData(TaskSnapshot snapshot) { thumbnail = makeThumbnail(snapshot); insets = new Rect(snapshot.getContentInsets()); + letterboxInsets = new Rect(snapshot.getLetterboxInsets()); orientation = snapshot.getOrientation(); rotation = snapshot.getRotation(); reducedResolution = snapshot.isLowResolution(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 3d4e896178f6..9238b8226bbc 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -11,7 +11,6 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.FrameLayout; import android.widget.RelativeLayout; @@ -89,7 +88,6 @@ public class KeyguardClockSwitch extends RelativeLayout { private int mClockSwitchYAmount; @VisibleForTesting boolean mChildrenAreLaidOut = false; - private OnPreDrawListener mPreDrawListener; public KeyguardClockSwitch(Context context, AttributeSet attrs) { super(context, attrs); @@ -284,30 +282,21 @@ public class KeyguardClockSwitch extends RelativeLayout { // translate them properly if (mChildrenAreLaidOut) { animateClockChange(clockSize == LARGE); - mDisplayedClockSize = clockSize; - } else if (mPreDrawListener == null) { - mPreDrawListener = () -> { - switchToClock(clockSize); - getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); - mPreDrawListener = null; - return true; - }; - getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); } + + mDisplayedClockSize = clockSize; return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); - mChildrenAreLaidOut = true; - } - void onViewDetached() { - if (mPreDrawListener != null) { - getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); - mPreDrawListener = null; + if (mDisplayedClockSize != null && !mChildrenAreLaidOut) { + animateClockChange(mDisplayedClockSize == LARGE); } + + mChildrenAreLaidOut = true; } public Paint getPaint() { @@ -368,5 +357,6 @@ public class KeyguardClockSwitch extends RelativeLayout { pw.println(" mDarkAmount: " + mDarkAmount); pw.println(" mSupportsDarkText: " + mSupportsDarkText); pw.println(" mColorPalette: " + Arrays.toString(mColorPalette)); + pw.println(" mDisplayedClockSize: " + mDisplayedClockSize); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 905495d369a0..c628d4401bb1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -23,6 +23,8 @@ import static com.android.keyguard.KeyguardClockSwitch.LARGE; import android.app.WallpaperManager; import android.content.res.Resources; +import android.database.ContentObserver; +import android.provider.Settings; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -49,11 +51,13 @@ 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 com.android.systemui.util.settings.SecureSettings; import java.util.HashSet; import java.util.Locale; import java.util.Set; import java.util.TimeZone; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -72,6 +76,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS private final BatteryController mBatteryController; private final LockscreenSmartspaceController mSmartspaceController; private final Resources mResources; + private final SecureSettings mSecureSettings; /** * Clock for both small and large sizes @@ -109,6 +114,14 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS private SmartspaceTransitionController mSmartspaceTransitionController; private boolean mOnlyClock = false; + private Executor mUiExecutor; + private boolean mCanShowDoubleLineClock = true; + private ContentObserver mDoubleLineClockObserver = new ContentObserver(null) { + @Override + public void onChange(boolean change) { + updateDoubleLineClock(); + } + }; @Inject public KeyguardClockSwitchController( @@ -125,6 +138,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS LockscreenSmartspaceController smartspaceController, KeyguardUnlockAnimationController keyguardUnlockAnimationController, SmartspaceTransitionController smartspaceTransitionController, + SecureSettings secureSettings, + @Main Executor uiExecutor, @Main Resources resources) { super(keyguardClockSwitch); mStatusBarStateController = statusBarStateController; @@ -138,7 +153,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mBypassController = bypassController; mSmartspaceController = smartspaceController; mResources = resources; - + mSecureSettings = secureSettings; + mUiExecutor = uiExecutor; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mSmartspaceTransitionController = smartspaceTransitionController; } @@ -223,6 +239,14 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS updateClockLayout(); mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceView); } + + mSecureSettings.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK), + false, /* notifyForDescendants */ + mDoubleLineClockObserver + ); + + updateDoubleLineClock(); } int getNotificationIconAreaHeight() { @@ -236,7 +260,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } mColorExtractor.removeOnColorsChangedListener(mColorsListener); mView.setClockPlugin(null, mStatusBarStateController.getState()); - mView.onViewDetached(); + + mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver); } /** @@ -268,6 +293,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS * hidden. */ public void displayClock(@KeyguardClockSwitch.ClockSize int clockSize) { + if (!mCanShowDoubleLineClock && clockSize == KeyguardClockSwitch.LARGE) { + return; + } + boolean appeared = mView.switchToClock(clockSize); if (appeared && clockSize == LARGE) { mLargeClockViewController.animateAppear(); @@ -410,4 +439,13 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS private int getCurrentLayoutDirection() { return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()); } + + private void updateDoubleLineClock() { + mCanShowDoubleLineClock = mSecureSettings.getInt( + Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1) != 0; + + if (!mCanShowDoubleLineClock) { + mUiExecutor.execute(() -> displayClock(KeyguardClockSwitch.SMALL)); + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index 9286175cc2ea..471bac16642b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -43,8 +43,7 @@ data class KeyguardFingerprintListenModel( val shouldListenForFingerprintAssistant: Boolean, val switchingUser: Boolean, val udfps: Boolean, - val userDoesNotHaveTrust: Boolean, - val userNeedsStrongAuth: Boolean + val userDoesNotHaveTrust: Boolean ) : KeyguardListenModel() { override val modality: Int = TYPE_FACE } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index d27bc675ecb8..e24f07c21076 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2222,11 +2222,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab !(mFingerprintLockedOut && mBouncer && mCredentialAttempted); final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user); - final boolean userNeedsStrongAuth = userNeedsStrongAuth(); final boolean shouldListenUdfpsState = !isUdfps || (!userCanSkipBouncer && !isEncryptedOrLockdownForUser - && !userNeedsStrongAuth && userDoesNotHaveTrust && !mFingerprintLockedOut); @@ -2257,8 +2255,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab shouldListenForFingerprintAssistant, mSwitchingUser, isUdfps, - userDoesNotHaveTrust, - userNeedsStrongAuth)); + userDoesNotHaveTrust)); } return shouldListen; @@ -2362,7 +2359,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || (DEBUG_FINGERPRINT && model instanceof KeyguardFingerprintListenModel && mFingerprintRunningState != BIOMETRIC_STATE_RUNNING); - if (notYetRunning && model.getListening()) { + final boolean running = + (DEBUG_FACE + && model instanceof KeyguardFaceListenModel + && mFaceRunningState == BIOMETRIC_STATE_RUNNING) + || (DEBUG_FINGERPRINT + && model instanceof KeyguardFingerprintListenModel + && mFingerprintRunningState == BIOMETRIC_STATE_RUNNING); + if (notYetRunning && model.getListening() + || running && !model.getListening()) { mListenModels.add(model); } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index b1197e6aa6f5..9d5b93c2b329 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -7,7 +7,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.SearchManager; import android.content.ActivityNotFoundException; @@ -27,17 +26,16 @@ import android.util.Log; import com.android.internal.app.AssistUtils; import com.android.internal.app.IVoiceInteractionSessionListener; -import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.assist.ui.DefaultUiController; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import javax.inject.Inject; @@ -124,23 +122,8 @@ public class AssistManager { private final DeviceProvisionedController mDeviceProvisionedController; private final CommandQueue mCommandQueue; - private final AssistOrbController mOrbController; protected final AssistUtils mAssistUtils; - private IVoiceInteractionSessionShowCallback mShowCallback = - new IVoiceInteractionSessionShowCallback.Stub() { - - @Override - public void onFailed() throws RemoteException { - mOrbController.postHide(); - } - - @Override - public void onShown() throws RemoteException { - mOrbController.postHide(); - } - }; - @Inject public AssistManager( DeviceProvisionedController controller, @@ -149,20 +132,18 @@ public class AssistManager { CommandQueue commandQueue, PhoneStateMonitor phoneStateMonitor, OverviewProxyService overviewProxyService, - ConfigurationController configurationController, Lazy<SysUiState> sysUiState, DefaultUiController defaultUiController, - AssistLogger assistLogger) { + AssistLogger assistLogger, + @Main Handler uiHandler) { mContext = context; mDeviceProvisionedController = controller; mCommandQueue = commandQueue; mAssistUtils = assistUtils; - mAssistDisclosure = new AssistDisclosure(context, new Handler()); + mAssistDisclosure = new AssistDisclosure(context, uiHandler); mPhoneStateMonitor = phoneStateMonitor; mAssistLogger = assistLogger; - mOrbController = new AssistOrbController(configurationController, context); - registerVoiceInteractionSessionListener(); mUiController = defaultUiController; @@ -223,10 +204,6 @@ public class AssistManager { }); } - protected boolean shouldShowOrb() { - return !ActivityManager.isLowRamDeviceStatic(); - } - public void startAssist(Bundle args) { final ComponentName assistComponent = getAssistInfo(); if (assistComponent == null) { @@ -234,10 +211,6 @@ public class AssistManager { } final boolean isService = assistComponent.equals(getVoiceInteractorComponentName()); - if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) { - mOrbController.showOrb(assistComponent, isService); - mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY); - } if (args == null) { args = new Bundle(); @@ -329,7 +302,7 @@ public class AssistManager { private void startVoiceInteractor(Bundle args) { mAssistUtils.showSessionForActiveService(args, - VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null); + VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, null, null); } public void launchVoiceAssistFromKeyguard() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java deleted file mode 100644 index 95b9e81a0b14..000000000000 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui.assist; - -import android.annotation.Nullable; -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.systemui.R; -import com.android.systemui.animation.Interpolators; - -public class AssistOrbContainer extends FrameLayout { - - private static final long EXIT_START_DELAY = 150; - - private View mScrim; - private View mNavbarScrim; - private AssistOrbView mOrb; - - private boolean mAnimatingOut; - - public AssistOrbContainer(Context context) { - this(context, null); - } - - public AssistOrbContainer(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public AssistOrbContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mScrim = findViewById(R.id.assist_orb_scrim); - mNavbarScrim = findViewById(R.id.assist_orb_navbar_scrim); - mOrb = (AssistOrbView) findViewById(R.id.assist_orb); - } - - public void show(final boolean show, boolean animate, Runnable onDone) { - if (show) { - if (getVisibility() != View.VISIBLE) { - setVisibility(View.VISIBLE); - if (animate) { - startEnterAnimation(onDone); - } else { - reset(); - if (onDone != null) { - onDone.run(); - } - } - } - } else { - if (animate) { - startExitAnimation(new Runnable() { - @Override - public void run() { - mAnimatingOut = false; - setVisibility(View.GONE); - if (onDone != null) { - onDone.run(); - } - } - }); - } else { - setVisibility(View.GONE); - if (onDone != null) { - onDone.run(); - } - } - } - } - - private void reset() { - mAnimatingOut = false; - mOrb.reset(); - mScrim.setAlpha(1f); - mNavbarScrim.setAlpha(1f); - } - - private void startEnterAnimation(Runnable onDone) { - if (mAnimatingOut) { - return; - } - mOrb.startEnterAnimation(); - mScrim.setAlpha(0f); - mNavbarScrim.setAlpha(0f); - post(new Runnable() { - @Override - public void run() { - mScrim.animate() - .alpha(1f) - .setDuration(300) - .setStartDelay(0) - .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - mNavbarScrim.animate() - .alpha(1f) - .setDuration(300) - .setStartDelay(0) - .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) - .withEndAction(onDone); - } - }); - } - - private void startExitAnimation(final Runnable endRunnable) { - if (mAnimatingOut) { - if (endRunnable != null) { - endRunnable.run(); - } - return; - } - mAnimatingOut = true; - mOrb.startExitAnimation(EXIT_START_DELAY); - mScrim.animate() - .alpha(0f) - .setDuration(250) - .setStartDelay(EXIT_START_DELAY) - .setInterpolator(Interpolators.FAST_OUT_SLOW_IN); - mNavbarScrim.animate() - .alpha(0f) - .setDuration(250) - .setStartDelay(EXIT_START_DELAY) - .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) - .withEndAction(endRunnable); - } - - /** - * Whether the panel is showing, or, if it's animating, whether it will be - * when the animation is done. - */ - public boolean isShowing() { - return getVisibility() == View.VISIBLE && !mAnimatingOut; - } - - public AssistOrbView getOrb() { - return mOrb; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java deleted file mode 100644 index 408201558a9b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.assist; - -import android.annotation.NonNull; -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.PixelFormat; -import android.os.Binder; -import android.os.Bundle; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.ImageView; - -import com.android.settingslib.applications.InterestingConfigChanges; -import com.android.systemui.R; -import com.android.systemui.statusbar.policy.ConfigurationController; - -/** - * AssistOrbController controls the showing and hiding of the assistant orb. - */ -public class AssistOrbController { - private static final String ASSIST_ICON_METADATA_NAME = - "com.android.systemui.action_assist_icon"; - private static final String TAG = "AssistOrbController"; - private static final boolean VERBOSE = false; - - private final InterestingConfigChanges mInterestingConfigChanges; - private AssistOrbContainer mView; - private final Context mContext; - private final WindowManager mWindowManager; - - private Runnable mHideRunnable = new Runnable() { - @Override - public void run() { - mView.removeCallbacks(this); - mView.show(false /* show */, true /* animate */, () -> { - if (mView.isAttachedToWindow()) { - mWindowManager.removeView(mView); - } - }); - } - }; - - private ConfigurationController.ConfigurationListener mConfigurationListener = - new ConfigurationController.ConfigurationListener() { - @Override - public void onConfigChanged(Configuration newConfig) { - if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { - return; - } - boolean visible = false; - if (mView != null) { - visible = mView.isShowing(); - if (mView.isAttachedToWindow()) { - mWindowManager.removeView(mView); - } - } - - if (visible) { - showOrb(false); - } - } - }; - - AssistOrbController(ConfigurationController configurationController, Context context) { - mContext = context; - mWindowManager = mContext.getSystemService(WindowManager.class); - mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION - | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE - | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS); - - configurationController.addCallback(mConfigurationListener); - mConfigurationListener.onConfigChanged(context.getResources().getConfiguration()); - } - - public void postHide() { - mView.post(mHideRunnable); - } - - public void postHideDelayed(long delayMs) { - mView.postDelayed(mHideRunnable, delayMs); - } - - private void showOrb(boolean animated) { - if (mView == null) { - mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate( - R.layout.assist_orb, null); - mView.setVisibility(View.GONE); - mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - } - if (!mView.isAttachedToWindow()) { - WindowManager.LayoutParams params = getLayoutParams(); - mWindowManager.addView(mView, params); - } - mView.show(true, animated, null); - } - - private WindowManager.LayoutParams getLayoutParams() { - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height), - WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING, - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - PixelFormat.TRANSLUCENT); - lp.token = new Binder(); - lp.gravity = Gravity.BOTTOM | Gravity.START; - lp.setTitle("AssistPreviewPanel"); - lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED - | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; - return lp; - } - - public void showOrb(@NonNull ComponentName assistComponent, boolean isService) { - showOrb(true); - maybeSwapSearchIcon(assistComponent, isService); - } - - private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) { - replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME, - isService); - } - - public void replaceDrawable(ImageView v, ComponentName component, String name, - boolean isService) { - if (component != null) { - try { - PackageManager packageManager = mContext.getPackageManager(); - // Look for the search icon specified in the activity meta-data - Bundle metaData = isService - ? packageManager.getServiceInfo( - component, PackageManager.GET_META_DATA).metaData - : packageManager.getActivityInfo( - component, PackageManager.GET_META_DATA).metaData; - if (metaData != null) { - int iconResId = metaData.getInt(name); - if (iconResId != 0) { - Resources res = packageManager.getResourcesForApplication( - component.getPackageName()); - v.setImageDrawable(res.getDrawable(iconResId)); - return; - } - } - } catch (PackageManager.NameNotFoundException e) { - if (VERBOSE) { - Log.v(TAG, "Assistant component " - + component.flattenToShortString() + " not found"); - } - } catch (Resources.NotFoundException nfe) { - Log.w(TAG, "Failed to swap drawable from " - + component.flattenToShortString(), nfe); - } - } - v.setImageDrawable(null); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java deleted file mode 100644 index 16d9c84c8734..000000000000 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2014 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.assist; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Outline; -import android.graphics.Paint; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewOutlineProvider; -import android.view.animation.Interpolator; -import android.view.animation.OvershootInterpolator; -import android.widget.FrameLayout; -import android.widget.ImageView; - -import com.android.systemui.R; -import com.android.systemui.animation.Interpolators; - -public class AssistOrbView extends FrameLayout { - - private final int mCircleMinSize; - private final int mBaseMargin; - private final int mStaticOffset; - private final Paint mBackgroundPaint = new Paint(); - private final Rect mCircleRect = new Rect(); - private final Rect mStaticRect = new Rect(); - private final Interpolator mOvershootInterpolator = new OvershootInterpolator(); - - private boolean mClipToOutline; - private final int mMaxElevation; - private float mOutlineAlpha; - private float mOffset; - private float mCircleSize; - private ImageView mLogo; - private float mCircleAnimationEndValue; - - private ValueAnimator mOffsetAnimator; - private ValueAnimator mCircleAnimator; - - private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener - = new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - applyCircleSize((float) animation.getAnimatedValue()); - updateElevation(); - } - }; - private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mCircleAnimator = null; - } - }; - private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener - = new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mOffset = (float) animation.getAnimatedValue(); - updateLayout(); - } - }; - - - public AssistOrbView(Context context) { - this(context, null); - } - - public AssistOrbView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - if (mCircleSize > 0.0f) { - outline.setOval(mCircleRect); - } else { - outline.setEmpty(); - } - outline.setAlpha(mOutlineAlpha); - } - }); - setWillNotDraw(false); - mCircleMinSize = context.getResources().getDimensionPixelSize( - R.dimen.assist_orb_size); - mBaseMargin = context.getResources().getDimensionPixelSize( - R.dimen.assist_orb_base_margin); - mStaticOffset = context.getResources().getDimensionPixelSize( - R.dimen.assist_orb_travel_distance); - mMaxElevation = context.getResources().getDimensionPixelSize( - R.dimen.assist_orb_elevation); - mBackgroundPaint.setAntiAlias(true); - mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color)); - } - - public ImageView getLogo() { - return mLogo; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawBackground(canvas); - } - - private void drawBackground(Canvas canvas) { - canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2, - mBackgroundPaint); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mLogo = findViewById(R.id.search_logo); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight()); - if (changed) { - updateCircleRect(mStaticRect, mStaticOffset, true); - } - } - - public void animateCircleSize(float circleSize, long duration, - long startDelay, Interpolator interpolator) { - if (circleSize == mCircleAnimationEndValue) { - return; - } - if (mCircleAnimator != null) { - mCircleAnimator.cancel(); - } - mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize); - mCircleAnimator.addUpdateListener(mCircleUpdateListener); - mCircleAnimator.addListener(mClearAnimatorListener); - mCircleAnimator.setInterpolator(interpolator); - mCircleAnimator.setDuration(duration); - mCircleAnimator.setStartDelay(startDelay); - mCircleAnimator.start(); - mCircleAnimationEndValue = circleSize; - } - - private void applyCircleSize(float circleSize) { - mCircleSize = circleSize; - updateLayout(); - } - - private void updateElevation() { - float t = (mStaticOffset - mOffset) / (float) mStaticOffset; - t = 1.0f - Math.max(t, 0.0f); - float offset = t * mMaxElevation; - setElevation(offset); - } - - /** - * Animates the offset to the edge of the screen. - * - * @param offset The offset to apply. - * @param startDelay The desired start delay if animated. - * - * @param interpolator The desired interpolator if animated. If null, - * a default interpolator will be taken designed for appearing or - * disappearing. - */ - private void animateOffset(float offset, long duration, long startDelay, - Interpolator interpolator) { - if (mOffsetAnimator != null) { - mOffsetAnimator.removeAllListeners(); - mOffsetAnimator.cancel(); - } - mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset); - mOffsetAnimator.addUpdateListener(mOffsetUpdateListener); - mOffsetAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mOffsetAnimator = null; - } - }); - mOffsetAnimator.setInterpolator(interpolator); - mOffsetAnimator.setStartDelay(startDelay); - mOffsetAnimator.setDuration(duration); - mOffsetAnimator.start(); - } - - private void updateLayout() { - updateCircleRect(); - updateLogo(); - invalidateOutline(); - invalidate(); - updateClipping(); - } - - private void updateClipping() { - boolean clip = mCircleSize < mCircleMinSize; - if (clip != mClipToOutline) { - setClipToOutline(clip); - mClipToOutline = clip; - } - } - - private void updateLogo() { - float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f; - float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f - - mLogo.getHeight() / 2.0f - mCircleMinSize / 7f; - float t = (mStaticOffset - mOffset) / (float) mStaticOffset; - translationY += t * mStaticOffset * 0.1f; - float alpha = 1.0f-t; - alpha = Math.max((alpha - 0.5f) * 2.0f, 0); - mLogo.setImageAlpha((int) (alpha * 255)); - mLogo.setTranslationX(translationX); - mLogo.setTranslationY(translationY); - } - - private void updateCircleRect() { - updateCircleRect(mCircleRect, mOffset, false); - } - - private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) { - int left, top; - float circleSize = useStaticSize ? mCircleMinSize : mCircleSize; - left = (int) (getWidth() - circleSize) / 2; - top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset); - rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize)); - } - - public void startExitAnimation(long delay) { - animateCircleSize(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN); - animateOffset(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN); - } - - public void startEnterAnimation() { - applyCircleSize(0); - post(new Runnable() { - @Override - public void run() { - animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator); - animateOffset(mStaticOffset, 400, 0 /* delay */, Interpolators.LINEAR_OUT_SLOW_IN); - } - }); - } - - public void reset() { - mClipToOutline = false; - mBackgroundPaint.setAlpha(255); - mOutlineAlpha = 1.0f; - } - - @Override - public boolean hasOverlappingRendering() { - // not really true but it's ok during an animation, as it's never permanent - return false; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index de45766af47d..9ce0e94cca18 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -47,6 +47,7 @@ import android.os.RemoteException; import android.os.Trace; import android.os.VibrationEffect; import android.os.Vibrator; +import android.provider.Settings; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; @@ -162,6 +163,7 @@ public class UdfpsController implements DozeReceiver { private boolean mOnFingerDown; private boolean mAttemptedToDismissKeyguard; private Set<Callback> mCallbacks = new HashSet<>(); + private final VibrationEffect mLowTick; @VisibleForTesting public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = @@ -171,6 +173,7 @@ public class UdfpsController implements DozeReceiver { .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY) .build(); + // haptic to use for successful device entry public static final VibrationEffect EFFECT_CLICK = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); @@ -276,6 +279,9 @@ public class UdfpsController implements DozeReceiver { return; } mGoodCaptureReceived = true; + if (mVibrator != null) { + mVibrator.cancel(); + } mView.stopIllumination(); if (mServerRequest != null) { mServerRequest.onAcquiredGood(); @@ -434,7 +440,7 @@ public class UdfpsController implements DozeReceiver { if (idx == event.getActionIndex()) { boolean actionMoveWithinSensorArea = isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx), - fromUdfpsView); + fromUdfpsView); if ((fromUdfpsView || actionMoveWithinSensorArea) && shouldTryToDismissKeyguard()) { Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE"); @@ -508,9 +514,9 @@ public class UdfpsController implements DozeReceiver { private boolean shouldTryToDismissKeyguard() { return mView.getAnimationViewController() != null - && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController - && mKeyguardStateController.canDismissLockScreen() - && !mAttemptedToDismissKeyguard; + && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController + && mKeyguardStateController.canDismissLockScreen() + && !mAttemptedToDismissKeyguard; } @Inject @@ -542,7 +548,6 @@ public class UdfpsController implements DozeReceiver { @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { mContext = context; mExecution = execution; - // TODO (b/185124905): inject main handler and vibrator once done prototyping mVibrator = vibrator; mInflater = inflater; // The fingerprint manager is queried for UDFPS before this class is constructed, so the @@ -567,6 +572,7 @@ public class UdfpsController implements DozeReceiver { mConfigurationController = configurationController; mSystemClock = systemClock; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + mLowTick = lowTick(); mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -601,6 +607,27 @@ public class UdfpsController implements DozeReceiver { udfpsHapticsSimulator.setUdfpsController(this); } + private VibrationEffect lowTick() { + float tickIntensity = Settings.Global.getFloat( + mContext.getContentResolver(), "low-tick-intensity", .5f); + VibrationEffect.Composition composition = VibrationEffect.startComposition(); + composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, + tickIntensity, 0); + int tickDelay = Settings.Global.getInt( + mContext.getContentResolver(), "low-tick-delay", 25); + int primitives = 1000 / tickDelay; + float[] rampUp = new float[]{.48f, .58f, .69f, .83f}; + for (int i = 0; i < rampUp.length; i++) { + composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, + tickIntensity * rampUp[i], tickDelay); + } + for (int i = rampUp.length; i < primitives; i++) { + composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, + tickIntensity, tickDelay); + } + return composition.compose(); + } + /** * Play haptic to signal udfps scanning started. */ @@ -610,8 +637,8 @@ public class UdfpsController implements DozeReceiver { mVibrator.vibrate( Process.myUid(), mContext.getOpPackageName(), - EFFECT_CLICK, - "udfps-onStart", + mLowTick, + "udfps-onStart-tick", VIBRATION_SONIFICATION_ATTRIBUTES); } } @@ -998,6 +1025,7 @@ public class UdfpsController implements DozeReceiver { } } mOnFingerDown = false; + mVibrator.cancel(); if (mView.isIlluminationRequested()) { mView.stopIllumination(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index 79723188348e..b51eb0734a77 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -442,7 +442,11 @@ public class FrameworkServicesModule { @Provides @Singleton static PermissionManager providePermissionManager(Context context) { - return context.getSystemService(PermissionManager.class); + PermissionManager pm = context.getSystemService(PermissionManager.class); + if (pm != null) { + pm.initializeUsageHelper(); + } + return pm; } @Provides diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 12786f278a16..fd3fcdd1d58a 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -66,6 +66,7 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ZenModeController; @@ -124,6 +125,7 @@ import dagger.Provides; }, subcomponents = { StatusBarComponent.class, + StatusBarFragmentComponent.class, NotificationRowComponent.class, DozeComponent.class, ExpandableNotificationRowComponent.class, diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 765c24507662..d27c39a89319 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -16,6 +16,10 @@ package com.android.systemui.doze; +import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT; + +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -31,11 +35,13 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.IndentingPrintWriter; +import com.android.internal.R; import com.android.systemui.doze.dagger.BrightnessSensor; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.doze.dagger.WrappedService; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -57,6 +63,12 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi "com.android.systemui.doze.AOD_BRIGHTNESS"; protected static final String BRIGHTNESS_BUCKET = "brightness_bucket"; + /** + * Just before the screen times out from user inactivity, DisplayPowerController dims the screen + * brightness to the lower of {@link #mScreenBrightnessDim}, or the current brightness minus + * this amount. + */ + private final float mScreenBrightnessMinimumDimAmountFloat; private final Context mContext; private final DozeMachine.Service mDozeService; private final DozeHost mDozeHost; @@ -87,6 +99,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi */ private int mDebugBrightnessBucket = -1; + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Inject public DozeScreenBrightness( Context context, @@ -98,8 +112,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi WakefulnessLifecycle wakefulnessLifecycle, DozeParameters dozeParameters, DevicePostureController devicePostureController, - DozeLog dozeLog - ) { + DozeLog dozeLog, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { mContext = context; mDozeService = service; mSensorManager = sensorManager; @@ -111,6 +125,10 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi mDozeHost = host; mHandler = handler; mDozeLog = dozeLog; + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; + + mScreenBrightnessMinimumDimAmountFloat = context.getResources().getFloat( + R.dimen.config_screenBrightnessMinimumDimAmountFloat); mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness; mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness; @@ -163,14 +181,15 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } } - private void updateBrightnessAndReady(boolean force) { + public void updateBrightnessAndReady(boolean force) { if (force || mRegistered || mDebugBrightnessBucket != -1) { int sensorValue = mDebugBrightnessBucket == -1 ? mLastSensorValue : mDebugBrightnessBucket; int brightness = computeBrightness(sensorValue); boolean brightnessReady = brightness > 0; if (brightnessReady) { - mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness)); + mDozeService.setDozeScreenBrightness( + clampToDimBrightnessForScreenOff(clampToUserSetting(brightness))); } int scrimOpacity = -1; @@ -243,13 +262,24 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi /** * Clamp the brightness to the dim brightness value used by PowerManagerService just before the * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we - * don't raise the brightness back to the user setting before playing the screen off animation. + * don't raise the brightness back to the user setting before or during the screen off + * animation. */ private int clampToDimBrightnessForScreenOff(int brightness) { - if (mDozeParameters.shouldControlUnlockedScreenOff() - && mWakefulnessLifecycle.getLastSleepReason() - == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { - return Math.min(mScreenBrightnessDim, brightness); + final boolean screenTurningOff = + mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() + || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP; + if (screenTurningOff + && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) { + return Math.max( + PowerManager.BRIGHTNESS_OFF, + // Use the lower of either the dim brightness, or the current brightness reduced + // by the minimum dim amount. This is the same logic used in + // DisplayPowerController#updatePowerState to apply a minimum dim amount. + Math.min( + brightness - (int) Math.floor( + mScreenBrightnessMinimumDimAmountFloat * 255), + mScreenBrightnessDim)); } else { return brightness; } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 908397bd775c..36319380ad50 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -77,6 +77,7 @@ public class DozeScreenState implements DozeMachine.Part { private final Provider<UdfpsController> mUdfpsControllerProvider; @Nullable private UdfpsController mUdfpsController; private final DozeLog mDozeLog; + private final DozeScreenBrightness mDozeScreenBrightness; private int mPendingScreenState = Display.STATE_UNKNOWN; private SettableWakeLock mWakeLock; @@ -90,7 +91,8 @@ public class DozeScreenState implements DozeMachine.Part { WakeLock wakeLock, AuthController authController, Provider<UdfpsController> udfpsControllerProvider, - DozeLog dozeLog) { + DozeLog dozeLog, + DozeScreenBrightness dozeScreenBrightness) { mDozeService = service; mHandler = handler; mParameters = parameters; @@ -99,6 +101,7 @@ public class DozeScreenState implements DozeMachine.Part { mAuthController = authController; mUdfpsControllerProvider = udfpsControllerProvider; mDozeLog = dozeLog; + mDozeScreenBrightness = dozeScreenBrightness; updateUdfpsController(); if (mUdfpsController == null) { @@ -209,6 +212,12 @@ public class DozeScreenState implements DozeMachine.Part { if (screenState != Display.STATE_UNKNOWN) { if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")"); mDozeService.setDozeScreenState(screenState); + if (screenState == Display.STATE_DOZE) { + // If we're entering doze, update the doze screen brightness. We might have been + // clamping it to the dim brightness during the screen off animation, and we should + // now change it to the brightness we actually want according to the sensor. + mDozeScreenBrightness.updateBrightnessAndReady(false /* force */); + } mPendingScreenState = Display.STATE_UNKNOWN; mWakeLock.setAcquired(false); } diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index 4f5a969c9791..7f57fcc56117 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -24,7 +24,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.qs.QSFragment; -import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.FileDescriptor; diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java index c8afd72d1dde..9ca0293fbd86 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java @@ -26,8 +26,8 @@ import java.lang.annotation.Retention; import javax.inject.Qualifier; /** - * A {@link LogBuffer} for - * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}-related messages. + * A {@link LogBuffer} for {@link + * com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}-related messages. */ @Qualifier @Documented diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 46e2274970f7..1f0de4e10d05 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -102,7 +102,7 @@ public class LogModule { /** * Provides a logging buffer for - * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}. + * {@link com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}. */ @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index c6da3420ffe9..4d4962e7d4c2 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -101,8 +101,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private static final int MAX_NUM_LOGGED_PREDICTIONS = 10; private static final int MAX_NUM_LOGGED_GESTURES = 10; - // Temporary log until b/201642126 is resolved - static final boolean DEBUG_MISSING_GESTURE = true; + static final boolean DEBUG_MISSING_GESTURE = false; static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index dd876b7c7d24..e42c47b1d3be 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -15,10 +15,10 @@ package com.android.systemui.qs; import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; -import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState; import static com.android.systemui.media.dagger.MediaModule.QS_PANEL; import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL; +import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -696,6 +696,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca mQSPanelController.closeDetail(); } + @Override + public void closeCustomizer() { + mQSCustomizerController.hide(); + } + public void notifyCustomizeChanged() { // The customize state changed, so our height changed. mContainer.updateExpansion(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt index 17a815e72583..8544f61d7031 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt @@ -4,7 +4,6 @@ import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel import com.android.systemui.log.dagger.QSFragmentDisableLog import com.android.systemui.statusbar.DisableFlagsLogger -import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment import javax.inject.Inject /** A helper class for logging disable flag changes made in [QSFragment]. */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java index 8aa2d09459e5..d2bc38edd337 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java +++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java @@ -54,19 +54,23 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl } public int getValue() { - return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId); + return mListening ? mObservedValue : getValueFromProvider(); } public void setValue(int value) { mSecureSettings.putIntForUser(mSettingName, value, mUserId); } + private int getValueFromProvider() { + return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId); + } + @Override public void setListening(boolean listening) { if (listening == mListening) return; mListening = listening; if (listening) { - mObservedValue = getValue(); + mObservedValue = getValueFromProvider(); mSecureSettings.registerContentObserverForUser( mSecureSettings.getUriFor(mSettingName), false, this, mUserId); } else { @@ -77,9 +81,10 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl @Override public void onChange(boolean selfChange) { - final int value = getValue(); - handleValueChanged(value, value != mObservedValue); + final int value = getValueFromProvider(); + final boolean changed = value != mObservedValue; mObservedValue = value; + handleValueChanged(value, changed); } public void setUserId(int userId) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index e896c7ca87e6..b1cd68e5185c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -61,10 +61,12 @@ import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.SecureSetting; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.volume.ZenModePanel; import javax.inject.Inject; @@ -81,6 +83,7 @@ public class DndTile extends QSTileImpl<BooleanState> { private final ZenModeController mController; private final DndDetailAdapter mDetailAdapter; private final SharedPreferences mSharedPreferences; + private final SecureSetting mSettingZenDuration; private boolean mListening; private boolean mShowingDetail; @@ -96,7 +99,8 @@ public class DndTile extends QSTileImpl<BooleanState> { ActivityStarter activityStarter, QSLogger qsLogger, ZenModeController zenModeController, - @Main SharedPreferences sharedPreferences + @Main SharedPreferences sharedPreferences, + SecureSettings secureSettings ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); @@ -104,8 +108,17 @@ public class DndTile extends QSTileImpl<BooleanState> { mSharedPreferences = sharedPreferences; mDetailAdapter = new DndDetailAdapter(); mController.observe(getLifecycle(), mZenCallback); + mSettingZenDuration = new SecureSetting(secureSettings, mUiHandler, + Settings.Secure.ZEN_DURATION, getHost().getUserId()) { + @Override + protected void handleValueChanged(int value, boolean observedChange) { + refreshState(); + } + }; } + + public static void setVisible(Context context, boolean visible) { Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible); } @@ -144,14 +157,18 @@ public class DndTile extends QSTileImpl<BooleanState> { if (mState.value) { mController.setZen(ZEN_MODE_OFF, null, TAG); } else { - showDetail(true); + enableZenMode(view); } } @Override - public void showDetail(boolean show) { - int zenDuration = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ZEN_DURATION, 0); + protected void handleUserSwitch(int newUserId) { + super.handleUserSwitch(newUserId); + mSettingZenDuration.setUserId(newUserId); + } + + private void enableZenMode(@Nullable View view) { + int zenDuration = mSettingZenDuration.getValue(); boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 && Settings.Secure.getInt(mContext.getContentResolver(), @@ -270,6 +287,8 @@ public class DndTile extends QSTileImpl<BooleanState> { state.dualLabelContentDescription = mContext.getResources().getString( R.string.accessibility_quick_settings_open_settings, getTileLabel()); state.expandedAccessibilityClassName = Switch.class.getName(); + state.forceExpandIcon = + mSettingZenDuration.getValue() == Settings.Secure.ZEN_DURATION_PROMPT; } @Override @@ -296,6 +315,13 @@ public class DndTile extends QSTileImpl<BooleanState> { } else { Prefs.unregisterListener(mContext, mPrefListener); } + mSettingZenDuration.setListening(listening); + } + + @Override + protected void handleDestroy() { + super.handleDestroy(); + mSettingZenDuration.setListening(false); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 563c4cd628d2..77b9cc14fa6d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -306,12 +306,8 @@ public class InternetDialog extends SystemUIDialog implements final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled(); updateWifiToggle(isWifiEnabled, isDeviceLocked); updateConnectedWifi(isWifiEnabled, isDeviceLocked); + updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked); updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked); - - final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0) - ? View.GONE : View.VISIBLE; - mWifiRecyclerView.setVisibility(visibility); - mSeeAllLayout.setVisibility(visibility); } private void setOnClickListener() { @@ -414,6 +410,18 @@ public class InternetDialog extends SystemUIDialog implements } @MainThread + private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) { + if (!isWifiEnabled || isDeviceLocked) { + mWifiRecyclerView.setVisibility(View.GONE); + mSeeAllLayout.setVisibility(View.GONE); + return; + } + mWifiRecyclerView.setVisibility(mWifiEntriesCount > 0 ? View.VISIBLE : View.GONE); + mSeeAllLayout.setVisibility( + (mConnectedWifiEntry != null || mWifiEntriesCount > 0) ? View.VISIBLE : View.GONE); + } + + @MainThread private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, boolean isDeviceLocked) { if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index dcb1e4f34188..ef7285b03a7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -33,11 +33,9 @@ import android.graphics.drawable.Icon; import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; -import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.AsyncTask; import android.os.Trace; -import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; @@ -83,7 +81,6 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -132,7 +129,6 @@ public class NotificationMediaManager implements Dumpable { private final DelayableExecutor mMainExecutor; private final Context mContext; - private final MediaSessionManager mMediaSessionManager; private final ArrayList<MediaListener> mMediaListeners; private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy; private final MediaArtworkProcessor mMediaArtworkProcessor; @@ -194,10 +190,6 @@ public class NotificationMediaManager implements Dumpable { mMediaArtworkProcessor = mediaArtworkProcessor; mKeyguardBypassController = keyguardBypassController; mMediaListeners = new ArrayList<>(); - // TODO: use MediaSessionManager.SessionListener to hook us up to future updates - // in session state - mMediaSessionManager = (MediaSessionManager) mContext.getSystemService( - Context.MEDIA_SESSION_SERVICE); // TODO: use KeyguardStateController#isOccluded to remove this dependency mStatusBarOptionalLazy = statusBarOptionalLazy; mNotificationShadeWindowController = notificationShadeWindowController; @@ -487,35 +479,6 @@ public class NotificationMediaManager implements Dumpable { } } } - if (mediaNotification == null) { - // Still nothing? OK, let's just look for live media sessions and see if they match - // one of our notifications. This will catch apps that aren't (yet!) using media - // notifications. - - if (mMediaSessionManager != null) { - // TODO: Should this really be for all users? It appears that inactive users - // can't have active sessions, which would mean it is fine. - final List<MediaController> sessions = - mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.ALL); - - for (MediaController aController : sessions) { - // now to see if we have one like this - final String pkg = aController.getPackageName(); - - for (NotificationEntry entry : allNotifications) { - if (entry.getSbn().getPackageName().equals(pkg)) { - if (DEBUG_MEDIA) { - Log.v(TAG, "DEBUG_MEDIA: found controller matching " - + entry.getSbn().getKey()); - } - controller = aController; - mediaNotification = entry; - break; - } - } - } - } - } if (controller != null && !sameSessions(mMediaController, controller)) { // We have a new media session @@ -561,8 +524,6 @@ public class NotificationMediaManager implements Dumpable { @Override public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { - pw.print(" mMediaSessionManager="); - pw.println(mMediaSessionManager); pw.print(" mMediaNotificationKey="); pw.println(mMediaNotificationKey); pw.print(" mMediaController="); 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 988034f9c5fd..9b5fa2a49ff1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -172,6 +172,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.phone.panelstate.PanelState; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -2869,6 +2870,10 @@ public class NotificationPanelViewController extends PanelViewController { mStatusBarTouchableRegionManager.setPanelExpanded(isExpanded); mStatusBar.setPanelExpanded(isExpanded); mPanelExpanded = isExpanded; + + if (!isExpanded && mQs != null && mQs.isCustomizing()) { + mQs.closeCustomizer(); + } } } @@ -3167,10 +3172,20 @@ public class NotificationPanelViewController extends PanelViewController { return mQs.isShowingDetail(); } + /** Returns whether the QS customizer is currently active. */ + public boolean isQsCustomizing() { + return mQs.isCustomizing(); + } + public void closeQsDetail() { mQs.closeDetail(); } + /** Close the QS customizer if it is open. */ + public void closeQsCustomizer() { + mQs.closeCustomizer(); + } + public boolean isLaunchTransitionFinished() { return mIsLaunchTransitionFinished; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index cbaa4683c364..b8b8e5634164 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -40,7 +40,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode; -import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST; import android.annotation.Nullable; import android.app.ActivityManager; @@ -137,7 +136,6 @@ import com.android.systemui.SystemUI; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.DelegateLaunchAnimatorController; import com.android.systemui.assist.AssistManager; -import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.biometrics.AuthRippleController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.camera.CameraIntents; @@ -217,6 +215,9 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -488,6 +489,7 @@ public class StatusBar extends SystemUI implements private final DozeParameters mDozeParameters; private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final StatusBarComponent.Factory mStatusBarComponentFactory; + private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; private final PluginManager mPluginManager; private final Optional<LegacySplitScreen> mSplitScreenOptional; private final StatusBarNotificationActivityStarter.Builder @@ -672,7 +674,6 @@ public class StatusBar extends SystemUI implements private final ActivityIntentHelper mActivityIntentHelper; private NotificationStackScrollLayoutController mStackScrollerController; - private BatteryMeterViewController mBatteryMeterViewController; private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener = (extractor, which) -> updateTheme(); @@ -744,6 +745,7 @@ public class StatusBar extends SystemUI implements CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, + StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -848,6 +850,7 @@ public class StatusBar extends SystemUI implements mCommandQueue = commandQueue; mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger; mStatusBarComponentFactory = statusBarComponentFactory; + mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mPluginManager = pluginManager; mSplitScreenOptional = splitScreenOptional; mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder; @@ -918,8 +921,6 @@ public class StatusBar extends SystemUI implements mBypassHeadsUpNotifier.setUp(); if (mBubblesOptional.isPresent()) { mBubblesOptional.get().setExpandListener(mBubbleExpandListener); - IntentFilter filter = new IntentFilter(TASKBAR_CHANGED_BROADCAST); - mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter); } mKeyguardIndicationController.init(); @@ -1134,28 +1135,21 @@ public class StatusBar extends SystemUI implements mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class); mStatusBarWindowController.getFragmentHostManager() .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { - CollapsedStatusBarFragment statusBarFragment = - (CollapsedStatusBarFragment) fragment; + StatusBarFragmentComponent statusBarFragmentComponent = + ((CollapsedStatusBarFragment) fragment).getStatusBarFragmentComponent(); + if (statusBarFragmentComponent == null) { + throw new IllegalStateException( + "CollapsedStatusBarFragment should have a valid component"); + } - PhoneStatusBarView oldStatusBarView = mStatusBarView; - mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView(); + mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView(); + // TODO(b/205609837): Migrate this to StatusBarFragmentComponent. mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory .create(mStatusBarView, mNotificationPanelViewController .getStatusBarTouchEventHandler()); mPhoneStatusBarViewController.init(); - mBatteryMeterViewController = new BatteryMeterViewController( - mStatusBarView.findViewById(R.id.battery), - mConfigurationController, - mTunerService, - mBroadcastDispatcher, - mMainHandler, - mContext.getContentResolver(), - mBatteryController - ); - mBatteryMeterViewController.init(); - // Ensure we re-propagate panel expansion values to the panel controller and // any listeners it may have, such as PanelBar. This will also ensure we // re-display the notification panel if necessary (for example, if @@ -1169,8 +1163,8 @@ public class StatusBar extends SystemUI implements // This view is being recreated, let's destroy the old one mHeadsUpAppearanceController.destroy(); } - // TODO: this should probably be scoped to the StatusBarComponent // TODO (b/136993073) Separate notification shade and status bar + // TODO(b/205609837): Migrate this to StatusBarFragmentComponent. mHeadsUpAppearanceController = new HeadsUpAppearanceController( mNotificationIconAreaController, mHeadsUpManager, mStackScrollerController, @@ -1187,6 +1181,7 @@ public class StatusBar extends SystemUI implements .beginTransaction() .replace(R.id.status_bar_container, new CollapsedStatusBarFragment( + mStatusBarFragmentComponentFactory, mOngoingCallController, mAnimationScheduler, mStatusBarLocationPublisher, @@ -3283,6 +3278,10 @@ public class StatusBar extends SystemUI implements } return true; } + if (mNotificationPanelViewController.isQsCustomizing()) { + mNotificationPanelViewController.closeQsCustomizer(); + return true; + } if (mNotificationPanelViewController.isQsExpanded()) { if (mNotificationPanelViewController.isQsDetailShowing()) { mNotificationPanelViewController.closeQsDetail(); @@ -4270,13 +4269,6 @@ public class StatusBar extends SystemUI implements } }; - BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - mBubblesOptional.ifPresent(bubbles -> bubbles.onTaskbarChanged(intent.getExtras())); - } - }; - private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { @Override public void onConfigChanged(Configuration newConfig) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 3259f6b8027b..56fd6e4446de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -75,7 +75,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.BiometricUnlockController; -import com.android.systemui.statusbar.phone.CollapsedStatusBarFragmentLogger; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.DozeScrimController; import com.android.systemui.statusbar.phone.DozeServiceHost; @@ -99,6 +98,8 @@ import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -197,6 +198,7 @@ public interface StatusBarPhoneModule { CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, + StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -297,6 +299,7 @@ public interface StatusBarPhoneModule { commandQueue, collapsedStatusBarFragmentLogger, statusBarComponentFactory, + statusBarFragmentComponentFactory, pluginManager, splitScreenOptional, lightsOutNotifController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index fe621da17767..9bcf4a58ce0b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -12,7 +12,7 @@ * permissions and limitations under the License. */ -package com.android.systemui.statusbar.phone; +package com.android.systemui.statusbar.phone.fragment; import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; import static android.app.StatusBarManager.DISABLE_CLOCK; @@ -52,7 +52,14 @@ import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; +import com.android.systemui.statusbar.phone.PhoneStatusBarView; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; +import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager; +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; @@ -83,6 +90,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager"; public static final int FADE_IN_DURATION = 320; public static final int FADE_IN_DELAY = 50; + private StatusBarFragmentComponent mStatusBarFragmentComponent; private PhoneStatusBarView mStatusBar; private final StatusBarStateController mStatusBarStateController; private final KeyguardStateController mKeyguardStateController; @@ -96,6 +104,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private int mDisabled2; private Lazy<Optional<StatusBar>> mStatusBarOptionalLazy; private DarkIconManager mDarkIconManager; + private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; private final CommandQueue mCommandQueue; private final CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger; private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory; @@ -127,6 +136,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue @Inject public CollapsedStatusBarFragment( + StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, StatusBarLocationPublisher locationPublisher, @@ -143,6 +153,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, OperatorNameViewController.Factory operatorNameViewControllerFactory ) { + mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; mLocationPublisher = locationPublisher; @@ -169,6 +180,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(this); + mStatusBarFragmentComponent.init(); + mStatusBar = (PhoneStatusBarView) view; View contents = mStatusBar.findViewById(R.id.status_bar_contents); contents.addOnLayoutChangeListener(mStatusBarLayoutListener); @@ -252,6 +266,17 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue updateNotificationIconAreaAndCallChip(mDisabled1, false); } + /** + * Returns the dagger component for this fragment. + * + * TODO(b/205609837): Eventually, the dagger component should encapsulate all status bar + * fragment functionality and we won't need to expose it here anymore. + */ + @Nullable + public StatusBarFragmentComponent getStatusBarFragmentComponent() { + return mStatusBarFragmentComponent; + } + @Override public void disable(int displayId, int state1, int state2, boolean animate) { if (displayId != getContext().getDisplayId()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt index 4d472e47a387..9ae378f34fc0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.phone +package com.android.systemui.statusbar.phone.fragment import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java new file mode 100644 index 000000000000..47c187540740 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java @@ -0,0 +1,69 @@ +/* + * 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.statusbar.phone.fragment.dagger; + +import com.android.systemui.battery.BatteryMeterViewController; +import com.android.systemui.dagger.qualifiers.RootView; +import com.android.systemui.statusbar.phone.PhoneStatusBarView; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; + +import dagger.BindsInstance; +import dagger.Subcomponent; + +/** + * A subcomponent that gets re-created each time we create a new {@link CollapsedStatusBarFragment}. + * + * This component will also re-create all classes that depend on {@link CollapsedStatusBarFragment} + * and friends. Specifically, the fragment creates a new {@link PhoneStatusBarView} and multiple + * controllers need access to that view, so those controllers will be re-created whenever the + * fragment is recreated. + * + * Note that this is completely separate from + * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent}. This component gets + * re-created on each new fragment creation, whereas + * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent} is only created once in + * {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created. + */ + +@Subcomponent(modules = {StatusBarFragmentModule.class}) +@StatusBarFragmentScope +public interface StatusBarFragmentComponent { + /** Simple factory. */ + @Subcomponent.Factory + interface Factory { + StatusBarFragmentComponent create( + @BindsInstance CollapsedStatusBarFragment collapsedStatusBarFragment); + } + + /** + * Initialize anything extra for the component. Must be called after the component is created. + */ + default void init() { + // No one accesses this controller, so we need to make sure we reference it here so it does + // get initialized. + getBatteryMeterViewController().init(); + } + + /** */ + @StatusBarFragmentScope + BatteryMeterViewController getBatteryMeterViewController(); + + /** */ + @StatusBarFragmentScope + @RootView + PhoneStatusBarView getPhoneStatusBarView(); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java new file mode 100644 index 000000000000..969361bb6100 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java @@ -0,0 +1,46 @@ +/* + * 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.statusbar.phone.fragment.dagger; + +import com.android.systemui.R; +import com.android.systemui.battery.BatteryMeterView; +import com.android.systemui.dagger.qualifiers.RootView; +import com.android.systemui.statusbar.phone.PhoneStatusBarView; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; + +import dagger.Module; +import dagger.Provides; + +/** Dagger module for {@link StatusBarFragmentComponent}. */ +@Module +public interface StatusBarFragmentModule { + /** */ + @Provides + @RootView + @StatusBarFragmentScope + static PhoneStatusBarView providePhoneStatusBarView( + CollapsedStatusBarFragment collapsedStatusBarFragment) { + return (PhoneStatusBarView) collapsedStatusBarFragment.getView(); + } + + /** */ + @Provides + @StatusBarFragmentScope + static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) { + return view.findViewById(R.id.battery); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java new file mode 100644 index 000000000000..96cff5960d68 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.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.statusbar.phone.fragment.dagger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import javax.inject.Scope; + +/** + * Scope annotation for singleton items within the {@link StatusBarFragmentComponent}. + */ +@Documented +@Retention(RUNTIME) +@Scope +public @interface StatusBarFragmentScope {} diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 426bc91a606d..592fa152b406 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -176,6 +176,34 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { ? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM; } + private boolean isSeedColorSet(JSONObject jsonObject, WallpaperColors newWallpaperColors) { + if (newWallpaperColors == null) { + return false; + } + // Gets the color that was overridden in the theme setting if any. + String sysPaletteColor = (String) jsonObject.opt(OVERLAY_CATEGORY_SYSTEM_PALETTE); + if (sysPaletteColor == null) { + return false; + } + if (!sysPaletteColor.startsWith("#")) { + sysPaletteColor = "#" + sysPaletteColor; + } + final int systemPaletteColorArgb = Color.parseColor(sysPaletteColor); + // Gets seed colors from incoming {@link WallpaperColors} instance. + List<Integer> seedColors = ColorScheme.getSeedColors(newWallpaperColors); + for (int seedColor : seedColors) { + // The seed color from incoming {@link WallpaperColors} instance + // was set as color override. + if (seedColor == systemPaletteColorArgb) { + if (DEBUG) { + Log.d(TAG, "Same as previous set system palette: " + sysPaletteColor); + } + return true; + } + } + return false; + } + private void handleWallpaperColors(WallpaperColors wallpaperColors, int flags) { final boolean hadWallpaperColors = mCurrentColors != null; int latestWallpaperType = getLatestWallpaperType(); @@ -213,8 +241,11 @@ public class ThemeOverlayController extends SystemUI implements Dumpable { try { JSONObject jsonObject = (overlayPackageJson == null) ? new JSONObject() : new JSONObject(overlayPackageJson); + // The latest applied wallpaper should be the source of system colors when: + // There is not preset color applied and the incoming wallpaper color is not applied if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE)) - && ((flags & latestWallpaperType) != 0)) { + && ((flags & latestWallpaperType) != 0 && !isSeedColorSet(jsonObject, + wallpaperColors))) { mSkipSettingChange = true; if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has( OVERLAY_CATEGORY_SYSTEM_PALETTE)) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 5e0f427800fc..e967033b69a2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -18,14 +18,19 @@ package com.android.keyguard; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.res.Resources; +import android.database.ContentObserver; +import android.net.Uri; +import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.view.View; import android.widget.FrameLayout; @@ -50,6 +55,9 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; 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.concurrency.FakeExecutor; +import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; @@ -104,11 +112,14 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { private AnimatableClockView mLargeClockView; @Mock private FrameLayout mLargeClockFrame; + @Mock + private SecureSettings mSecureSettings; private final View mFakeSmartspaceView = new View(mContext); private KeyguardClockSwitchController mController; private View mSliceView; + private FakeExecutor mExecutor; @Before public void setup() { @@ -129,6 +140,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { when(mView.isAttachedToWindow()).thenReturn(true); when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView); + mExecutor = new FakeExecutor(new FakeSystemClock()); mController = new KeyguardClockSwitchController( mView, mStatusBarStateController, @@ -143,6 +155,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mSmartspaceController, mKeyguardUnlockAnimationController, mSmartSpaceTransitionController, + mSecureSettings, + mExecutor, mResources ); @@ -194,7 +208,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { verifyAttachment(times(1)); listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView); - verify(mView).onViewDetached(); verify(mColorExtractor).removeOnColorsChangedListener( any(ColorExtractor.OnColorsChangedListener.class)); } @@ -235,6 +248,25 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { verify(mSmartspaceController).requestSmartspaceUpdate(); } + @Test + public void testChangeToDoubleLineClockSetsSmallClock() { + when(mSecureSettings.getInt(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1)) + .thenReturn(0); + ArgumentCaptor<ContentObserver> observerCaptor = + ArgumentCaptor.forClass(ContentObserver.class); + mController.init(); + verify(mSecureSettings).registerContentObserver(any(Uri.class), + anyBoolean(), observerCaptor.capture()); + ContentObserver observer = observerCaptor.getValue(); + mExecutor.runAllReady(); + + // When a settings change has occurred to the small clock, make sure the view is adjusted + reset(mView); + observer.onChange(true); + mExecutor.runAllReady(); + verify(mView).switchToClock(KeyguardClockSwitch.SMALL); + } + private void verifyAttachment(VerificationMode times) { verify(mClockManager, times).addOnClockChangedListener( any(ClockManager.ClockChangedListener.class)); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt index db87c5df16e1..4bdab7658a06 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt @@ -75,8 +75,7 @@ private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel( shouldListenForFingerprintAssistant = false, switchingUser = false, udfps = false, - userDoesNotHaveTrust = false, - userNeedsStrongAuth = false + userDoesNotHaveTrust = false ) private fun faceModel(user: Int) = KeyguardFaceListenModel( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index ff5960bc33ce..de8cc8992da0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -19,6 +19,7 @@ package com.android.keyguard; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.google.common.truth.Truth.assertThat; @@ -961,6 +962,19 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void testStartUdfpsServiceStrongAuthRequiredAfterTimeout() { + // GIVEN status bar state is on the keyguard + mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); + + // WHEN user loses smart unlock trust + when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser())) + .thenReturn(SOME_AUTH_REQUIRED_AFTER_USER_REQUEST); + + // THEN we should still listen for udfps + assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true); + } + + @Test public void testShouldNotListenForUdfps_whenTrustEnabled() { // GIVEN a "we should listen for udfps" state mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index d90eb73a1595..9e42ff37ea69 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -642,12 +642,12 @@ public class UdfpsControllerTest extends SysuiTestCase { mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); moveEvent.recycle(); - // THEN click haptic is played + // THEN low-tick haptic is played verify(mVibrator).vibrate( anyInt(), anyString(), - eq(mUdfpsController.EFFECT_CLICK), - eq("udfps-onStart"), + any(), + eq("udfps-onStart-tick"), eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES)); // THEN make sure vibration attributes has so that it always will play the haptic, diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 886f84e19e0b..5b472ba6557b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -51,6 +51,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeThreadFactory; @@ -93,6 +94,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { DevicePostureController mDevicePostureController; @Mock DozeLog mDozeLog; + @Mock + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor); @@ -130,7 +133,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); } @Test @@ -236,7 +240,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); reset(mDozeHost); @@ -273,7 +278,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -304,7 +310,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); // GIVEN the device is in AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -342,7 +349,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); // GIVEN device is in AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); @@ -384,7 +392,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mWakefulnessLifecycle, mDozeParameters, mDevicePostureController, - mDozeLog); + mDozeLog, + mUnlockedScreenOffAnimationController); verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture()); // GIVEN device is in AOD @@ -466,24 +475,26 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void transitionToDoze_duringScreenOff_afterTimeout_clampsToDim() { + public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_clampsToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); // If we're dozing after a timeout, and playing the unlocked screen animation, we should - // stay at dim brightness, because the screen dims just before timeout. - assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS); + // stay at or below dim brightness, because the screen dims just before timeout. + assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); } @Test - public void transitionToDoze_duringScreenOff_notAfterTimeout_doesNotClampToDim() { + public void transitionToDoze_duringUnlockedScreenOff_notAfterTimeout_doesNotClampToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -494,10 +505,11 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void transitionToDoze_duringScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() { + public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -506,6 +518,36 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); } + @Test + public void transitionToDoze_duringLockedScreenOff_afterTimeout_clampsToDim() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + when(mWakefulnessLifecycle.getWakefulness()).thenReturn( + WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); + when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + + assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); + } + + @Test + public void transitionToDoze_duringLockedScreenOff_notAfterTimeout_doesNotClampToDim() { + when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); + when(mWakefulnessLifecycle.getWakefulness()).thenReturn( + WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); + when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE); + + assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); + } + private void waitForSensorManager() { mFakeExecutor.runAllReady(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 150ab7700e4b..3e19cc436dca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -82,6 +82,8 @@ public class DozeScreenStateTest extends SysuiTestCase { private UdfpsController mUdfpsController; @Mock private DozeLog mDozeLog; + @Mock + private DozeScreenBrightness mDozeScreenBrightness; @Before public void setUp() throws Exception { @@ -96,7 +98,8 @@ public class DozeScreenStateTest extends SysuiTestCase { mHandlerFake = new FakeHandler(Looper.getMainLooper()); mWakeLock = new WakeLockFake(); mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters, - mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog); + mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog, + mDozeScreenBrightness); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt new file mode 100644 index 000000000000..f99703e2415d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt @@ -0,0 +1,150 @@ +/* + * 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.tiles + +import android.content.ContextWrapper +import android.content.SharedPreferences +import android.os.Handler +import android.provider.Settings +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.UiEventLogger +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingManagerFake +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.QSHost +import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.statusbar.policy.ZenModeController +import com.android.systemui.util.settings.FakeSettings +import com.android.systemui.util.settings.SecureSettings +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import java.io.File + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class DndTileTest : SysuiTestCase() { + + companion object { + private const val DEFAULT_USER = 0 + private const val KEY = Settings.Secure.ZEN_DURATION + } + + @Mock + private lateinit var qsHost: QSHost + @Mock + private lateinit var metricsLogger: MetricsLogger + @Mock + private lateinit var statusBarStateController: StatusBarStateController + @Mock + private lateinit var activityStarter: ActivityStarter + @Mock + private lateinit var qsLogger: QSLogger + @Mock + private lateinit var uiEventLogger: UiEventLogger + @Mock + private lateinit var zenModeController: ZenModeController + @Mock + private lateinit var sharedPreferences: SharedPreferences + + private lateinit var secureSettings: SecureSettings + private lateinit var testableLooper: TestableLooper + private lateinit var tile: DndTile + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + testableLooper = TestableLooper.get(this) + secureSettings = FakeSettings() + + Mockito.`when`(qsHost.userId).thenReturn(DEFAULT_USER) + Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) + + val wrappedContext = object : ContextWrapper(context) { + override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences { + return sharedPreferences + } + } + Mockito.`when`(qsHost.context).thenReturn(wrappedContext) + + tile = DndTile( + qsHost, + testableLooper.looper, + Handler(testableLooper.looper), + FalsingManagerFake(), + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger, + zenModeController, + sharedPreferences, + secureSettings + ) + } + + @After + fun tearDown() { + tile.handleSetListening(false) + } + + @Test + fun testForceExpandIcon_durationAskAlways_true() { + secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER) + + tile.refreshState() + testableLooper.processAllMessages() + + assertThat(tile.state.forceExpandIcon).isTrue() + } + + @Test + fun testForceExpandIcon_durationNotAskAlways_false() { + secureSettings.putIntForUser(KEY, 60, DEFAULT_USER) + + tile.refreshState() + testableLooper.processAllMessages() + + assertThat(tile.state.forceExpandIcon).isFalse() + } + + @Test + fun testForceExpandIcon_changeWhileListening() { + secureSettings.putIntForUser(KEY, 60, DEFAULT_USER) + + tile.refreshState() + testableLooper.processAllMessages() + + assertThat(tile.state.forceExpandIcon).isFalse() + + tile.handleSetListening(true) + + secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER) + testableLooper.processAllMessages() + + assertThat(tile.state.forceExpandIcon).isTrue() + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index b6e8979db189..b32b4d4f3810 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -219,61 +219,89 @@ public class InternetDialogTest extends SysuiTestCase { } @Test - public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() { + public void updateDialog_wifiOnAndNoWifiEntry_hideWifiEntryAndSeeAll() { // The precondition WiFi ON is already in setUp() + mInternetDialog.mConnectedWifiEntry = null; mInternetDialog.mWifiEntriesCount = 0; mInternetDialog.updateDialog(false); + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); } @Test + public void updateDialog_wifiOnAndHasConnectedWifi_showConnectedWifiAndSeeAll() { + // The preconditions WiFi ON and WiFi entries are already in setUp() + mInternetDialog.mWifiEntriesCount = 0; + + mInternetDialog.updateDialog(false); + + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() { // The preconditions WiFi ON and WiFi entries are already in setUp() + mInternetDialog.mConnectedWifiEntry = null; mInternetDialog.updateDialog(false); + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); } @Test - public void updateDialog_deviceLockedAndHasInternetWifi_showHighlightWifiToggle() { - // The preconditions WiFi ON and Internet WiFi are already in setUp() - when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + public void updateDialog_wifiOnAndHasBothWifiEntry_showBothWifiEntryAndSeeAll() { + // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialog.updateDialog(false); - assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiToggle.getBackground()).isNotNull(); + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); } @Test - public void updateDialog_deviceLockedAndHasInternetWifi_hideConnectedWifi() { - // The preconditions WiFi ON and Internet WiFi are already in setUp() + public void updateDialog_deviceLockedAndNoConnectedWifi_showWifiToggle() { + // The preconditions WiFi entries are already in setUp() when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + mInternetDialog.mConnectedWifiEntry = null; mInternetDialog.updateDialog(false); + // Show WiFi Toggle without background + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggle.getBackground()).isNull(); + // Hide Wi-Fi networks and See all assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); + assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); } @Test - public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() { - // The preconditions WiFi entries are already in setUp() + public void updateDialog_deviceLockedAndHasConnectedWifi_showWifiToggleWithBackground() { + // The preconditions WiFi ON and WiFi entries are already in setUp() when(mInternetDialogController.isDeviceLocked()).thenReturn(true); mInternetDialog.updateDialog(false); + // Show WiFi Toggle with highlight background + assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggle.getBackground()).isNotNull(); + // Hide Wi-Fi networks and See all + assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); } @Test public void updateDialog_wifiOn_hideWifiScanNotify() { - // The preconditions WiFi ON and Internet WiFi are already in setUp() + // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialog.updateDialog(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index bd87a5021f8b..c3d72b71028b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -131,6 +131,8 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -241,6 +243,8 @@ public class StatusBarTest extends SysuiTestCase { @Mock private CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger; @Mock private StatusBarComponent.Factory mStatusBarComponentFactory; @Mock private StatusBarComponent mStatusBarComponent; + @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; + @Mock private StatusBarFragmentComponent mStatusBarFragmentComponent; @Mock private PluginManager mPluginManager; @Mock private LegacySplitScreen mLegacySplitScreen; @Mock private LightsOutNotifController mLightsOutNotifController; @@ -345,6 +349,8 @@ public class StatusBarTest extends SysuiTestCase { when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent); + when(mStatusBarFragmentComponentFactory.create(any())) + .thenReturn(mStatusBarFragmentComponent); when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( mNotificationShadeWindowViewController); @@ -414,6 +420,7 @@ public class StatusBarTest extends SysuiTestCase { mCommandQueue, mCollapsedStatusBarFragmentLogger, mStatusBarComponentFactory, + mStatusBarFragmentComponentFactory, mPluginManager, Optional.of(mLegacySplitScreen), mLightsOutNotifController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt index bf8cc37697b4..1ee8875eada8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.phone +package com.android.systemui.statusbar.phone.fragment import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index c300021ac53a..ec35edfdfab2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -12,7 +12,7 @@ * permissions and limitations under the License. */ -package com.android.systemui.statusbar.phone; +package com.android.systemui.statusbar.phone.fragment; import static android.view.Display.DEFAULT_DISPLAY; @@ -48,6 +48,13 @@ import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -83,6 +90,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private OperatorNameViewController.Factory mOperatorNameViewControllerFactory; private OperatorNameViewController mOperatorNameViewController; + private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; + private StatusBarFragmentComponent mStatusBarFragmentComponent; + public CollapsedStatusBarFragmentTest() { super(CollapsedStatusBarFragment.class); } @@ -243,8 +253,22 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE)); } + @Test + public void setUp_fragmentCreatesDaggerComponent() { + mFragments.dispatchResume(); + processAllMessages(); + CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + + assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent()); + } + @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { + mStatusBarFragmentComponentFactory = + mock(StatusBarFragmentComponent.Factory.class); + mStatusBarFragmentComponent = mock(StatusBarFragmentComponent.class); + when(mStatusBarFragmentComponentFactory.create(any())) + .thenReturn(mStatusBarFragmentComponent); mOngoingCallController = mock(OngoingCallController.class); mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); mLocationPublisher = mock(StatusBarLocationPublisher.class); @@ -259,6 +283,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { setUpNotificationIconAreaController(); return new CollapsedStatusBarFragment( + mStatusBarFragmentComponentFactory, mOngoingCallController, mAnimationScheduler, mLocationPublisher, diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java index 766471b9a695..3ff5666271bf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -248,8 +248,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( @@ -274,14 +275,15 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { } @Test - public void onWallpaperColorsChanged_ResetThemeWithDifferentWallpapers() { + public void onWallpaperColorsChanged_ResetThemeWithNewHomeWallpapers() { // Should ask for a new theme when wallpaper colors change WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( @@ -304,14 +306,15 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { } @Test - public void onWallpaperColorsChanged_ResetThemeWithSameWallpaper() { + public void onWallpaperColorsChanged_ResetThemeWithNewHomeAndLockWallpaper() { // Should ask for a new theme when wallpaper colors change WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( @@ -339,8 +342,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt())) @@ -366,8 +370,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"lock_wallpaper\"," + "{\"android.theme.customization.color_source\":\"lock_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt())) @@ -394,8 +399,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( @@ -416,6 +422,36 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { } @Test + public void onWallpaperColorsChanged_keepThemeWhenFromLatestWallpaperAndSpecifiedColor() { + // Shouldn't ask for a new theme when the colors of the last applied wallpaper change + // with the same specified system palette one. + WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), + Color.valueOf(0xffa16b00), null); + + String jsonString = + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + + "\"android.theme.customization.color_index\":\"2\"}"; + + when(mSecureSettings.getStringForUser( + eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt())) + .thenReturn(jsonString); + when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(1); + // SYSTEM wallpaper is the last applied one + when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM)).thenReturn(2); + + mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM); + + ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class); + verify(mSecureSettings, never()).putString( + eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture()); + + // Apply overlay by existing theme from secure setting + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + } + + @Test public void onWallpaperColorsChanged_keepThemeIfNotLatestWallpaper() { // Shouldn't ask for a new theme when the colors of the wallpaper that is not the last // applied one change @@ -423,8 +459,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { Color.valueOf(Color.BLUE), null); String jsonString = - "{\"android.theme.customization.system_palette\":\"override.package.name\"," - + "\"android.theme.customization.color_source\":\"home_wallpaper\"," + "{\"android.theme.customization.color_source\":\"home_wallpaper\"," + + "\"android.theme.customization.system_palette\":\"A16B00\"," + + "\"android.theme.customization.accent_color\":\"A16B00\"," + "\"android.theme.customization.color_index\":\"2\"}"; when(mSecureSettings.getStringForUser( diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto index 4b0e4c218c86..1cbc17ed9f41 100644 --- a/proto/src/task_snapshot.proto +++ b/proto/src/task_snapshot.proto @@ -41,4 +41,8 @@ // The task height when the snapshot was taken int32 task_height = 15; int32 appearance = 16; + int32 letterbox_inset_left = 17; + int32 letterbox_inset_top = 18; + int32 letterbox_inset_right = 19; + int32 letterbox_inset_bottom = 20; } diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 2bf1ccd51939..f2408cfa4124 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -220,11 +220,18 @@ final class CompatConfig { * Overrides the enabled state for a given change and app. * * - * @param overrides list of overrides to default changes config. - * @param packageName app for which the overrides will be applied. + * @param overrides list of overrides to default changes config. + * @param packageName app for which the overrides will be applied. + * @param skipUnknownChangeIds whether to skip unknown change IDs in {@code overrides}. */ - synchronized void addOverrides(CompatibilityOverrideConfig overrides, String packageName) { + synchronized void addPackageOverrides(CompatibilityOverrideConfig overrides, + String packageName, boolean skipUnknownChangeIds) { for (Long changeId : overrides.overrides.keySet()) { + if (skipUnknownChangeIds && !isKnownChangeId(changeId)) { + Slog.w(TAG, "Trying to add overrides for unknown Change ID " + changeId + ". " + + "Skipping Change ID."); + continue; + } addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId)); } saveOverrides(); @@ -335,7 +342,8 @@ final class CompatConfig { /** * Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or - * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package. + * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain + * package. * * <p>This restores the default behaviour for the given app. * @@ -356,7 +364,8 @@ final class CompatConfig { /** * Removes overrides whose change ID is specified in {@code overridesToRemove} that were * previously added via {@link #addOverride(long, String, boolean)} or - * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package. + * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain + * package. * * <p>This restores the default behaviour for the given change IDs and app. * @@ -367,6 +376,11 @@ final class CompatConfig { String packageName) { boolean shouldInvalidateCache = false; for (Long changeId : overridesToRemove.changeIds) { + if (!isKnownChangeId(changeId)) { + Slog.w(TAG, "Trying to remove overrides for unknown Change ID " + changeId + ". " + + "Skipping Change ID."); + continue; + } shouldInvalidateCache |= removeOverrideUnsafe(changeId, packageName); } if (shouldInvalidateCache) { diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index b32d1d749680..6ea89d445402 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -205,7 +205,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { overridesMap.put(change, new PackageOverride.Builder().setEnabled(false) .build()); } - mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName); + mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap), + packageName, /* skipUnknownChangeIds */ false); killPackage(packageName); } @@ -220,7 +221,8 @@ public class PlatformCompat extends IPlatformCompat.Stub { overridesMap.put(change, new PackageOverride.Builder().setEnabled(false) .build()); } - mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName); + mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap), + packageName, /* skipUnknownChangeIds */ false); } @Override @@ -229,7 +231,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods. checkCompatChangeOverrideOverridablePermission(); checkAllCompatOverridesAreOverridable(overrides.overrides.keySet()); - mCompatConfig.addOverrides(overrides, packageName); + mCompatConfig.addPackageOverrides(overrides, packageName, /* skipUnknownChangeIds= */ true); } @Override @@ -435,7 +437,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) { for (Long changeId : changeIds) { - if (!mCompatConfig.isOverridable(changeId)) { + if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) { throw new SecurityException("Only change ids marked as Overridable can be " + "overridden."); } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 2f3342f20fcb..22dd2c05c157 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -108,8 +108,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // screen state returns. Playing the animation can also be somewhat slow. private static final boolean USE_COLOR_FADE_ON_ANIMATION = false; - // The minimum reduction in brightness when dimmed. - private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f; private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f; private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250; @@ -200,6 +198,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The dim screen brightness. private final float mScreenBrightnessDimConfig; + // The minimum dim amount to use if the screen brightness is already below + // mScreenBrightnessDimConfig. + private final float mScreenBrightnessMinimumDimAmount; + private final float mScreenBrightnessDefault; // The minimum allowed brightness while in VR. @@ -485,6 +487,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE)); mScreenBrightnessDimConfig = clampAbsoluteBrightness( pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM)); + mScreenBrightnessMinimumDimAmount = resources.getFloat( + com.android.internal.R.dimen.config_screenBrightnessMinimumDimAmountFloat); + // NORMAL SCREEN SETTINGS mScreenBrightnessDefault = clampAbsoluteBrightness( @@ -1284,7 +1289,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { if (brightnessState > PowerManager.BRIGHTNESS_MIN) { brightnessState = Math.max( - Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT, + Math.min(brightnessState - mScreenBrightnessMinimumDimAmount, mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN); mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED); diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index aa4fa7c6f470..4a41cb6d81e2 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -917,7 +917,7 @@ public final class MultiClientInputMethodManagerService { .putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( context, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), - PendingIntent.FLAG_MUTABLE)); + PendingIntent.FLAG_IMMUTABLE)); // Note: Instead of re-dispatching callback from the main thread to the worker thread // where OnWorkerThreadCallback is running, we pass the Handler object here so that diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index 72ab8c1e2d1a..f7c4d03bfdf3 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -911,18 +911,21 @@ public class LocationProviderManager extends @Override public void onPreExecute() { mUseWakeLock = false; - final int size = locationResult.size(); - for (int i = 0; i < size; ++i) { - if (!locationResult.get(i).isMock()) { - mUseWakeLock = true; - break; + + // don't acquire a wakelock for passive requests or for mock locations + if (getRequest().getIntervalMillis() != LocationRequest.PASSIVE_INTERVAL) { + final int size = locationResult.size(); + for (int i = 0; i < size; ++i) { + if (!locationResult.get(i).isMock()) { + mUseWakeLock = true; + break; + } } } // update last delivered location setLastDeliveredLocation(locationResult.getLastLocation()); - // don't acquire a wakelock for mock locations to prevent abuse if (mUseWakeLock) { mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 83ea1e22e6ea..141d889c1804 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -290,11 +290,13 @@ class TaskSnapshotController { final WindowState mainWindow = result.second; final Rect contentInsets = getSystemBarInsets(task.getBounds(), mainWindow.getInsetsStateWithVisibilityOverride()); - InsetUtils.addInsets(contentInsets, activity.getLetterboxInsets()); + final Rect letterboxInsets = activity.getLetterboxInsets(); + InsetUtils.addInsets(contentInsets, letterboxInsets); builder.setIsRealSnapshot(true); builder.setId(System.currentTimeMillis()); builder.setContentInsets(contentInsets); + builder.setLetterboxInsets(letterboxInsets); final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE; final boolean isShowWallpaper = mainWindow.hasWallpaper(); @@ -575,7 +577,8 @@ class TaskSnapshotController { return null; } final Rect contentInsets = new Rect(systemBarInsets); - InsetUtils.addInsets(contentInsets, topChild.getLetterboxInsets()); + final Rect letterboxInsets = topChild.getLetterboxInsets(); + InsetUtils.addInsets(contentInsets, letterboxInsets); // Note, the app theme snapshot is never translucent because we enforce a non-translucent // color above @@ -584,9 +587,9 @@ class TaskSnapshotController { topChild.mActivityComponent, hwBitmap.getHardwareBuffer(), hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation, mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight), - contentInsets, false /* isLowResolution */, false /* isRealSnapshot */, - task.getWindowingMode(), getAppearance(task), false /* isTranslucent */, - false /* hasImeSurface */); + contentInsets, letterboxInsets, false /* isLowResolution */, + false /* isRealSnapshot */, task.getWindowingMode(), + getAppearance(task), false /* isTranslucent */, false /* hasImeSurface */); } /** diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java index d3bfbab8106f..9189e51f860c 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java @@ -20,7 +20,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.app.ActivityManager; -import android.window.TaskSnapshot; import android.content.ComponentName; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -30,6 +29,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.util.Slog; +import android.window.TaskSnapshot; import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; @@ -196,6 +196,8 @@ class TaskSnapshotLoader { return new TaskSnapshot(proto.id, topActivityComponent, buffer, hwBitmap.getColorSpace(), proto.orientation, proto.rotation, taskSize, new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom), + new Rect(proto.letterboxInsetLeft, proto.letterboxInsetTop, + proto.letterboxInsetRight, proto.letterboxInsetBottom), loadLowResolutionBitmap, proto.isRealSnapshot, proto.windowingMode, proto.appearance, proto.isTranslucent, false /* hasImeSurface */); } catch (IOException e) { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index 60c4766ea18f..9fbcd7cc5d84 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -23,7 +23,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; import android.annotation.TestApi; -import android.window.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.os.Process; @@ -31,6 +30,7 @@ import android.os.SystemClock; import android.util.ArraySet; import android.util.AtomicFile; import android.util.Slog; +import android.window.TaskSnapshot; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -380,6 +380,10 @@ class TaskSnapshotPersister { proto.insetTop = mSnapshot.getContentInsets().top; proto.insetRight = mSnapshot.getContentInsets().right; proto.insetBottom = mSnapshot.getContentInsets().bottom; + proto.letterboxInsetLeft = mSnapshot.getLetterboxInsets().left; + proto.letterboxInsetTop = mSnapshot.getLetterboxInsets().top; + proto.letterboxInsetRight = mSnapshot.getLetterboxInsets().right; + proto.letterboxInsetBottom = mSnapshot.getLetterboxInsets().bottom; proto.isRealSnapshot = mSnapshot.isRealSnapshot(); proto.windowingMode = mSnapshot.getWindowingMode(); proto.appearance = mSnapshot.getAppearance(); diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index 0248b9b88788..d926dcba54a3 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -265,9 +265,10 @@ public class CompatConfigTest { } @Test - public void testInstallerCanSetOverrides() throws Exception { + public void testInstallerCanAddOverrides() throws Exception { final long disabledChangeId1 = 1234L; final long disabledChangeId2 = 1235L; + final long unknownChangeId = 1236L; // We make disabledChangeId2 non-overridable to make sure it is ignored. CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addDisabledOverridableChangeWithId(disabledChangeId1) @@ -284,19 +285,25 @@ public class CompatConfigTest { // Force the validator to prevent overriding non-overridable changes by using a user build. when(mBuildClassifier.isDebuggableBuild()).thenReturn(false); when(mBuildClassifier.isFinalBuild()).thenReturn(true); + Map<Long, PackageOverride> overrides = new HashMap<>(); + overrides.put(disabledChangeId1, new PackageOverride.Builder() + .setMaxVersionCode(99L) + .setEnabled(true) + .build()); + // Adding an unknown change ID to make sure it's skipped if skipUnknownChangeIds is true. + overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build()); + CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides); - CompatibilityOverrideConfig config = new CompatibilityOverrideConfig( - Collections.singletonMap(disabledChangeId1, - new PackageOverride.Builder() - .setMaxVersionCode(99L) - .setEnabled(true) - .build())); - - compatConfig.addOverrides(config, "com.some.package"); + compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */ + true); assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue(); assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse(); + // Making sure the unknown change ID is still unknown and isChangeEnabled returns true. + assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse(); + assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isTrue(); } + @Test public void testPreventInstallerSetNonOverridable() throws Exception { final long disabledChangeId1 = 1234L; @@ -326,7 +333,8 @@ public class CompatConfigTest { CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides); assertThrows(SecurityException.class, - () -> compatConfig.addOverrides(config, "com.some.package") + () -> compatConfig.addPackageOverrides(config, "com.some.package", + /* skipUnknownChangeIds */ true) ); assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue(); assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse(); @@ -334,6 +342,38 @@ public class CompatConfigTest { } @Test + public void testCanAddOverridesForUnknownChangeIdOnDebugBuild() throws Exception { + final long disabledChangeId = 1234L; + final long unknownChangeId = 1235L; + // We make disabledChangeId2 non-overridable to make sure it is ignored. + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(disabledChangeId) + .build(); + ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() + .withPackageName("com.some.package") + .build(); + PackageManager packageManager = mock(PackageManager.class); + when(mContext.getPackageManager()).thenReturn(packageManager); + when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt())) + .thenReturn(applicationInfo); + + when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); + Map<Long, PackageOverride> overrides = new HashMap<>(); + overrides.put(disabledChangeId, new PackageOverride.Builder().setEnabled(true).build()); + // Adding an unknown change ID to make sure it isn't skipped if skipUnknownChangeIds is + // false. + overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build()); + CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides); + + compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */ + false); + assertThat(compatConfig.isChangeEnabled(disabledChangeId, applicationInfo)).isTrue(); + // Making sure the unknown change ID is now known and has an override. + assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isTrue(); + assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isFalse(); + } + + @Test public void testApplyDeferredOverridesAfterInstallingApp() throws Exception { ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("com.notinstalled.foo") @@ -377,7 +417,8 @@ public class CompatConfigTest { .setMaxVersionCode(99L) .setEnabled(true) .build())); - compatConfig.addOverrides(config, "com.installed.foo"); + compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */ + true); assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); // Add override that does include the installed app version @@ -388,7 +429,8 @@ public class CompatConfigTest { .setMaxVersionCode(100L) .setEnabled(true) .build())); - compatConfig.addOverrides(config, "com.installed.foo"); + compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */ + true); assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue(); } @@ -411,7 +453,8 @@ public class CompatConfigTest { .setMaxVersionCode(99L) .setEnabled(true) .build())); - compatConfig.addOverrides(config, "com.notinstalled.foo"); + compatConfig.addPackageOverrides(config, "com.notinstalled.foo", /* skipUnknownChangeIds */ + true); assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse(); // Pretend the app is now installed. @@ -557,6 +600,7 @@ public class CompatConfigTest { final long disabledChangeId1 = 1234L; final long disabledChangeId2 = 1235L; final long enabledChangeId = 1236L; + final long unknownChangeId = 1237L; // We make disabledChangeId2 non-overridable to make sure it is ignored. CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) .addDisabledOverridableChangeWithId(disabledChangeId1) @@ -583,6 +627,8 @@ public class CompatConfigTest { Set<Long> overridesToRemove = new HashSet<>(); overridesToRemove.add(disabledChangeId1); overridesToRemove.add(enabledChangeId); + // Adding an unknown change ID to make sure it's skipped. + overridesToRemove.add(unknownChangeId); CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig( overridesToRemove); @@ -590,6 +636,8 @@ public class CompatConfigTest { assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse(); assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue(); assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue(); + // Making sure the unknown change ID is still unknown. + assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse(); } @Test @@ -797,18 +845,18 @@ public class CompatConfigTest { .build()); when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) .thenThrow(new NameNotFoundException()); - compatConfig.addOverrides( + compatConfig.addPackageOverrides( new CompatibilityOverrideConfig( Collections.singletonMap( 1L, new PackageOverride.Builder().setEnabled(true).build())), - "foo.bar"); - compatConfig.addOverrides( + "foo.bar", /* skipUnknownChangeIds */ true); + compatConfig.addPackageOverrides( new CompatibilityOverrideConfig( Collections.singletonMap( 2L, new PackageOverride.Builder().setEnabled(false).build())), - "bar.baz"); + "bar.baz", /* skipUnknownChangeIds */ true); assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<overrides>\n" @@ -847,12 +895,12 @@ public class CompatConfigTest { compatConfig.forceNonDebuggableFinalForTest(true); compatConfig.initOverrides(overridesFile, new File("")); - compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L, - new PackageOverride.Builder() + compatConfig.addPackageOverrides(new CompatibilityOverrideConfig( + Collections.singletonMap(1L, new PackageOverride.Builder() .setMinVersionCode(99L) .setMaxVersionCode(101L) .setEnabled(true) - .build())), "foo.bar"); + .build())), "foo.bar", /* skipUnknownChangeIds */ true); assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<overrides>\n" diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 22e687a0bb15..284728397c9f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1244,7 +1244,8 @@ public class RecentTasksTest extends WindowTestsBase { } return new TaskSnapshot(1, new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, - Surface.ROTATION_0, taskSize, new Rect() /* insets */, false /* isLowResolution */, + Surface.ROTATION_0, taskSize, new Rect() /* contentInsets */, + new Rect() /* letterboxInsets*/, false /* isLowResolution */, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* mSystemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java index 97afc165624a..f573b70352af 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java @@ -144,7 +144,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase { final int orientation = Configuration.ORIENTATION_PORTRAIT; final float scaleFraction = 0.25f; final Rect contentInsets = new Rect(1, 2, 3, 4); - final Point taskSize = new Point(5, 6); + final Rect letterboxInsets = new Rect(5, 6, 7, 8); + final Point taskSize = new Point(9, 10); try { TaskSnapshot.Builder builder = @@ -156,6 +157,7 @@ public class TaskSnapshotControllerTest extends WindowTestsBase { builder.setColorSpace(sRGB); builder.setOrientation(orientation); builder.setContentInsets(contentInsets); + builder.setLetterboxInsets(letterboxInsets); builder.setIsTranslucent(true); builder.setSnapshot(buffer); builder.setIsRealSnapshot(true); @@ -176,6 +178,7 @@ public class TaskSnapshotControllerTest extends WindowTestsBase { assertFalse(snapshot.isLowResolution()); assertEquals(orientation, snapshot.getOrientation()); assertEquals(contentInsets, snapshot.getContentInsets()); + assertEquals(letterboxInsets, snapshot.getLetterboxInsets()); assertTrue(snapshot.isTranslucent()); assertSame(buffer, snapshot.getHardwareBuffer()); assertTrue(snapshot.isRealSnapshot()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java index b5219fda1cc8..b8ac0be250a4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java @@ -59,7 +59,8 @@ import java.util.function.Predicate; */ class TaskSnapshotPersisterTestBase extends WindowTestsBase { - private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40); + private static final Rect TEST_CONTENT_INSETS = new Rect(10, 20, 30, 40); + private static final Rect TEST_LETTERBOX_INSETS = new Rect(); static final File FILES_DIR = getInstrumentation().getTargetContext().getFilesDir(); static final long MOCK_SNAPSHOT_ID = 12345678; @@ -208,7 +209,7 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase { return new TaskSnapshot(MOCK_SNAPSHOT_ID, mTopActivityComponent, HardwareBuffer.createFromGraphicBuffer(buffer), ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, - mRotation, taskSize, TEST_INSETS, + mRotation, taskSize, TEST_CONTENT_INSETS, TEST_LETTERBOX_INSETS, // When building a TaskSnapshot with the Builder class, isLowResolution // is always false. Low-res snapshots are only created when loading from // disk. diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java index 9372530f0e80..294aad237977 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java @@ -100,7 +100,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase { System.currentTimeMillis(), new ComponentName("", ""), buffer, ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, - Surface.ROTATION_0, taskSize, contentInsets, false, + Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets*/, false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 4d2e00785d49..9c9e41b64892 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -5865,7 +5865,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, ""); sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false); sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false); - sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false); + sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false); } |