Merge "Add traces around updateZenModeConfig" into udc-dev
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 3d76b28..d7195a7 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -65,7 +65,7 @@
* thread of your app.
*
* <p>Note on threading: the state inside of this class is not itself
- * thread-safe, however you can use it from any thread if you properly
+ * thread-safe. However, you can use it from any thread if you make
* sure that you do not have races. Typically this means you will hand
* the entire object to another thread, which will be solely responsible
* for setting any results and finally calling {@link #finish()}.
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index a7cd168..690dfcf 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -137,8 +137,10 @@
*/
@UnsupportedAppUsage
public void onConfigurationChange(@Config int configChanges) {
- prune(configChanges);
- mGeneration++;
+ synchronized (this) {
+ pruneLocked(configChanges);
+ mGeneration++;
+ }
}
/**
@@ -214,22 +216,20 @@
* simply prune missing weak references
* @return {@code true} if the cache is completely empty after pruning
*/
- private boolean prune(@Config int configChanges) {
- synchronized (this) {
- if (mThemedEntries != null) {
- for (int i = mThemedEntries.size() - 1; i >= 0; i--) {
- if (pruneEntriesLocked(mThemedEntries.valueAt(i), configChanges)) {
- mThemedEntries.removeAt(i);
- }
+ private boolean pruneLocked(@Config int configChanges) {
+ if (mThemedEntries != null) {
+ for (int i = mThemedEntries.size() - 1; i >= 0; i--) {
+ if (pruneEntriesLocked(mThemedEntries.valueAt(i), configChanges)) {
+ mThemedEntries.removeAt(i);
}
}
-
- pruneEntriesLocked(mNullThemedEntries, configChanges);
- pruneEntriesLocked(mUnthemedEntries, configChanges);
-
- return mThemedEntries == null && mNullThemedEntries == null
- && mUnthemedEntries == null;
}
+
+ pruneEntriesLocked(mNullThemedEntries, configChanges);
+ pruneEntriesLocked(mUnthemedEntries, configChanges);
+
+ return mThemedEntries == null && mNullThemedEntries == null
+ && mUnthemedEntries == null;
}
private boolean pruneEntriesLocked(@Nullable LongSparseArray<WeakReference<T>> entries,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 6d7f761..73eb62a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -339,19 +339,36 @@
}
// This means an expand happened before enter-pip finished and we are now "merging" a
// no-op transition that happens to match our exit-pip.
+ // Or that the keyguard is up and preventing the transition from applying, in which case we
+ // want to manually reset pip. (b/283783868)
boolean cancelled = false;
if (mPipAnimationController.getCurrentAnimator() != null) {
mPipAnimationController.getCurrentAnimator().cancel();
+ mPipAnimationController.resetAnimatorState();
cancelled = true;
}
+
// Unset exitTransition AFTER cancel so that finishResize knows we are merging.
mExitTransition = null;
- if (!cancelled || aborted) return;
+ if (!cancelled) return;
final ActivityManager.RunningTaskInfo taskInfo = mPipOrganizer.getTaskInfo();
if (taskInfo != null) {
- startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
- mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
- new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */);
+ if (aborted) {
+ // keyguard case - the transition got aborted, so we want to reset state and
+ // windowing mode before reapplying the resize transaction
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_LEAVE_PIP);
+ mPipOrganizer.onExitPipFinished(taskInfo);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP);
+ wct.setBounds(taskInfo.token, null);
+ mPipOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_LEAVE_PIP, false);
+ } else {
+ // merge case
+ startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
+ mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
+ new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */);
+ }
}
mExitDestinationBounds.setEmpty();
mCurrentPipTaskToken = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index c964df1..c2f15f6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.startingsurface;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.graphics.Color.WHITE;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -77,6 +78,13 @@
@NonNull Runnable clearWindowHandler) {
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
final int taskId = runningTaskInfo.taskId;
+
+ // if we're in PIP we don't want to create the snapshot
+ if (runningTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "did not create taskSnapshot due to being in PIP");
+ return null;
+ }
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"create taskSnapshot surface for task: %d", taskId);
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index cd6609e..963bd9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -15,6 +15,8 @@
*/
package com.android.settingslib.media;
+import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
+
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
@@ -22,6 +24,7 @@
import android.media.AudioManager;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
+import android.media.RouteListingPreference;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -39,7 +42,13 @@
BluetoothMediaDevice(Context context, CachedBluetoothDevice device,
MediaRouter2Manager routerManager, MediaRoute2Info info, String packageName) {
- super(context, routerManager, info, packageName, null);
+ this(context, device, routerManager, info, packageName, null);
+ }
+
+ BluetoothMediaDevice(Context context, CachedBluetoothDevice device,
+ MediaRouter2Manager routerManager, MediaRoute2Info info, String packageName,
+ RouteListingPreference.Item item) {
+ super(context, routerManager, info, packageName, item);
mCachedDevice = device;
mAudioManager = context.getSystemService(AudioManager.class);
initDeviceRecord();
@@ -58,6 +67,12 @@
}
@Override
+ public int getSelectionBehavior() {
+ // We don't allow apps to override the selection behavior of system routes.
+ return SELECTION_BEHAVIOR_TRANSFER;
+ }
+
+ @Override
public Drawable getIcon() {
return BluetoothUtils.isAdvancedUntetheredDevice(mCachedDevice.getDevice())
? mContext.getDrawable(R.drawable.ic_earbuds_advanced)
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 2a486a9..1728e40 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -568,8 +568,10 @@
case TYPE_HDMI:
case TYPE_WIRED_HEADSET:
case TYPE_WIRED_HEADPHONES:
- mediaDevice =
- new PhoneMediaDevice(mContext, mRouterManager, route, mPackageName);
+ mediaDevice = mPreferenceItemMap.containsKey(route.getId()) ? new PhoneMediaDevice(
+ mContext, mRouterManager, route, mPackageName,
+ mPreferenceItemMap.get(route.getId())) : new PhoneMediaDevice(mContext,
+ mRouterManager, route, mPackageName);
break;
case TYPE_HEARING_AID:
case TYPE_BLUETOOTH_A2DP:
@@ -579,8 +581,11 @@
final CachedBluetoothDevice cachedDevice =
mBluetoothManager.getCachedDeviceManager().findDevice(device);
if (cachedDevice != null) {
- mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
- route, mPackageName);
+ mediaDevice = mPreferenceItemMap.containsKey(route.getId())
+ ? new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
+ route, mPackageName, mPreferenceItemMap.get(route.getId()))
+ : new BluetoothMediaDevice(mContext, cachedDevice, mRouterManager,
+ route, mPackageName);
}
break;
case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 34519c9..accd88c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -24,10 +24,13 @@
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
+
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
+import android.media.RouteListingPreference;
import androidx.annotation.VisibleForTesting;
@@ -51,7 +54,12 @@
PhoneMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
String packageName) {
- super(context, routerManager, info, packageName, null);
+ this(context, routerManager, info, packageName, null);
+ }
+
+ PhoneMediaDevice(Context context, MediaRouter2Manager routerManager, MediaRoute2Info info,
+ String packageName, RouteListingPreference.Item item) {
+ super(context, routerManager, info, packageName, item);
mDeviceIconUtil = new DeviceIconUtil();
initDeviceRecord();
}
@@ -86,6 +94,12 @@
}
@Override
+ public int getSelectionBehavior() {
+ // We don't allow apps to override the selection behavior of system routes.
+ return SELECTION_BEHAVIOR_TRANSFER;
+ }
+
+ @Override
public String getSummary() {
return mSummary;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index c058a61..f22e090 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -19,6 +19,9 @@
import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_GO_TO_APP;
+
+import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +35,7 @@
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.NearbyDevice;
+import android.media.RouteListingPreference;
import android.os.Parcel;
import com.android.settingslib.bluetooth.A2dpProfile;
@@ -110,6 +114,8 @@
@Mock
private MediaRouter2Manager mMediaRouter2Manager;
+ private RouteListingPreference.Item mItem;
+
private BluetoothMediaDevice mBluetoothMediaDevice1;
private BluetoothMediaDevice mBluetoothMediaDevice2;
private BluetoothMediaDevice mBluetoothMediaDevice3;
@@ -497,4 +503,21 @@
assertThat(mBluetoothMediaDevice1.getFeatures().size()).isEqualTo(0);
}
+
+ @Test
+ public void getSelectionBehavior_setItemWithSelectionBehaviorOnSystemRoute_returnTransfer() {
+ mItem = new RouteListingPreference.Item.Builder(DEVICE_ADDRESS_1)
+ .setSelectionBehavior(SELECTION_BEHAVIOR_GO_TO_APP)
+ .build();
+ mBluetoothMediaDevice1 = new BluetoothMediaDevice(mContext, mCachedDevice1,
+ mMediaRouter2Manager, null /* MediaRoute2Info */, TEST_PACKAGE_NAME, mItem);
+ mPhoneMediaDevice =
+ new PhoneMediaDevice(mContext, mMediaRouter2Manager, mPhoneRouteInfo,
+ TEST_PACKAGE_NAME, mItem);
+
+ assertThat(mBluetoothMediaDevice1.getSelectionBehavior()).isEqualTo(
+ SELECTION_BEHAVIOR_TRANSFER);
+ assertThat(mPhoneMediaDevice.getSelectionBehavior()).isEqualTo(
+ SELECTION_BEHAVIOR_TRANSFER);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 239a0cc..9003c43 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -62,6 +62,7 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -112,6 +113,7 @@
@NonNull private final VibratorHelper mVibrator;
@Nullable private final AuthRippleController mAuthRippleController;
@NonNull private final FeatureFlags mFeatureFlags;
+ @NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@NonNull private final KeyguardTransitionInteractor mTransitionInteractor;
@NonNull private final KeyguardInteractor mKeyguardInteractor;
@@ -180,7 +182,8 @@
@NonNull @Main Resources resources,
@NonNull KeyguardTransitionInteractor transitionInteractor,
@NonNull KeyguardInteractor keyguardInteractor,
- @NonNull FeatureFlags featureFlags
+ @NonNull FeatureFlags featureFlags,
+ PrimaryBouncerInteractor primaryBouncerInteractor
) {
super(view);
mStatusBarStateController = statusBarStateController;
@@ -197,6 +200,7 @@
mTransitionInteractor = transitionInteractor;
mKeyguardInteractor = keyguardInteractor;
mFeatureFlags = featureFlags;
+ mPrimaryBouncerInteractor = primaryBouncerInteractor;
mMaxBurnInOffsetX = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
mMaxBurnInOffsetY = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
@@ -325,8 +329,14 @@
mView.setContentDescription(null);
}
+ boolean accessibilityEnabled =
+ !mPrimaryBouncerInteractor.isAnimatingAway() && mView.isVisibleToUser();
+ mView.setImportantForAccessibility(
+ accessibilityEnabled ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
+ : View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+
if (!Objects.equals(prevContentDescription, mView.getContentDescription())
- && mView.getContentDescription() != null && mView.isVisibleToUser()) {
+ && mView.getContentDescription() != null && accessibilityEnabled) {
mView.announceForAccessibility(mView.getContentDescription());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 30ee147..2883210 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
@@ -128,6 +128,15 @@
var visibilityChangedListener: ((Boolean) -> Unit)? = null
+ /**
+ * Whether the doze wake up animation is delayed and we are currently waiting for it to start.
+ */
+ var isDozeWakeUpAnimationWaiting: Boolean = false
+ set(value) {
+ field = value
+ refreshMediaPosition()
+ }
+
/** single pane media container placed at the top of the notifications list */
var singlePaneContainer: MediaContainerView? = null
private set
@@ -221,7 +230,13 @@
// by the clock. This is not the case for single-line clock though.
// For single shade, we don't need to do it, because media is a child of NSSL, which already
// gets hidden on AOD.
- return !statusBarStateController.isDozing
+ // Media also has to be hidden when waking up from dozing, and the doze wake up animation is
+ // delayed and waiting to be started.
+ // This is to stay in sync with the delaying of the horizontal alignment of the rest of the
+ // keyguard container, that is also delayed until the "wait" is over.
+ // If we show media during this waiting period, the shade will still be centered, and using
+ // the entire width of the screen, and making media show fully stretched.
+ return !statusBarStateController.isDozing && !isDozeWakeUpAnimationWaiting
}
private fun showMediaPlayer() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 3acfe6c..267b147 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1621,6 +1621,7 @@
mWillPlayDelayedDozeAmountAnimation = willPlay;
mWakeUpCoordinator.logDelayingClockWakeUpAnimation(willPlay);
+ mKeyguardMediaController.setDozeWakeUpAnimationWaiting(willPlay);
// Once changing this value, see if we should move the clock.
positionClockAndNotifications();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index bcf3b0c..4a9921e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -240,8 +240,10 @@
Insets.of(0, safeTouchRegionHeight, 0, 0));
}
lp.providedInsets = new InsetsFrameProvider[] {
- new InsetsFrameProvider(mInsetsSourceOwner, 0, statusBars()),
- new InsetsFrameProvider(mInsetsSourceOwner, 0, tappableElement()),
+ new InsetsFrameProvider(mInsetsSourceOwner, 0, statusBars())
+ .setInsetsSize(Insets.of(0, height, 0, 0)),
+ new InsetsFrameProvider(mInsetsSourceOwner, 0, tappableElement())
+ .setInsetsSize(Insets.of(0, height, 0, 0)),
gestureInsetsProvider
};
return lp;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 84e58be..403bd8c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -48,6 +48,7 @@
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
@@ -95,6 +96,8 @@
protected @Mock KeyguardTransitionRepository mTransitionRepository;
protected @Mock CommandQueue mCommandQueue;
protected FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
+ protected @Mock PrimaryBouncerInteractor mPrimaryBouncerInteractor;
+
protected LockIconViewController mUnderTest;
@@ -167,7 +170,8 @@
mFeatureFlags,
new FakeKeyguardBouncerRepository()
),
- mFeatureFlags
+ mFeatureFlags,
+ mPrimaryBouncerInteractor
);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index b6287598..ed6a891 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -33,6 +33,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
+import android.view.View;
import androidx.test.filters.SmallTest;
@@ -267,4 +268,75 @@
// THEN the lock icon is shown
verify(mLockIconView).setContentDescription(LOCKED_LABEL);
}
+
+ @Test
+ public void lockIconAccessibility_notVisibleToUser() {
+ // GIVEN lock icon controller is initialized and view is attached
+ init(/* useMigrationFlag= */false);
+ captureKeyguardStateCallback();
+ captureKeyguardUpdateMonitorCallback();
+
+ // GIVEN user has unlocked with a biometric auth (ie: face auth)
+ // and biometric running state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
+ mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false,
+ BiometricSourceType.FACE);
+ reset(mLockIconView);
+ when(mLockIconView.isVisibleToUser()).thenReturn(false);
+
+ // WHEN the unlocked state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false);
+ mKeyguardStateCallback.onUnlockedChanged();
+
+ // THEN the lock icon is shown
+ verify(mLockIconView).setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ }
+
+ @Test
+ public void lockIconAccessibility_bouncerAnimatingAway() {
+ // GIVEN lock icon controller is initialized and view is attached
+ init(/* useMigrationFlag= */false);
+ captureKeyguardStateCallback();
+ captureKeyguardUpdateMonitorCallback();
+
+ // GIVEN user has unlocked with a biometric auth (ie: face auth)
+ // and biometric running state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
+ mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false,
+ BiometricSourceType.FACE);
+ reset(mLockIconView);
+ when(mLockIconView.isVisibleToUser()).thenReturn(true);
+ when(mPrimaryBouncerInteractor.isAnimatingAway()).thenReturn(true);
+
+ // WHEN the unlocked state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false);
+ mKeyguardStateCallback.onUnlockedChanged();
+
+ // THEN the lock icon is shown
+ verify(mLockIconView).setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ }
+
+ @Test
+ public void lockIconAccessibility_bouncerNotAnimatingAway_viewVisible() {
+ // GIVEN lock icon controller is initialized and view is attached
+ init(/* useMigrationFlag= */false);
+ captureKeyguardStateCallback();
+ captureKeyguardUpdateMonitorCallback();
+
+ // GIVEN user has unlocked with a biometric auth (ie: face auth)
+ // and biometric running state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
+ mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false,
+ BiometricSourceType.FACE);
+ reset(mLockIconView);
+ when(mLockIconView.isVisibleToUser()).thenReturn(true);
+ when(mPrimaryBouncerInteractor.isAnimatingAway()).thenReturn(false);
+
+ // WHEN the unlocked state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false);
+ mKeyguardStateCallback.onUnlockedChanged();
+
+ // THEN the lock icon is shown
+ verify(mLockIconView).setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
index b40ebc9..91b0245 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
@@ -193,6 +193,17 @@
}
@Test
+ fun dozeWakeUpAnimationWaiting_inSplitShade_mediaIsHidden() {
+ val splitShadeContainer = FrameLayout(context)
+ keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
+ keyguardMediaController.useSplitShade = true
+
+ keyguardMediaController.isDozeWakeUpAnimationWaiting = true
+
+ assertThat(splitShadeContainer.visibility).isEqualTo(GONE)
+ }
+
+ @Test
fun dozing_inSingleShade_mediaIsVisible() {
val splitShadeContainer = FrameLayout(context)
keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
@@ -203,6 +214,17 @@
assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
}
+ @Test
+ fun dozeWakeUpAnimationWaiting_inSingleShade_mediaIsVisible() {
+ val splitShadeContainer = FrameLayout(context)
+ keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
+ keyguardMediaController.useSplitShade = false
+
+ keyguardMediaController.isDozeWakeUpAnimationWaiting = true
+
+ assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
+ }
+
private fun setDozing() {
whenever(statusBarStateController.isDozing).thenReturn(true)
statusBarStateListener.onDozingChanged(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 8f2ee91..987e09c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -510,6 +510,17 @@
}
@Test
+ public void keyguardStatusView_willPlayDelayedDoze_notifiesKeyguardMediaController() {
+ when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
+ mStatusBarStateController.setState(KEYGUARD);
+ enableSplitShade(/* enabled= */ true);
+
+ mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(true);
+
+ verify(mKeyguardMediaController).setDozeWakeUpAnimationWaiting(true);
+ }
+
+ @Test
public void keyguardStatusView_willPlayDelayedDoze_isCentered_thenStillCenteredIfNoNotifs() {
when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
mStatusBarStateController.setState(KEYGUARD);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index cbded89..a88e2b0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -702,8 +702,11 @@
finishKeyguardDrawn();
break;
case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
- if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
- finishWindowsDrawn(msg.arg1);
+ final int displayId = msg.arg1;
+ if (DEBUG_WAKEUP) Slog.w(TAG, "All windows drawn on display " + displayId);
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
+ TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, displayId /* cookie */);
+ finishWindowsDrawn(displayId);
break;
case MSG_HIDE_BOOT_MESSAGE:
handleHideBootMessage();
@@ -4996,15 +4999,10 @@
// ... eventually calls finishWindowsDrawn which will finalize our screen turn on
// as well as enabling the orientation change logic/sensor.
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
- TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
- mWindowManagerInternal.waitForAllWindowsDrawn(() -> {
- if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for every display");
- mHandler.sendMessage(mHandler.obtainMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE,
- INVALID_DISPLAY, 0));
-
- Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
- TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
- }, WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY);
+ TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, INVALID_DISPLAY /* cookie */);
+ mWindowManagerInternal.waitForAllWindowsDrawn(mHandler.obtainMessage(
+ MSG_WINDOW_MANAGER_DRAWN_COMPLETE, INVALID_DISPLAY, 0),
+ WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY);
}
// Called on the DisplayManager's DisplayPowerController thread.
@@ -5084,15 +5082,10 @@
mScreenOnListeners.put(displayId, screenOnListener);
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
- TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
- mWindowManagerInternal.waitForAllWindowsDrawn(() -> {
- if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display: " + displayId);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE,
- displayId, 0));
-
- Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
- TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
- }, WAITING_FOR_DRAWN_TIMEOUT, displayId);
+ TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, displayId /* cookie */);
+ mWindowManagerInternal.waitForAllWindowsDrawn(mHandler.obtainMessage(
+ MSG_WINDOW_MANAGER_DRAWN_COMPLETE, displayId, 0),
+ WAITING_FOR_DRAWN_TIMEOUT, displayId);
}
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index e31b53c..cd3d603 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3050,7 +3050,10 @@
if (which == FLAG_SYSTEM && systemIsStatic && systemIsBoth) {
Slog.i(TAG, "Migrating current wallpaper to be lock-only before"
+ " updating system wallpaper");
- migrateStaticSystemToLockWallpaperLocked(userId);
+ if (!migrateStaticSystemToLockWallpaperLocked(userId)
+ && !isLockscreenLiveWallpaperEnabled()) {
+ which |= FLAG_LOCK;
+ }
}
wallpaper = getWallpaperSafeLocked(userId, which);
@@ -3078,13 +3081,13 @@
}
}
- private void migrateStaticSystemToLockWallpaperLocked(int userId) {
+ private boolean migrateStaticSystemToLockWallpaperLocked(int userId) {
WallpaperData sysWP = mWallpaperMap.get(userId);
if (sysWP == null) {
if (DEBUG) {
Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
}
- return;
+ return true;
}
// We know a-priori that there is no lock-only wallpaper currently
@@ -3105,11 +3108,13 @@
SELinux.restorecon(lockWP.wallpaperFile);
mLastLockWallpaper = lockWP;
}
+ return true;
} catch (ErrnoException e) {
- Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
+ // can happen when migrating default wallpaper (which is not stored in wallpaperFile)
+ Slog.w(TAG, "Couldn't migrate system wallpaper: " + e.getMessage());
lockWP.wallpaperFile.delete();
lockWP.cropFile.delete();
- return;
+ return false;
}
}
@@ -3310,7 +3315,9 @@
// therefore it's a shared system+lock image that we need to migrate.
Slog.i(TAG, "Migrating current wallpaper to be lock-only before"
+ "updating system wallpaper");
- migrateStaticSystemToLockWallpaperLocked(userId);
+ if (!migrateStaticSystemToLockWallpaperLocked(userId)) {
+ which |= FLAG_LOCK;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 9e7df00..805e7ff 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -30,6 +30,7 @@
import android.hardware.display.DisplayManagerInternal;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Message;
import android.util.Pair;
import android.view.ContentRecordingSession;
import android.view.Display;
@@ -515,12 +516,13 @@
* Invalidate all visible windows on a given display, and report back on the callback when all
* windows have redrawn.
*
- * @param callback reporting callback to be called when all windows have redrawn.
+ * @param message The message will be sent when all windows have redrawn. Note that the message
+ * must be obtained from handler, otherwise it will throw NPE.
* @param timeout calls the callback anyway after the timeout.
* @param displayId waits for the windows on the given display, INVALID_DISPLAY to wait for all
* windows on all displays.
*/
- public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId);
+ public abstract void waitForAllWindowsDrawn(Message message, long timeout, int displayId);
/**
* Overrides the display size.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 67572bf..d9ff91f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -601,7 +601,7 @@
* The callbacks to make when the windows all have been drawn for a given
* {@link WindowContainer}.
*/
- final HashMap<WindowContainer, Runnable> mWaitingForDrawnCallbacks = new HashMap<>();
+ final ArrayMap<WindowContainer<?>, Message> mWaitingForDrawnCallbacks = new ArrayMap<>();
/** List of window currently causing non-system overlay windows to be hidden. */
private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
@@ -5368,8 +5368,6 @@
public static final int CLIENT_FREEZE_TIMEOUT = 30;
public static final int NOTIFY_ACTIVITY_DRAWN = 32;
- public static final int ALL_WINDOWS_DRAWN = 33;
-
public static final int NEW_ANIMATOR_SCALE = 34;
public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
@@ -5491,7 +5489,7 @@
}
case WAITING_FOR_DRAWN_TIMEOUT: {
- Runnable callback = null;
+ final Message callback;
final WindowContainer<?> container = (WindowContainer<?>) msg.obj;
synchronized (mGlobalLock) {
ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s",
@@ -5505,7 +5503,7 @@
callback = mWaitingForDrawnCallbacks.remove(container);
}
if (callback != null) {
- callback.run();
+ callback.sendToTarget();
}
break;
}
@@ -5529,17 +5527,6 @@
}
break;
}
- case ALL_WINDOWS_DRAWN: {
- Runnable callback;
- final WindowContainer container = (WindowContainer) msg.obj;
- synchronized (mGlobalLock) {
- callback = mWaitingForDrawnCallbacks.remove(container);
- }
- if (callback != null) {
- callback.run();
- }
- break;
- }
case NEW_ANIMATOR_SCALE: {
float scale = getCurrentAnimatorScale();
ValueAnimator.setDurationScale(scale);
@@ -6097,7 +6084,8 @@
if (mWaitingForDrawnCallbacks.isEmpty()) {
return;
}
- mWaitingForDrawnCallbacks.forEach((container, callback) -> {
+ for (int i = mWaitingForDrawnCallbacks.size() - 1; i >= 0; i--) {
+ final WindowContainer<?> container = mWaitingForDrawnCallbacks.keyAt(i);
for (int j = container.mWaitingForDrawn.size() - 1; j >= 0; j--) {
final WindowState win = (WindowState) container.mWaitingForDrawn.get(j);
ProtoLog.i(WM_DEBUG_SCREEN_ON,
@@ -6123,9 +6111,9 @@
if (container.mWaitingForDrawn.isEmpty()) {
ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!");
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
- mH.sendMessage(mH.obtainMessage(H.ALL_WINDOWS_DRAWN, container));
+ mWaitingForDrawnCallbacks.removeAt(i).sendToTarget();
}
- });
+ }
}
private void traceStartWaitingForWindowDrawn(WindowState window) {
@@ -7811,13 +7799,14 @@
}
@Override
- public void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId) {
+ public void waitForAllWindowsDrawn(Message message, long timeout, int displayId) {
+ Objects.requireNonNull(message.getTarget());
final WindowContainer<?> container = displayId == INVALID_DISPLAY
? mRoot : mRoot.getDisplayContent(displayId);
if (container == null) {
// The waiting container doesn't exist, no need to wait to run the callback. Run and
// return;
- callback.run();
+ message.sendToTarget();
return;
}
boolean allWindowsDrawn = false;
@@ -7834,13 +7823,13 @@
}
}
- mWaitingForDrawnCallbacks.put(container, callback);
+ mWaitingForDrawnCallbacks.put(container, message);
mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
checkDrawnWindowsLocked();
}
}
if (allWindowsDrawn) {
- callback.run();
+ message.sendToTarget();
}
}
diff --git a/services/tests/PackageManagerServiceTests/server/res/raw/install_app2_cert5_rotated_cert6 b/services/tests/PackageManagerServiceTests/server/res/raw/install_app2_cert5_rotated_cert6
index 30bb647..6feebb8 100644
--- a/services/tests/PackageManagerServiceTests/server/res/raw/install_app2_cert5_rotated_cert6
+++ b/services/tests/PackageManagerServiceTests/server/res/raw/install_app2_cert5_rotated_cert6
Binary files differ