Merge "Add power stats collector and processor for Camera and GNSS" into main
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index ffb920b..15b13dc 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -757,15 +757,6 @@
void addStartInfoTimestamp(int key, long timestampNs, int userId);
/**
- * Reports view related timestamps to be added to the calling apps most
- * recent {@link ApplicationStartInfo}.
- *
- * @param renderThreadDrawStartTimeNs Clock monotonic time in nanoseconds of RenderThread draw start
- * @param framePresentedTimeNs Clock monotonic time in nanoseconds of frame presented
- */
- oneway void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs, long framePresentedTimeNs);
-
- /**
* Return a list of {@link ApplicationExitInfo} records.
*
* <p class="note"> Note: System stores these historical information in a ring buffer, older
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 61f1ee1..e2159f7 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -38,6 +38,9 @@
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Binder;
@@ -193,7 +196,11 @@
@RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
@NonNull
public BiometricPrompt.Builder setLogoRes(@DrawableRes int logoRes) {
- mPromptInfo.setLogoRes(logoRes);
+ if (mPromptInfo.getLogoBitmap() != null) {
+ throw new IllegalStateException(
+ "Exclusively one of logo resource or logo bitmap can be set");
+ }
+ mPromptInfo.setLogo(logoRes, convertDrawableToBitmap(mContext.getDrawable(logoRes)));
return this;
}
@@ -212,7 +219,11 @@
@RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
@NonNull
public BiometricPrompt.Builder setLogoBitmap(@NonNull Bitmap logoBitmap) {
- mPromptInfo.setLogoBitmap(logoBitmap);
+ if (mPromptInfo.getLogoRes() != -1) {
+ throw new IllegalStateException(
+ "Exclusively one of logo resource or logo bitmap can be set");
+ }
+ mPromptInfo.setLogo(-1, logoBitmap);
return this;
}
@@ -1516,4 +1527,29 @@
private static boolean isCredentialAllowed(@Authenticators.Types int allowedAuthenticators) {
return (allowedAuthenticators & Authenticators.DEVICE_CREDENTIAL) != 0;
}
+
+ /** Converts {@code drawable} to a {@link Bitmap}. */
+ private static Bitmap convertDrawableToBitmap(Drawable drawable) {
+ if (drawable == null) {
+ return null;
+ }
+
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+
+ Bitmap bitmap;
+ if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
+ bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ // Single color bitmap will be created of 1x1 pixel
+ } else {
+ bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+ }
+
+ final Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ }
}
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index bb07b9b..f4a3c87 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -217,14 +217,17 @@
// LINT.ThenChange(frameworks/base/core/java/android/hardware/biometrics/BiometricPrompt.java)
// Setters
- public void setLogoRes(@DrawableRes int logoRes) {
- mLogoRes = logoRes;
- checkOnlyOneLogoSet();
- }
- public void setLogoBitmap(@NonNull Bitmap logoBitmap) {
+ /**
+ * Sets logo res and bitmap
+ *
+ * @param logoRes The logo res set by the app; Or -1 if the app sets bitmap directly.
+ * @param logoBitmap The bitmap from logoRes if the app sets logoRes; Or the bitmap set by the
+ * app directly.
+ */
+ public void setLogo(@DrawableRes int logoRes, @NonNull Bitmap logoBitmap) {
+ mLogoRes = logoRes;
mLogoBitmap = logoBitmap;
- checkOnlyOneLogoSet();
}
public void setLogoDescription(@NonNull String logoDescription) {
@@ -326,13 +329,29 @@
}
// Getters
+
+ /**
+ * Returns the logo bitmap either from logo resource or bitmap passed in from the app.
+ */
+ public Bitmap getLogo() {
+ return mLogoBitmap;
+ }
+
+ /**
+ * Returns the logo res set by the app.
+ */
@DrawableRes
public int getLogoRes() {
return mLogoRes;
}
+ /**
+ * Returns the logo bitmap set by the app.
+ */
public Bitmap getLogoBitmap() {
- return mLogoBitmap;
+ // If mLogoRes has been set, return null since mLogoBitmap is from the res, but not from
+ // the app directly.
+ return mLogoRes == -1 ? mLogoBitmap : null;
}
public String getLogoDescription() {
@@ -436,10 +455,4 @@
return mComponentNameForConfirmDeviceCredentialActivity;
}
- private void checkOnlyOneLogoSet() {
- if (mLogoRes != -1 && mLogoBitmap != null) {
- throw new IllegalStateException(
- "Exclusively one of logo resource or logo bitmap can be set");
- }
- }
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a11bb78..a26150c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -177,7 +177,6 @@
import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
-import android.hardware.SyncFence;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerGlobal;
@@ -220,7 +219,6 @@
import android.view.InputDevice.InputSourceClass;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceControl.TransactionStats;
import android.view.View.AttachInfo;
import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
@@ -295,7 +293,6 @@
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
-import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* The top of a view hierarchy, implementing the needed protocol between View
@@ -1192,13 +1189,6 @@
private String mFpsTraceName;
private String mLargestViewTraceName;
- private final boolean mAppStartInfoTimestampsFlagValue;
- @GuardedBy("this")
- private boolean mAppStartTimestampsSent = false;
- private boolean mAppStartTrackingStarted = false;
- private long mRenderThreadDrawStartTimeNs = -1;
- private long mFirstFramePresentedTimeNs = -1;
-
private static boolean sToolkitSetFrameRateReadOnlyFlagValue;
private static boolean sToolkitFrameRateFunctionEnablingReadOnlyFlagValue;
private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
@@ -1316,8 +1306,6 @@
} else {
mSensitiveContentProtectionService = null;
}
-
- mAppStartInfoTimestampsFlagValue = android.app.Flags.appStartInfoTimestamps();
}
public static void addFirstDrawHandler(Runnable callback) {
@@ -2590,12 +2578,6 @@
notifySurfaceDestroyed();
}
destroySurface();
-
- // Reset so they can be sent again for warm starts.
- mAppStartTimestampsSent = false;
- mAppStartTrackingStarted = false;
- mRenderThreadDrawStartTimeNs = -1;
- mFirstFramePresentedTimeNs = -1;
}
}
}
@@ -4394,30 +4376,6 @@
reportDrawFinished(t, seqId);
}
});
-
- // Only trigger once per {@link ViewRootImpl} instance, so don't add listener if
- // {link mTransactionCompletedTimeNs} has already been set.
- if (mAppStartInfoTimestampsFlagValue && !mAppStartTrackingStarted) {
- mAppStartTrackingStarted = true;
- Transaction transaction = new Transaction();
- transaction.addTransactionCompletedListener(mExecutor,
- new Consumer<TransactionStats>() {
- @Override
- public void accept(TransactionStats transactionStats) {
- SyncFence presentFence = transactionStats.getPresentFence();
- if (presentFence.awaitForever()) {
- if (mFirstFramePresentedTimeNs == -1) {
- // Only trigger once per {@link ViewRootImpl} instance.
- mFirstFramePresentedTimeNs = presentFence.getSignalTime();
- maybeSendAppStartTimes();
- }
- }
- presentFence.close();
- }
- });
- applyTransactionOnDraw(transaction);
- }
-
if (DEBUG_BLAST) {
Log.d(mTag, "Setup new sync=" + mWmsRequestSyncGroup.getName());
}
@@ -4425,45 +4383,6 @@
mWmsRequestSyncGroup.add(this, null /* runnable */);
}
- private void maybeSendAppStartTimes() {
- synchronized (this) {
- if (mAppStartTimestampsSent) {
- // Don't send timestamps more than once.
- return;
- }
-
- // If we already have {@link mRenderThreadDrawStartTimeNs} then pass it through, if not
- // post to main thread and check if we have it there.
- if (mRenderThreadDrawStartTimeNs != -1) {
- sendAppStartTimesLocked();
- } else {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- synchronized (ViewRootImpl.this) {
- if (mRenderThreadDrawStartTimeNs == -1) {
- return;
- }
- sendAppStartTimesLocked();
- }
- }
- });
- }
- }
- }
-
- @GuardedBy("this")
- private void sendAppStartTimesLocked() {
- try {
- ActivityManager.getService().reportStartInfoViewTimestamps(
- mRenderThreadDrawStartTimeNs, mFirstFramePresentedTimeNs);
- mAppStartTimestampsSent = true;
- } catch (RemoteException e) {
- // Ignore, timestamps may be lost.
- if (DBG) Log.d(TAG, "Exception attempting to report start timestamps.", e);
- }
- }
-
/**
* Helper used to notify the service to block projection when a sensitive
* view (the view displays sensitive content) is attached to the window.
@@ -5650,13 +5569,7 @@
registerCallbackForPendingTransactions();
}
- long timeNs = SystemClock.uptimeNanos();
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
-
- // Only trigger once per {@link ViewRootImpl} instance.
- if (mAppStartInfoTimestampsFlagValue && mRenderThreadDrawStartTimeNs == -1) {
- mRenderThreadDrawStartTimeNs = timeNs;
- }
} else {
// If we get here with a disabled & requested hardware renderer, something went
// wrong (an invalidate posted right before we destroyed the hardware surface
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
index 8718fb1..5b09a8b 100644
--- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -181,26 +181,6 @@
}
/**
- * Converts {@link Settings.Secure} key to {@link UserShortcutType}.
- *
- * @param key The shortcut key.
- * @return Mapping type in Settings.
- */
- public static int convertToType(String key) {
- return switch (key) {
- case Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS -> UserShortcutType.SOFTWARE;
- case Settings.Secure.ACCESSIBILITY_QS_TARGETS -> UserShortcutType.QUICK_SETTINGS;
- case Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE -> UserShortcutType.HARDWARE;
- case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED ->
- UserShortcutType.TRIPLETAP;
- case Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED ->
- UserShortcutType.TWOFINGER_DOUBLETAP;
- default -> throw new IllegalArgumentException(
- "Unsupported user shortcut key: " + key);
- };
- }
-
- /**
* Updates an accessibility state if the accessibility service is a Always-On a11y service,
* a.k.a. AccessibilityServices that has FLAG_REQUEST_ACCESSIBILITY_BUTTON
* <p>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4dfe000..f43351a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7076,4 +7076,8 @@
<!-- Whether the system uses auto-suspend mode. -->
<bool name="config_useAutoSuspend">true</bool>
+
+ <!-- Whether to show GAIA education screen during account login of private space setup.
+ OEM/Partner can explicitly opt to disable the screen. -->
+ <bool name="config_enableGaiaEducationInPrivateSpace">true</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cc74d02..639b746 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -521,6 +521,7 @@
<java-symbol type="bool" name="config_preferKeepClearForFocus" />
<java-symbol type="bool" name="config_hibernationDeletesOatArtifactsEnabled"/>
<java-symbol type="integer" name="config_defaultAnalogClockSecondsHandFps"/>
+ <java-symbol type="bool" name="config_enableGaiaEducationInPrivateSpace"/>
<java-symbol type="color" name="tab_indicator_text_v4" />
diff --git a/packages/EasterEgg/src/com/android/egg/landroid/Physics.kt b/packages/EasterEgg/src/com/android/egg/landroid/Physics.kt
index fc66ad6..d14234e 100644
--- a/packages/EasterEgg/src/com/android/egg/landroid/Physics.kt
+++ b/packages/EasterEgg/src/com/android/egg/landroid/Physics.kt
@@ -20,7 +20,7 @@
import kotlin.random.Random
// artificially speed up or slow down the simulation
-const val TIME_SCALE = 1f
+const val TIME_SCALE = 1f // simulation seconds per wall clock second
// if it's been over 1 real second since our last timestep, don't simulate that elapsed time.
// this allows the simulation to "pause" when, for example, the activity pauses
@@ -36,6 +36,19 @@
fun postUpdate(sim: Simulator, dt: Float)
}
+interface Removable {
+ fun canBeRemoved(): Boolean
+}
+
+class Fuse(var lifetime: Float) : Removable {
+ fun update(dt: Float) {
+ lifetime -= dt
+ }
+ override fun canBeRemoved(): Boolean {
+ return lifetime < 0
+ }
+}
+
open class Body(var name: String = "Unknown") : Entity {
var pos = Vec2.Zero
var opos = Vec2.Zero
diff --git a/packages/EasterEgg/src/com/android/egg/landroid/Universe.kt b/packages/EasterEgg/src/com/android/egg/landroid/Universe.kt
index 1e54569..d6fbc11 100644
--- a/packages/EasterEgg/src/com/android/egg/landroid/Universe.kt
+++ b/packages/EasterEgg/src/com/android/egg/landroid/Universe.kt
@@ -43,11 +43,9 @@
const val MAIN_ENGINE_ACCEL = 1000f // thrust effect, pixels per second squared
const val LAUNCH_MECO = 2f // how long to suspend gravity when launching
-const val SCALED_THRUST = true
+const val LANDING_REMOVAL_TIME = 3600f // one hour of simulation time
-interface Removable {
- fun canBeRemoved(): Boolean
-}
+const val SCALED_THRUST = true
open class Planet(
val orbitCenter: Vec2,
@@ -321,7 +319,7 @@
//
(1..10).forEach {
Spark(
- lifetime = rng.nextFloatInRange(0.5f, 2f),
+ ttl = rng.nextFloatInRange(0.5f, 2f),
style = Spark.Style.DOT,
color = Color.White,
size = 1f
@@ -359,13 +357,22 @@
entities
.filterIsInstance<Removable>()
.filter(predicate = Removable::canBeRemoved)
- .filterIsInstance<Entity>()
- .forEach { remove(it) }
+ .forEach { remove(it as Entity) }
+
+ constraints
+ .filterIsInstance<Removable>()
+ .filter(predicate = Removable::canBeRemoved)
+ .forEach { remove(it as Constraint) }
}
}
-class Landing(var ship: Spacecraft?, val planet: Planet, val angle: Float, val text: String = "") :
- Constraint {
+class Landing(
+ var ship: Spacecraft?,
+ val planet: Planet,
+ val angle: Float,
+ val text: String = "",
+ private val fuse: Fuse = Fuse(LANDING_REMOVAL_TIME)
+) : Constraint, Removable by fuse {
override fun solve(sim: Simulator, dt: Float) {
ship?.let { ship ->
val landingVector = Vec2.makeWithAngleMag(angle, ship.radius + planet.radius)
@@ -373,17 +380,20 @@
ship.pos = (ship.pos * 0.5f) + (desiredPos * 0.5f) // @@@ FIXME
ship.angle = angle
}
+
+ fuse.update(dt)
}
}
class Spark(
- var lifetime: Float,
+ var ttl: Float,
collides: Boolean = false,
mass: Float = 0f,
val style: Style = Style.LINE,
val color: Color = Color.Gray,
- val size: Float = 2f
-) : Removable, Body() {
+ val size: Float = 2f,
+ val fuse: Fuse = Fuse(ttl)
+) : Removable by fuse, Body(name = "Spark") {
enum class Style {
LINE,
LINE_ABSOLUTE,
@@ -398,10 +408,7 @@
}
override fun update(sim: Simulator, dt: Float) {
super.update(sim, dt)
- lifetime -= dt
- }
- override fun canBeRemoved(): Boolean {
- return lifetime < 0
+ fuse.update(dt)
}
}
@@ -486,11 +493,11 @@
// exhaust
sim.add(
Spark(
- lifetime = sim.rng.nextFloatInRange(0.5f, 1f),
+ ttl = sim.rng.nextFloatInRange(0.5f, 1f),
collides = true,
mass = 1f,
style = Spark.Style.RING,
- size = 3f,
+ size = 1f,
color = Color(0x40FFFFFF)
)
.also { spark ->
diff --git a/packages/EasterEgg/src/com/android/egg/landroid/VisibleUniverse.kt b/packages/EasterEgg/src/com/android/egg/landroid/VisibleUniverse.kt
index 974784d..ed3ebc7 100644
--- a/packages/EasterEgg/src/com/android/egg/landroid/VisibleUniverse.kt
+++ b/packages/EasterEgg/src/com/android/egg/landroid/VisibleUniverse.kt
@@ -30,6 +30,7 @@
import androidx.core.math.MathUtils.clamp
import com.android.egg.flags.Flags.flagFlag
import java.lang.Float.max
+import kotlin.math.exp
import kotlin.math.sqrt
const val DRAW_ORBITS = true
@@ -289,7 +290,8 @@
fun ZoomedDrawScope.drawSpark(spark: Spark) {
with(spark) {
- if (lifetime < 0) return
+ if (fuse.lifetime < 0) return
+ val life = 1f - fuse.lifetime / ttl
when (style) {
Spark.Style.LINE ->
if (opos != Vec2.Zero) drawLine(color, opos, pos, strokeWidth = size)
@@ -297,7 +299,13 @@
if (opos != Vec2.Zero) drawLine(color, opos, pos, strokeWidth = size / zoom)
Spark.Style.DOT -> drawCircle(color, size, pos)
Spark.Style.DOT_ABSOLUTE -> drawCircle(color, size, pos / zoom)
- Spark.Style.RING -> drawCircle(color, size, pos, style = Stroke(width = 1f / zoom))
+ Spark.Style.RING ->
+ drawCircle(
+ color = color.copy(alpha = color.alpha * (1f - life)),
+ radius = exp(lerp(size, 3f * size, life)) - 1f,
+ center = pos,
+ style = Stroke(width = 1f / zoom)
+ )
}
}
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 29b57c9..85aa33a 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -981,6 +981,16 @@
}
flag {
+ name: "media_controls_lockscreen_shade_bug_fix"
+ namespace: "systemui"
+ description: "Use ShadeInteractor for media location changes"
+ bug: "319244625"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
namespace: "systemui"
name: "enable_view_capture_tracing"
description: "Enables view capture tracing in System UI."
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java
similarity index 87%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java
index f561c53..d84d151 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.dreams;
+package com.android.systemui.ambient.statusbar.ui;
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
@@ -44,6 +44,10 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.FakeLogBuffer;
import com.android.systemui.res.R;
@@ -54,7 +58,6 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
-import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.time.DateFormatUtil;
import org.junit.Before;
@@ -72,14 +75,12 @@
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4.class)
-public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
+public class AmbientStatusBarViewControllerTest extends SysuiTestCase {
private static final String NOTIFICATION_INDICATOR_FORMATTER_STRING =
"{count, plural, =1 {# notification} other {# notifications}}";
@Mock
- MockDreamOverlayStatusBarView mView;
- @Mock
- TouchInsetManager.TouchInsetSession mTouchSession;
+ MockAmbientStatusBarView mView;
@Mock
Resources mResources;
@Mock
@@ -114,9 +115,11 @@
private final Executor mMainExecutor = Runnable::run;
- private final FakeWifiRepository mWifiRepository = new FakeWifiRepository();
+ private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
- DreamOverlayStatusBarViewController mController;
+ private final FakeWifiRepository mWifiRepository = mKosmos.getFakeWifiRepository();
+
+ AmbientStatusBarViewController mController;
@Before
public void setup() {
@@ -128,11 +131,10 @@
doCallRealMethod().when(mView).getVisibility();
when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
- mController = new DreamOverlayStatusBarViewController(
+ mController = new AmbientStatusBarViewController(
mView,
mResources,
mMainExecutor,
- mTouchSession,
mAlarmManager,
mNextAlarmController,
mDateFormatUtil,
@@ -143,7 +145,7 @@
mDreamOverlayStatusBarItemsProvider,
mDreamOverlayStateController,
mUserTracker,
- mWifiRepository,
+ mKosmos.getWifiInteractor(),
mLogBuffer);
}
@@ -164,7 +166,7 @@
mController.updateWifiUnavailableStatusIcon(false);
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
+ AmbientStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, true, null);
}
@Test
@@ -173,7 +175,7 @@
mController.updateWifiUnavailableStatusIcon(true);
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
+ AmbientStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, false, null);
}
@Test
@@ -183,7 +185,7 @@
when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(alarmClockInfo);
mController.onViewAttached();
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET), eq(true), any());
+ eq(AmbientStatusBarView.STATUS_ICON_ALARM_SET), eq(true), any());
}
@Test
@@ -191,7 +193,7 @@
when(mAlarmManager.getNextAlarmClock(anyInt())).thenReturn(null);
mController.onViewAttached();
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET), eq(false), isNull());
+ eq(AmbientStatusBarView.STATUS_ICON_ALARM_SET), eq(false), isNull());
}
@Test
@@ -202,7 +204,7 @@
.thenReturn(false);
mController.onViewAttached();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED, true, null);
+ AmbientStatusBarView.STATUS_ICON_MIC_DISABLED, true, null);
}
@Test
@@ -213,7 +215,7 @@
.thenReturn(true);
mController.onViewAttached();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED, true, null);
+ AmbientStatusBarView.STATUS_ICON_CAMERA_DISABLED, true, null);
}
@Test
@@ -224,7 +226,7 @@
.thenReturn(true);
mController.onViewAttached();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
+ AmbientStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
}
@Test
@@ -237,7 +239,7 @@
callbackCapture.getValue().onNotificationCountChanged(1);
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
+ eq(AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
}
@Test
@@ -250,16 +252,15 @@
callbackCapture.getValue().onNotificationCountChanged(0);
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), isNull());
+ eq(AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), isNull());
}
@Test
public void testNotificationsIconNotShownWhenCountProviderAbsent() {
- DreamOverlayStatusBarViewController controller = new DreamOverlayStatusBarViewController(
+ AmbientStatusBarViewController controller = new AmbientStatusBarViewController(
mView,
mResources,
mMainExecutor,
- mTouchSession,
mAlarmManager,
mNextAlarmController,
mDateFormatUtil,
@@ -270,11 +271,11 @@
mDreamOverlayStatusBarItemsProvider,
mDreamOverlayStateController,
mUserTracker,
- mWifiRepository,
+ mKosmos.getWifiInteractor(),
mLogBuffer);
controller.onViewAttached();
verify(mView, never()).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
+ eq(AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
}
@Test
@@ -283,7 +284,7 @@
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
mController.onViewAttached();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
+ AmbientStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
}
@Test
@@ -292,7 +293,7 @@
Settings.Global.ZEN_MODE_OFF);
mController.onViewAttached();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
+ AmbientStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
}
@Test
@@ -322,7 +323,7 @@
callbackCapture.getValue().onNotificationCountChanged(1);
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
+ eq(AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
}
@Test
@@ -335,7 +336,7 @@
callbackCapture.getValue().onNotificationCountChanged(0);
verify(mView).showIcon(
- eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), any());
+ eq(AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), any());
}
@Test
@@ -354,7 +355,7 @@
SensorPrivacyManager.Sensors.MICROPHONE, true);
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
+ AmbientStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, true, null);
}
@Test
@@ -369,7 +370,7 @@
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS);
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
+ AmbientStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, true, null);
}
@Test
@@ -384,7 +385,7 @@
callbackCapture.getValue().onZenChanged(Settings.Global.ZEN_MODE_OFF);
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
+ AmbientStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null);
}
@Test
@@ -399,7 +400,7 @@
callbackCapture.getValue().onStateChanged();
verify(mView).showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE, true, null);
+ AmbientStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE, true, null);
}
@Test
@@ -460,7 +461,7 @@
final ArgumentCaptor<DreamOverlayStatusBarItemsProvider.Callback>
callbackCapture = ArgumentCaptor.forClass(
- DreamOverlayStatusBarItemsProvider.Callback.class);
+ DreamOverlayStatusBarItemsProvider.Callback.class);
verify(mDreamOverlayStatusBarItemsProvider).addCallback(callbackCapture.capture());
callbackCapture.getValue().onStatusBarItemsChanged(List.of(mStatusBarItem));
@@ -532,10 +533,10 @@
callback.onStateChanged();
}
- private static class MockDreamOverlayStatusBarView extends DreamOverlayStatusBarView {
+ private static class MockAmbientStatusBarView extends AmbientStatusBarView {
private int mVisibility = View.VISIBLE;
- private MockDreamOverlayStatusBarView(Context context) {
+ private MockAmbientStatusBarView(Context context) {
super(context);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
index 9c2791f..75a77cf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
@@ -131,8 +131,9 @@
negativeButton: String = "neg",
): PromptInfo {
val info = PromptInfo()
- info.logoRes = logoRes
- info.logoBitmap = logoBitmap
+ if (logoBitmap != null) {
+ info.setLogo(logoRes, logoBitmap)
+ }
info.logoDescription = logoDescription
info.title = title
info.subtitle = subtitle
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 86fdaa5..73ef775 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -7,6 +7,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.dreams.ui.viewmodel.DreamViewModel
import com.android.systemui.log.core.FakeLogBuffer
@@ -43,7 +44,7 @@
@Mock private lateinit var mockAnimator: AnimatorSet
@Mock private lateinit var blurUtils: BlurUtils
@Mock private lateinit var hostViewController: ComplicationHostViewController
- @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController
+ @Mock private lateinit var statusBarViewController: AmbientStatusBarViewController
@Mock private lateinit var stateController: DreamOverlayStateController
@Mock private lateinit var transitionViewModel: DreamViewModel
private val logBuffer = FakeLogBuffer.Factory.create()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index f5c86e0..4c8c113 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -47,6 +47,7 @@
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController;
import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
@@ -55,6 +56,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.touch.TouchInsetManager;
import kotlinx.coroutines.CoroutineDispatcher;
@@ -80,7 +82,7 @@
ViewTreeObserver mViewTreeObserver;
@Mock
- DreamOverlayStatusBarViewController mDreamOverlayStatusBarViewController;
+ AmbientStatusBarViewController mAmbientStatusBarViewController;
@Mock
LowLightTransitionCoordinator mLowLightTransitionCoordinator;
@@ -131,6 +133,8 @@
CommunalInteractor mCommunalInteractor;
@Mock
private DreamManager mDreamManager;
+ @Mock
+ private TouchInsetManager.TouchInsetSession mTouchInsetSession;
DreamOverlayContainerViewController mController;
@@ -150,8 +154,9 @@
mComplicationHostViewController,
mDreamOverlayContentView,
mHubGestureIndicatorView,
- mDreamOverlayStatusBarViewController,
+ mAmbientStatusBarViewController,
mLowLightTransitionCoordinator,
+ mTouchInsetSession,
mBlurUtils,
mHandler,
mDispatcher,
@@ -190,7 +195,7 @@
@Test
public void testDreamOverlayStatusBarViewControllerInitialized() {
mController.init();
- verify(mDreamOverlayStatusBarViewController).init();
+ verify(mAmbientStatusBarViewController).init();
}
@Test
diff --git a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml b/packages/SystemUI/res/layout/ambient_status_bar_view.xml
similarity index 97%
rename from packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
rename to packages/SystemUI/res/layout/ambient_status_bar_view.xml
index ec2edb5..7d765ce 100644
--- a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
+++ b/packages/SystemUI/res/layout/ambient_status_bar_view.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<com.android.systemui.dreams.DreamOverlayStatusBarView
+<com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/dream_overlay_status_bar"
@@ -118,4 +118,4 @@
android:contentDescription="@string/assistant_attention_content_description" />
</LinearLayout>
-</com.android.systemui.dreams.DreamOverlayStatusBarView>
+</com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView>
diff --git a/packages/SystemUI/res/layout/dream_overlay_container.xml b/packages/SystemUI/res/layout/dream_overlay_container.xml
index 4234fca5..dcd3fa6 100644
--- a/packages/SystemUI/res/layout/dream_overlay_container.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_container.xml
@@ -44,5 +44,5 @@
app:layout_constraintBottom_toBottomOf="parent"
/>
- <include layout="@layout/dream_overlay_status_bar_view" />
+ <include layout="@layout/ambient_status_bar_view" />
</com.android.systemui.dreams.DreamOverlayContainerView>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
index 8979ef1..12d881b 100644
--- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
+++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/Utils.kt
@@ -25,7 +25,11 @@
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
import android.content.Context
import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.Canvas
import android.graphics.Insets
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
import android.hardware.biometrics.BiometricManager.Authenticators
import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.SensorPropertiesInternal
@@ -122,4 +126,26 @@
return windowMetrics?.windowInsets?.getInsets(WindowInsets.Type.navigationBars())
?: Insets.NONE
}
+
+ /** Converts `drawable` to a [Bitmap]. */
+ @JvmStatic
+ fun Drawable?.toBitmap(): Bitmap? {
+ if (this == null) {
+ return null
+ }
+ if (this is BitmapDrawable) {
+ return bitmap
+ }
+ val bitmap: Bitmap =
+ if (intrinsicWidth <= 0 || intrinsicHeight <= 0) {
+ Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+ // Single color bitmap will be created of 1x1 pixel
+ } else {
+ Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
+ }
+ val canvas = Canvas(bitmap)
+ setBounds(0, 0, canvas.width, canvas.height)
+ draw(canvas)
+ return bitmap
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
index ea00398..b0314d8 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
@@ -16,11 +16,19 @@
package com.android.systemui.ambient.dagger
+import com.android.systemui.ambient.statusbar.dagger.AmbientStatusBarComponent
import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
import com.android.systemui.ambient.touch.dagger.InputSessionComponent
import dagger.Module
-@Module(subcomponents = [AmbientTouchComponent::class, InputSessionComponent::class])
+@Module(
+ subcomponents =
+ [
+ AmbientStatusBarComponent::class,
+ AmbientTouchComponent::class,
+ InputSessionComponent::class,
+ ]
+)
interface AmbientModule {
companion object {
const val TOUCH_HANDLERS = "touch_handlers"
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/statusbar/dagger/AmbientStatusBarComponent.kt b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/dagger/AmbientStatusBarComponent.kt
new file mode 100644
index 0000000..8ad4d00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/dagger/AmbientStatusBarComponent.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.ambient.statusbar.dagger
+
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController
+import dagger.BindsInstance
+import dagger.Subcomponent
+
+/**
+ * [AmbientStatusBarComponent] can be used for displaying a status bar over ambient surfaces like
+ * the dream or communal hub.
+ */
+@Subcomponent
+interface AmbientStatusBarComponent {
+ @Subcomponent.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance view: AmbientStatusBarView,
+ ): AmbientStatusBarComponent
+ }
+
+ /** Builds a [AmbientStatusBarViewController] */
+ fun getController(): AmbientStatusBarViewController
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
rename to packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java
index 8e77079..aa96231 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.dreams;
+package com.android.systemui.ambient.statusbar.ui;
import android.annotation.IntDef;
import android.annotation.Nullable;
@@ -39,10 +39,10 @@
import java.util.Objects;
/**
- * {@link DreamOverlayStatusBarView} is the view responsible for displaying the status bar in a
+ * {@link AmbientStatusBarView} is the view responsible for displaying the status bar in a
* dream. The status bar displays conditional status icons such as "priority mode" and "no wifi".
*/
-public class DreamOverlayStatusBarView extends ConstraintLayout {
+public class AmbientStatusBarView extends ConstraintLayout {
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "STATUS_ICON_" }, value = {
@@ -76,20 +76,20 @@
private static final float KEY_SHADOW_ALPHA = 0.35f;
private static final float AMBIENT_SHADOW_ALPHA = 0.4f;
- public DreamOverlayStatusBarView(Context context) {
+ public AmbientStatusBarView(Context context) {
this(context, null);
}
- public DreamOverlayStatusBarView(Context context, AttributeSet attrs) {
+ public AmbientStatusBarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
- public DreamOverlayStatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public AmbientStatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
mContext = context;
}
- public DreamOverlayStatusBarView(
+ public AmbientStatusBarView(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
rename to packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java
index da72a56..a242d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/statusbar/ui/AmbientStatusBarViewController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.dreams;
+package com.android.systemui.ambient.statusbar.ui;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -31,20 +31,22 @@
import androidx.annotation.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamLogger;
+import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider;
import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
-import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.dagger.DreamLog;
import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository;
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor;
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.time.DateFormatUtil;
@@ -59,13 +61,11 @@
import javax.inject.Inject;
/**
- * View controller for {@link DreamOverlayStatusBarView}.
+ * View controller for {@link AmbientStatusBarView}.
*/
-@DreamOverlayComponent.DreamOverlayScope
-public class DreamOverlayStatusBarViewController extends ViewController<DreamOverlayStatusBarView> {
+public class AmbientStatusBarViewController extends ViewController<AmbientStatusBarView> {
private static final String TAG = "DreamStatusBarCtrl";
- private final TouchInsetManager.TouchInsetSession mTouchInsetSession;
private final NextAlarmController mNextAlarmController;
private final AlarmManager mAlarmManager;
private final Resources mResources;
@@ -76,7 +76,7 @@
private final ZenModeController mZenModeController;
private final DreamOverlayStateController mDreamOverlayStateController;
private final UserTracker mUserTracker;
- private final WifiRepository mWifiRepository;
+ private final WifiInteractor mWifiInteractor;
private final StatusBarWindowStateController mStatusBarWindowStateController;
private final DreamOverlayStatusBarItemsProvider mStatusBarItemsProvider;
private final Executor mMainExecutor;
@@ -115,7 +115,7 @@
private final DreamOverlayNotificationCountProvider.Callback mNotificationCountCallback =
notificationCount -> showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS,
+ AmbientStatusBarView.STATUS_ICON_NOTIFICATIONS,
notificationCount > 0,
notificationCount > 0
? buildNotificationsContentDescription(notificationCount)
@@ -125,11 +125,10 @@
this::onStatusBarItemsChanged;
@Inject
- public DreamOverlayStatusBarViewController(
- DreamOverlayStatusBarView view,
+ public AmbientStatusBarViewController(
+ AmbientStatusBarView view,
@Main Resources resources,
@Main Executor mainExecutor,
- TouchInsetManager.TouchInsetSession touchInsetSession,
AlarmManager alarmManager,
NextAlarmController nextAlarmController,
DateFormatUtil dateFormatUtil,
@@ -140,12 +139,11 @@
DreamOverlayStatusBarItemsProvider statusBarItemsProvider,
DreamOverlayStateController dreamOverlayStateController,
UserTracker userTracker,
- WifiRepository wifiRepository,
+ WifiInteractor wifiInteractor,
@DreamLog LogBuffer logBuffer) {
super(view);
mResources = resources;
mMainExecutor = mainExecutor;
- mTouchInsetSession = touchInsetSession;
mAlarmManager = alarmManager;
mNextAlarmController = nextAlarmController;
mDateFormatUtil = dateFormatUtil;
@@ -156,7 +154,7 @@
mZenModeController = zenModeController;
mDreamOverlayStateController = dreamOverlayStateController;
mUserTracker = userTracker;
- mWifiRepository = wifiRepository;
+ mWifiInteractor = wifiInteractor;
mLogger = new DreamLogger(logBuffer, TAG);
// Register to receive show/hide updates for the system status bar. Our custom status bar
@@ -170,7 +168,7 @@
collectFlow(
mView,
- mWifiRepository.getWifiNetwork(),
+ mWifiInteractor.getWifiNetwork(),
network -> updateWifiUnavailableStatusIcon(
network instanceof WifiNetworkModel.Active));
@@ -202,7 +200,6 @@
mView.removeAllExtraStatusBarItemViews();
mDreamOverlayStateController.setDreamOverlayStatusBarVisible(false);
mDreamOverlayStateController.removeCallback(mDreamOverlayStateCallback);
- mTouchInsetSession.clear();
mIsAttached = false;
}
@@ -212,7 +209,7 @@
*
* No-op if the dream overlay status bar should not be shown.
*/
- protected void setFadeAmount(float fadeAmount, boolean fadingOut) {
+ public void setFadeAmount(float fadeAmount, boolean fadingOut) {
updateVisibility();
if (mView.getVisibility() != View.VISIBLE) {
@@ -240,7 +237,7 @@
@VisibleForTesting
void updateWifiUnavailableStatusIcon(boolean available) {
- showIcon(DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available,
+ showIcon(AmbientStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, !available,
R.string.wifi_unavailable_dream_overlay_content_description);
}
@@ -249,13 +246,13 @@
mAlarmManager.getNextAlarmClock(mUserTracker.getUserId());
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET,
+ AmbientStatusBarView.STATUS_ICON_ALARM_SET,
hasAlarm,
hasAlarm ? buildAlarmContentDescription(alarm) : null);
}
private void updateAssistantAttentionIcon() {
- showIcon(DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE,
+ showIcon(AmbientStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE,
mDreamOverlayStateController.hasAssistantAttention(),
R.string.assistant_attention_content_description);
}
@@ -284,17 +281,17 @@
.isSensorBlocked(SensorPrivacyManager.Sensors.MICROPHONE);
final boolean cameraBlocked = mSensorPrivacyController
.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA);
- @DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL;
+ @AmbientStatusBarView.StatusIconType int iconType = Resources.ID_NULL;
showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED,
+ AmbientStatusBarView.STATUS_ICON_CAMERA_DISABLED,
!micBlocked && cameraBlocked,
R.string.camera_blocked_dream_overlay_content_description);
showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED,
+ AmbientStatusBarView.STATUS_ICON_MIC_DISABLED,
micBlocked && !cameraBlocked,
R.string.microphone_blocked_dream_overlay_content_description);
showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
+ AmbientStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
micBlocked && cameraBlocked,
R.string.camera_and_microphone_blocked_dream_overlay_content_description);
}
@@ -308,24 +305,24 @@
private void updatePriorityModeStatusIcon() {
showIcon(
- DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON,
+ AmbientStatusBarView.STATUS_ICON_PRIORITY_MODE_ON,
mZenModeController.getZen() != Settings.Global.ZEN_MODE_OFF,
R.string.priority_mode_dream_overlay_content_description);
}
- private void showIcon(@DreamOverlayStatusBarView.StatusIconType int iconType, boolean show,
+ private void showIcon(@AmbientStatusBarView.StatusIconType int iconType, boolean show,
int contentDescriptionResId) {
showIcon(iconType, show, mResources.getString(contentDescriptionResId));
}
private void showIcon(
- @DreamOverlayStatusBarView.StatusIconType int iconType,
+ @AmbientStatusBarView.StatusIconType int iconType,
boolean show,
@Nullable String contentDescription) {
mMainExecutor.execute(() -> {
if (mIsAttached) {
mLogger.logShowOrHideStatusBarItem(
- show, DreamOverlayStatusBarView.getLoggableStatusIconType(iconType));
+ show, AmbientStatusBarView.getLoggableStatusIconType(iconType));
mView.showIcon(iconType, show, contentDescription);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt
index 9b14d6f..2fa4a89 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/DisplayStateRepository.kt
@@ -139,9 +139,10 @@
}
.stateIn(
backgroundScope,
- started = SharingStarted.WhileSubscribed(),
+ started = SharingStarted.Eagerly,
initialValue = false,
)
+
private fun dpiFromPx(size: Float, densityDpi: Int): Float {
val densityRatio = densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT
return size / densityRatio
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
index 4f96c1e..348b423 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt
@@ -40,8 +40,7 @@
operationInfo = operationInfo,
showEmergencyCallButton = info.isShowEmergencyCallButton
) {
- val logoRes: Int = info.logoRes
- val logoBitmap: Bitmap? = info.logoBitmap
+ val logoBitmap: Bitmap? = info.logo
val logoDescription: String? = info.logoDescription
val negativeButtonText: String = info.negativeButtonText?.toString() ?: ""
val componentNameForConfirmDeviceCredentialActivity: ComponentName? =
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index a39a74f..d95a893 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -504,7 +504,6 @@
.map {
when {
!(customBiometricPrompt() && constraintBp()) || it == null -> null
- it.logoRes != -1 -> context.resources.getDrawable(it.logoRes, context.theme)
it.logoBitmap != null -> BitmapDrawable(context.resources, it.logoBitmap)
else -> context.getUserBadgedIcon(it, iconProvider, activityTaskManager)
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index f860893..3294c81 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -27,11 +27,13 @@
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
import com.android.dream.lowlight.util.TruncatedInterpolator
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.complication.ComplicationLayoutParams
import com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTOM
import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP
import com.android.systemui.complication.ComplicationLayoutParams.Position
+import com.android.systemui.dreams.dagger.DreamOverlayComponent.DreamOverlayScope
import com.android.systemui.dreams.dagger.DreamOverlayModule
import com.android.systemui.dreams.ui.viewmodel.DreamViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -45,12 +47,13 @@
import kotlinx.coroutines.launch
/** Controller for dream overlay animations. */
+@DreamOverlayScope
class DreamOverlayAnimationsController
@Inject
constructor(
private val mBlurUtils: BlurUtils,
private val mComplicationHostViewController: ComplicationHostViewController,
- private val mStatusBarViewController: DreamOverlayStatusBarViewController,
+ private val mStatusBarViewController: AmbientStatusBarViewController,
private val mOverlayStateController: DreamOverlayStateController,
@Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int,
private val dreamViewModel: DreamViewModel,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 1e725eb..245def8 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -40,6 +40,7 @@
import com.android.app.animation.Interpolators;
import com.android.dream.lowlight.LowLightTransitionCoordinator;
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController;
import com.android.systemui.ambient.touch.scrim.BouncerlessScrimController;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
@@ -55,6 +56,7 @@
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.ViewController;
import kotlinx.coroutines.CoroutineDispatcher;
@@ -72,10 +74,12 @@
public class DreamOverlayContainerViewController extends
ViewController<DreamOverlayContainerView> implements
LowLightTransitionCoordinator.LowLightEnterListener {
- private final DreamOverlayStatusBarViewController mStatusBarViewController;
+ private final AmbientStatusBarViewController mStatusBarViewController;
+ private final TouchInsetManager.TouchInsetSession mTouchInsetSession;
private final BlurUtils mBlurUtils;
private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
private final DreamOverlayStateController mStateController;
+
private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final ShadeInteractor mShadeInteractor;
@@ -188,8 +192,9 @@
ComplicationHostViewController complicationHostViewController,
@Named(DreamOverlayModule.DREAM_OVERLAY_CONTENT_VIEW) ViewGroup contentView,
@Named(DreamOverlayModule.HUB_GESTURE_INDICATOR_VIEW) View hubGestureIndicatorView,
- DreamOverlayStatusBarViewController statusBarViewController,
+ AmbientStatusBarViewController statusBarViewController,
LowLightTransitionCoordinator lowLightTransitionCoordinator,
+ TouchInsetManager.TouchInsetSession touchInsetSession,
BlurUtils blurUtils,
@Main Handler handler,
@Background CoroutineDispatcher backgroundDispatcher,
@@ -209,6 +214,7 @@
super(containerView);
mDreamOverlayContentView = contentView;
mStatusBarViewController = statusBarViewController;
+ mTouchInsetSession = touchInsetSession;
mBlurUtils = blurUtils;
mDreamOverlayAnimationsController = animationsController;
mStateController = stateController;
@@ -294,6 +300,7 @@
mHandler.removeCallbacksAndMessages(null);
mPrimaryBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
mBouncerlessScrimController.removeCallback(mBouncerlessExpansionCallback);
+ mTouchInsetSession.clear();
mDreamOverlayAnimationsController.cancelAnimations();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java
index 409b196..0833518 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java
@@ -31,12 +31,13 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
/**
* An {@link AlphaOptimizedImageView} that is responsible for rendering a dot. Used by
- * {@link DreamOverlayStatusBarView}.
+ * {@link AmbientStatusBarView}.
*/
public class DreamOverlayDotImageView extends AlphaOptimizedImageView {
private final @ColorInt int mDotColor;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index 789b7f8..76fcabd 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -25,9 +25,11 @@
import androidx.lifecycle.LifecycleOwner;
import com.android.internal.util.Preconditions;
+import com.android.systemui.ambient.statusbar.dagger.AmbientStatusBarComponent;
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarView;
+import com.android.systemui.ambient.statusbar.ui.AmbientStatusBarViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayContainerView;
-import com.android.systemui.dreams.DreamOverlayStatusBarView;
import com.android.systemui.res.R;
import com.android.systemui.touch.TouchInsetManager;
@@ -60,7 +62,7 @@
public static DreamOverlayContainerView providesDreamOverlayContainerView(
LayoutInflater layoutInflater) {
return Preconditions.checkNotNull((DreamOverlayContainerView)
- layoutInflater.inflate(R.layout.dream_overlay_container, null),
+ layoutInflater.inflate(R.layout.dream_overlay_container, null),
"R.layout.dream_layout_container could not be properly inflated");
}
@@ -95,13 +97,23 @@
/** */
@Provides
@DreamOverlayComponent.DreamOverlayScope
- public static DreamOverlayStatusBarView providesDreamOverlayStatusBarView(
+ public static AmbientStatusBarView providesDreamOverlayStatusBarView(
DreamOverlayContainerView view) {
return Preconditions.checkNotNull(view.findViewById(R.id.dream_overlay_status_bar),
"R.id.status_bar must not be null");
}
- /** */
+ /**
+ * Provides the view controller for the {@link AmbientStatusBarView}
+ */
+ @Provides
+ @DreamOverlayComponent.DreamOverlayScope
+ public static AmbientStatusBarViewController providesStatusBarViewController(
+ AmbientStatusBarView view, AmbientStatusBarComponent.Factory factory) {
+ return factory.create(view).getController();
+ }
+
+ /** */
@Provides
@DreamOverlayComponent.DreamOverlayScope
@Named(MAX_BURN_IN_OFFSET)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
index 180afb2..1b342ed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerLockscreenVisibilityManager.kt
@@ -142,17 +142,15 @@
nonApps: Array<RemoteAnimationTarget>,
finishedCallback: IRemoteAnimationFinishedCallback
) {
- // Ensure that we've started a dismiss keyguard transition. WindowManager can start the
- // going away animation on its own, if an activity launches and then requests dismissing the
- // keyguard. In this case, this is the first and only signal we'll receive to start
- // a transition to GONE. This transition needs to start even if we're not provided an app
- // animation target - it's possible the app is destroyed on creation, etc. but we'll still
- // be unlocking.
- keyguardTransitionInteractor.startDismissKeyguardTransition(
- reason = "Going away remote animation started"
- )
-
if (apps.isNotEmpty()) {
+ // Ensure that we've started a dismiss keyguard transition. WindowManager can start the
+ // going away animation on its own, if an activity launches and then requests dismissing
+ // the keyguard. In this case, this is the first and only signal we'll receive to start
+ // a transition to GONE.
+ keyguardTransitionInteractor.startDismissKeyguardTransition(
+ reason = "Going away remote animation started"
+ )
+
goingAwayRemoteAnimationFinishedCallback = finishedCallback
keyguardSurfaceBehindAnimator.applyParamsToSurface(apps[0])
} else {
@@ -185,11 +183,25 @@
/**
* Sets the lockscreen state WM-side by calling ATMS#setLockScreenShown.
*
- * If [lockscreenShowing] is null, it means we don't know if the lockscreen is showing yet. This
- * will be decided by the [KeyguardTransitionBootInteractor] shortly.
+ * [lockscreenShowing] defaults to true, since it's only ever null during the boot sequence,
+ * when we haven't yet called ATMS#setLockScreenShown. Typically,
+ * setWmLockscreenState(lockscreenShowing = true) is called early in the boot sequence, before
+ * setWmLockscreenState(aodVisible = true), so we don't expect to need to use this default, but
+ * if so, true should be the right choice.
*/
private fun setWmLockscreenState(
- lockscreenShowing: Boolean? = this.isLockscreenShowing,
+ lockscreenShowing: Boolean =
+ this.isLockscreenShowing
+ ?: true.also {
+ Log.d(
+ TAG,
+ "Using isLockscreenShowing=true default in setWmLockscreenState, " +
+ "because setAodVisible was called before the first " +
+ "setLockscreenShown call during boot. This is not typical, but is " +
+ "theoretically possible. If you're investigating the lockscreen " +
+ "showing unexpectedly, start here."
+ )
+ },
aodVisible: Boolean = this.isAodVisible
) {
Log.d(
@@ -199,27 +211,10 @@
"aodVisible=$aodVisible)."
)
- if (lockscreenShowing == null) {
- Log.d(
- TAG,
- "isAodVisible=$aodVisible, but lockscreenShowing=null. Waiting for" +
- "non-null lockscreenShowing before calling ATMS#setLockScreenShown, which" +
- "will happen once KeyguardTransitionBootInteractor starts the boot transition."
- )
- this.isAodVisible = aodVisible
- return
- }
-
if (this.isLockscreenShowing == lockscreenShowing && this.isAodVisible == aodVisible) {
return
}
- Log.d(
- TAG,
- "ATMS#setLockScreenShown(" +
- "isLockscreenShowing=$lockscreenShowing, " +
- "aodVisible=$aodVisible)."
- )
activityTaskManagerService.setLockScreenShown(lockscreenShowing, aodVisible)
this.isLockscreenShowing = lockscreenShowing
this.isAodVisible = aodVisible
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
index 3a43b1c..88e6602 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
@@ -229,14 +229,11 @@
val aodVisibility: Flow<Boolean> =
combine(
keyguardInteractor.isDozing,
- keyguardInteractor.isAodAvailable,
keyguardInteractor.biometricUnlockState,
- ) { isDozing, isAodAvailable, biometricUnlockState ->
+ ) { isDozing, biometricUnlockState ->
// AOD is visible if we're dozing, unless we are wake and unlocking (where we go
// directly from AOD to unlocked while dozing).
- isDozing &&
- isAodAvailable &&
- !BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode)
+ isDozing && !BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode)
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index 601d563..88a28bf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -36,6 +36,7 @@
import com.android.app.animation.Interpolators
import com.android.app.tracing.traceSection
import com.android.keyguard.KeyguardViewController
+import com.android.systemui.Flags.mediaControlsLockscreenShadeBugFix
import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -483,8 +484,7 @@
object : StatusBarStateController.StateListener {
override fun onStatePreChange(oldState: Int, newState: Int) {
// We're updating the location before the state change happens, since we want
- // the
- // location of the previous state to still be up to date when the animation
+ // the location of the previous state to still be up to date when the animation
// starts
if (
newState == StatusBarState.SHADE_LOCKED &&
@@ -588,6 +588,17 @@
}
}
+ if (mediaControlsLockscreenShadeBugFix()) {
+ coroutineScope.launch {
+ shadeInteractor.shadeExpansion.collect { expansion ->
+ if (expansion >= 1f || expansion <= 0f) {
+ // Shade has fully expanded or collapsed: force transition amount update
+ setTransitionToFullShadeAmount(expansion)
+ }
+ }
+ }
+ }
+
val settingsObserver: ContentObserver =
object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
index 1f6a8b8..08f139c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
@@ -7,6 +7,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.Utils.toBitmap
import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal
import com.android.systemui.biometrics.promptInfo
import com.android.systemui.biometrics.shared.model.BiometricModalities
@@ -28,6 +29,7 @@
@Test
fun biometricRequestFromPromptInfo() {
val logoRes = R.drawable.ic_cake
+ val logoBitmapFromRes = context.getDrawable(logoRes).toBitmap()
val logoDescription = "test cake"
val title = "what"
val subtitle = "a"
@@ -44,6 +46,7 @@
BiometricPromptRequest.Biometric(
promptInfo(
logoRes = logoRes,
+ logoBitmap = logoBitmapFromRes,
logoDescription = logoDescription,
title = title,
subtitle = subtitle,
@@ -56,7 +59,8 @@
OP_PACKAGE_NAME,
)
- assertThat(request.logoRes).isEqualTo(logoRes)
+ assertThat(request.logoBitmap).isNotNull()
+ assertThat(request.logoBitmap!!.sameAs(logoBitmapFromRes)).isTrue()
assertThat(request.logoDescription).isEqualTo(logoDescription)
assertThat(request.title).isEqualTo(title)
assertThat(request.subtitle).isEqualTo(subtitle)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index db6aba3..7076954 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -48,6 +48,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.UdfpsUtils
+import com.android.systemui.biometrics.Utils.toBitmap
import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
@@ -129,7 +130,7 @@
private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android)
private val defaultLogoIconWithOverrides = context.getDrawable(R.drawable.ic_add)
private val logoResFromApp = R.drawable.ic_cake
- private val logoFromApp = context.getDrawable(logoResFromApp)
+ private val logoDrawableFromAppRes = context.getDrawable(logoResFromApp)
private val logoBitmapFromApp = Bitmap.createBitmap(400, 400, Bitmap.Config.RGB_565)
private val defaultLogoDescription = "Test Android App"
private val logoDescriptionFromApp = "Test Cake App"
@@ -223,7 +224,7 @@
context.setMockPackageManager(packageManager)
val resources = context.getOrCreateTestableResources()
- resources.addOverride(logoResFromApp, logoFromApp)
+ resources.addOverride(logoResFromApp, logoDrawableFromAppRes)
resources.addOverride(
R.array.biometric_dialog_package_names_for_logo_with_overrides,
arrayOf(packageNameForLogoWithOverrides)
@@ -1251,7 +1252,7 @@
@Test
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun descriptionOverriddenByVerticalListContentView() =
- runGenericTest(contentView = promptContentView, description = "test description") {
+ runGenericTest(description = "test description", contentView = promptContentView) {
val contentView by collectLastValue(viewModel.contentView)
val description by collectLastValue(viewModel.description)
@@ -1263,8 +1264,8 @@
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun descriptionOverriddenByContentViewWithMoreOptionsButton() =
runGenericTest(
- contentView = promptContentViewWithMoreOptionsButton,
- description = "test description"
+ description = "test description",
+ contentView = promptContentViewWithMoreOptionsButton
) {
val contentView by collectLastValue(viewModel.contentView)
val description by collectLastValue(viewModel.description)
@@ -1324,8 +1325,9 @@
@EnableFlags(FLAG_CUSTOM_BIOMETRIC_PROMPT, FLAG_CONSTRAINT_BP)
fun logo_resSetByApp() =
runGenericTest(logoRes = logoResFromApp) {
+ val expectedBitmap = context.getDrawable(logoResFromApp).toBitmap()
val logo by collectLastValue(viewModel.logo)
- assertThat(logo).isEqualTo(logoFromApp)
+ assertThat((logo as BitmapDrawable).bitmap.sameAs(expectedBitmap)).isTrue()
}
@Test
@@ -1438,7 +1440,8 @@
descriptionFromApp = description,
contentViewFromApp = contentView,
logoResFromApp = logoRes,
- logoBitmapFromApp = logoBitmap,
+ logoBitmapFromApp =
+ if (logoRes != -1) logoDrawableFromAppRes.toBitmap() else logoBitmap,
logoDescriptionFromApp = logoDescription,
packageName = packageName,
)
@@ -1631,8 +1634,6 @@
) {
val info =
PromptInfo().apply {
- logoRes = logoResFromApp
- logoBitmap = logoBitmapFromApp
logoDescription = logoDescriptionFromApp
title = "t"
subtitle = "s"
@@ -1642,6 +1643,9 @@
isDeviceCredentialAllowed = allowCredentialFallback
isConfirmationRequested = requireConfirmation
}
+ if (logoBitmapFromApp != null) {
+ info.setLogo(logoResFromApp, logoBitmapFromApp)
+ }
setPrompt(
info,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
index 4e1b12f..1f13298 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
@@ -100,11 +100,9 @@
}
@Test
- fun testAodVisible_noLockscreenShownCallYet_doesNotShowLockscreenUntilLater() {
+ fun testAodVisible_noLockscreenShownCallYet_defaultsToShowLockscreen() {
underTest.setAodVisible(false)
- verifyNoMoreInteractions(activityTaskManagerService)
- underTest.setLockscreenShown(true)
verify(activityTaskManagerService).setLockScreenShown(true, false)
verifyNoMoreInteractions(activityTaskManagerService)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 6d2d04a..45a14ad 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -62,6 +62,8 @@
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.scrimController
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.fakeWifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.wifiInteractor
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
import com.android.systemui.util.time.systemClock
@@ -130,6 +132,8 @@
val shadeController by lazy { kosmos.shadeController }
val shadeRepository by lazy { kosmos.shadeRepository }
val shadeInteractor by lazy { kosmos.shadeInteractor }
+ val wifiInteractor by lazy { kosmos.wifiInteractor }
+ val fakeWifiRepository by lazy { kosmos.fakeWifiRepository }
val ongoingActivityChipsViewModel by lazy { kosmos.ongoingActivityChipsViewModel }
val scrimController by lazy { kosmos.scrimController }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryKosmos.kt
new file mode 100644
index 0000000..8e656cf
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.pipeline.shared.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.fakeConnectivityRepository: FakeConnectivityRepository by
+ Kosmos.Fixture { FakeConnectivityRepository() }
+val Kosmos.connectivityRepository: ConnectivityRepository by
+ Kosmos.Fixture { fakeConnectivityRepository }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
index 97c8d5f..709be5e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 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.
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryKosmos.kt
new file mode 100644
index 0000000..e44061a
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 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.pipeline.wifi.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.fakeWifiRepository: FakeWifiRepository by Kosmos.Fixture { FakeWifiRepository() }
+val Kosmos.wifiRepository: WifiRepository by Kosmos.Fixture { fakeWifiRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorKosmos.kt
new file mode 100644
index 0000000..7036199
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.pipeline.wifi.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.wifiRepository
+
+val Kosmos.wifiInteractor: WifiInteractor by
+ Kosmos.Fixture {
+ WifiInteractorImpl(
+ connectivityRepository,
+ wifiRepository,
+ applicationCoroutineScope,
+ )
+ }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 02a7b0f..4f9db8b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -47,11 +47,6 @@
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
import static com.android.internal.accessibility.common.ShortcutConstants.USER_SHORTCUT_TYPES;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TRIPLETAP;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.TWOFINGER_DOUBLETAP;
import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logAccessibilityShortcutActivated;
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -928,11 +923,25 @@
newValue, restoredFromSdk);
}
}
- case Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
- Settings.Secure.ACCESSIBILITY_QS_TARGETS,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE ->
- restoreAccessibilityShortcutTargets(previousValue, newValue,
- ShortcutUtils.convertToType(which));
+ case Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS -> {
+ synchronized (mLock) {
+ restoreAccessibilityButtonTargetsLocked(
+ previousValue, newValue);
+ }
+ }
+ case Settings.Secure.ACCESSIBILITY_QS_TARGETS -> {
+ if (!android.view.accessibility.Flags.a11yQsShortcut()) {
+ return;
+ }
+ restoreAccessibilityQsTargets(newValue);
+ }
+ case Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE -> {
+ if (!android.view.accessibility.Flags
+ .restoreA11yShortcutTargetService()) {
+ return;
+ }
+ restoreAccessibilityShortcutTargetService(previousValue, newValue);
+ }
}
}
}
@@ -1031,7 +1040,7 @@
}
persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
userState.mUserId, targetsFromSetting, str -> str);
- readAccessibilityShortcutTargetsLocked(userState, SOFTWARE);
+ readAccessibilityButtonTargetsLocked(userState);
onUserStateChangedLocked(userState);
}
@@ -1711,12 +1720,12 @@
}
// Turn on/off a11y qs shortcut for the a11y features based on the change in QS Panel
if (!a11yFeaturesToEnable.isEmpty()) {
- enableShortcutForTargets(/* enable= */ true, QUICK_SETTINGS,
+ enableShortcutForTargets(/* enable= */ true, UserShortcutType.QUICK_SETTINGS,
a11yFeaturesToEnable, userId);
}
if (!a11yFeaturesToRemove.isEmpty()) {
- enableShortcutForTargets(/* enable= */ false, QUICK_SETTINGS,
+ enableShortcutForTargets(/* enable= */ false, UserShortcutType.QUICK_SETTINGS,
a11yFeaturesToRemove, userId);
}
}
@@ -2048,70 +2057,99 @@
}
/**
- * User could configure accessibility shortcut during the SUW before restoring user data.
- * Merges the current value and the new value to make sure we don't lost the setting the user's
- * preferences of accessibility shortcut updated in SUW are not lost.
- * Called only during settings restore; currently supports only the owner user.
- * <P>
- * Throws an exception if used with {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP}.
- * </P>
+ * User could enable accessibility services and configure accessibility button during the SUW.
+ * Merges current value of accessibility button settings into the restored one to make sure
+ * user's preferences of accessibility button updated in SUW are not lost.
+ *
+ * Called only during settings restore; currently supports only the owner user
* TODO: http://b/22388012
*/
- private void restoreAccessibilityShortcutTargets(String oldValue, String newValue,
- @UserShortcutType int shortcutType) {
- assertNoTapShortcut(shortcutType);
- if (shortcutType == QUICK_SETTINGS && !android.view.accessibility.Flags.a11yQsShortcut()) {
- return;
- }
- if (shortcutType == HARDWARE && !android.view.accessibility.Flags
- .restoreA11yShortcutTargetService()) {
- return;
- }
+ void restoreAccessibilityButtonTargetsLocked(String oldSetting, String newSetting) {
+ final Set<String> targetsFromSetting = new ArraySet<>();
+ readColonDelimitedStringToSet(oldSetting, str -> str, targetsFromSetting,
+ /* doMerge = */false);
+ readColonDelimitedStringToSet(newSetting, str -> str, targetsFromSetting,
+ /* doMerge = */true);
+ final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
+ userState.mAccessibilityButtonTargets.clear();
+ userState.mAccessibilityButtonTargets.addAll(targetsFromSetting);
+ persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ UserHandle.USER_SYSTEM, userState.mAccessibilityButtonTargets, str -> str);
+
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ onUserStateChangedLocked(userState);
+ }
+
+ /**
+ * User could configure accessibility shortcut during the SUW before restoring user data.
+ * Merges the current value and the new value to make sure we don't lost the setting the user's
+ * preferences of accessibility qs shortcut updated in SUW are not lost.
+ *
+ * Called only during settings restore; currently supports only the owner user
+ * TODO: http://b/22388012
+ */
+ private void restoreAccessibilityQsTargets(String newValue) {
synchronized (mLock) {
final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
- final Set<String> mergedTargets = userState.getShortcutTargetsLocked(shortcutType);
- readColonDelimitedStringToSet(oldValue, str -> str, mergedTargets,
+ final Set<String> mergedTargets = userState.getA11yQsTargets();
+ readColonDelimitedStringToSet(newValue, str -> str, mergedTargets,
/* doMerge = */ true);
- // If dealing with the hardware shortcut,
- // remove the default service if it wasn't present before restore.
- // Otherwise, merge the old and new targets normally.
- if (Flags.clearDefaultFromA11yShortcutTargetServiceRestore()
- && shortcutType == HARDWARE) {
- final String defaultService =
- mContext.getString(R.string.config_defaultAccessibilityService);
- final ComponentName defaultServiceComponent = TextUtils.isEmpty(defaultService)
- ? null : ComponentName.unflattenFromString(defaultService);
- boolean shouldClearDefaultService = defaultServiceComponent != null
- && !stringSetContainsComponentName(mergedTargets, defaultServiceComponent);
- readColonDelimitedStringToSet(newValue, str -> str, mergedTargets,
- /* doMerge = */ true);
-
- if (shouldClearDefaultService && stringSetContainsComponentName(
- mergedTargets, defaultServiceComponent)) {
- Slog.i(LOG_TAG, "Removing default service " + defaultService
- + " from restore of "
- + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
- mergedTargets.removeIf(str ->
- defaultServiceComponent.equals(ComponentName.unflattenFromString(str)));
- }
- if (mergedTargets.isEmpty()) {
- return;
- }
- } else {
- readColonDelimitedStringToSet(newValue, str -> str, mergedTargets,
- /* doMerge = */ true);
- }
-
- userState.updateShortcutTargetsLocked(mergedTargets, shortcutType);
- persistColonDelimitedSetToSettingLocked(ShortcutUtils.convertToKey(shortcutType),
+ userState.updateA11yQsTargetLocked(mergedTargets);
+ persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
UserHandle.USER_SYSTEM, mergedTargets, str -> str);
scheduleNotifyClientsOfServicesStateChangeLocked(userState);
onUserStateChangedLocked(userState);
}
}
+ /**
+ * Merges the old and restored value of
+ * {@link Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE}.
+ *
+ * <p>Also clears out {@link R.string#config_defaultAccessibilityService} from
+ * the merged set if it was not present before restoring.
+ */
+ private void restoreAccessibilityShortcutTargetService(
+ String oldValue, String restoredValue) {
+ final Set<String> targetsFromSetting = new ArraySet<>();
+ readColonDelimitedStringToSet(oldValue, str -> str,
+ targetsFromSetting, /*doMerge=*/false);
+ final String defaultService =
+ mContext.getString(R.string.config_defaultAccessibilityService);
+ final ComponentName defaultServiceComponent = TextUtils.isEmpty(defaultService)
+ ? null : ComponentName.unflattenFromString(defaultService);
+ boolean shouldClearDefaultService = defaultServiceComponent != null
+ && !stringSetContainsComponentName(targetsFromSetting, defaultServiceComponent);
+ readColonDelimitedStringToSet(restoredValue, str -> str,
+ targetsFromSetting, /*doMerge=*/true);
+ if (Flags.clearDefaultFromA11yShortcutTargetServiceRestore()) {
+ if (shouldClearDefaultService && stringSetContainsComponentName(
+ targetsFromSetting, defaultServiceComponent)) {
+ Slog.i(LOG_TAG, "Removing default service " + defaultService
+ + " from restore of "
+ + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ targetsFromSetting.removeIf(str ->
+ defaultServiceComponent.equals(ComponentName.unflattenFromString(str)));
+ }
+ if (targetsFromSetting.isEmpty()) {
+ return;
+ }
+ }
+ synchronized (mLock) {
+ final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
+ final Set<String> shortcutTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.HARDWARE);
+ shortcutTargets.clear();
+ shortcutTargets.addAll(targetsFromSetting);
+ persistColonDelimitedSetToSettingLocked(
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+ UserHandle.USER_SYSTEM, targetsFromSetting, str -> str);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ onUserStateChangedLocked(userState);
+ }
+ }
/**
* Returns {@code true} if the set contains the provided non-null {@link ComponentName}.
@@ -2225,7 +2263,7 @@
private void showAccessibilityTargetsSelection(int displayId,
@UserShortcutType int shortcutType) {
final Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
- final String chooserClassName = (shortcutType == HARDWARE)
+ final String chooserClassName = (shortcutType == UserShortcutType.HARDWARE)
? AccessibilityShortcutChooserActivity.class.getName()
: AccessibilityButtonChooserActivity.class.getName();
intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
@@ -3198,9 +3236,9 @@
somethingChanged |= readAudioDescriptionEnabledSettingLocked(userState);
somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
somethingChanged |= readAutoclickEnabledSettingLocked(userState);
- somethingChanged |= readAccessibilityShortcutTargetsLocked(userState, HARDWARE);
- somethingChanged |= readAccessibilityShortcutTargetsLocked(userState, QUICK_SETTINGS);
- somethingChanged |= readAccessibilityShortcutTargetsLocked(userState, SOFTWARE);
+ somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState);
+ somethingChanged |= readAccessibilityQsTargetsLocked(userState);
+ somethingChanged |= readAccessibilityButtonTargetsLocked(userState);
somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState);
somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState);
@@ -3348,31 +3386,60 @@
userState.setSendMotionEventsEnabled(sendMotionEvents);
}
- /**
- * Throws an exception for {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP} types.
- */
- private boolean readAccessibilityShortcutTargetsLocked(AccessibilityUserState userState,
- @UserShortcutType int shortcutType) {
- assertNoTapShortcut(shortcutType);
+ private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- ShortcutUtils.convertToKey(shortcutType), userState.mUserId);
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userState.mUserId);
final Set<String> targetsFromSetting = new ArraySet<>();
- // If dealing with an empty hardware shortcut, fall back to the default value.
- if (shortcutType == HARDWARE && settingValue == null) {
+ readColonDelimitedStringToSet(settingValue, str -> str, targetsFromSetting, false);
+ // Fall back to device's default a11y service, only when setting is never updated.
+ if (settingValue == null) {
final String defaultService = mContext.getString(
R.string.config_defaultAccessibilityService);
if (!TextUtils.isEmpty(defaultService)) {
targetsFromSetting.add(defaultService);
}
- } else {
- readColonDelimitedStringToSet(settingValue, str -> str, targetsFromSetting, false);
}
- if (userState.updateShortcutTargetsLocked(targetsFromSetting, shortcutType)) {
- scheduleNotifyClientsOfServicesStateChangeLocked(userState);
- return true;
+ final Set<String> currentTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.HARDWARE);
+ if (targetsFromSetting.equals(currentTargets)) {
+ return false;
}
- return false;
+ currentTargets.clear();
+ currentTargets.addAll(targetsFromSetting);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ return true;
+ }
+
+ private boolean readAccessibilityQsTargetsLocked(AccessibilityUserState userState) {
+ final Set<String> targetsFromSetting = new ArraySet<>();
+ readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+ userState.mUserId, str -> str, targetsFromSetting);
+
+ final Set<String> currentTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
+ if (targetsFromSetting.equals(currentTargets)) {
+ return false;
+ }
+ userState.updateA11yQsTargetLocked(targetsFromSetting);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ return true;
+ }
+
+ private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
+ final Set<String> targetsFromSetting = new ArraySet<>();
+ readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ userState.mUserId, str -> str, targetsFromSetting);
+
+ final Set<String> currentTargets =
+ userState.getShortcutTargetsLocked(UserShortcutType.SOFTWARE);
+ if (targetsFromSetting.equals(currentTargets)) {
+ return false;
+ }
+ currentTargets.clear();
+ currentTargets.addAll(targetsFromSetting);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ return true;
}
private boolean readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState) {
@@ -3420,7 +3487,7 @@
*/
private void updateAccessibilityShortcutKeyTargetsLocked(AccessibilityUserState userState) {
final Set<String> currentTargets =
- userState.getShortcutTargetsLocked(HARDWARE);
+ userState.getShortcutTargetsLocked(UserShortcutType.HARDWARE);
final int lastSize = currentTargets.size();
if (lastSize == 0) {
return;
@@ -3689,9 +3756,9 @@
lastSize = buttonTargets.size();
final Set<String> shortcutKeyTargets =
- userState.getShortcutTargetsLocked(HARDWARE);
+ userState.getShortcutTargetsLocked(UserShortcutType.HARDWARE);
final Set<String> qsShortcutTargets =
- userState.getShortcutTargetsLocked(QUICK_SETTINGS);
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
userState.mEnabledServices.forEach(componentName -> {
if (packageName != null && componentName != null
&& !packageName.equals(componentName.getPackageName())) {
@@ -3748,7 +3815,7 @@
}
final Set<String> targets =
- userState.getShortcutTargetsLocked(QUICK_SETTINGS);
+ userState.getShortcutTargetsLocked(UserShortcutType.QUICK_SETTINGS);
// Removes the targets that are no longer installed on the device.
boolean somethingChanged = targets.removeIf(
@@ -3769,7 +3836,7 @@
if (!somethingChanged) {
return;
}
- userState.updateShortcutTargetsLocked(targets, QUICK_SETTINGS);
+ userState.updateA11yQsTargetLocked(targets);
// Update setting key with new value.
persistColonDelimitedSetToSettingLocked(
@@ -3795,14 +3862,14 @@
final List<Pair<Integer, String>> shortcutTypeAndShortcutSetting = new ArrayList<>(3);
shortcutTypeAndShortcutSetting.add(
- new Pair<>(HARDWARE,
+ new Pair<>(UserShortcutType.HARDWARE,
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
shortcutTypeAndShortcutSetting.add(
new Pair<>(UserShortcutType.SOFTWARE,
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS));
if (android.view.accessibility.Flags.a11yQsShortcut()) {
shortcutTypeAndShortcutSetting.add(
- new Pair<>(QUICK_SETTINGS,
+ new Pair<>(UserShortcutType.QUICK_SETTINGS,
Settings.Secure.ACCESSIBILITY_QS_TARGETS));
}
@@ -3816,7 +3883,7 @@
shortcutSettingName,
userState.mUserId, currentTargets, str -> str);
- if (shortcutType != QUICK_SETTINGS) {
+ if (shortcutType != UserShortcutType.QUICK_SETTINGS) {
continue;
}
@@ -3901,7 +3968,7 @@
mMainHandler.sendMessage(obtainMessage(
AccessibilityManagerService::performAccessibilityShortcutInternal, this,
- Display.DEFAULT_DISPLAY, HARDWARE, targetName));
+ Display.DEFAULT_DISPLAY, UserShortcutType.HARDWARE, targetName));
}
/**
@@ -4048,7 +4115,7 @@
final boolean requestA11yButton = (installedServiceInfo.flags
& FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
// Turns on / off the accessibility service
- if ((targetSdk <= Build.VERSION_CODES.Q && shortcutType == HARDWARE)
+ if ((targetSdk <= Build.VERSION_CODES.Q && shortcutType == UserShortcutType.HARDWARE)
|| (targetSdk > Build.VERSION_CODES.Q && !requestA11yButton)) {
if (serviceConnection == null) {
logAccessibilityShortcutActivated(mContext, assignedTarget, shortcutType,
@@ -4062,7 +4129,7 @@
}
return true;
}
- if (shortcutType == HARDWARE && targetSdk > Build.VERSION_CODES.Q
+ if (shortcutType == UserShortcutType.HARDWARE && targetSdk > Build.VERSION_CODES.Q
&& requestA11yButton) {
if (!userState.getEnabledServicesLocked().contains(assignedTarget)) {
enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
@@ -4155,7 +4222,7 @@
validNewTargets = newTargets;
// filter out targets that doesn't have qs shortcut
- if (shortcutType == QUICK_SETTINGS) {
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
validNewTargets = newTargets.stream().filter(target -> {
ComponentName targetComponent = ComponentName.unflattenFromString(target);
return featureToTileMap.containsKey(targetComponent);
@@ -4173,10 +4240,10 @@
/* defaultEmptyString= */ ""
);
- if (shortcutType == QUICK_SETTINGS) {
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
int numOfFeatureChanged = Math.abs(currentTargets.size() - validNewTargets.size());
logMetricForQsShortcutConfiguration(enable, numOfFeatureChanged);
- userState.updateShortcutTargetsLocked(validNewTargets, QUICK_SETTINGS);
+ userState.updateA11yQsTargetLocked(validNewTargets);
scheduleNotifyClientsOfServicesStateChangeLocked(userState);
onUserStateChangedLocked(userState);
}
@@ -4190,7 +4257,7 @@
}
// Add or Remove tile in QS Panel
- if (shortcutType == QUICK_SETTINGS) {
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
mMainHandler.sendMessage(obtainMessage(
AccessibilityManagerService::updateA11yTileServicesInQuickSettingsPanel,
this, validNewTargets, currentTargets, userId));
@@ -4199,7 +4266,7 @@
if (!enable) {
return;
}
- if (shortcutType == HARDWARE) {
+ if (shortcutType == UserShortcutType.HARDWARE) {
skipVolumeShortcutDialogTimeoutRestriction(userId);
if (com.android.server.accessibility.Flags.enableHardwareShortcutDisablesWarning()) {
persistIntToSetting(
@@ -5605,7 +5672,7 @@
|| mShowImeWithHardKeyboardUri.equals(uri)) {
userState.reconcileSoftKeyboardModeWithSettingsLocked();
} else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
- if (readAccessibilityShortcutTargetsLocked(userState, HARDWARE)) {
+ if (readAccessibilityShortcutKeySettingLocked(userState)) {
onUserStateChangedLocked(userState);
}
} else if (mAccessibilityButtonComponentIdUri.equals(uri)) {
@@ -5613,7 +5680,7 @@
onUserStateChangedLocked(userState);
}
} else if (mAccessibilityButtonTargetsUri.equals(uri)) {
- if (readAccessibilityShortcutTargetsLocked(userState, SOFTWARE)) {
+ if (readAccessibilityButtonTargetsLocked(userState)) {
onUserStateChangedLocked(userState);
}
} else if (mUserNonInteractiveUiTimeoutUri.equals(uri)
@@ -6438,10 +6505,4 @@
String metricId = enable ? METRIC_ID_QS_SHORTCUT_ADD : METRIC_ID_QS_SHORTCUT_REMOVE;
Counter.logIncrementWithUid(metricId, Binder.getCallingUid(), numOfFeatures);
}
-
- private void assertNoTapShortcut(@UserShortcutType int shortcutType) {
- if ((shortcutType & (TRIPLETAP | TWOFINGER_DOUBLETAP)) != 0) {
- throw new IllegalArgumentException("Tap shortcuts are not supported.");
- }
- }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 365d1d4..a37a184 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -777,20 +777,12 @@
* @return The array set of the strings
*/
public ArraySet<String> getShortcutTargetsLocked(@UserShortcutType int shortcutType) {
- ArraySet<String> set = getShortcutTargetsInternalLocked(shortcutType);
- // if it's Quick Settings, make a defensive copy. Otherwise, return the raw set.
- if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
- set = new ArraySet<>(set);
- }
- return set;
- }
- private ArraySet<String> getShortcutTargetsInternalLocked(@UserShortcutType int shortcutType) {
if (shortcutType == UserShortcutType.HARDWARE) {
return mAccessibilityShortcutKeyTargets;
} else if (shortcutType == UserShortcutType.SOFTWARE) {
return mAccessibilityButtonTargets;
} else if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
- return mAccessibilityQsTargets;
+ return getA11yQsTargets();
} else if ((shortcutType == UserShortcutType.TRIPLETAP
&& isMagnificationSingleFingerTripleTapEnabledLocked()) || (
shortcutType == UserShortcutType.TWOFINGER_DOUBLETAP
@@ -803,32 +795,6 @@
}
/**
- * Updates the corresponding shortcut targets with the provided set.
- * Tap shortcuts don't operate using sets of targets,
- * so trying to update {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP}
- * will instead throw an {@code IllegalArgumentException}
- * @param newTargets set of targets to replace the existing set.
- * @param shortcutType type to be replaced.
- * @return {@code true} if the set was changed, or {@code false} if the elements are the same.
- * @throws IllegalArgumentException if {@code TRIPLETAP} or {@code TWOFINGER_DOUBLETAP} is used.
- */
- boolean updateShortcutTargetsLocked(
- Set<String> newTargets, @UserShortcutType int shortcutType) {
- final int mask = UserShortcutType.TRIPLETAP | UserShortcutType.TWOFINGER_DOUBLETAP;
- if ((shortcutType & mask) != 0) {
- throw new IllegalArgumentException("Tap shortcuts cannot be updated with target sets.");
- }
-
- final Set<String> currentTargets = getShortcutTargetsInternalLocked(shortcutType);
- if (newTargets.equals(currentTargets)) {
- return false;
- }
- currentTargets.clear();
- currentTargets.addAll(newTargets);
- return true;
- }
-
- /**
* Whether or not the given shortcut target is installed in device.
*
* @param name The shortcut target name
@@ -878,8 +844,8 @@
);
}
- Set<String> targets = getShortcutTargetsInternalLocked(shortcutType);
- return targets.removeIf(name -> {
+ Set<String> targets = getShortcutTargetsLocked(shortcutType);
+ boolean result = targets.removeIf(name -> {
ComponentName componentName;
if (name == null
|| (componentName = ComponentName.unflattenFromString(name)) == null) {
@@ -887,6 +853,11 @@
}
return componentName.equals(target);
});
+ if (shortcutType == UserShortcutType.QUICK_SETTINGS) {
+ updateA11yQsTargetLocked(targets);
+ }
+
+ return result;
}
/**
@@ -1143,6 +1114,11 @@
);
}
+ public void updateA11yQsTargetLocked(Set<String> targets) {
+ mAccessibilityQsTargets.clear();
+ mAccessibilityQsTargets.addAll(targets);
+ }
+
/**
* Returns a copy of the targets which has qs shortcut turned on
*/
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d79d198..73253b2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10207,19 +10207,6 @@
addStartInfoTimestampInternal(key, timestampNs, userId, callingUid);
}
- @Override
- public void reportStartInfoViewTimestamps(long renderThreadDrawStartTimeNs,
- long framePresentedTimeNs) {
- int callingUid = Binder.getCallingUid();
- int userId = UserHandle.getUserId(callingUid);
- addStartInfoTimestampInternal(
- ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME,
- renderThreadDrawStartTimeNs, userId, callingUid);
- addStartInfoTimestampInternal(
- ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE,
- framePresentedTimeNs, userId, callingUid);
- }
-
private void addStartInfoTimestampInternal(int key, long timestampNs, int userId, int uid) {
mProcessList.getAppStartInfoTracker().addTimestampToStart(
Settings.getPackageNameForUid(mContext, uid),
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 4a7ad31..3042b2a 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -1195,8 +1195,21 @@
// Records are sorted newest to oldest, grab record at index 0.
ApplicationStartInfo startInfo = mInfos.get(0);
+ int startupState = startInfo.getStartupState();
- if (!isAddTimestampAllowed(startInfo, key, timestampNs)) {
+ // If startup state is error then don't accept any further timestamps.
+ if (startupState == ApplicationStartInfo.STARTUP_STATE_ERROR) {
+ if (DEBUG) Slog.d(TAG, "Startup state is error, not accepting new timestamps.");
+ return;
+ }
+
+ // If startup state is first frame drawn then only accept fully drawn timestamp.
+ if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN
+ && key != ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN) {
+ if (DEBUG) {
+ Slog.d(TAG, "Startup state is first frame drawn and timestamp is not fully "
+ + "drawn, not accepting new timestamps.");
+ }
return;
}
@@ -1209,55 +1222,6 @@
}
}
- private boolean isAddTimestampAllowed(ApplicationStartInfo startInfo, int key,
- long timestampNs) {
- int startupState = startInfo.getStartupState();
-
- // If startup state is error then don't accept any further timestamps.
- if (startupState == ApplicationStartInfo.STARTUP_STATE_ERROR) {
- if (DEBUG) Slog.d(TAG, "Startup state is error, not accepting new timestamps.");
- return false;
- }
-
- Map<Integer, Long> timestamps = startInfo.getStartupTimestamps();
-
- if (startupState == ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN) {
- switch (key) {
- case ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN:
- // Allowed, continue to confirm it's not already added.
- break;
- case ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME:
- Long firstFrameTimeNs = timestamps
- .get(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME);
- if (firstFrameTimeNs == null) {
- // This should never happen. State can't be first frame drawn if first
- // frame timestamp was not provided.
- return false;
- }
-
- if (timestampNs > firstFrameTimeNs) {
- // Initial renderthread frame has to occur before first frame.
- return false;
- }
-
- // Allowed, continue to confirm it's not already added.
- break;
- case ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE:
- // Allowed, continue to confirm it's not already added.
- break;
- default:
- return false;
- }
- }
-
- if (timestamps.get(key) != null) {
- // Timestamp should not occur more than once for a given start.
- return false;
- }
-
- return true;
- }
-
@GuardedBy("mLock")
void dumpLocked(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
if (mMonitoringModeEnabled) {
diff --git a/services/core/java/com/android/server/pm/PackageFreezer.java b/services/core/java/com/android/server/pm/PackageFreezer.java
index 0afda45..11f2059 100644
--- a/services/core/java/com/android/server/pm/PackageFreezer.java
+++ b/services/core/java/com/android/server/pm/PackageFreezer.java
@@ -62,6 +62,12 @@
PackageFreezer(String packageName, int userId, String killReason,
PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request) {
+ this(packageName, userId, killReason, pm, exitInfoReason, request, false);
+ }
+
+ PackageFreezer(String packageName, int userId, String killReason,
+ PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request,
+ boolean waitAppKilled) {
mPm = pm;
mPackageName = packageName;
mInstallRequest = request;
@@ -77,7 +83,7 @@
ps = mPm.mSettings.getPackageLPr(mPackageName);
}
if (ps != null) {
- if (Flags.waitApplicationKilled()) {
+ if (waitAppKilled && Flags.waitApplicationKilled()) {
mPm.killApplicationSync(ps.getPackageName(), ps.getAppId(), userId, killReason,
exitInfoReason);
} else {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ca84d68..66a93d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4347,7 +4347,14 @@
public PackageFreezer freezePackage(String packageName, int userId, String killReason,
int exitInfoReason, InstallRequest request) {
- return new PackageFreezer(packageName, userId, killReason, this, exitInfoReason, request);
+ return freezePackage(packageName, userId, killReason, exitInfoReason, request,
+ /* waitAppKilled= */ false);
+ }
+
+ private PackageFreezer freezePackage(String packageName, int userId, String killReason,
+ int exitInfoReason, InstallRequest request, boolean waitAppKilled) {
+ return new PackageFreezer(packageName, userId, killReason, this, exitInfoReason, request,
+ waitAppKilled);
}
public PackageFreezer freezePackageForDelete(String packageName, int userId, int deleteFlags,
@@ -4772,7 +4779,8 @@
final boolean succeeded;
try (PackageFreezer freezer = freezePackage(packageName, UserHandle.USER_ALL,
"clearApplicationUserData",
- ApplicationExitInfo.REASON_USER_REQUESTED, null /* request */)) {
+ ApplicationExitInfo.REASON_USER_REQUESTED, null /* request */,
+ /* waitAppKilled= */ true)) {
try (PackageManagerTracedLock installLock = mInstallLock.acquireLock()) {
succeeded = clearApplicationUserDataLIF(snapshotComputer(), packageName,
userId);
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
index 23872d4f..119b659 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
@@ -336,8 +336,13 @@
final PermissionManagerServiceInternal permissionManagerInternal =
LocalServices.getService(PermissionManagerServiceInternal.class);
for (final int userId : UserManagerService.getInstance().getUserIds()) {
- packageManagerInternal.forEachPackage(pkg ->
- permissionManagerInternal.resetRuntimePermissions(pkg, userId));
+ packageManagerInternal.forEachPackage(pkg -> {
+ // Filter out packages that don't have app IDs which means they don't have
+ // permission states either.
+ if (pkg.getUid() != -1) {
+ permissionManagerInternal.resetRuntimePermissions(pkg, userId);
+ }
+ });
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 47258d6..4e8c755 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -25,7 +25,6 @@
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.server.accessibility.AccessibilityManagerService.ACTION_LAUNCH_HEARING_DEVICES_DIALOG;
import static com.android.window.flags.Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER;
@@ -1391,14 +1390,14 @@
mA11yms.enableShortcutsForTargets(
/* enable= */ true,
- QUICK_SETTINGS,
+ UserShortcutType.QUICK_SETTINGS,
List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
mA11yms.getCurrentUserIdLocked());
mTestableLooper.processAllMessages();
assertThat(
ShortcutUtils.isComponentIdExistingInSettings(
- mTestableContext, QUICK_SETTINGS,
+ mTestableContext, UserShortcutType.QUICK_SETTINGS,
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString())
).isTrue();
verify(mStatusBarManagerInternal)
@@ -1418,14 +1417,14 @@
mA11yms.enableShortcutsForTargets(
/* enable= */ false,
- QUICK_SETTINGS,
+ UserShortcutType.QUICK_SETTINGS,
List.of(TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString()),
mA11yms.getCurrentUserIdLocked());
mTestableLooper.processAllMessages();
assertThat(
ShortcutUtils.isComponentIdExistingInSettings(
- mTestableContext, QUICK_SETTINGS,
+ mTestableContext, UserShortcutType.QUICK_SETTINGS,
TARGET_ALWAYS_ON_A11Y_SERVICE.flattenToString())
).isFalse();
verify(mStatusBarManagerInternal)
@@ -1622,7 +1621,7 @@
AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME.flattenToString();
final AccessibilityUserState userState = new AccessibilityUserState(
UserHandle.USER_SYSTEM, mTestableContext, mA11yms);
- userState.updateShortcutTargetsLocked(Set.of(daltonizerTile), QUICK_SETTINGS);
+ userState.updateA11yQsTargetLocked(Set.of(daltonizerTile));
mA11yms.mUserStates.put(UserHandle.USER_SYSTEM, userState);
broadcastSettingRestored(
@@ -1643,7 +1642,7 @@
AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME.flattenToString();
final AccessibilityUserState userState = new AccessibilityUserState(
UserHandle.USER_SYSTEM, mTestableContext, mA11yms);
- userState.updateShortcutTargetsLocked(Set.of(daltonizerTile), QUICK_SETTINGS);
+ userState.updateA11yQsTargetLocked(Set.of(daltonizerTile));
mA11yms.mUserStates.put(UserHandle.USER_SYSTEM, userState);
broadcastSettingRestored(
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index 9fad14d..b269beb9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -28,7 +28,6 @@
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
-import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain;
import static com.google.common.truth.Truth.assertThat;
@@ -430,20 +429,20 @@
}
@Test
- public void updateShortcutTargetsLocked_quickSettings_valueUpdated() {
+ public void updateA11yQsTargetLocked_valueUpdated() {
Set<String> newTargets = Set.of(
AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME.flattenToString(),
AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME.flattenToString()
);
- mUserState.updateShortcutTargetsLocked(newTargets, QUICK_SETTINGS);
+ mUserState.updateA11yQsTargetLocked(newTargets);
assertThat(mUserState.getA11yQsTargets()).isEqualTo(newTargets);
}
@Test
public void getA11yQsTargets_returnsCopiedData() {
- updateShortcutTargetsLocked_quickSettings_valueUpdated();
+ updateA11yQsTargetLocked_valueUpdated();
Set<String> targets = mUserState.getA11yQsTargets();
targets.clear();
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
index a23f211..379b45c 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt
@@ -24,7 +24,6 @@
import android.tools.flicker.legacy.LegacyFlickerTest
import android.tools.flicker.legacy.LegacyFlickerTestFactory
import android.tools.traces.parsers.toFlickerComponent
-import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
@@ -175,12 +174,6 @@
}
}
- @FlakyTest(bugId = 342596801)
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
- }
-
@Ignore("Not applicable to this CUJ.")
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {}
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
index 56dbde0..fff1dd1 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java
@@ -39,11 +39,13 @@
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(BedsteadJUnit4.class)
+@Ignore("b/345557347")
public final class ConcurrentMultiUserTest {
@ClassRule