Merge "Convert from Handlers to Executors in NotificationLockscreenUserManager" into main
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index d940e38..b0f378d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -159,6 +159,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -513,6 +514,10 @@
if (name == null) {
continue;
}
+ if (DEBUG) {
+ Slog.d(TAG, "DeviceConfig " + name
+ + " changed to " + properties.getString(name, null));
+ }
switch (name) {
case Constants.KEY_ENABLE_API_QUOTAS:
case Constants.KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC:
@@ -3507,7 +3512,10 @@
}
final boolean shouldForceBatchJob;
- if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
+ if (job.overrideState > JobStatus.OVERRIDE_NONE) {
+ // The job should run for some test. Don't force batch it.
+ shouldForceBatchJob = false;
+ } else if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
// Never batch expedited or user-initiated jobs, even for RESTRICTED apps.
shouldForceBatchJob = false;
} else if (job.getEffectiveStandbyBucket() == RESTRICTED_INDEX) {
@@ -4960,6 +4968,8 @@
Slog.d(TAG, "executeRunCommand(): " + pkgName + "/" + namespace + "/" + userId
+ " " + jobId + " s=" + satisfied + " f=" + force);
+ final CountDownLatch delayLatch = new CountDownLatch(1);
+ final JobStatus js;
try {
final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
@@ -4968,7 +4978,7 @@
}
synchronized (mLock) {
- final JobStatus js = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
+ js = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
if (js == null) {
return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
}
@@ -4979,23 +4989,71 @@
// Re-evaluate constraints after the override is set in case one of the overridden
// constraints was preventing another constraint from thinking it needed to update.
for (int c = mControllers.size() - 1; c >= 0; --c) {
- mControllers.get(c).reevaluateStateLocked(uid);
+ mControllers.get(c).evaluateStateLocked(js);
}
if (!js.isConstraintsSatisfied()) {
- js.overrideState = JobStatus.OVERRIDE_NONE;
- return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
+ if (js.hasConnectivityConstraint()
+ && !js.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)
+ && js.wouldBeReadyWithConstraint(JobStatus.CONSTRAINT_CONNECTIVITY)) {
+ // Because of how asynchronous the connectivity signals are, JobScheduler
+ // may not get the connectivity satisfaction signal immediately. In this
+ // case, wait a few seconds to see if it comes in before saying the
+ // connectivity constraint isn't satisfied.
+ mHandler.postDelayed(
+ checkConstraintRunnableForTesting(
+ mHandler, js, delayLatch, 5, 1000),
+ 1000);
+ } else {
+ // There's no asynchronous signal to wait for. We can immediately say the
+ // job's constraints aren't satisfied and return.
+ js.overrideState = JobStatus.OVERRIDE_NONE;
+ return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
+ }
+ } else {
+ delayLatch.countDown();
}
-
- queueReadyJobsForExecutionLocked();
- maybeRunPendingJobsLocked();
}
} catch (RemoteException e) {
// can't happen
+ return 0;
+ }
+
+ // Choose to block the return until we're sure about the state of the connectivity job
+ // so that tests can expect a reliable state after calling the run command.
+ try {
+ delayLatch.await(7L, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Couldn't wait for asynchronous constraint change", e);
+ }
+
+ synchronized (mLock) {
+ if (!js.isConstraintsSatisfied()) {
+ js.overrideState = JobStatus.OVERRIDE_NONE;
+ return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
+ }
+
+ queueReadyJobsForExecutionLocked();
+ maybeRunPendingJobsLocked();
}
return 0;
}
+ private static Runnable checkConstraintRunnableForTesting(@NonNull final Handler handler,
+ @NonNull final JobStatus js, @NonNull final CountDownLatch latch,
+ final int remainingAttempts, final long delayMs) {
+ return () -> {
+ if (remainingAttempts <= 0 || js.isConstraintsSatisfied()) {
+ latch.countDown();
+ return;
+ }
+ handler.postDelayed(
+ checkConstraintRunnableForTesting(
+ handler, js, latch, remainingAttempts - 1, delayMs),
+ delayMs);
+ };
+ }
+
// Shell command infrastructure: immediately timeout currently executing jobs
int executeStopCommand(PrintWriter pw, String pkgName, int userId,
@Nullable String namespace, boolean hasJobId, int jobId,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index bdc2246..d39863c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -2192,7 +2192,7 @@
* @return Whether or not this job would be ready to run if it had the specified constraint
* granted, based on its requirements.
*/
- boolean wouldBeReadyWithConstraint(int constraint) {
+ public boolean wouldBeReadyWithConstraint(int constraint) {
return readinessStatusWithConstraint(constraint, true);
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 2e22071..bbe03a3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3735,6 +3735,7 @@
public class AnimationUtils {
method @FlaggedApi("android.view.flags.expected_presentation_time_read_only") public static void lockAnimationClock(long, long);
+ method public static void lockAnimationClock(long);
method public static void unlockAnimationClock();
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f5260ef..47065e1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -108,7 +108,6 @@
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -3586,10 +3585,12 @@
|| applicationInfo.isSignedWithPlatformKey();
}
- public ArrayMap<String, String> getStringsForPrefix(ContentResolver cr, String prefix,
- List<String> names) {
+ private ArrayMap<String, String> getStringsForPrefixStripPrefix(
+ ContentResolver cr, String prefix, String[] names) {
String namespace = prefix.substring(0, prefix.length() - 1);
ArrayMap<String, String> keyValues = new ArrayMap<>();
+ int substringLength = prefix.length();
+
int currentGeneration = -1;
boolean needsGenerationTracker = false;
@@ -3619,10 +3620,13 @@
if (DEBUG) {
Log.i(TAG, "Cache hit for prefix:" + prefix);
}
- if (!names.isEmpty()) {
+ if (names.length > 0) {
for (String name : names) {
+ // mValues can contain "null" values, need to use containsKey.
if (mValues.containsKey(name)) {
- keyValues.put(name, mValues.get(name));
+ keyValues.put(
+ name.substring(substringLength),
+ mValues.get(name));
}
}
} else {
@@ -3631,7 +3635,10 @@
// Explicitly exclude the prefix as it is only there to
// signal that the prefix has been cached.
if (key.startsWith(prefix) && !key.equals(prefix)) {
- keyValues.put(key, mValues.get(key));
+ String value = mValues.valueAt(i);
+ keyValues.put(
+ key.substring(substringLength),
+ value);
}
}
}
@@ -3691,14 +3698,22 @@
Map<String, String> flagsToValues =
(HashMap) b.getSerializable(Settings.NameValueTable.VALUE, java.util.HashMap.class);
// Only the flags requested by the caller
- if (!names.isEmpty()) {
- for (Map.Entry<String, String> flag : flagsToValues.entrySet()) {
- if (names.contains(flag.getKey())) {
- keyValues.put(flag.getKey(), flag.getValue());
+ if (names.length > 0) {
+ for (String name : names) {
+ // flagsToValues can contain "null" values, need to use containsKey.
+ if (flagsToValues.containsKey(name)) {
+ keyValues.put(
+ name.substring(substringLength),
+ flagsToValues.get(name));
}
}
} else {
- keyValues.putAll(flagsToValues);
+ keyValues.ensureCapacity(keyValues.size() + flagsToValues.size());
+ for (Map.Entry<String, String> flag : flagsToValues.entrySet()) {
+ keyValues.put(
+ flag.getKey().substring(substringLength),
+ flag.getValue());
+ }
}
synchronized (NameValueCache.this) {
@@ -12165,6 +12180,36 @@
*/
public static final String HIDE_PRIVATESPACE_ENTRY_POINT = "hide_privatespace_entry_point";
+ /** @hide */
+ public static final int PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK = 0;
+ /** @hide */
+ public static final int PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY = 1;
+ /** @hide */
+ public static final int PRIVATE_SPACE_AUTO_LOCK_NEVER = 2;
+
+ /**
+ * The different auto lock options for private space.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"PRIVATE_SPACE_AUTO_LOCK_"}, value = {
+ PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK,
+ PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY,
+ PRIVATE_SPACE_AUTO_LOCK_NEVER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrivateSpaceAutoLockOption {
+ }
+
+
+ /**
+ * Store auto lock value for private space.
+ * The possible values are defined in {@link PrivateSpaceAutoLockOption}.
+ *
+ * @hide
+ */
+ public static final String PRIVATE_SPACE_AUTO_LOCK = "private_space_auto_lock";
+
/**
* These entries are considered common between the personal and the managed profile,
* since the managed profile doesn't get to change them.
@@ -19854,21 +19899,15 @@
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
public static Map<String, String> getStrings(@NonNull ContentResolver resolver,
@NonNull String namespace, @NonNull List<String> names) {
- List<String> compositeNames = new ArrayList<>(names.size());
- for (String name : names) {
- compositeNames.add(createCompositeName(namespace, name));
+ String[] compositeNames = new String[names.size()];
+ for (int i = 0, size = names.size(); i < size; ++i) {
+ compositeNames[i] = createCompositeName(namespace, names.get(i));
}
String prefix = createPrefix(namespace);
- ArrayMap<String, String> rawKeyValues = sNameValueCache.getStringsForPrefix(
+
+ ArrayMap<String, String> keyValues = sNameValueCache.getStringsForPrefixStripPrefix(
resolver, prefix, compositeNames);
- int size = rawKeyValues.size();
- int substringLength = prefix.length();
- ArrayMap<String, String> keyValues = new ArrayMap<>(size);
- for (int i = 0; i < size; ++i) {
- keyValues.put(rawKeyValues.keyAt(i).substring(substringLength),
- rawKeyValues.valueAt(i));
- }
return keyValues;
}
@@ -20194,12 +20233,13 @@
private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
Preconditions.checkNotNull(namespace);
Preconditions.checkNotNull(name);
- return createPrefix(namespace) + name;
+ var sb = new StringBuilder(namespace.length() + 1 + name.length());
+ return sb.append(namespace).append('/').append(name).toString();
}
private static String createPrefix(@NonNull String namespace) {
Preconditions.checkNotNull(namespace);
- return namespace + "/";
+ return namespace + '/';
}
private static Uri createNamespaceUri(@NonNull String namespace) {
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 70d8abe..57a3b76 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -109,6 +109,40 @@
}
/**
+ * Locks AnimationUtils{@link #currentAnimationTimeMillis()} to a fixed value for the current
+ * thread. This is used by {@link android.view.Choreographer} to ensure that all accesses
+ * during a vsync update are synchronized to the timestamp of the vsync.
+ *
+ * It is also exposed to tests to allow for rapid, flake-free headless testing.
+ *
+ * Must be followed by a call to {@link #unlockAnimationClock()} to allow time to
+ * progress. Failing to do this will result in stuck animations, scrolls, and flings.
+ *
+ * Note that time is not allowed to "rewind" and must perpetually flow forward. So the
+ * lock may fail if the time is in the past from a previously returned value, however
+ * time will be frozen for the duration of the lock. The clock is a thread-local, so
+ * ensure that {@link #lockAnimationClock(long)}, {@link #unlockAnimationClock()}, and
+ * {@link #currentAnimationTimeMillis()} are all called on the same thread.
+ *
+ * This is also not reference counted in any way. Any call to {@link #unlockAnimationClock()}
+ * will unlock the clock for everyone on the same thread. It is therefore recommended
+ * for tests to use their own thread to ensure that there is no collision with any existing
+ * {@link android.view.Choreographer} instance.
+ *
+ * Have to add the method back because of b/307888459.
+ * Remove this method once the lockAnimationClock(long, long) change
+ * is landed to aosp/android14-tests-dev branch.
+ *
+ * @hide
+ */
+ @TestApi
+ public static void lockAnimationClock(long vsyncMillis) {
+ AnimationState state = sAnimationState.get();
+ state.animationClockLocked = true;
+ state.currentVsyncTimeMillis = vsyncMillis;
+ }
+
+ /**
* Frees the time lock set in place by {@link #lockAnimationClock(long)}. Must be called
* to allow the animation clock to self-update.
*
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
index bd5f809..e118c98d 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
@@ -255,6 +255,7 @@
final String query = "--comment\nSELECT count(*) from t1";
+ database.beginTransactionReadOnly();
try {
for (int i = count; i > 0; i--) {
ticker.arriveAndAwaitAdvance();
@@ -268,6 +269,7 @@
} catch (Throwable t) {
errors.add(t);
} finally {
+ database.endTransaction();
ticker.arriveAndDeregister();
}
}
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index ffe3d1d..8b16d64 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -62,6 +62,7 @@
],
lint: {
baseline_filename: "lint-baseline.xml",
+ extra_check_modules: ["SettingsLibLintChecker"],
},
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 1481d97..d26c5ff 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -867,6 +867,7 @@
Settings.Secure.NEARBY_SHARING_SLICE_URI,
Settings.Secure.NOTIFIED_NON_ACCESSIBILITY_CATEGORY_SERVICES,
Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT,
+ Settings.Secure.PRIVATE_SPACE_AUTO_LOCK,
Settings.Secure.RELEASE_COMPRESS_BLOCKS_ON_INSTALL,
Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED,
Settings.Secure.SHOW_QR_CODE_SCANNER_SETTING,
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 5b21854..5fbffbe 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -258,6 +258,15 @@
}
flag {
+ name: "centralized_status_bar_dimens_refactor"
+ namespace: "systemui"
+ description: "Refactors shade header and keyguard status bar to read status bar dimens from a"
+ " central place, instead of reading resources directly. This is to take into account display"
+ " cutouts and other special cases. "
+ bug: "317199366"
+}
+
+flag {
name: "enable_layout_tracing"
namespace: "systemui"
description: "Enables detailed traversal slices during measure and layout in perfetto traces"
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index cbcca55..f775175 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -100,9 +100,12 @@
mSelectedUserInteractor
)
underTest.init()
+ underTest.onViewAttached()
underTest.onResume(0)
verify(keyguardUpdateMonitor)
.registerCallback(updateMonitorCallbackArgumentCaptor.capture())
+ reset(keyguardMessageAreaController)
+ reset(keyguardUpdateMonitor)
}
@Test
@@ -110,25 +113,24 @@
underTest.onViewAttached()
verify(keyguardMessageAreaController)
.setMessage(context.resources.getString(R.string.keyguard_enter_your_pin), false)
- }
-
- @Test
- fun onViewDetached() {
- underTest.onViewDetached()
- }
-
- @Test
- fun onResume() {
- reset(keyguardUpdateMonitor)
- underTest.onResume(KeyguardSecurityView.VIEW_REVEALED)
verify(keyguardUpdateMonitor)
.registerCallback(any(KeyguardUpdateMonitorCallback::class.java))
}
@Test
+ fun onViewDetached() {
+ underTest.onViewDetached()
+ verify(keyguardUpdateMonitor).removeCallback(any(KeyguardUpdateMonitorCallback::class.java))
+ }
+
+ @Test
+ fun onResume() {
+ underTest.onResume(KeyguardSecurityView.VIEW_REVEALED)
+ }
+
+ @Test
fun onPause() {
underTest.onPause()
- verify(keyguardUpdateMonitor).removeCallback(any(KeyguardUpdateMonitorCallback::class.java))
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 3d1efa5..5827671 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -293,8 +293,8 @@
}
/**
- * Verifies that swiping up when the lock pattern is not secure does not consume the scroll
- * gesture or expand.
+ * Verifies that swiping up when the lock pattern is not secure dismissed dream and consumes
+ * the gesture.
*/
@Test
public void testSwipeUp_keyguardNotSecure_doesNotExpand() {
@@ -314,11 +314,44 @@
reset(mScrimController);
- // Scroll gesture is not consumed.
+ // Scroll gesture is consumed.
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
- .isFalse();
+ .isTrue();
// We should not expand since the keyguard is not secure
verify(mScrimController, never()).expand(any());
+ // Since we are swiping up, we should wake from dreams.
+ verify(mCentralSurfaces).awakenDreams();
+ }
+
+ /**
+ * Verifies that swiping down when the lock pattern is not secure does not dismiss the dream.
+ */
+ @Test
+ public void testSwipeDown_keyguardNotSecure_doesNotExpand() {
+ when(mLockPatternUtils.isSecure(CURRENT_USER_INFO.id)).thenReturn(false);
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+ final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+ final float distanceY = SCREEN_HEIGHT_PX * 0.3f;
+ // Swiping down near the bottom of the screen where the touch initiation region is.
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX, 0);
+
+ reset(mScrimController);
+
+ // Scroll gesture is not consumed.
+ assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+ .isTrue();
+ // We should not expand since the keyguard is not secure
+ verify(mScrimController, never()).expand(any());
+ // Since we are swiping down, we should not dismiss the dream.
+ verify(mCentralSurfaces, never()).awakenDreams();
}
private void verifyScroll(float percent, Direction direction,
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 6d7ce06..e602d6c 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -107,4 +107,13 @@
<include layout="@layout/ambient_indication"
android:id="@id/ambient_indication_container" />
+
+ <FrameLayout
+ android:id="@+id/smartspace_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="@dimen/ambient_indication_margin_bottom"
+ android:visibility="gone">
+ </FrameLayout>
</com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index fc0bf24..4cb7591 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -23,7 +23,6 @@
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_header_height_keyguard"
android:baselineAligned="false"
- android:gravity="center_vertical"
>
<LinearLayout
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 74b975c..de7c12d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -22,6 +22,7 @@
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.Flags.migrateClocksToBlueprint;
+import static com.android.systemui.Flags.smartspaceRelocateToBottom;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -421,6 +422,10 @@
return;
}
+ if (smartspaceRelocateToBottom()) {
+ return;
+ }
+
mSmartspaceView = mSmartspaceController.buildAndConnectView(mView);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
MATCH_PARENT, WRAP_CONTENT);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index c5e7070..5729119 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -105,6 +105,13 @@
@Override
protected void onViewAttached() {
super.onViewAttached();
+ mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ super.onViewDetached();
+ mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
}
@Override
@@ -128,14 +135,12 @@
@Override
public void onResume(int reason) {
super.onResume(reason);
- mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mView.resetState();
}
@Override
public void onPause() {
super.onPause();
- mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
// dismiss the dialog.
if (mSimUnlockProgressDialog != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 2a54a4e..d372f5a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -20,6 +20,7 @@
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
+import static com.android.systemui.Flags.migrateClocksToBlueprint;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.animation.Animator;
@@ -492,7 +493,12 @@
boolean splitShadeEnabled,
boolean shouldBeCentered,
boolean animate) {
- mKeyguardClockSwitchController.setSplitShadeCentered(splitShadeEnabled && shouldBeCentered);
+ if (migrateClocksToBlueprint()) {
+ mKeyguardInteractor.setClockShouldBeCentered(mSplitShadeEnabled && shouldBeCentered);
+ } else {
+ mKeyguardClockSwitchController.setSplitShadeCentered(
+ splitShadeEnabled && shouldBeCentered);
+ }
if (mStatusViewCentered == shouldBeCentered) {
return;
}
@@ -548,8 +554,9 @@
ClockController clock = mKeyguardClockSwitchController.getClock();
boolean customClockAnimation = clock != null
&& clock.getLargeClock().getConfig().getHasCustomPositionUpdatedAnimation();
-
- if (customClockAnimation) {
+ // When migrateClocksToBlueprint is on, customized clock animation is conducted in
+ // KeyguardClockViewBinder
+ if (customClockAnimation && !migrateClocksToBlueprint()) {
// Find the clock, so we can exclude it from this transition.
FrameLayout clockContainerView = mView.findViewById(R.id.lockscreen_clock_view_large);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index 4e4b79c..7f3b5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -155,12 +155,12 @@
return true;
}
- // Don't set expansion if the user doesn't have a pin/password set so that no
- // animations are played we're not transitioning to the bouncer.
- if (!mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
- // Return false so the gesture is not consumed, allowing the dream to wake
- // if it wants instead of doing nothing.
- return false;
+ // If scrolling up and keyguard is not locked, dismiss the dream since there's
+ // no bouncer to show.
+ if (e1.getY() > e2.getY()
+ && !mLockPatternUtils.isSecure(mUserTracker.getUserId())) {
+ mCentralSurfaces.get().awakenDreams();
+ return true;
}
// For consistency, we adopt the expansion definition found in the
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a34730e..5cebd96 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1486,6 +1486,9 @@
mOrderUnlockAndWake = context.getResources().getBoolean(
com.android.internal.R.bool.config_orderUnlockAndWake);
+
+ mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
+ mShowKeyguardWakeLock.setReferenceCounted(false);
}
public void userActivity() {
@@ -1493,9 +1496,6 @@
}
private void setupLocked() {
- mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
- mShowKeyguardWakeLock.setReferenceCounted(false);
-
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SHUTDOWN);
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
index 05fe0b2..bf763b4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
@@ -16,13 +16,20 @@
package com.android.systemui.keyguard.ui.binder
+import android.animation.Animator
+import android.animation.ValueAnimator
+import android.transition.Transition
import android.transition.TransitionManager
+import android.transition.TransitionSet
+import android.transition.TransitionValues
+import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.helper.widget.Layer
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
@@ -32,6 +39,8 @@
import com.android.systemui.res.R
import kotlinx.coroutines.launch
+private const val KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION_MS = 1000L
+
object KeyguardClockViewBinder {
@JvmStatic
fun bind(
@@ -69,7 +78,13 @@
launch {
if (!migrateClocksToBlueprint()) return@launch
viewModel.clockShouldBeCentered.collect {
- applyConstraints(clockSection, keyguardRootView, true)
+ viewModel.clock?.let {
+ if (it.largeClock.config.hasCustomPositionUpdatedAnimation) {
+ playClockCenteringAnimation(clockSection, keyguardRootView, it)
+ } else {
+ applyConstraints(clockSection, keyguardRootView, true)
+ }
+ }
}
}
}
@@ -125,12 +140,84 @@
clockSection: ClockSection,
rootView: ConstraintLayout,
animated: Boolean,
+ set: TransitionSet? = null,
) {
val constraintSet = ConstraintSet().apply { clone(rootView) }
clockSection.applyConstraints(constraintSet)
if (animated) {
- TransitionManager.beginDelayedTransition(rootView)
+ set?.let { TransitionManager.beginDelayedTransition(rootView, it) }
+ ?: run { TransitionManager.beginDelayedTransition(rootView) }
}
constraintSet.applyTo(rootView)
}
+
+ private fun playClockCenteringAnimation(
+ clockSection: ClockSection,
+ keyguardRootView: ConstraintLayout,
+ clock: ClockController,
+ ) {
+ // Find the clock, so we can exclude it from this transition.
+ val clockView = clock.largeClock.view
+ val set = TransitionSet()
+ val adapter = SplitShadeTransitionAdapter(clock)
+ adapter.setInterpolator(Interpolators.LINEAR)
+ adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION_MS)
+ adapter.addTarget(clockView)
+ set.addTransition(adapter)
+ applyConstraints(clockSection, keyguardRootView, true, set)
+ }
+
+ internal class SplitShadeTransitionAdapter
+ @VisibleForTesting
+ constructor(private val clock: ClockController) : Transition() {
+ private fun captureValues(transitionValues: TransitionValues) {
+ transitionValues.values[PROP_BOUNDS_LEFT] = transitionValues.view.left
+ val locationInWindowTmp = IntArray(2)
+ transitionValues.view.getLocationInWindow(locationInWindowTmp)
+ transitionValues.values[PROP_X_IN_WINDOW] = locationInWindowTmp[0]
+ }
+
+ override fun captureEndValues(transitionValues: TransitionValues) {
+ captureValues(transitionValues)
+ }
+
+ override fun captureStartValues(transitionValues: TransitionValues) {
+ captureValues(transitionValues)
+ }
+
+ override fun createAnimator(
+ sceneRoot: ViewGroup,
+ startValues: TransitionValues?,
+ endValues: TransitionValues?
+ ): Animator? {
+ if (startValues == null || endValues == null) {
+ return null
+ }
+ val anim = ValueAnimator.ofFloat(0f, 1f)
+ val fromLeft = startValues.values[PROP_BOUNDS_LEFT] as Int
+ val fromWindowX = startValues.values[PROP_X_IN_WINDOW] as Int
+ val toWindowX = endValues.values[PROP_X_IN_WINDOW] as Int
+ // Using windowX, to determine direction, instead of left, as in RTL the difference of
+ // toLeft - fromLeft is always positive, even when moving left.
+ val direction = if (toWindowX - fromWindowX > 0) 1 else -1
+ anim.addUpdateListener { animation: ValueAnimator ->
+ clock.largeClock.animations.onPositionUpdated(
+ fromLeft,
+ direction,
+ animation.animatedFraction
+ )
+ }
+ return anim
+ }
+
+ override fun getTransitionProperties(): Array<String> {
+ return TRANSITION_PROPERTIES
+ }
+
+ companion object {
+ private const val PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft"
+ private const val PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow"
+ private val TRANSITION_PROPERTIES = arrayOf(PROP_BOUNDS_LEFT, PROP_X_IN_WINDOW)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
index 92270ad..81ce8f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt
@@ -23,6 +23,7 @@
import androidx.constraintlayout.widget.ConstraintSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
@@ -42,6 +43,7 @@
keyguardRootView.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
+ if (!migrateClocksToBlueprint()) return@launch
clockViewModel.hasCustomWeatherDataDisplay.collect { hasCustomWeatherDataDisplay
->
if (hasCustomWeatherDataDisplay) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
index f2b28d9..f33aed0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt
@@ -29,4 +29,8 @@
ConstraintLayout(
context,
attrs,
- )
+ ) {
+ init {
+ clipChildren = false
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
index 0f8e673..756a4cc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
@@ -23,11 +23,13 @@
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
+import com.android.systemui.Flags.centralizedStatusBarDimensRefactor
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
@@ -35,6 +37,7 @@
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -53,6 +56,7 @@
notificationStackSizeCalculator: NotificationStackSizeCalculator,
private val smartspaceViewModel: KeyguardSmartspaceViewModel,
@Main mainDispatcher: CoroutineDispatcher,
+ private val largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
) :
NotificationStackScrollLayoutSection(
context,
@@ -72,7 +76,13 @@
}
constraintSet.apply {
val splitShadeTopMargin =
- context.resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height)
+ if (centralizedStatusBarDimensRefactor()) {
+ largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ } else {
+ context.resources.getDimensionPixelSize(
+ R.dimen.large_screen_shade_header_height
+ )
+ }
connect(R.id.nssl_placeholder, TOP, PARENT_ID, TOP, splitShadeTopMargin)
connect(R.id.nssl_placeholder, START, PARENT_ID, START)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 0644237..a3b9254 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -18,6 +18,8 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static com.android.systemui.Flags.centralizedStatusBarDimensRefactor;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
@@ -30,6 +32,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.res.R;
+import com.android.systemui.shade.LargeScreenHeaderHelper;
import com.android.systemui.shade.TouchLogger;
import com.android.systemui.util.LargeScreenUtils;
@@ -162,8 +165,12 @@
QuickStatusBarHeaderController quickStatusBarHeaderController) {
int topPadding = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
if (!LargeScreenUtils.shouldUseLargeScreenShadeHeader(mContext.getResources())) {
- topPadding = mContext.getResources()
- .getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
+ topPadding =
+ centralizedStatusBarDimensRefactor()
+ ? LargeScreenHeaderHelper.getLargeScreenHeaderHeight(mContext)
+ : mContext.getResources()
+ .getDimensionPixelSize(
+ R.dimen.large_screen_shade_header_height);
}
mQSPanelContainer.setPaddingRelative(
mQSPanelContainer.getPaddingStart(),
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenHeaderHelper.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenHeaderHelper.kt
new file mode 100644
index 0000000..c74f038
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenHeaderHelper.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.shade
+
+import android.content.Context
+import com.android.internal.policy.SystemBarUtils
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlin.math.max
+
+class LargeScreenHeaderHelper @Inject constructor(private val context: Context) {
+
+ fun getLargeScreenHeaderHeight(): Int = getLargeScreenHeaderHeight(context)
+
+ companion object {
+ @JvmStatic
+ fun getLargeScreenHeaderHeight(context: Context): Int {
+ val defaultHeight =
+ context.resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height)
+ val statusBarHeight = SystemBarUtils.getStatusBarHeight(context)
+ // Height has to be at least as tall as the status bar, as the status bar height takes
+ // into account display cutouts.
+ return max(defaultHeight, statusBarHeight)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 6f4a1e7..aeccf00 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -27,6 +27,7 @@
import static com.android.systemui.Flags.keyguardBottomAreaRefactor;
import static com.android.systemui.Flags.migrateClocksToBlueprint;
import static com.android.systemui.Flags.predictiveBackAnimateShade;
+import static com.android.systemui.Flags.smartspaceRelocateToBottom;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
@@ -1214,7 +1215,7 @@
.setMaxLengthSeconds(0.4f).build();
mStatusBarMinHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
mStatusBarHeaderHeightKeyguard = Utils.getStatusBarHeaderHeightKeyguard(mView.getContext());
- mClockPositionAlgorithm.loadDimens(mResources);
+ mClockPositionAlgorithm.loadDimens(mView.getContext(), mResources);
mIndicationBottomPadding = mResources.getDimensionPixelSize(
R.dimen.keyguard_indication_bottom_padding);
int statusbarHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
@@ -1428,7 +1429,12 @@
int index = mView.indexOfChild(mKeyguardBottomArea);
mView.removeView(mKeyguardBottomArea);
KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
- setKeyguardBottomArea(mKeyguardBottomAreaViewControllerProvider.get().getView());
+ KeyguardBottomAreaViewController keyguardBottomAreaViewController =
+ mKeyguardBottomAreaViewControllerProvider.get();
+ if (smartspaceRelocateToBottom()) {
+ keyguardBottomAreaViewController.init();
+ }
+ setKeyguardBottomArea(keyguardBottomAreaViewController.getView());
mKeyguardBottomArea.initFrom(oldBottomArea);
mView.addView(mKeyguardBottomArea, index);
@@ -1751,14 +1757,9 @@
} else {
layout = mNotificationContainerParent;
}
-
- if (migrateClocksToBlueprint()) {
- mKeyguardInteractor.setClockShouldBeCentered(mSplitShadeEnabled && shouldBeCentered);
- } else {
- mKeyguardStatusViewController.updateAlignment(
- layout, mSplitShadeEnabled, shouldBeCentered, animate);
- mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
- }
+ mKeyguardStatusViewController.updateAlignment(
+ layout, mSplitShadeEnabled, shouldBeCentered, animate);
+ mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
}
private boolean shouldKeyguardStatusViewBeCentered() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index 9c8a286..84cad1d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -27,6 +27,7 @@
import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import androidx.lifecycle.lifecycleScope
+import com.android.systemui.Flags.centralizedStatusBarDimensRefactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
@@ -47,10 +48,11 @@
import com.android.systemui.util.LargeScreenUtils
import com.android.systemui.util.ViewController
import com.android.systemui.util.concurrency.DelayableExecutor
-import kotlinx.coroutines.launch
+import dagger.Lazy
import java.util.function.Consumer
import javax.inject.Inject
import kotlin.reflect.KMutableProperty0
+import kotlinx.coroutines.launch
@VisibleForTesting
internal const val INSET_DEBOUNCE_MILLIS = 500L
@@ -67,7 +69,8 @@
private val featureFlags: FeatureFlags,
private val
notificationStackScrollLayoutController: NotificationStackScrollLayoutController,
- private val splitShadeStateController: SplitShadeStateController
+ private val splitShadeStateController: SplitShadeStateController,
+ private val largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController {
private var splitShadeEnabled = false
@@ -186,7 +189,11 @@
}
private fun calculateLargeShadeHeaderHeight(): Int {
- return resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height)
+ return if (centralizedStatusBarDimensRefactor()) {
+ largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ } else {
+ resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height)
+ }
}
private fun calculateShadeHeaderHeight(): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 1dff99d..f3e9c75 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -20,6 +20,7 @@
import static android.view.WindowInsets.Type.ime;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
+import static com.android.systemui.Flags.centralizedStatusBarDimensRefactor;
import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
import static com.android.systemui.shade.NotificationPanelViewController.COUNTER_PANEL_OPEN_QS;
import static com.android.systemui.shade.NotificationPanelViewController.FLING_COLLAPSE;
@@ -126,6 +127,7 @@
private final Lazy<NotificationPanelViewController> mPanelViewControllerLazy;
private final NotificationPanelView mPanelView;
+ private final Lazy<LargeScreenHeaderHelper> mLargeScreenHeaderHelperLazy;
private final KeyguardStatusBarView mKeyguardStatusBar;
private final FrameLayout mQsFrame;
@@ -344,10 +346,12 @@
ActiveNotificationsInteractor activeNotificationsInteractor,
JavaAdapter javaAdapter,
CastController castController,
- SplitShadeStateController splitShadeStateController
+ SplitShadeStateController splitShadeStateController,
+ Lazy<LargeScreenHeaderHelper> largeScreenHeaderHelperLazy
) {
mPanelViewControllerLazy = panelViewControllerLazy;
mPanelView = panelView;
+ mLargeScreenHeaderHelperLazy = largeScreenHeaderHelperLazy;
mQsFrame = mPanelView.findViewById(R.id.qs_frame);
mKeyguardStatusBar = mPanelView.findViewById(R.id.keyguard_header);
mResources = mPanelView.getResources();
@@ -449,7 +453,10 @@
mUseLargeScreenShadeHeader =
LargeScreenUtils.shouldUseLargeScreenShadeHeader(mPanelView.getResources());
mLargeScreenShadeHeaderHeight =
- mResources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
+ centralizedStatusBarDimensRefactor()
+ ? mLargeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ : mResources.getDimensionPixelSize(
+ R.dimen.large_screen_shade_header_height);
int topMargin = mUseLargeScreenShadeHeader ? mLargeScreenShadeHeaderHeight :
mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top);
mShadeHeaderController.setLargeScreenActive(mUseLargeScreenShadeHeader);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 2460a33..a66bacd 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -38,6 +38,7 @@
import com.android.app.animation.Interpolators
import com.android.settingslib.Utils
import com.android.systemui.Dumpable
+import com.android.systemui.Flags.centralizedStatusBarDimensRefactor
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
@@ -432,6 +433,9 @@
changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
}
+ if (centralizedStatusBarDimensRefactor()) {
+ view.setPadding(view.paddingLeft, sbInsets.top, view.paddingRight, view.paddingBottom)
+ }
view.updateAllConstraints(changes)
updateBatteryMode()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
index 625fdc1..4b8fb1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
@@ -18,12 +18,15 @@
package com.android.systemui.statusbar.notification.stack.domain.interactor
import android.content.Context
+import com.android.systemui.Flags.centralizedStatusBarDimensRefactor
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.res.R
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.statusbar.policy.SplitShadeStateController
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -45,6 +48,7 @@
private val splitShadeStateController: SplitShadeStateController,
keyguardInteractor: KeyguardInteractor,
deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
+ largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
) {
private val _topPosition = MutableStateFlow(0f)
@@ -72,7 +76,11 @@
getDimensionPixelSize(R.dimen.notification_panel_margin_bottom),
marginTop = getDimensionPixelSize(R.dimen.notification_panel_margin_top),
marginTopLargeScreen =
- getDimensionPixelSize(R.dimen.large_screen_shade_header_height),
+ if (centralizedStatusBarDimensRefactor()) {
+ largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ } else {
+ getDimensionPixelSize(R.dimen.large_screen_shade_header_height)
+ },
keyguardSplitShadeTopMargin =
getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin),
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
index 0bad47e..8a45ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
@@ -18,12 +18,23 @@
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
+import com.android.systemui.Flags.smartspaceRelocateToBottom
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
import com.android.systemui.util.ViewController
import javax.inject.Inject
class KeyguardBottomAreaViewController
- @Inject constructor(view: KeyguardBottomAreaView, featureFlags: FeatureFlagsClassic) :
- ViewController<KeyguardBottomAreaView> (view) {
+ @Inject constructor(
+ view: KeyguardBottomAreaView,
+ private val smartspaceController: LockscreenSmartspaceController,
+ featureFlags: FeatureFlagsClassic
+) : ViewController<KeyguardBottomAreaView> (view) {
+
+ private var smartspaceView: View? = null
init {
view.setIsLockscreenLandscapeEnabled(
@@ -31,6 +42,14 @@
}
override fun onViewAttached() {
+ if (!smartspaceRelocateToBottom() || !smartspaceController.isEnabled()) {
+ return
+ }
+
+ val ambientIndicationArea = mView.findViewById<View>(R.id.ambient_indication_container)
+ ambientIndicationArea?.visibility = View.GONE
+
+ addSmartspaceView()
}
override fun onViewDetached() {
@@ -40,4 +59,24 @@
// TODO: remove this method.
return mView
}
+
+ private fun addSmartspaceView() {
+ if (!smartspaceRelocateToBottom()) {
+ return
+ }
+
+ val smartspaceContainer = mView.findViewById<View>(R.id.smartspace_container)
+ smartspaceContainer!!.visibility = View.VISIBLE
+
+ smartspaceView = smartspaceController.buildAndConnectView(smartspaceContainer as ViewGroup)
+ val lp = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ (smartspaceContainer as ViewGroup).addView(smartspaceView, 0, lp)
+ val startPadding = context.resources.getDimensionPixelSize(
+ R.dimen.below_clock_padding_start)
+ val endPadding = context.resources.getDimensionPixelSize(
+ R.dimen.below_clock_padding_end)
+ smartspaceView?.setPaddingRelative(startPadding, 0, endPadding, 0)
+// mKeyguardUnlockAnimationController.lockscreenSmartspace = smartspaceView
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 0a03af7..ca3e3c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -16,10 +16,12 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.Flags.centralizedStatusBarDimensRefactor;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInScale;
import static com.android.systemui.statusbar.notification.NotificationUtils.interpolate;
+import android.content.Context;
import android.content.res.Resources;
import android.util.MathUtils;
@@ -30,6 +32,7 @@
import com.android.systemui.log.core.Logger;
import com.android.systemui.log.dagger.KeyguardClockLog;
import com.android.systemui.res.R;
+import com.android.systemui.shade.LargeScreenHeaderHelper;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
@@ -160,14 +163,14 @@
mLogger = new Logger(logBuffer, TAG);
}
- /**
- * Refreshes the dimension values.
- */
- public void loadDimens(Resources res) {
- mStatusViewBottomMargin = res.getDimensionPixelSize(
- R.dimen.keyguard_status_view_bottom_margin);
+ /** Refreshes the dimension values. */
+ public void loadDimens(Context context, Resources res) {
+ mStatusViewBottomMargin =
+ res.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin);
mSplitShadeTopNotificationsMargin =
- res.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
+ centralizedStatusBarDimensRefactor()
+ ? LargeScreenHeaderHelper.getLargeScreenHeaderHeight(context)
+ : res.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
mSplitShadeTargetTopMargin =
res.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7cc0888..7691459 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.Flags.centralizedStatusBarDimensRefactor;
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
import static com.android.systemui.util.Utils.getStatusBarHeaderHeightKeyguard;
@@ -130,6 +131,9 @@
mUserSwitcherContainer = findViewById(R.id.user_switcher_container);
mIsPrivacyDotEnabled = mContext.getResources().getBoolean(R.bool.config_enablePrivacyDot);
loadDimens();
+ if (!centralizedStatusBarDimensRefactor()) {
+ setGravity(Gravity.CENTER_VERTICAL);
+ }
}
/**
@@ -307,7 +311,8 @@
final int minRight = (!isLayoutRtl() && mIsPrivacyDotEnabled)
? Math.max(mMinDotWidth, mPadding.right) : mPadding.right;
- setPadding(minLeft, waterfallTop, minRight, 0);
+ int top = centralizedStatusBarDimensRefactor() ? waterfallTop + mPadding.top : waterfallTop;
+ setPadding(minLeft, top, minRight, 0);
}
private boolean updateLayoutParamsNoCutout() {
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 20fef92..e57c0e7 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -210,7 +210,13 @@
if (DEBUG) {
Log.i(TAG, "onSurfaceDestroyed");
}
- mSurfaceHolder = null;
+ mLongExecutor.execute(this::onSurfaceDestroyedSynchronized);
+ }
+
+ private void onSurfaceDestroyedSynchronized() {
+ synchronized (mLock) {
+ mSurfaceHolder = null;
+ }
}
@Override
@@ -241,7 +247,7 @@
private void drawFrameInternal() {
if (mSurfaceHolder == null) {
- Log.e(TAG, "attempt to draw a frame without a valid surface");
+ Log.i(TAG, "attempt to draw a frame without a valid surface");
return;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index a206581..b239482 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -346,6 +346,7 @@
@Mock protected ActiveNotificationsInteractor mActiveNotificationsInteractor;
@Mock private KeyguardClockPositionAlgorithm mKeyguardClockPositionAlgorithm;
@Mock private NaturalScrollingSettingObserver mNaturalScrollingSettingObserver;
+ @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
protected final int mMaxUdfpsBurnInOffsetY = 5;
protected FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
@@ -426,7 +427,8 @@
mContext,
new ResourcesSplitShadeStateController(),
mKeyguardInteractor,
- deviceEntryUdfpsInteractor
+ deviceEntryUdfpsInteractor,
+ () -> mLargeScreenHeaderHelper
),
mShadeRepository
)
@@ -812,7 +814,8 @@
mActiveNotificationsInteractor,
mJavaAdapter,
mCastController,
- new ResourcesSplitShadeStateController()
+ new ResourcesSplitShadeStateController(),
+ () -> mLargeScreenHeaderHelper
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 9d8b214..437d00a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -143,6 +143,7 @@
@Mock private SelectedUserInteractor mSelectedUserInteractor;
@Mock private UserTracker mUserTracker;
@Mock private SceneContainerFlags mSceneContainerFlags;
+ @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
@Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
@@ -261,7 +262,8 @@
mContext,
new ResourcesSplitShadeStateController(),
keyguardInteractor,
- deviceEntryUdfpsInteractor),
+ deviceEntryUdfpsInteractor,
+ () -> mLargeScreenHeaderHelper),
shadeRepository
)
);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
index 88a47eb..ea3caa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -52,7 +53,6 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
-import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.RETURNS_DEEP_STUBS
import org.mockito.Mockito.any
@@ -74,15 +74,16 @@
@SmallTest
class NotificationsQSContainerControllerLegacyTest : SysuiTestCase() {
- @Mock lateinit var view: NotificationsQuickSettingsContainer
- @Mock lateinit var navigationModeController: NavigationModeController
- @Mock lateinit var overviewProxyService: OverviewProxyService
- @Mock lateinit var shadeHeaderController: ShadeHeaderController
- @Mock lateinit var shadeInteractor: ShadeInteractor
- @Mock lateinit var fragmentService: FragmentService
- @Mock lateinit var fragmentHostManager: FragmentHostManager
- @Mock
- lateinit var notificationStackScrollLayoutController: NotificationStackScrollLayoutController
+ private val view = mock<NotificationsQuickSettingsContainer>()
+ private val navigationModeController = mock<NavigationModeController>()
+ private val overviewProxyService = mock<OverviewProxyService>()
+ private val shadeHeaderController = mock<ShadeHeaderController>()
+ private val shadeInteractor = mock<ShadeInteractor>()
+ private val fragmentService = mock<FragmentService>()
+ private val fragmentHostManager = mock<FragmentHostManager>()
+ private val notificationStackScrollLayoutController =
+ mock<NotificationStackScrollLayoutController>()
+ private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
@Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener>
@Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<OverviewProxyListener>
@@ -123,7 +124,8 @@
delayableExecutor,
featureFlags,
notificationStackScrollLayoutController,
- ResourcesSplitShadeStateController()
+ ResourcesSplitShadeStateController(),
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
)
overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN)
@@ -480,7 +482,8 @@
delayableExecutor,
featureFlags,
notificationStackScrollLayoutController,
- ResourcesSplitShadeStateController()
+ ResourcesSplitShadeStateController(),
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
)
controller.updateConstraints()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
index 1f37ca0..c1bc303 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -53,7 +54,6 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
-import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.RETURNS_DEEP_STUBS
import org.mockito.Mockito.any
@@ -71,15 +71,16 @@
@SmallTest
class NotificationsQSContainerControllerTest : SysuiTestCase() {
- @Mock lateinit var view: NotificationsQuickSettingsContainer
- @Mock lateinit var navigationModeController: NavigationModeController
- @Mock lateinit var overviewProxyService: OverviewProxyService
- @Mock lateinit var shadeHeaderController: ShadeHeaderController
- @Mock lateinit var shadeInteractor: ShadeInteractor
- @Mock lateinit var fragmentService: FragmentService
- @Mock lateinit var fragmentHostManager: FragmentHostManager
- @Mock
- lateinit var notificationStackScrollLayoutController: NotificationStackScrollLayoutController
+ private val view = mock<NotificationsQuickSettingsContainer>()
+ private val navigationModeController = mock<NavigationModeController>()
+ private val overviewProxyService = mock<OverviewProxyService>()
+ private val shadeHeaderController = mock<ShadeHeaderController>()
+ private val shadeInteractor = mock<ShadeInteractor>()
+ private val fragmentService = mock<FragmentService>()
+ private val fragmentHostManager = mock<FragmentHostManager>()
+ private val notificationStackScrollLayoutController =
+ mock<NotificationStackScrollLayoutController>()
+ private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
@Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener>
@Captor lateinit var taskbarVisibilityCaptor: ArgumentCaptor<OverviewProxyListener>
@@ -122,7 +123,8 @@
delayableExecutor,
featureFlags,
notificationStackScrollLayoutController,
- ResourcesSplitShadeStateController()
+ ResourcesSplitShadeStateController(),
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
)
overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN)
@@ -463,7 +465,8 @@
delayableExecutor,
featureFlags,
notificationStackScrollLayoutController,
- ResourcesSplitShadeStateController()
+ ResourcesSplitShadeStateController(),
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
)
controller.updateConstraints()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index 727a6c3..39051eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -176,6 +176,7 @@
@Mock protected CastController mCastController;
@Mock protected UserSwitcherInteractor mUserSwitcherInteractor;
@Mock protected SelectedUserInteractor mSelectedUserInteractor;
+ @Mock protected LargeScreenHeaderHelper mLargeScreenHeaderHelper;
protected FakeDisableFlagsRepository mDisableFlagsRepository =
new FakeDisableFlagsRepository();
@@ -299,7 +300,8 @@
mContext,
splitShadeStateController,
keyguardInteractor,
- deviceEntryUdfpsInteractor),
+ deviceEntryUdfpsInteractor,
+ () -> mLargeScreenHeaderHelper),
mShadeRepository
)
);
@@ -384,7 +386,8 @@
mActiveNotificationsInteractor,
new JavaAdapter(mTestScope.getBackgroundScope()),
mCastController,
- splitShadeStateController
+ splitShadeStateController,
+ () -> mLargeScreenHeaderHelper
);
mQsController.init();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index f25ce0a..aed6163 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -27,7 +27,7 @@
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -44,6 +44,7 @@
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl
@@ -65,7 +66,6 @@
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
@@ -83,9 +83,10 @@
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
private lateinit var fromPrimaryBouncerTransitionInteractor:
FromPrimaryBouncerTransitionInteractor
- @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
- @Mock lateinit var mockDarkAnimator: ObjectAnimator
- @Mock lateinit var deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor
+ private val interactionJankMonitor = mock<InteractionJankMonitor>()
+ private val mockDarkAnimator = mock<ObjectAnimator>()
+ private val deviceEntryUdfpsInteractor = mock<DeviceEntryUdfpsInteractor>()
+ private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
private lateinit var controller: StatusBarStateControllerImpl
private lateinit var uiEventLogger: UiEventLoggerFake
@@ -189,6 +190,7 @@
ResourcesSplitShadeStateController(),
keyguardInteractor,
deviceEntryUdfpsInteractor,
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
),
shadeRepository,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 3556703..4dc4798 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -84,7 +84,7 @@
LogBuffer logBuffer = FakeLogBuffer.Factory.Companion.create();
mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm(logBuffer);
when(mResources.getDimensionPixelSize(anyInt())).thenReturn(0);
- mClockPositionAlgorithm.loadDimens(mResources);
+ mClockPositionAlgorithm.loadDimens(mContext, mResources);
mClockPosition = new KeyguardClockPositionAlgorithm.Result();
}
@@ -297,7 +297,7 @@
.thenReturn(100);
when(mResources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height))
.thenReturn(70);
- mClockPositionAlgorithm.loadDimens(mResources);
+ mClockPositionAlgorithm.loadDimens(mContext, mResources);
givenLockScreen();
mIsSplitShade = true;
// WHEN the position algorithm is run
@@ -589,7 +589,7 @@
private void setSplitShadeTopMargin(int value) {
when(mResources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin))
.thenReturn(value);
- mClockPositionAlgorithm.loadDimens(mResources);
+ mClockPositionAlgorithm.loadDimens(mContext, mResources);
}
private void givenHighestBurnInOffset() {
@@ -603,7 +603,7 @@
private void givenMaxBurnInOffset(int offset) {
when(mResources.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y_clock))
.thenReturn(offset);
- mClockPositionAlgorithm.loadDimens(mResources);
+ mClockPositionAlgorithm.loadDimens(mContext, mResources);
}
private void givenAOD() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
index 6714c94..fb5375a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserSwitcherInteractorTest.kt
@@ -32,6 +32,7 @@
import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
@@ -121,6 +122,7 @@
)
utils.featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ mSetFlagsRule.enableFlags(AConfigFlags.FLAG_SWITCH_USER_ON_BG)
spyContext = spy(context)
keyguardReply = KeyguardInteractorFactory.create(featureFlags = utils.featureFlags)
keyguardRepository = keyguardReply.repository
@@ -172,6 +174,7 @@
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
underTest.onRecordSelected(UserRecord(info = userInfos[1]), dialogShower)
+ runCurrent()
verify(uiEventLogger, times(1))
.log(MultiUserActionsEvent.SWITCH_TO_USER_FROM_USER_SWITCHER)
@@ -191,6 +194,7 @@
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
underTest.onRecordSelected(UserRecord(info = userInfos.last()))
+ runCurrent()
verify(uiEventLogger, times(1))
.log(MultiUserActionsEvent.SWITCH_TO_GUEST_FROM_USER_SWITCHER)
@@ -218,6 +222,7 @@
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
underTest.onRecordSelected(UserRecord(info = userInfos.last()))
+ runCurrent()
verify(uiEventLogger, times(1))
.log(MultiUserActionsEvent.SWITCH_TO_RESTRICTED_USER_FROM_USER_SWITCHER)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 814ea19..b7529a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -126,6 +126,7 @@
import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.LargeScreenHeaderHelper;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
@@ -349,6 +350,8 @@
private Display mDefaultDisplay;
@Mock
private SceneContainerFlags mSceneContainerFlags;
+ @Mock
+ private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
private final SceneTestUtils mUtils = new SceneTestUtils(this);
private final TestScope mTestScope = mUtils.getTestScope();
@@ -490,7 +493,8 @@
mContext,
splitShadeStateController,
keyguardInteractor,
- deviceEntryUdfpsInteractor),
+ deviceEntryUdfpsInteractor,
+ () -> mLargeScreenHeaderHelper),
shadeRepository
)
);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/LargeScreenHeaderHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/LargeScreenHeaderHelperKosmos.kt
new file mode 100644
index 0000000..d3e7574
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/LargeScreenHeaderHelperKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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.shade
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+
+var Kosmos.largeScreenHeaderHelper by Fixture { mockLargeScreenHeaderHelper }
+val Kosmos.mockLargeScreenHeaderHelper by Fixture { mock<LargeScreenHeaderHelper>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
index 13d577b..8909d75 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
@@ -21,6 +21,7 @@
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.shade.largeScreenHeaderHelper
import com.android.systemui.statusbar.policy.splitShadeStateController
val Kosmos.sharedNotificationContainerInteractor by
@@ -31,5 +32,6 @@
splitShadeStateController = splitShadeStateController,
keyguardInteractor = keyguardInteractor,
deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
)
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index dada72e..f80228a 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1812,6 +1812,7 @@
"msg: MSG_L_SET_BT_ACTIVE_DEVICE "
+ "received with null profile proxy: "
+ btInfo)).printLog(TAG));
+ sendMsg(MSG_CHECK_MUTE_MUSIC, SENDMSG_REPLACE, 0 /*delay*/);
return;
}
@AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index dd9541e..92be4ee 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -698,7 +698,7 @@
pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
// Clear any existing archive state.
- pkgSetting.setArchiveState(null, userId);
+ mPm.mInstallerService.mPackageArchiver.clearArchiveState(packageName, userId);
mPm.mSettings.writePackageRestrictionsLPr(userId);
mPm.mSettings.writeKernelMappingLPr(pkgSetting);
installed = true;
@@ -2281,7 +2281,7 @@
installerPackageName);
}
// Clear any existing archive state.
- ps.setArchiveState(null, userId);
+ mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName, userId);
} else if (allUsers != null) {
// The caller explicitly specified INSTALL_ALL_USERS flag.
// Thus, updating the settings to install the app for all users.
@@ -2305,7 +2305,8 @@
installerPackageName);
}
// Clear any existing archive state.
- ps.setArchiveState(null, currentUserId);
+ mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgName,
+ currentUserId);
} else {
ps.setInstalled(false, currentUserId);
}
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index a4af5e7..3e5759a 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -71,6 +71,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.IBinder;
import android.os.ParcelableException;
import android.os.Process;
@@ -309,6 +310,26 @@
return false;
}
+ void clearArchiveState(String packageName, int userId) {
+ synchronized (mPm.mLock) {
+ PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
+ if (ps != null) {
+ ps.setArchiveState(/* archiveState= */ null, userId);
+ }
+ }
+ mPm.mBackgroundHandler.post(
+ () -> {
+ File iconsDir = getIconsDir(packageName, userId);
+ if (!iconsDir.exists()) {
+ return;
+ }
+ // TODO(b/319238030) Move this into installd.
+ if (!FileUtils.deleteContentsAndDir(iconsDir)) {
+ Slog.e(TAG, "Failed to clean up archive files for " + packageName);
+ }
+ });
+ }
+
@Nullable
private String getCurrentLauncherPackageName(int userId) {
ComponentName defaultLauncherComponent = mPm.snapshotComputer().getDefaultHomeActivity(
@@ -437,8 +458,8 @@
if (mainActivity.iconBitmap == null) {
return null;
}
- File iconsDir = createIconsDir(userId);
- File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
+ File iconsDir = createIconsDir(packageName, userId);
+ File iconFile = new File(iconsDir, index + ".png");
try (FileOutputStream out = new FileOutputStream(iconFile)) {
out.write(mainActivity.iconBitmap);
out.flush();
@@ -454,14 +475,14 @@
// The app doesn't define an icon. No need to store anything.
return null;
}
- File iconsDir = createIconsDir(userId);
- File iconFile = new File(iconsDir, packageName + "-" + index + ".png");
+ File iconsDir = createIconsDir(packageName, userId);
+ File iconFile = new File(iconsDir, index + ".png");
Bitmap icon = drawableToBitmap(mainActivity.getIcon(/* density= */ 0), iconSize);
try (FileOutputStream out = new FileOutputStream(iconFile)) {
// Note: Quality is ignored for PNGs.
if (!icon.compress(Bitmap.CompressFormat.PNG, /* quality= */ 100, out)) {
throw new IOException(TextUtils.formatSimple("Failure to store icon file %s",
- iconFile.getName()));
+ iconFile.getAbsolutePath()));
}
out.flush();
}
@@ -793,8 +814,20 @@
}
@VisibleForTesting
- Bitmap decodeIcon(ArchiveActivityInfo archiveActivityInfo) {
- return BitmapFactory.decodeFile(archiveActivityInfo.getIconBitmap().toString());
+ @Nullable
+ Bitmap decodeIcon(ArchiveActivityInfo activityInfo) {
+ Path iconBitmap = activityInfo.getIconBitmap();
+ if (iconBitmap == null) {
+ return null;
+ }
+ Bitmap bitmap = BitmapFactory.decodeFile(iconBitmap.toString());
+ // TODO(b/278553670) We should throw here after some time. Failing graciously now because
+ // we've just changed the place where we store icons.
+ if (bitmap == null) {
+ Slog.e(TAG, "Archived icon cannot be decoded " + iconBitmap.toAbsolutePath());
+ return null;
+ }
+ return bitmap;
}
Bitmap includeCloudOverlay(Bitmap bitmap) {
@@ -1075,8 +1108,9 @@
}
}
- private static File createIconsDir(@UserIdInt int userId) throws IOException {
- File iconsDir = getIconsDir(userId);
+ private static File createIconsDir(String packageName, @UserIdInt int userId)
+ throws IOException {
+ File iconsDir = getIconsDir(packageName, userId);
if (!iconsDir.isDirectory()) {
iconsDir.delete();
iconsDir.mkdirs();
@@ -1088,8 +1122,10 @@
return iconsDir;
}
- private static File getIconsDir(int userId) {
- return new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR);
+ private static File getIconsDir(String packageName, int userId) {
+ return new File(
+ new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR),
+ packageName);
}
private static byte[] bytesFromBitmapFile(Path path) throws IOException {
@@ -1195,7 +1231,7 @@
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
if (extraIntent != null && user != null
&& mAppStateHelper.isAppTopVisible(
- getCurrentLauncherPackageName(user.getIdentifier()))) {
+ getCurrentLauncherPackageName(user.getIdentifier()))) {
extraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(extraIntent, user);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a9118d4..fdcd28b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -25,6 +25,7 @@
import static android.content.pm.PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED;
import static android.content.pm.PackageInstaller.UNARCHIVAL_GENERIC_ERROR;
import static android.content.pm.PackageInstaller.UNARCHIVAL_OK;
+import static android.content.pm.PackageManager.DELETE_ARCHIVE;
import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -1405,7 +1406,7 @@
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, versionedPackage.getPackageName(),
- canSilentlyInstallPackage, userId);
+ canSilentlyInstallPackage, userId, mPackageArchiver, flags);
final boolean shouldShowConfirmationDialog =
(flags & PackageManager.DELETE_SHOW_DIALOG) != 0;
if (!shouldShowConfirmationDialog
@@ -1759,7 +1760,7 @@
binderUid, unarchiveId));
}
- session.reportUnarchivalStatus(unarchiveId, status, requiredStorageBytes,
+ session.reportUnarchivalStatus(status, unarchiveId, requiredStorageBytes,
userActionIntent);
}
}
@@ -1828,9 +1829,23 @@
private final IntentSender mTarget;
private final String mPackageName;
private final Notification mNotification;
+ private final int mUserId;
- public PackageDeleteObserverAdapter(Context context, IntentSender target,
+ @DeleteFlags
+ private final int mFlags;
+
+ @Nullable
+ private final PackageArchiver mPackageArchiver;
+
+ PackageDeleteObserverAdapter(Context context, IntentSender target,
String packageName, boolean showNotification, int userId) {
+ this(context, target, packageName, showNotification, userId,
+ /* packageArchiver= */ null, /* flags= */ 0);
+ }
+
+ PackageDeleteObserverAdapter(Context context, IntentSender target,
+ String packageName, boolean showNotification, int userId,
+ PackageArchiver packageArchiver, @DeleteFlags int flags) {
mContext = context;
mTarget = target;
mPackageName = packageName;
@@ -1842,6 +1857,9 @@
} else {
mNotification = null;
}
+ mUserId = userId;
+ mPackageArchiver = packageArchiver;
+ mFlags = flags;
}
private String getDeviceOwnerDeletedPackageMsg() {
@@ -1883,6 +1901,11 @@
SystemMessage.NOTE_PACKAGE_STATE,
mNotification);
}
+ if (mPackageArchiver != null
+ && PackageManager.DELETE_SUCCEEDED != returnCode
+ && (mFlags & DELETE_ARCHIVE) != 0) {
+ mPackageArchiver.clearArchiveState(mPackageName, mUserId);
+ }
if (mTarget == null) {
return;
}