Merge "Tap to wake up dreaming for lockscreen hosted dream" into udc-qpr-dev
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index dbc1be1..d9ac4850 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -868,6 +868,11 @@
* This will trigger a {@link #onComputeColors()} call.
*/
public void notifyColorsChanged() {
+ if (mDestroyed) {
+ Log.i(TAG, "Ignoring notifyColorsChanged(), Engine has already been destroyed.");
+ return;
+ }
+
final long now = mClockFunction.get();
if (now - mLastColorInvalidation < NOTIFY_COLORS_RATE_LIMIT_MS) {
Log.w(TAG, "This call has been deferred. You should only call "
@@ -2226,7 +2231,11 @@
}
}
- void detach() {
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public void detach() {
if (mDestroyed) {
return;
}
@@ -2442,6 +2451,14 @@
}
public void reportShown() {
+ if (mEngine == null) {
+ Log.i(TAG, "Can't report null engine as shown.");
+ return;
+ }
+ if (mEngine.mDestroyed) {
+ Log.i(TAG, "Engine was destroyed before we could draw.");
+ return;
+ }
if (!mShownReported) {
mShownReported = true;
Trace.beginSection("WPMS.mConnection.engineShown");
diff --git a/core/java/com/android/internal/os/TimeoutRecord.java b/core/java/com/android/internal/os/TimeoutRecord.java
index a0e2934..f8a5520 100644
--- a/core/java/com/android/internal/os/TimeoutRecord.java
+++ b/core/java/com/android/internal/os/TimeoutRecord.java
@@ -58,6 +58,7 @@
int APP_REGISTERED = 7;
int SHORT_FGS_TIMEOUT = 8;
int JOB_SERVICE = 9;
+ int APP_START = 10;
}
/** Kind of timeout, e.g. BROADCAST_RECEIVER, etc. */
@@ -186,4 +187,10 @@
public static TimeoutRecord forJobService(String reason) {
return TimeoutRecord.endingNow(TimeoutKind.JOB_SERVICE, reason);
}
+
+ /** Record for app startup timeout. */
+ @NonNull
+ public static TimeoutRecord forAppStart(String reason) {
+ return TimeoutRecord.endingNow(TimeoutKind.APP_START, reason);
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e018393..1b1efee 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1035,7 +1035,7 @@
CREDENTIAL_TYPE_API, CREDENTIAL_TYPE_API, mCredentialTypeQuery);
/**
- * Invalidate the credential cache
+ * Invalidate the credential type cache
* @hide
*/
public final static void invalidateCredentialTypeCache() {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2d8bfbb..66ff01e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5236,7 +5236,7 @@
</string-array>
<!-- The integer index of the selected option in config_udfps_touch_detection_options -->
- <integer name="config_selected_udfps_touch_detection">3</integer>
+ <integer name="config_selected_udfps_touch_detection">0</integer>
<!-- An array of arrays of side fingerprint sensor properties relative to each display.
Note: this value is temporary and is expected to be queried directly
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 2c85fe4..c4530f6 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -346,4 +346,8 @@
<!-- Allow IMS service entitlement app to schedule jobs to run when app in background. -->
<allow-in-power-save-except-idle package="com.android.imsserviceentitlement" />
+
+ <!-- Allow device lock controller app to schedule jobs and alarms when app in background,
+ otherwise, it may not be able to enforce provision for managed devices. -->
+ <allow-in-power-save package="com.android.devicelockcontroller" />
</permissions>
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index f71e728..b870023 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -88,6 +88,9 @@
mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
validateCache(identity, size);
mInitialized = true;
+ if (identity != nullptr && size > 0 && mIDHash.size()) {
+ set(&sIDKey, sizeof(sIDKey), mIDHash.data(), mIDHash.size());
+ }
}
}
@@ -96,11 +99,6 @@
mFilename = filename;
}
-BlobCache* ShaderCache::getBlobCacheLocked() {
- LOG_ALWAYS_FATAL_IF(!mInitialized, "ShaderCache has not been initialized");
- return mBlobCache.get();
-}
-
sk_sp<SkData> ShaderCache::load(const SkData& key) {
ATRACE_NAME("ShaderCache::load");
size_t keySize = key.size();
@@ -115,8 +113,7 @@
if (!valueBuffer) {
return nullptr;
}
- BlobCache* bc = getBlobCacheLocked();
- size_t valueSize = bc->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
+ size_t valueSize = mBlobCache->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
int maxTries = 3;
while (valueSize > mObservedBlobValueSize && maxTries > 0) {
mObservedBlobValueSize = std::min(valueSize, maxValueSize);
@@ -126,7 +123,7 @@
return nullptr;
}
valueBuffer = newValueBuffer;
- valueSize = bc->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
+ valueSize = mBlobCache->get(key.data(), keySize, valueBuffer, mObservedBlobValueSize);
maxTries--;
}
if (!valueSize) {
@@ -143,16 +140,17 @@
return SkData::MakeFromMalloc(valueBuffer, valueSize);
}
-namespace {
-// Helper for BlobCache::set to trace the result.
-void set(BlobCache* cache, const void* key, size_t keySize, const void* value, size_t valueSize) {
- switch (cache->set(key, keySize, value, valueSize)) {
+void ShaderCache::set(const void* key, size_t keySize, const void* value, size_t valueSize) {
+ switch (mBlobCache->set(key, keySize, value, valueSize)) {
case BlobCache::InsertResult::kInserted:
// This is what we expect/hope. It means the cache is large enough.
return;
case BlobCache::InsertResult::kDidClean: {
ATRACE_FORMAT("ShaderCache: evicted an entry to fit {key: %lu value %lu}!", keySize,
valueSize);
+ if (mIDHash.size()) {
+ set(&sIDKey, sizeof(sIDKey), mIDHash.data(), mIDHash.size());
+ }
return;
}
case BlobCache::InsertResult::kNotEnoughSpace: {
@@ -172,15 +170,10 @@
}
}
}
-} // namespace
void ShaderCache::saveToDiskLocked() {
ATRACE_NAME("ShaderCache::saveToDiskLocked");
if (mInitialized && mBlobCache) {
- if (mIDHash.size()) {
- auto key = sIDKey;
- set(mBlobCache.get(), &key, sizeof(key), mIDHash.data(), mIDHash.size());
- }
// The most straightforward way to make ownership shared
mMutex.unlock();
mMutex.lock_shared();
@@ -209,11 +202,10 @@
const void* value = data.data();
- BlobCache* bc = getBlobCacheLocked();
if (mInStoreVkPipelineInProgress) {
if (mOldPipelineCacheSize == -1) {
// Record the initial pipeline cache size stored in the file.
- mOldPipelineCacheSize = bc->get(key.data(), keySize, nullptr, 0);
+ mOldPipelineCacheSize = mBlobCache->get(key.data(), keySize, nullptr, 0);
}
if (mNewPipelineCacheSize != -1 && mNewPipelineCacheSize == valueSize) {
// There has not been change in pipeline cache size. Stop trying to save.
@@ -228,7 +220,7 @@
mNewPipelineCacheSize = -1;
mTryToStorePipelineCache = true;
}
- set(bc, key.data(), keySize, value, valueSize);
+ set(key.data(), keySize, value, valueSize);
if (!mSavePending && mDeferredSaveDelayMs > 0) {
mSavePending = true;
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index 2f91c77..7495550 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -96,20 +96,18 @@
void operator=(const ShaderCache&) = delete;
/**
- * "getBlobCacheLocked" returns the BlobCache object being used to store the
- * key/value blob pairs. If the BlobCache object has not yet been created,
- * this will do so, loading the serialized cache contents from disk if
- * possible.
- */
- BlobCache* getBlobCacheLocked() REQUIRES(mMutex);
-
- /**
* "validateCache" updates the cache to match the given identity. If the
* cache currently has the wrong identity, all entries in the cache are cleared.
*/
bool validateCache(const void* identity, ssize_t size) REQUIRES(mMutex);
/**
+ * Helper for BlobCache::set to trace the result and ensure the identity hash
+ * does not get evicted.
+ */
+ void set(const void* key, size_t keySize, const void* value, size_t valueSize) REQUIRES(mMutex);
+
+ /**
* "saveToDiskLocked" attempts to save the current contents of the cache to
* disk. If the identity hash exists, we will insert the identity hash into
* the cache for next validation.
@@ -127,11 +125,9 @@
bool mInitialized GUARDED_BY(mMutex) = false;
/**
- * "mBlobCache" is the cache in which the key/value blob pairs are stored. It
- * is initially NULL, and will be initialized by getBlobCacheLocked the
- * first time it's needed.
- * The blob cache contains the Android build number. We treat version mismatches as an empty
- * cache (logic implemented in BlobCache::unflatten).
+ * "mBlobCache" is the cache in which the key/value blob pairs are stored.
+ * The blob cache contains the Android build number. We treat version mismatches
+ * as an empty cache (logic implemented in BlobCache::unflatten).
*/
std::unique_ptr<FileBlobCache> mBlobCache GUARDED_BY(mMutex);
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index 8e79e3c..38b99cc 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -70,6 +70,9 @@
* If a new layout change happens while an animation is already in progress, the animation
* is updated to continue from the current values to the new end state.
*
+ * A set of [excludedViews] can be passed. If any dependent view from [rootView] matches an
+ * entry in this set, changes to that view will not be animated.
+ *
* The animator continues to respond to layout changes until [stopAnimating] is called.
*
* Successive calls to this method override the previous settings ([interpolator] and
@@ -82,9 +85,16 @@
fun animate(
rootView: View,
interpolator: Interpolator = DEFAULT_INTERPOLATOR,
- duration: Long = DEFAULT_DURATION
+ duration: Long = DEFAULT_DURATION,
+ excludedViews: Set<View> = emptySet()
): Boolean {
- return animate(rootView, interpolator, duration, ephemeral = false)
+ return animate(
+ rootView,
+ interpolator,
+ duration,
+ ephemeral = false,
+ excludedViews = excludedViews
+ )
}
/**
@@ -95,16 +105,24 @@
fun animateNextUpdate(
rootView: View,
interpolator: Interpolator = DEFAULT_INTERPOLATOR,
- duration: Long = DEFAULT_DURATION
+ duration: Long = DEFAULT_DURATION,
+ excludedViews: Set<View> = emptySet()
): Boolean {
- return animate(rootView, interpolator, duration, ephemeral = true)
+ return animate(
+ rootView,
+ interpolator,
+ duration,
+ ephemeral = true,
+ excludedViews = excludedViews
+ )
}
private fun animate(
rootView: View,
interpolator: Interpolator,
duration: Long,
- ephemeral: Boolean
+ ephemeral: Boolean,
+ excludedViews: Set<View> = emptySet()
): Boolean {
if (
!occupiesSpace(
@@ -119,7 +137,7 @@
}
val listener = createUpdateListener(interpolator, duration, ephemeral)
- addListener(rootView, listener, recursive = true)
+ addListener(rootView, listener, recursive = true, excludedViews = excludedViews)
return true
}
@@ -921,8 +939,11 @@
private fun addListener(
view: View,
listener: View.OnLayoutChangeListener,
- recursive: Boolean = false
+ recursive: Boolean = false,
+ excludedViews: Set<View> = emptySet()
) {
+ if (excludedViews.contains(view)) return
+
// Make sure that only one listener is active at a time.
val previousListener = view.getTag(R.id.tag_layout_listener)
if (previousListener != null && previousListener is View.OnLayoutChangeListener) {
@@ -933,7 +954,12 @@
view.setTag(R.id.tag_layout_listener, listener)
if (view is ViewGroup && recursive) {
for (i in 0 until view.childCount) {
- addListener(view.getChildAt(i), listener, recursive = true)
+ addListener(
+ view.getChildAt(i),
+ listener,
+ recursive = true,
+ excludedViews = excludedViews
+ )
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index ca91b8a..38b751c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -17,15 +17,19 @@
package com.android.systemui.notifications.ui.composable
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
@Composable
@@ -34,10 +38,26 @@
) {
// TODO(b/272779828): implement.
Column(
- modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 300.dp).padding(4.dp),
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .defaultMinSize(minHeight = 300.dp)
+ .clip(RoundedCornerShape(32.dp))
+ .background(MaterialTheme.colorScheme.surface)
+ .padding(16.dp),
) {
- Text("Notifications", modifier = Modifier.align(Alignment.CenterHorizontally))
+ Text(
+ text = "Notifications",
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.onSurface,
+ )
Spacer(modifier = Modifier.weight(1f))
- Text("Shelf", modifier = Modifier.align(Alignment.CenterHorizontally))
+ Text(
+ text = "Shelf",
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ style = MaterialTheme.typography.titleSmall,
+ color = MaterialTheme.colorScheme.onSurface,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt
index 665d6dd..1bb341c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt
@@ -17,15 +17,19 @@
package com.android.systemui.qs.footer.ui.compose
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
@Composable
@@ -34,10 +38,26 @@
) {
// TODO(b/272780058): implement.
Column(
- modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 300.dp).padding(4.dp),
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .defaultMinSize(minHeight = 300.dp)
+ .clip(RoundedCornerShape(32.dp))
+ .background(MaterialTheme.colorScheme.primary)
+ .padding(16.dp),
) {
- Text("Quick settings", modifier = Modifier.align(Alignment.CenterHorizontally))
+ Text(
+ text = "Quick settings",
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.onPrimary,
+ )
Spacer(modifier = Modifier.weight(1f))
- Text("QS footer actions", modifier = Modifier.align(Alignment.CenterHorizontally))
+ Text(
+ text = "QS footer actions",
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ style = MaterialTheme.typography.titleSmall,
+ color = MaterialTheme.colorScheme.onPrimary,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 20e1751..27358f5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -16,18 +16,19 @@
package com.android.systemui.shade.ui.composable
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.material3.Button
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.notifications.ui.composable.Notifications
+import com.android.systemui.qs.footer.ui.compose.QuickSettings
import com.android.systemui.scene.shared.model.Direction
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
@@ -62,12 +63,7 @@
override fun Content(
containerName: String,
modifier: Modifier,
- ) {
- ShadeScene(
- viewModel = viewModel,
- modifier = modifier,
- )
- }
+ ) = ShadeScene(viewModel, modifier)
private fun destinationScenes(
up: SceneKey,
@@ -84,23 +80,15 @@
viewModel: ShadeSceneViewModel,
modifier: Modifier = Modifier,
) {
- // TODO(b/280887022): implement the real UI.
-
- Box(modifier = modifier) {
- Column(
- horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier.align(Alignment.Center)
- ) {
- Text("Shade", style = MaterialTheme.typography.headlineMedium)
- Row(
- horizontalArrangement = Arrangement.spacedBy(8.dp),
- ) {
- Button(
- onClick = { viewModel.onContentClicked() },
- ) {
- Text("Open some content")
- }
- }
- }
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ modifier =
+ Modifier.fillMaxSize()
+ .clickable(onClick = { viewModel.onContentClicked() })
+ .padding(horizontal = 16.dp, vertical = 48.dp)
+ ) {
+ QuickSettings(modifier = modifier.height(160.dp))
+ Notifications(modifier = modifier.weight(1f))
}
}
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
deleted file mode 100644
index 9304ff7..0000000
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<!-- Layout for media recommendations inside QSPanel carousel -->
-<!-- See media_recommendation_expanded.xml and media_recommendation_collapsed.xml for the
- constraints. -->
-<com.android.systemui.util.animation.TransitionLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/media_recommendations"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:forceHasOverlappingRendering="false"
- android:background="@drawable/qs_media_background"
- android:theme="@style/MediaPlayer">
-
- <!-- This view just ensures the full media player is a certain height. -->
- <View
- android:id="@+id/sizing_view"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_media_session_height_expanded" />
-
- <com.android.internal.widget.CachingIconView
- android:id="@+id/recommendation_card_icon"
- android:layout_width="@dimen/qs_media_app_icon_size"
- android:layout_height="@dimen/qs_media_app_icon_size"
- android:minWidth="@dimen/qs_media_app_icon_size"
- android:minHeight="@dimen/qs_media_app_icon_size"
- android:layout_marginStart="@dimen/qs_media_padding"
- android:layout_marginTop="@dimen/qs_media_rec_icon_top_margin"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- <FrameLayout
- android:id="@+id/media_cover1_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- >
- <ImageView
- android:id="@+id/media_cover1"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:minWidth="@dimen/qs_media_rec_album_size"
- android:minHeight="@dimen/qs_media_rec_album_size"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Recommendation.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <TextView
- android:id="@+id/media_title1"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- />
-
- <TextView
- android:id="@+id/media_subtitle1"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- />
-
- <FrameLayout
- android:id="@+id/media_cover2_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- >
- <ImageView
- android:id="@+id/media_cover2"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:minWidth="@dimen/qs_media_rec_album_size"
- android:minHeight="@dimen/qs_media_rec_album_size"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Recommendation.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <TextView
- android:id="@+id/media_title2"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- />
-
- <TextView
- android:id="@+id/media_subtitle2"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- />
-
- <FrameLayout
- android:id="@+id/media_cover3_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- >
- <ImageView
- android:id="@+id/media_cover3"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:minWidth="@dimen/qs_media_rec_album_size"
- android:minHeight="@dimen/qs_media_rec_album_size"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Recommendation.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <TextView
- android:id="@+id/media_title3"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- />
-
- <TextView
- android:id="@+id/media_subtitle3"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- />
-
- <include
- layout="@layout/media_long_press_menu" />
-
-</com.android.systemui.util.animation.TransitionLayout>
diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
deleted file mode 100644
index b7d4b3a..0000000
--- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto" >
-
- <Constraint
- android:id="@+id/sizing_view"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_media_session_height_collapsed"
- />
-
- <!-- Only the constraintBottom and marginBottom are different. The rest of the constraints are
- the same as the constraints in media_recommendations_expanded.xml. But, due to how
- ConstraintSets work, all the constraints need to be in the same place. So, the shared
- constraints can't be put in the shared layout file media_smartspace_recommendations.xml and
- the constraints are instead duplicated between here and media_recommendations_expanded.xml.
- Ditto for the other cover containers. -->
- <Constraint
- android:id="@+id/media_cover1_container"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
- android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1.0"
- app:layout_constraintVertical_bias="0.5"
- />
-
- <Constraint
- android:id="@+id/media_title1"
- android:visibility="gone"
- />
-
- <Constraint
- android:id="@+id/media_subtitle1"
- android:visibility="gone"
- />
-
- <Constraint
- android:id="@+id/media_cover2_container"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover1_container"
- app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
- android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin"
- app:layout_constraintVertical_bias="0.5"
- />
-
- <Constraint
- android:id="@+id/media_title2"
- android:visibility="gone"
- />
-
- <Constraint
- android:id="@+id/media_subtitle2"
- android:visibility="gone"
- />
-
- <Constraint
- android:id="@+id/media_cover3_container"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="parent"
- android:layout_marginEnd="@dimen/qs_media_padding"
- app:layout_constraintVertical_bias="0.5"
- />
-
- <Constraint
- android:id="@+id/media_title3"
- android:visibility="gone"
- />
-
- <Constraint
- android:id="@+id/media_subtitle3"
- android:visibility="gone"
- />
-
-</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
deleted file mode 100644
index ce25a7d..0000000
--- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- >
-
- <Constraint
- android:id="@+id/sizing_view"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_media_session_height_expanded"
- />
-
- <Constraint
- android:id="@+id/media_cover1_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/media_title1"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
- android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1.0"
- app:layout_constraintVertical_bias="0.4"
- />
-
- <Constraint
- android:id="@+id/media_title1"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- app:layout_constraintStart_toStartOf="@+id/media_cover1_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover1_container"
- app:layout_constraintTop_toBottomOf="@+id/media_cover1_container"
- app:layout_constraintBottom_toTopOf="@+id/media_subtitle1"
- />
-
- <Constraint
- android:id="@+id/media_subtitle1"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- app:layout_constraintStart_toStartOf="@+id/media_cover1_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover1_container"
- app:layout_constraintTop_toBottomOf="@+id/media_title1"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- />
-
- <Constraint
- android:id="@+id/media_cover2_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/media_title2"
- app:layout_constraintStart_toEndOf="@id/media_cover1_container"
- app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
- android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="0.4"
- />
-
- <Constraint
- android:id="@+id/media_title2"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- app:layout_constraintStart_toStartOf="@+id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover2_container"
- app:layout_constraintTop_toBottomOf="@+id/media_cover2_container"
- app:layout_constraintBottom_toTopOf="@+id/media_subtitle2"
- />
-
- <Constraint
- android:id="@+id/media_subtitle2"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- app:layout_constraintStart_toStartOf="@+id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover2_container"
- app:layout_constraintTop_toBottomOf="@+id/media_title2"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- />
-
- <Constraint
- android:id="@+id/media_cover3_container"
- style="@style/MediaPlayer.Recommendation.AlbumContainer"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/media_title3"
- app:layout_constraintStart_toEndOf="@id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="parent"
- android:layout_marginEnd="@dimen/qs_media_padding"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="0.4"
- />
-
- <Constraint
- android:id="@+id/media_title3"
- style="@style/MediaPlayer.Recommendation.Text.Title"
- app:layout_constraintStart_toStartOf="@+id/media_cover3_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover3_container"
- app:layout_constraintTop_toBottomOf="@+id/media_cover3_container"
- app:layout_constraintBottom_toTopOf="@+id/media_subtitle3"
- />
-
- <Constraint
- android:id="@+id/media_subtitle3"
- style="@style/MediaPlayer.Recommendation.Text.Subtitle"
- app:layout_constraintStart_toStartOf="@+id/media_cover3_container"
- app:layout_constraintEnd_toEndOf="@+id/media_cover3_container"
- app:layout_constraintTop_toBottomOf="@+id/media_title3"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginBottom="@dimen/qs_media_padding"
- />
-
-</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_recommendations_view_collapsed.xml b/packages/SystemUI/res/xml/media_recommendations_collapsed.xml
similarity index 100%
rename from packages/SystemUI/res/xml/media_recommendations_view_collapsed.xml
rename to packages/SystemUI/res/xml/media_recommendations_collapsed.xml
diff --git a/packages/SystemUI/res/xml/media_recommendations_view_expanded.xml b/packages/SystemUI/res/xml/media_recommendations_expanded.xml
similarity index 100%
rename from packages/SystemUI/res/xml/media_recommendations_view_expanded.xml
rename to packages/SystemUI/res/xml/media_recommendations_expanded.xml
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 7a2f244..9df56fc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -250,7 +250,7 @@
.setMessage(messageBody)
.setPositiveButton(android.R.string.ok, null)
.create();
- alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
+ alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
alertDialog.show();
}
@@ -263,7 +263,7 @@
.setOnDismissListener(
dialog -> animateAway(AuthDialogCallback.DISMISSED_ERROR))
.create();
- alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
+ alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
alertDialog.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index add32398..0670ec3 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -438,10 +438,6 @@
// TODO(b/266157412): Tracking Bug
val MEDIA_RETAIN_SESSIONS = unreleasedFlag(913, "media_retain_sessions")
- // TODO(b/266739309): Tracking Bug
- @JvmField
- val MEDIA_RECOMMENDATION_CARD_UPDATE = releasedFlag(914, "media_recommendation_card_update")
-
// TODO(b/267007629): Tracking Bug
val MEDIA_RESUME_PROGRESS = releasedFlag(915, "media_resume_progress")
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
index 0b33904..258284e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
@@ -31,15 +31,12 @@
private const val TAG = "RecommendationViewHolder"
/** ViewHolder for a Smartspace media recommendation. */
-class RecommendationViewHolder private constructor(itemView: View, updatedView: Boolean) {
+class RecommendationViewHolder private constructor(itemView: View) {
val recommendations = itemView as TransitionLayout
// Recommendation screen
- lateinit var cardIcon: ImageView
- lateinit var mediaAppIcons: List<CachingIconView>
- lateinit var mediaProgressBars: List<SeekBar>
- lateinit var cardTitle: TextView
+ val cardTitle: TextView = itemView.requireViewById(R.id.media_rec_title)
val mediaCoverContainers =
listOf<ViewGroup>(
@@ -47,53 +44,25 @@
itemView.requireViewById(R.id.media_cover2_container),
itemView.requireViewById(R.id.media_cover3_container)
)
+ val mediaAppIcons: List<CachingIconView> =
+ mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
val mediaTitles: List<TextView> =
- if (updatedView) {
- mediaCoverContainers.map { it.requireViewById(R.id.media_title) }
- } else {
- listOf(
- itemView.requireViewById(R.id.media_title1),
- itemView.requireViewById(R.id.media_title2),
- itemView.requireViewById(R.id.media_title3)
- )
- }
+ mediaCoverContainers.map { it.requireViewById(R.id.media_title) }
val mediaSubtitles: List<TextView> =
- if (updatedView) {
- mediaCoverContainers.map { it.requireViewById(R.id.media_subtitle) }
- } else {
- listOf(
- itemView.requireViewById(R.id.media_subtitle1),
- itemView.requireViewById(R.id.media_subtitle2),
- itemView.requireViewById(R.id.media_subtitle3)
- )
+ mediaCoverContainers.map { it.requireViewById(R.id.media_subtitle) }
+ val mediaProgressBars: List<SeekBar> =
+ mediaCoverContainers.map {
+ it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
+ // Media playback is in the direction of tape, not time, so it stays LTR
+ layoutDirection = View.LAYOUT_DIRECTION_LTR
+ }
}
val mediaCoverItems: List<ImageView> =
- if (updatedView) {
- mediaCoverContainers.map { it.requireViewById(R.id.media_cover) }
- } else {
- listOf(
- itemView.requireViewById(R.id.media_cover1),
- itemView.requireViewById(R.id.media_cover2),
- itemView.requireViewById(R.id.media_cover3)
- )
- }
+ mediaCoverContainers.map { it.requireViewById(R.id.media_cover) }
val gutsViewHolder = GutsViewHolder(itemView)
init {
- if (updatedView) {
- mediaAppIcons = mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
- cardTitle = itemView.requireViewById(R.id.media_rec_title)
- mediaProgressBars =
- mediaCoverContainers.map {
- it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
- // Media playback is in the direction of tape, not time, so it stays LTR
- layoutDirection = View.LAYOUT_DIRECTION_LTR
- }
- }
- } else {
- cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
- }
(recommendations.background as IlluminationDrawable).let { background ->
mediaCoverContainers.forEach { background.registerLightSource(it) }
background.registerLightSource(gutsViewHolder.cancel)
@@ -114,63 +83,31 @@
* @param parent Parent of inflated view.
*/
@JvmStatic
- fun create(
- inflater: LayoutInflater,
- parent: ViewGroup,
- updatedView: Boolean,
- ): RecommendationViewHolder {
+ fun create(inflater: LayoutInflater, parent: ViewGroup): RecommendationViewHolder {
val itemView =
- if (updatedView) {
- inflater.inflate(
- R.layout.media_recommendations,
- parent,
- false /* attachToRoot */
- )
- } else {
- inflater.inflate(
- R.layout.media_smartspace_recommendations,
- parent,
- false /* attachToRoot */
- )
- }
+ inflater.inflate(R.layout.media_recommendations, parent, false /* attachToRoot */)
// Because this media view (a TransitionLayout) is used to measure and layout the views
// in various states before being attached to its parent, we can't depend on the default
// LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
itemView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
- return RecommendationViewHolder(itemView, updatedView)
+ return RecommendationViewHolder(itemView)
}
// Res Ids for the control components on the recommendation view.
val controlsIds =
setOf(
- R.id.recommendation_card_icon,
R.id.media_rec_title,
- R.id.media_cover1,
- R.id.media_cover2,
- R.id.media_cover3,
R.id.media_cover,
R.id.media_cover1_container,
R.id.media_cover2_container,
R.id.media_cover3_container,
- R.id.media_title1,
- R.id.media_title2,
- R.id.media_title3,
R.id.media_title,
- R.id.media_subtitle1,
- R.id.media_subtitle2,
- R.id.media_subtitle3,
R.id.media_subtitle,
)
val mediaTitlesAndSubtitlesIds =
setOf(
- R.id.media_title1,
- R.id.media_title2,
- R.id.media_title3,
R.id.media_title,
- R.id.media_subtitle1,
- R.id.media_subtitle2,
- R.id.media_subtitle3,
R.id.media_subtitle,
)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 70b5e75..398dcf2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -744,11 +744,7 @@
val newRecs = mediaControlPanelFactory.get()
newRecs.attachRecommendation(
- RecommendationViewHolder.create(
- LayoutInflater.from(context),
- mediaContent,
- mediaFlags.isRecommendationCardUpdateEnabled()
- )
+ RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)
)
newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index a978b92..a12bc2c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -784,14 +784,7 @@
contentDescription =
mRecommendationViewHolder.getGutsViewHolder().getGutsText().getText();
} else if (data != null) {
- if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- contentDescription = mContext.getString(
- R.string.controls_media_smartspace_rec_header);
- } else {
- contentDescription = mContext.getString(
- R.string.controls_media_smartspace_rec_description,
- data.getAppName(mContext));
- }
+ contentDescription = mContext.getString(R.string.controls_media_smartspace_rec_header);
} else {
contentDescription = null;
}
@@ -1377,10 +1370,6 @@
PackageManager packageManager = mContext.getPackageManager();
// Set up media source app's logo.
Drawable icon = packageManager.getApplicationIcon(applicationInfo);
- if (!mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- ImageView headerLogoImageView = mRecommendationViewHolder.getCardIcon();
- headerLogoImageView.setImageDrawable(icon);
- }
fetchAndUpdateRecommendationColors(icon);
// Set up media rec card's tap action if applicable.
@@ -1401,16 +1390,7 @@
// Set up media item cover.
ImageView mediaCoverImageView = mediaCoverItems.get(itemIndex);
- if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- bindRecommendationArtwork(
- recommendation,
- data.getPackageName(),
- itemIndex
- );
- } else {
- mediaCoverImageView.post(
- () -> mediaCoverImageView.setImageIcon(recommendation.getIcon()));
- }
+ bindRecommendationArtwork(recommendation, data.getPackageName(), itemIndex);
// Set up the media item's click listener if applicable.
ViewGroup mediaCoverContainer = mediaCoverContainers.get(itemIndex);
@@ -1455,21 +1435,18 @@
subtitleView.setText(subtitle);
// Set up progress bar
- if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- SeekBar mediaProgressBar =
- mRecommendationViewHolder.getMediaProgressBars().get(itemIndex);
- TextView mediaSubtitle =
- mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
- // show progress bar if the recommended album is played.
- Double progress = MediaDataUtils.getDescriptionProgress(recommendation.getExtras());
- if (progress == null || progress <= 0.0) {
- mediaProgressBar.setVisibility(View.GONE);
- mediaSubtitle.setVisibility(View.VISIBLE);
- } else {
- mediaProgressBar.setProgress((int) (progress * 100));
- mediaProgressBar.setVisibility(View.VISIBLE);
- mediaSubtitle.setVisibility(View.GONE);
- }
+ SeekBar mediaProgressBar =
+ mRecommendationViewHolder.getMediaProgressBars().get(itemIndex);
+ TextView mediaSubtitle = mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
+ // show progress bar if the recommended album is played.
+ Double progress = MediaDataUtils.getDescriptionProgress(recommendation.getExtras());
+ if (progress == null || progress <= 0.0) {
+ mediaProgressBar.setVisibility(View.GONE);
+ mediaSubtitle.setVisibility(View.VISIBLE);
+ } else {
+ mediaProgressBar.setProgress((int) (progress * 100));
+ mediaProgressBar.setVisibility(View.VISIBLE);
+ mediaSubtitle.setVisibility(View.GONE);
}
}
mSmartspaceMediaItemsCount = NUM_REQUIRED_RECOMMENDATIONS;
@@ -1588,9 +1565,7 @@
int textPrimaryColor = MediaColorSchemesKt.textPrimaryFromScheme(colorScheme);
int textSecondaryColor = MediaColorSchemesKt.textSecondaryFromScheme(colorScheme);
- if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- mRecommendationViewHolder.getCardTitle().setTextColor(textPrimaryColor);
- }
+ mRecommendationViewHolder.getCardTitle().setTextColor(textPrimaryColor);
mRecommendationViewHolder.getRecommendations()
.setBackgroundTintList(ColorStateList.valueOf(backgroundColor));
@@ -1598,12 +1573,9 @@
(title) -> title.setTextColor(textPrimaryColor));
mRecommendationViewHolder.getMediaSubtitles().forEach(
(subtitle) -> subtitle.setTextColor(textSecondaryColor));
- if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
- mRecommendationViewHolder.getMediaProgressBars().forEach(
- (progressBar) -> progressBar.setProgressTintList(
- ColorStateList.valueOf(textPrimaryColor))
- );
- }
+ mRecommendationViewHolder.getMediaProgressBars().forEach(
+ (progressBar) -> progressBar.setProgressTintList(
+ ColorStateList.valueOf(textPrimaryColor)));
mRecommendationViewHolder.getGutsViewHolder().setColors(colorScheme);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index 4bca778..1dd969f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -655,13 +655,8 @@
expandedLayout.load(context, R.xml.media_session_expanded)
}
TYPE.RECOMMENDATION -> {
- if (mediaFlags.isRecommendationCardUpdateEnabled()) {
- collapsedLayout.load(context, R.xml.media_recommendations_view_collapsed)
- expandedLayout.load(context, R.xml.media_recommendations_view_expanded)
- } else {
- collapsedLayout.load(context, R.xml.media_recommendation_collapsed)
- expandedLayout.load(context, R.xml.media_recommendation_expanded)
- }
+ collapsedLayout.load(context, R.xml.media_recommendations_collapsed)
+ expandedLayout.load(context, R.xml.media_recommendations_expanded)
}
}
refreshState()
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 01f047c..09aef88 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -49,10 +49,6 @@
*/
fun isRetainingPlayersEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_SESSIONS)
- /** Check whether we show the updated recommendation card. */
- fun isRecommendationCardUpdateEnabled() =
- featureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)
-
/** Check whether to get progress information for resume players */
fun isResumeProgressEnabled() = featureFlags.isEnabled(Flags.MEDIA_RESUME_PROGRESS)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 83b373d..856a92e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -58,6 +58,7 @@
private final BrightnessSliderController mBrightnessSliderController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private boolean mListening;
private View.OnTouchListener mTileLayoutTouchListener = new View.OnTouchListener() {
@Override
@@ -159,12 +160,15 @@
public void setListening(boolean listening, boolean expanded) {
setListening(listening && expanded);
- // Set the listening as soon as the QS fragment starts listening regardless of the
- //expansion, so it will update the current brightness before the slider is visible.
- if (listening) {
- mBrightnessController.registerCallbacks();
- } else {
- mBrightnessController.unregisterCallbacks();
+ if (listening != mListening) {
+ mListening = listening;
+ // Set the listening as soon as the QS fragment starts listening regardless of the
+ //expansion, so it will update the current brightness before the slider is visible.
+ if (listening) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 9594ba3..6af9b73 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -22,7 +22,6 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
-import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.BrightnessInfo;
@@ -31,10 +30,10 @@
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerExecutor;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -43,6 +42,8 @@
import android.util.Log;
import android.util.MathUtils;
+import androidx.annotation.Nullable;
+
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -52,10 +53,13 @@
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.concurrent.Executor;
-import javax.inject.Inject;
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
private static final String TAG = "CentralSurfaces.BrightnessController";
@@ -75,8 +79,11 @@
private final DisplayManager mDisplayManager;
private final UserTracker mUserTracker;
private final DisplayTracker mDisplayTracker;
+ @Nullable
private final IVrManager mVrManager;
+ private final SecureSettings mSecureSettings;
+
private final Executor mMainExecutor;
private final Handler mBackgroundHandler;
private final BrightnessObserver mBrightnessObserver;
@@ -106,6 +113,8 @@
/** ContentObserver to watch brightness */
private class BrightnessObserver extends ContentObserver {
+ private boolean mObserving = false;
+
BrightnessObserver(Handler handler) {
super(handler);
}
@@ -124,19 +133,17 @@
}
public void startObserving() {
- final ContentResolver cr = mContext.getContentResolver();
- cr.unregisterContentObserver(this);
- cr.registerContentObserver(
- BRIGHTNESS_MODE_URI,
- false, this, UserHandle.USER_ALL);
- mDisplayTracker.addBrightnessChangeCallback(mBrightnessListener,
- new HandlerExecutor(mHandler));
+ if (!mObserving) {
+ mObserving = true;
+ mSecureSettings.registerContentObserverForUser(
+ BRIGHTNESS_MODE_URI,
+ false, this, UserHandle.USER_ALL);
+ }
}
public void stopObserving() {
- final ContentResolver cr = mContext.getContentResolver();
- cr.unregisterContentObserver(this);
- mDisplayTracker.removeCallback(mBrightnessListener);
+ mSecureSettings.unregisterContentObserver(this);
+ mObserving = false;
}
}
@@ -159,6 +166,8 @@
}
mBrightnessObserver.startObserving();
+ mDisplayTracker.addBrightnessChangeCallback(mBrightnessListener,
+ new HandlerExecutor(mMainHandler));
mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
// Update the slider and mode before attaching the listener so we don't
@@ -166,7 +175,7 @@
mUpdateModeRunnable.run();
mUpdateSliderRunnable.run();
- mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
+ mMainHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
}
};
@@ -187,9 +196,10 @@
}
mBrightnessObserver.stopObserving();
+ mDisplayTracker.removeCallback(mBrightnessListener);
mUserTracker.removeCallback(mUserChangedCallback);
- mHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
+ mMainHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
}
};
@@ -225,7 +235,7 @@
mBrightnessMin = info.brightnessMinimum;
// Value is passed as intbits, since this is what the message takes.
final int valueAsIntBits = Float.floatToIntBits(info.brightness);
- mHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
+ mMainHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
inVrMode ? 1 : 0).sendToTarget();
}
};
@@ -233,14 +243,14 @@
private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
@Override
public void onVrStateChanged(boolean enabled) {
- mHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
+ mMainHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
.sendToTarget();
}
};
- private final Handler mHandler = new Handler() {
+ private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
- public void handleMessage(Message msg) {
+ public boolean handleMessage(Message msg) {
mExternalChange = true;
try {
switch (msg.what) {
@@ -257,14 +267,18 @@
updateVrMode(msg.arg1 != 0);
break;
default:
- super.handleMessage(msg);
+ return false;
+
}
} finally {
mExternalChange = false;
}
+ return true;
}
};
+ private final Handler mMainHandler;
+
private final UserTracker.Callback mUserChangedCallback =
new UserTracker.Callback() {
@Override
@@ -274,12 +288,17 @@
}
};
+ @AssistedInject
public BrightnessController(
Context context,
- ToggleSlider control,
+ @Assisted ToggleSlider control,
UserTracker userTracker,
DisplayTracker displayTracker,
+ DisplayManager displayManager,
+ SecureSettings secureSettings,
+ @Nullable IVrManager iVrManager,
@Main Executor mainExecutor,
+ @Main Looper mainLooper,
@Background Handler bgHandler) {
mContext = context;
mControl = control;
@@ -288,22 +307,23 @@
mBackgroundHandler = bgHandler;
mUserTracker = userTracker;
mDisplayTracker = displayTracker;
- mBrightnessObserver = new BrightnessObserver(mHandler);
-
+ mSecureSettings = secureSettings;
mDisplayId = mContext.getDisplayId();
- PowerManager pm = context.getSystemService(PowerManager.class);
+ mDisplayManager = displayManager;
+ mVrManager = iVrManager;
- mDisplayManager = context.getSystemService(DisplayManager.class);
- mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
- Context.VR_SERVICE));
+ mMainHandler = new Handler(mainLooper, mHandlerCallback);
+ mBrightnessObserver = new BrightnessObserver(mMainHandler);
}
public void registerCallbacks() {
+ mBackgroundHandler.removeCallbacks(mStartListeningRunnable);
mBackgroundHandler.post(mStartListeningRunnable);
}
/** Unregister all call backs, both to and from the controller */
public void unregisterCallbacks() {
+ mBackgroundHandler.removeCallbacks(mStopListeningRunnable);
mBackgroundHandler.post(mStopListeningRunnable);
mControlValueInitialized = false;
}
@@ -418,38 +438,12 @@
mSliderAnimator.start();
}
+
+
/** Factory for creating a {@link BrightnessController}. */
- public static class Factory {
- private final Context mContext;
- private final UserTracker mUserTracker;
- private final DisplayTracker mDisplayTracker;
- private final Executor mMainExecutor;
- private final Handler mBackgroundHandler;
-
- @Inject
- public Factory(
- Context context,
- UserTracker userTracker,
- DisplayTracker displayTracker,
- @Main Executor mainExecutor,
- @Background Handler bgHandler) {
- mContext = context;
- mUserTracker = userTracker;
- mDisplayTracker = displayTracker;
- mMainExecutor = mainExecutor;
- mBackgroundHandler = bgHandler;
- }
-
+ @AssistedFactory
+ public interface Factory {
/** Create a {@link BrightnessController} */
- public BrightnessController create(ToggleSlider toggleSlider) {
- return new BrightnessController(
- mContext,
- toggleSlider,
- mUserTracker,
- mDisplayTracker,
- mMainExecutor,
- mBackgroundHandler);
- }
+ BrightnessController create(ToggleSlider toggleSlider);
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 182e456..38b1f14 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -23,7 +23,6 @@
import android.app.Activity;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.Handler;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
@@ -37,10 +36,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.settings.DisplayTracker;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -56,26 +52,21 @@
private BrightnessController mBrightnessController;
private final BrightnessSliderController.Factory mToggleSliderFactory;
- private final UserTracker mUserTracker;
- private final DisplayTracker mDisplayTracker;
+ private final BrightnessController.Factory mBrightnessControllerFactory;
private final DelayableExecutor mMainExecutor;
- private final Handler mBackgroundHandler;
private final AccessibilityManagerWrapper mAccessibilityMgr;
private Runnable mCancelTimeoutRunnable;
@Inject
public BrightnessDialog(
- UserTracker userTracker,
- DisplayTracker displayTracker,
- BrightnessSliderController.Factory factory,
+ BrightnessSliderController.Factory brightnessSliderfactory,
+ BrightnessController.Factory brightnessControllerFactory,
@Main DelayableExecutor mainExecutor,
- @Background Handler bgHandler,
- AccessibilityManagerWrapper accessibilityMgr) {
- mUserTracker = userTracker;
- mDisplayTracker = displayTracker;
- mToggleSliderFactory = factory;
+ AccessibilityManagerWrapper accessibilityMgr
+ ) {
+ mToggleSliderFactory = brightnessSliderfactory;
+ mBrightnessControllerFactory = brightnessControllerFactory;
mMainExecutor = mainExecutor;
- mBackgroundHandler = bgHandler;
mAccessibilityMgr = accessibilityMgr;
}
@@ -121,8 +112,7 @@
controller.init();
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
- mBrightnessController = new BrightnessController(
- this, controller, mUserTracker, mDisplayTracker, mMainExecutor, mBackgroundHandler);
+ mBrightnessController = mBrightnessControllerFactory.create(controller);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index cfecf7d..9399d48 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -168,7 +168,6 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
@@ -224,6 +223,8 @@
import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.animation.FlingAnimationUtils;
+import kotlin.Unit;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
@@ -234,8 +235,6 @@
import javax.inject.Inject;
import javax.inject.Provider;
-import kotlin.Unit;
-
import kotlinx.coroutines.CoroutineDispatcher;
@SysUISingleton
@@ -440,8 +439,6 @@
private final FalsingCollector mFalsingCollector;
private final ShadeHeadsUpTrackerImpl mShadeHeadsUpTracker = new ShadeHeadsUpTrackerImpl();
private final ShadeFoldAnimator mShadeFoldAnimator = new ShadeFoldAnimatorImpl();
- private final ShadeNotificationPresenterImpl mShadeNotificationPresenter =
- new ShadeNotificationPresenterImpl();
private boolean mShowIconsWhenExpanded;
private int mIndicationBottomPadding;
@@ -3323,23 +3320,6 @@
).printTableData(ipw);
}
- private final class ShadeNotificationPresenterImpl implements ShadeNotificationPresenter{
- @Override
- public RemoteInputController.Delegate createRemoteInputDelegate() {
- return mNotificationStackScrollLayoutController.createDelegate();
- }
-
- @Override
- public boolean hasPulsingNotifications() {
- return mNotificationListContainer.hasPulsingNotifications();
- }
- }
-
- @Override
- public ShadeNotificationPresenter getShadeNotificationPresenter() {
- return mShadeNotificationPresenter;
- }
-
@Override
public void initDependencies(
CentralSurfaces centralSurfaces,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
index 8d5c30b..2532bad 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
@@ -18,6 +18,7 @@
import android.view.ViewPropertyAnimator
import com.android.systemui.statusbar.GestureRecorder
import com.android.systemui.statusbar.NotificationShelfController
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
@@ -63,6 +64,9 @@
/** Animates the view from its current alpha to zero then runs the runnable. */
fun fadeOut(startDelayMs: Long, durationMs: Long, endAction: Runnable): ViewPropertyAnimator
+ /** Returns the NSSL controller. */
+ val notificationStackScrollLayoutController: NotificationStackScrollLayoutController
+
/** Set whether the bouncer is showing. */
fun setBouncerShowing(bouncerShowing: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index 9aa5eb0..d5b5c87 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -19,9 +19,7 @@
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.keyguard.shared.model.WakefulnessModel
-import com.android.systemui.statusbar.RemoteInputController
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
import com.android.systemui.statusbar.phone.KeyguardStatusBarView
import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController
@@ -141,9 +139,6 @@
/** Returns the StatusBarState. */
val barState: Int
- /** Returns the NSSL controller. */
- val notificationStackScrollLayoutController: NotificationStackScrollLayoutController
-
/** Sets the amount of progress in the status bar launch animation. */
fun applyLaunchAnimationProgress(linearProgress: Float)
@@ -261,9 +256,6 @@
/** Returns the ShadeFoldAnimator. */
val shadeFoldAnimator: ShadeFoldAnimator
- /** Returns the ShadeNotificationPresenter. */
- val shadeNotificationPresenter: ShadeNotificationPresenter
-
companion object {
/**
* Returns a multiplicative factor to use when determining the falsing threshold for touches
@@ -325,16 +317,7 @@
fun cancelFoldToAodAnimation()
/** Returns the main view of the shade. */
- val view: ViewGroup
-}
-
-/** Handles the shade's interactions with StatusBarNotificationPresenter. */
-interface ShadeNotificationPresenter {
- /** Returns a new delegate for some view controller pieces of the remote input process. */
- fun createRemoteInputDelegate(): RemoteInputController.Delegate
-
- /** Returns whether the screen has temporarily woken up to display notifications. */
- fun hasPulsingNotifications(): Boolean
+ val view: ViewGroup?
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
new file mode 100644
index 0000000..287ac52
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.view.MotionEvent
+import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
+import java.util.function.Consumer
+import javax.inject.Inject
+
+/** Empty implementation of ShadeViewController for variants with no shade. */
+class ShadeViewControllerEmptyImpl @Inject constructor() : ShadeViewController {
+ override fun expand(animate: Boolean) {}
+ override fun expandToQs() {}
+ override fun expandToNotifications() {}
+ override val isExpandingOrCollapsing: Boolean = false
+ override val isExpanded: Boolean = false
+ override val isPanelExpanded: Boolean = false
+ override val isShadeFullyExpanded: Boolean = false
+ override fun collapse(delayed: Boolean, speedUpFactor: Float) {}
+ override fun collapse(animate: Boolean, delayed: Boolean, speedUpFactor: Float) {}
+ override fun collapseWithDuration(animationDuration: Int) {}
+ override fun instantCollapse() {}
+ override fun animateCollapseQs(fullyCollapse: Boolean) {}
+ override fun canBeCollapsed(): Boolean = false
+ override val isCollapsing: Boolean = false
+ override val isFullyCollapsed: Boolean = false
+ override val isTracking: Boolean = false
+ override val isViewEnabled: Boolean = false
+ override fun setOpenCloseListener(openCloseListener: OpenCloseListener) {}
+ override fun shouldHideStatusBarIconsWhenExpanded() = false
+ override fun blockExpansionForCurrentTouch() {}
+ override fun setTrackingStartedListener(trackingStartedListener: TrackingStartedListener) {}
+ override fun disableHeader(state1: Int, state2: Int, animated: Boolean) {}
+ override fun startExpandLatencyTracking() {}
+ override fun startBouncerPreHideAnimation() {}
+ override fun dozeTimeTick() {}
+ override fun resetViews(animate: Boolean) {}
+ override val barState: Int = 0
+ override fun applyLaunchAnimationProgress(linearProgress: Float) {}
+ override fun closeUserSwitcherIfOpen(): Boolean {
+ return false
+ }
+ override fun onBackPressed() {}
+ override fun setIsLaunchAnimationRunning(running: Boolean) {}
+ override fun setAlpha(alpha: Int, animate: Boolean) {}
+ override fun setAlphaChangeAnimationEndAction(r: Runnable) {}
+ override fun setPulsing(pulsing: Boolean) {}
+ override fun setQsScrimEnabled(qsScrimEnabled: Boolean) {}
+ override fun setAmbientIndicationTop(ambientIndicationTop: Int, ambientTextVisible: Boolean) {}
+ override fun updateSystemUiStateFlags() {}
+ override fun updateTouchableRegion() {}
+ override fun addOnGlobalLayoutListener(listener: ViewTreeObserver.OnGlobalLayoutListener) {}
+ override fun removeOnGlobalLayoutListener(listener: ViewTreeObserver.OnGlobalLayoutListener) {}
+ override fun postToView(action: Runnable): Boolean {
+ return false
+ }
+ override fun transitionToExpandedShade(delay: Long) {}
+ override val isUnlockHintRunning: Boolean = false
+
+ override fun resetViewGroupFade() {}
+ override fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int) {}
+ override fun setOverStretchAmount(amount: Float) {}
+ override fun setKeyguardStatusBarAlpha(alpha: Float) {}
+ override fun showAodUi() {}
+ override fun isFullyExpanded(): Boolean {
+ return false
+ }
+ override fun handleExternalTouch(event: MotionEvent): Boolean {
+ return false
+ }
+ override fun startTrackingExpansionFromStatusBar() {}
+ override val shadeHeadsUpTracker = ShadeHeadsUpTrackerEmptyImpl()
+ override val shadeFoldAnimator = ShadeFoldAnimatorEmptyImpl()
+}
+
+class ShadeHeadsUpTrackerEmptyImpl : ShadeHeadsUpTracker {
+ override fun addTrackingHeadsUpListener(listener: Consumer<ExpandableNotificationRow>) {}
+ override fun removeTrackingHeadsUpListener(listener: Consumer<ExpandableNotificationRow>) {}
+ override fun setHeadsUpAppearanceController(
+ headsUpAppearanceController: HeadsUpAppearanceController?
+ ) {}
+ override val trackedHeadsUpNotification: ExpandableNotificationRow? = null
+}
+
+class ShadeFoldAnimatorEmptyImpl : ShadeFoldAnimator {
+ override fun prepareFoldToAodAnimation() {}
+ override fun startFoldToAodAnimation(
+ startAction: Runnable,
+ endAction: Runnable,
+ cancelAction: Runnable,
+ ) {}
+ override fun cancelFoldToAodAnimation() {}
+ override val view: ViewGroup? = null
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java
index b2a3780..867e08b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java
@@ -18,6 +18,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import dagger.Binds;
import dagger.Module;
@@ -58,9 +59,13 @@
@ElementsIntoSet
@Named(NOTIF_REMOTEVIEWS_FACTORIES)
static Set<NotifRemoteViewsFactory> provideNotifRemoteViewsFactories(
- FeatureFlags featureFlags
+ FeatureFlags featureFlags,
+ PrecomputedTextViewFactory precomputedTextViewFactory
) {
final Set<NotifRemoteViewsFactory> replacementFactories = new HashSet<>();
+ if (featureFlags.isEnabled(Flags.PRECOMPUTED_TEXT)) {
+ replacementFactories.add(precomputedTextViewFactory);
+ }
return replacementFactories;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt
new file mode 100644
index 0000000..b002330
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PrecomputedTextViewFactory.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.statusbar.notification.row
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.TextView
+import com.android.internal.widget.ImageFloatingTextView
+import javax.inject.Inject
+
+class PrecomputedTextViewFactory @Inject constructor() : NotifRemoteViewsFactory {
+ override fun instantiate(
+ parent: View?,
+ name: String,
+ context: Context,
+ attrs: AttributeSet
+ ): View? {
+ return when (name) {
+ TextView::class.java.name,
+ TextView::class.java.simpleName -> PrecomputedTextView(context, attrs)
+ ImageFloatingTextView::class.java.name ->
+ PrecomputedImageFloatingTextView(context, attrs)
+ else -> null
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 2d8f371..1f9c9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -160,6 +160,7 @@
private KeyguardViewController mKeyguardViewController;
private DozeScrimController mDozeScrimController;
private KeyguardViewMediator mKeyguardViewMediator;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private PendingAuthenticated mPendingAuthenticated = null;
private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock;
@@ -280,7 +281,8 @@
LatencyTracker latencyTracker,
ScreenOffAnimationController screenOffAnimationController,
VibratorHelper vibrator,
- SystemClock systemClock
+ SystemClock systemClock,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager
) {
mPowerManager = powerManager;
mUpdateMonitor = keyguardUpdateMonitor;
@@ -308,6 +310,7 @@
mVibratorHelper = vibrator;
mLogger = biometricUnlockLogger;
mSystemClock = systemClock;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -449,8 +452,19 @@
// During wake and unlock, we need to draw black before waking up to avoid abrupt
// brightness changes due to display state transitions.
Runnable wakeUp = ()-> {
- if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
+ // Check to see if we are still locked when we are waking and unlocking from dream.
+ // This runnable should be executed after unlock. If that's true, we could be not
+ // dreaming, but still locked. In this case, we should attempt to authenticate instead
+ // of waking up.
+ if (mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM
+ && !mKeyguardStateController.isUnlocked()
+ && !mUpdateMonitor.isDreaming()) {
+ // Post wakeUp runnable is called from a callback in keyguard.
+ mHandler.post(() -> mKeyguardViewController.notifyKeyguardAuthenticated(
+ false /* primaryAuth */));
+ } else if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
mLogger.i("bio wakelock: Authenticated, waking up...");
+
mPowerManager.wakeUp(
mSystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_BIOMETRIC,
@@ -462,7 +476,7 @@
Trace.endSection();
};
- if (mMode != MODE_NONE) {
+ if (mMode != MODE_NONE && mMode != MODE_WAKE_AND_UNLOCK_FROM_DREAM) {
wakeUp.run();
}
switch (mMode) {
@@ -484,6 +498,10 @@
Trace.endSection();
break;
case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
+ // In the case of waking and unlocking from dream, waking up is delayed until after
+ // unlock is complete to avoid conflicts during each sequence's transitions.
+ mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(wakeUp);
+ // Execution falls through here to proceed unlocking.
case MODE_WAKE_AND_UNLOCK_PULSING:
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index f0fc143..862f169 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -30,6 +30,7 @@
import com.android.systemui.flags.Flags
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
+import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
@@ -51,6 +52,7 @@
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val centralSurfaces: CentralSurfaces,
private val shadeController: ShadeController,
+ private val shadeViewController: ShadeViewController,
private val shadeLogger: ShadeLogger,
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
@@ -165,20 +167,20 @@
if (event.action == MotionEvent.ACTION_DOWN) {
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
- if (!centralSurfaces.shadeViewController.isViewEnabled) {
+ if (!shadeViewController.isViewEnabled) {
shadeLogger.logMotionEvent(event,
"onTouchForwardedFromStatusBar: panel view disabled")
return true
}
- if (centralSurfaces.shadeViewController.isFullyCollapsed &&
+ if (shadeViewController.isFullyCollapsed &&
event.y < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
shadeLogger.logMotionEvent(event, "top edge touch ignored")
return true
}
- centralSurfaces.shadeViewController.startTrackingExpansionFromStatusBar()
+ shadeViewController.startTrackingExpansionFromStatusBar()
}
- return centralSurfaces.shadeViewController.handleExternalTouch(event)
+ return shadeViewController.handleExternalTouch(event)
}
}
@@ -222,6 +224,7 @@
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val shadeController: ShadeController,
+ private val shadeViewController: ShadeViewController,
private val shadeLogger: ShadeLogger,
private val viewUtil: ViewUtil,
private val configurationController: ConfigurationController,
@@ -241,6 +244,7 @@
progressProvider.getOrNull(),
centralSurfaces,
shadeController,
+ shadeViewController,
shadeLogger,
statusBarMoveFromCenterAnimationController,
userChipViewModel,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
index 481cf3c..9a295e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
@@ -21,6 +21,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.window.StatusBarWindowController;
@@ -35,6 +36,7 @@
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final StatusBarWindowController mStatusBarWindowController;
private final ShadeViewController mShadeViewController;
+ private final NotificationStackScrollLayoutController mNsslController;
private final KeyguardBypassController mKeyguardBypassController;
private final HeadsUpManagerPhone mHeadsUpManager;
private final StatusBarStateController mStatusBarStateController;
@@ -45,14 +47,15 @@
NotificationShadeWindowController notificationShadeWindowController,
StatusBarWindowController statusBarWindowController,
ShadeViewController shadeViewController,
+ NotificationStackScrollLayoutController nsslController,
KeyguardBypassController keyguardBypassController,
HeadsUpManagerPhone headsUpManager,
StatusBarStateController statusBarStateController,
NotificationRemoteInputManager notificationRemoteInputManager) {
-
mNotificationShadeWindowController = notificationShadeWindowController;
mStatusBarWindowController = statusBarWindowController;
mShadeViewController = shadeViewController;
+ mNsslController = nsslController;
mKeyguardBypassController = keyguardBypassController;
mHeadsUpManager = headsUpManager;
mStatusBarStateController = statusBarStateController;
@@ -85,8 +88,7 @@
//animation
// is finished.
mHeadsUpManager.setHeadsUpGoingAway(true);
- mShadeViewController.getNotificationStackScrollLayoutController()
- .runAfterAnimationFinished(() -> {
+ mNsslController.runAfterAnimationFinished(() -> {
if (!mHeadsUpManager.hasPinnedHeadsUp()) {
mNotificationShadeWindowController.setHeadsUpShowing(false);
mHeadsUpManager.setHeadsUpGoingAway(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 35285b2..e63fecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -28,7 +28,6 @@
import android.util.Log;
import android.util.Slog;
import android.view.View;
-import android.view.accessibility.AccessibilityManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.InitController;
@@ -50,7 +49,6 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.domain.interactor.NotificationsInteractor;
@@ -59,7 +57,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
-import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
@@ -78,21 +75,18 @@
private final NotifShadeEventSource mNotifShadeEventSource;
private final NotificationMediaManager mMediaManager;
private final NotificationGutsManager mGutsManager;
-
private final ShadeViewController mNotificationPanel;
private final HeadsUpManagerPhone mHeadsUpManager;
private final AboveShelfObserver mAboveShelfObserver;
private final DozeScrimController mDozeScrimController;
private final CentralSurfaces mCentralSurfaces;
private final NotificationsInteractor mNotificationsInteractor;
+ private final NotificationStackScrollLayoutController mNsslController;
private final LockscreenShadeTransitionController mShadeTransitionController;
private final PowerInteractor mPowerInteractor;
private final CommandQueue mCommandQueue;
-
- private final AccessibilityManager mAccessibilityManager;
private final KeyguardManager mKeyguardManager;
private final NotificationShadeWindowController mNotificationShadeWindowController;
- private final NotifPipelineFlags mNotifPipelineFlags;
private final IStatusBarService mBarService;
private final DynamicPrivacyController mDynamicPrivacyController;
private final NotificationListContainer mNotifListContainer;
@@ -123,11 +117,9 @@
NotifShadeEventSource notifShadeEventSource,
NotificationMediaManager notificationMediaManager,
NotificationGutsManager notificationGutsManager,
- LockscreenGestureLogger lockscreenGestureLogger,
InitController initController,
NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationRemoteInputManager remoteInputManager,
- NotifPipelineFlags notifPipelineFlags,
NotificationRemoteInputManager.Callback remoteInputManagerCallback,
NotificationListContainer notificationListContainer) {
mActivityStarter = activityStarter;
@@ -139,6 +131,7 @@
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mCentralSurfaces = centralSurfaces;
mNotificationsInteractor = notificationsInteractor;
+ mNsslController = stackScrollerController;
mShadeTransitionController = shadeTransitionController;
mPowerInteractor = powerInteractor;
mCommandQueue = commandQueue;
@@ -149,10 +142,8 @@
mGutsManager = notificationGutsManager;
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
mNotificationShadeWindowController = notificationShadeWindowController;
- mNotifPipelineFlags = notifPipelineFlags;
mAboveShelfObserver.setListener(statusBarWindow.findViewById(
R.id.notification_container_parent));
- mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mDozeScrimController = dozeScrimController;
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mBarService = IStatusBarService.Stub.asInterface(
@@ -170,7 +161,7 @@
}
remoteInputManager.setUpWithCallback(
remoteInputManagerCallback,
- mNotificationPanel.getShadeNotificationPresenter().createRemoteInputDelegate());
+ mNsslController.createDelegate());
initController.addPostInitTask(() -> {
mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
@@ -202,7 +193,7 @@
}
private void maybeEndAmbientPulse() {
- if (mNotificationPanel.getShadeNotificationPresenter().hasPulsingNotifications()
+ if (mNsslController.getNotificationListContainer().hasPulsingNotifications()
&& !mHeadsUpManager.hasNotifications()) {
// We were showing a pulse for a notification, but no notifications are pulsing anymore.
// Finish the pulse.
@@ -272,22 +263,6 @@
}
};
- private final CheckSaveListener mCheckSaveListener = new CheckSaveListener() {
- @Override
- public void checkSave(Runnable saveImportance, StatusBarNotification sbn) {
- // If the user has security enabled, show challenge if the setting is changed.
- if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
- && mKeyguardManager.isKeyguardLocked()) {
- onLockedNotificationImportanceChange(() -> {
- saveImportance.run();
- return true;
- });
- } else {
- saveImportance.run();
- }
- }
- };
-
private final OnSettingsClickListener mOnSettingsClickListener = new OnSettingsClickListener() {
@Override
public void onSettingsClick(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
index eed7950..cbe4020 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
@@ -94,7 +94,7 @@
wakefulnessLifecycle.addObserver(this)
// TODO(b/254878364): remove this call to NPVC.getView()
- getShadeFoldAnimator().view.repeatWhenAttached {
+ getShadeFoldAnimator().view?.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) }
}
}
@@ -161,10 +161,9 @@
// but we should wait for the initial animation preparations to be drawn
// (setting initial alpha/translation)
// TODO(b/254878364): remove this call to NPVC.getView()
- OneShotPreDrawListener.add(
- getShadeFoldAnimator().view,
- onReady
- )
+ getShadeFoldAnimator().view?.let {
+ OneShotPreDrawListener.add(it, onReady)
+ }
} else {
// No animation, call ready callback immediately
onReady.run()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index da9ceb4..212dad7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -8,6 +8,7 @@
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.children
import junit.framework.Assert.assertEquals
@@ -19,7 +20,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import com.android.app.animation.Interpolators
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -178,7 +178,7 @@
}
@Test
- fun animatesRootAndChildren() {
+ fun animatesRootAndChildren_withoutExcludedViews() {
setUpRootWithChildren()
val success = ViewHierarchyAnimator.animate(rootView)
@@ -208,6 +208,40 @@
}
@Test
+ fun animatesRootAndChildren_withExcludedViews() {
+ setUpRootWithChildren()
+
+ val success = ViewHierarchyAnimator.animate(
+ rootView,
+ excludedViews = setOf(rootView.getChildAt(0))
+ )
+ // Change all bounds.
+ rootView.measure(
+ View.MeasureSpec.makeMeasureSpec(180, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
+ )
+ rootView.layout(10 /* l */, 20 /* t */, 200 /* r */, 120 /* b */)
+
+ assertTrue(success)
+ assertNotNull(rootView.getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+ assertNotNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
+ // The initial values for the affected views should be those of the previous layout, while
+ // the excluded view should be at the final values from the beginning.
+ checkBounds(rootView, l = 0, t = 0, r = 200, b = 100)
+ checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 90, b = 100)
+ checkBounds(rootView.getChildAt(1), l = 100, t = 0, r = 200, b = 100)
+ endAnimation(rootView)
+ assertNull(rootView.getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
+ // The end values should be those of the latest layout.
+ checkBounds(rootView, l = 10, t = 20, r = 200, b = 120)
+ checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 90, b = 100)
+ checkBounds(rootView.getChildAt(1), l = 90, t = 0, r = 180, b = 100)
+ }
+
+ @Test
fun animatesInvisibleViews() {
rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */)
rootView.visibility = View.INVISIBLE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index b4b3073..9a90a5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -216,9 +216,6 @@
@Mock private lateinit var recCardTitle: TextView
@Mock private lateinit var coverItem: ImageView
@Mock private lateinit var matrix: Matrix
- private lateinit var coverItem1: ImageView
- private lateinit var coverItem2: ImageView
- private lateinit var coverItem3: ImageView
private lateinit var recTitle1: TextView
private lateinit var recTitle2: TextView
private lateinit var recTitle3: TextView
@@ -233,7 +230,6 @@
FakeFeatureFlags().apply {
this.set(Flags.UMO_SURFACE_RIPPLE, false)
this.set(Flags.UMO_TURBULENCE_NOISE, false)
- this.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, false)
}
@Mock private lateinit var globalSettings: GlobalSettings
@@ -467,21 +463,25 @@
recSubtitle3 = TextView(context)
whenever(recommendationViewHolder.recommendations).thenReturn(view)
- whenever(recommendationViewHolder.cardIcon).thenReturn(appIcon)
-
- // Add a recommendation item
- coverItem1 = ImageView(context).also { it.setId(R.id.media_cover1) }
- coverItem2 = ImageView(context).also { it.setId(R.id.media_cover2) }
- coverItem3 = ImageView(context).also { it.setId(R.id.media_cover3) }
-
+ whenever(recommendationViewHolder.mediaAppIcons)
+ .thenReturn(listOf(recAppIconItem, recAppIconItem, recAppIconItem))
+ whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
whenever(recommendationViewHolder.mediaCoverItems)
- .thenReturn(listOf(coverItem1, coverItem2, coverItem3))
+ .thenReturn(listOf(coverItem, coverItem, coverItem))
whenever(recommendationViewHolder.mediaCoverContainers)
.thenReturn(listOf(coverContainer1, coverContainer2, coverContainer3))
whenever(recommendationViewHolder.mediaTitles)
.thenReturn(listOf(recTitle1, recTitle2, recTitle3))
whenever(recommendationViewHolder.mediaSubtitles)
.thenReturn(listOf(recSubtitle1, recSubtitle2, recSubtitle3))
+ whenever(recommendationViewHolder.mediaProgressBars)
+ .thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
+ whenever(coverItem.imageMatrix).thenReturn(matrix)
+
+ // set ids for recommendation containers
+ whenever(coverContainer1.id).thenReturn(1)
+ whenever(coverContainer2.id).thenReturn(2)
+ whenever(coverContainer3.id).thenReturn(3)
whenever(recommendationViewHolder.gutsViewHolder).thenReturn(gutsViewHolder)
@@ -1561,7 +1561,8 @@
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
- assertThat(description).contains(REC_APP_NAME)
+ assertThat(description)
+ .isEqualTo(context.getString(R.string.controls_media_smartspace_rec_header))
}
@Test
@@ -1585,7 +1586,8 @@
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
- assertThat(description).contains(REC_APP_NAME)
+ assertThat(description)
+ .isEqualTo(context.getString(R.string.controls_media_smartspace_rec_header))
}
@Test
@@ -2151,7 +2153,6 @@
@Test
fun bindRecommendation_setAfterExecutors() {
- setupUpdatedRecommendationViewHolder()
val albumArt = getColorIcon(Color.RED)
val data =
smartspaceData.copy(
@@ -2189,7 +2190,6 @@
@Test
fun bindRecommendationWithProgressBars() {
useRealConstraintSets()
- setupUpdatedRecommendationViewHolder()
val albumArt = getColorIcon(Color.RED)
val bundle =
Bundle().apply {
@@ -2236,7 +2236,6 @@
@Test
fun bindRecommendation_carouselNotFitThreeRecs_OrientationPortrait() {
useRealConstraintSets()
- setupUpdatedRecommendationViewHolder()
val albumArt = getColorIcon(Color.RED)
val data =
smartspaceData.copy(
@@ -2290,7 +2289,6 @@
@Test
fun bindRecommendation_carouselNotFitThreeRecs_OrientationLandscape() {
useRealConstraintSets()
- setupUpdatedRecommendationViewHolder()
val albumArt = getColorIcon(Color.RED)
val data =
smartspaceData.copy(
@@ -2505,27 +2503,6 @@
verify(activityStarter).postStartActivityDismissingKeyguard(eq(pendingIntent))
}
- private fun setupUpdatedRecommendationViewHolder() {
- fakeFeatureFlag.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, true)
- whenever(recommendationViewHolder.mediaAppIcons)
- .thenReturn(listOf(recAppIconItem, recAppIconItem, recAppIconItem))
- whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
- whenever(recommendationViewHolder.mediaCoverContainers)
- .thenReturn(listOf(coverContainer1, coverContainer2, coverContainer3))
- whenever(recommendationViewHolder.mediaCoverItems)
- .thenReturn(listOf(coverItem, coverItem, coverItem))
- whenever(recommendationViewHolder.mediaProgressBars)
- .thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
- whenever(recommendationViewHolder.mediaSubtitles)
- .thenReturn(listOf(recSubtitle1, recSubtitle2, recSubtitle3))
- whenever(coverItem.imageMatrix).thenReturn(matrix)
-
- // set ids for recommendation containers
- whenever(coverContainer1.id).thenReturn(1)
- whenever(coverContainer2.id).thenReturn(2)
- whenever(coverContainer3.id).thenReturn(3)
- }
-
private fun getColorIcon(color: Int): Icon {
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmp)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
index c9956f3..ba97df9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
@@ -201,8 +201,8 @@
whenever(mockCopiedState.widgetStates)
.thenReturn(
mutableMapOf(
- R.id.media_title1 to mediaTitleWidgetState,
- R.id.media_subtitle1 to mediaSubTitleWidgetState,
+ R.id.media_title to mediaTitleWidgetState,
+ R.id.media_subtitle to mediaSubTitleWidgetState,
R.id.media_cover1_container to mediaContainerWidgetState
)
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index a0d8f98..9d9d0c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -154,6 +154,21 @@
verify(qsPanel).setCanCollapse(true)
}
+ @Test
+ fun multipleListeningOnlyCallsBrightnessControllerOnce() {
+ controller.setListening(true, true)
+ controller.setListening(true, false)
+ controller.setListening(true, true)
+
+ verify(brightnessController).registerCallbacks()
+
+ controller.setListening(false, true)
+ controller.setListening(false, false)
+ controller.setListening(false, true)
+
+ verify(brightnessController).unregisterCallbacks()
+ }
+
private fun setShouldUseSplitShade(shouldUse: Boolean) {
testableResources.addOverride(R.bool.config_use_split_notification_shade, shouldUse)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt
new file mode 100644
index 0000000..2b78405
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessControllerTest.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.settings.brightness
+
+import android.hardware.display.DisplayManager
+import android.os.Handler
+import android.service.vr.IVrManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.DisplayTracker
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class BrightnessControllerTest : SysuiTestCase() {
+
+ private val executor = FakeExecutor(FakeSystemClock())
+ private val secureSettings = FakeSettings()
+ @Mock private lateinit var toggleSlider: ToggleSlider
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var displayTracker: DisplayTracker
+ @Mock private lateinit var displayManager: DisplayManager
+ @Mock private lateinit var iVrManager: IVrManager
+
+ private lateinit var testableLooper: TestableLooper
+
+ private lateinit var underTest: BrightnessController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+
+ underTest =
+ BrightnessController(
+ context,
+ toggleSlider,
+ userTracker,
+ displayTracker,
+ displayManager,
+ secureSettings,
+ iVrManager,
+ executor,
+ mock(),
+ Handler(testableLooper.looper)
+ )
+ }
+
+ @Test
+ fun registerCallbacksMultipleTimes_onlyOneRegistration() {
+ val repeats = 100
+ repeat(repeats) { underTest.registerCallbacks() }
+ val messagesProcessed = testableLooper.processMessagesNonBlocking(repeats)
+
+ verify(displayTracker).addBrightnessChangeCallback(any(), any())
+ verify(iVrManager).registerListener(any())
+
+ assertThat(messagesProcessed).isEqualTo(1)
+ }
+
+ @Test
+ fun unregisterCallbacksMultipleTimes_onlyOneUnregistration() {
+ val repeats = 100
+ underTest.registerCallbacks()
+ testableLooper.processAllMessages()
+
+ repeat(repeats) { underTest.unregisterCallbacks() }
+ val messagesProcessed = testableLooper.processMessagesNonBlocking(repeats)
+
+ verify(displayTracker).removeCallback(any())
+ verify(iVrManager).unregisterListener(any())
+
+ assertThat(messagesProcessed).isEqualTo(1)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
index 5c35913..ed1397f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
@@ -18,7 +18,6 @@
import android.content.Intent
import android.graphics.Rect
-import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
@@ -29,8 +28,6 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.activity.SingleActivityFactory
-import com.android.systemui.settings.FakeDisplayTracker
-import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.FakeExecutor
@@ -53,28 +50,24 @@
@TestableLooper.RunWithLooper
class BrightnessDialogTest : SysuiTestCase() {
- @Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var brightnessSliderControllerFactory: BrightnessSliderController.Factory
- @Mock private lateinit var backgroundHandler: Handler
@Mock private lateinit var brightnessSliderController: BrightnessSliderController
+ @Mock private lateinit var brightnessControllerFactory: BrightnessController.Factory
+ @Mock private lateinit var brightnessController: BrightnessController
@Mock private lateinit var accessibilityMgr: AccessibilityManagerWrapper
private val clock = FakeSystemClock()
private val mainExecutor = FakeExecutor(clock)
- private var displayTracker = FakeDisplayTracker(mContext)
-
@Rule
@JvmField
var activityRule =
ActivityTestRule(
/* activityFactory= */ SingleActivityFactory {
TestDialog(
- userTracker,
- displayTracker,
brightnessSliderControllerFactory,
+ brightnessControllerFactory,
mainExecutor,
- backgroundHandler,
accessibilityMgr
)
},
@@ -88,6 +81,7 @@
`when`(brightnessSliderControllerFactory.create(any(), any()))
.thenReturn(brightnessSliderController)
`when`(brightnessSliderController.rootView).thenReturn(View(context))
+ `when`(brightnessControllerFactory.create(any())).thenReturn(brightnessController)
}
@After
@@ -178,19 +172,15 @@
}
class TestDialog(
- userTracker: UserTracker,
- displayTracker: FakeDisplayTracker,
brightnessSliderControllerFactory: BrightnessSliderController.Factory,
+ brightnessControllerFactory: BrightnessController.Factory,
mainExecutor: DelayableExecutor,
- backgroundHandler: Handler,
accessibilityMgr: AccessibilityManagerWrapper
) :
BrightnessDialog(
- userTracker,
- displayTracker,
brightnessSliderControllerFactory,
+ brightnessControllerFactory,
mainExecutor,
- backgroundHandler,
accessibilityMgr
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 89f8bdb..479803e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -142,7 +142,8 @@
mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
mAuthController, mStatusBarStateController,
mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper,
- mSystemClock
+ mSystemClock,
+ mStatusBarKeyguardViewManager
);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.addListener(mBiometricUnlockEventsListener);
@@ -464,6 +465,69 @@
}
@Test
+ public void onSideFingerprintSuccess_dreaming_unlockThenWake() {
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
+ final ArgumentCaptor<Runnable> afterKeyguardGoneRunnableCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+ givenDreamingLocked();
+ mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);
+
+ // Make sure the BiometricUnlockController has registered a callback for when the keyguard
+ // is gone
+ verify(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(
+ afterKeyguardGoneRunnableCaptor.capture());
+ // Ensure that the power hasn't been told to wake up yet.
+ verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
+ // Check that the keyguard has been told to unlock.
+ verify(mKeyguardViewMediator).onWakeAndUnlocking();
+
+ // Simulate the keyguard disappearing.
+ afterKeyguardGoneRunnableCaptor.getValue().run();
+ // Verify that the power manager has been told to wake up now.
+ verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
+ }
+
+ @Test
+ public void onSideFingerprintSuccess_dreaming_unlockIfStillLockedNotDreaming() {
+ when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
+ when(mWakefulnessLifecycle.getLastWakeReason())
+ .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
+ final ArgumentCaptor<Runnable> afterKeyguardGoneRunnableCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+ givenDreamingLocked();
+ mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);
+
+ // Make sure the BiometricUnlockController has registered a callback for when the keyguard
+ // is gone
+ verify(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(
+ afterKeyguardGoneRunnableCaptor.capture());
+ // Ensure that the power hasn't been told to wake up yet.
+ verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
+ // Check that the keyguard has been told to unlock.
+ verify(mKeyguardViewMediator).onWakeAndUnlocking();
+
+ when(mUpdateMonitor.isDreaming()).thenReturn(false);
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ // Simulate the keyguard disappearing.
+ afterKeyguardGoneRunnableCaptor.getValue().run();
+
+ final ArgumentCaptor<Runnable> dismissKeyguardRunnableCaptor =
+ ArgumentCaptor.forClass(Runnable.class);
+ verify(mHandler).post(dismissKeyguardRunnableCaptor.capture());
+
+ // Verify that the power manager was not told to wake up.
+ verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
+
+ dismissKeyguardRunnableCaptor.getValue().run();
+ // Verify that the keyguard controller is told to unlock.
+ verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+ }
+
+
+ @Test
public void onSideFingerprintSuccess_oldPowerButtonPress_playHaptic() {
// GIVEN side fingerprint enrolled, last wake reason was power button
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
@@ -537,6 +601,11 @@
verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
}
+ private void givenDreamingLocked() {
+ when(mUpdateMonitor.isDreaming()).thenReturn(true);
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ }
+
private void givenFingerprintModeUnlockCollapsing() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 2d96e59..c8ec1bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -204,6 +204,7 @@
userChipViewModel,
centralSurfacesImpl,
shadeControllerImpl,
+ shadeViewController,
shadeLogger,
viewUtil,
configurationController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 5bd6ff4..cd8aaa2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -42,7 +42,6 @@
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.QuickSettingsController;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.ShadeNotificationPresenter;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -52,7 +51,6 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
@@ -86,14 +84,11 @@
mock(NotificationsInteractor.class);
private final KeyguardStateController mKeyguardStateController =
mock(KeyguardStateController.class);
- private final NotifPipelineFlags mNotifPipelineFlags = mock(NotifPipelineFlags.class);
private final InitController mInitController = new InitController();
@Before
public void setup() {
mMetricsLogger = new FakeMetricsLogger();
- LockscreenGestureLogger lockscreenGestureLogger = new LockscreenGestureLogger(
- mMetricsLogger);
mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext));
mDependency.injectTestDependency(StatusBarStateController.class,
mock(SysuiStatusBarStateController.class));
@@ -111,8 +106,6 @@
when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources());
ShadeViewController shadeViewController = mock(ShadeViewController.class);
- when(shadeViewController.getShadeNotificationPresenter())
- .thenReturn(mock(ShadeNotificationPresenter.class));
mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(
mContext,
shadeViewController,
@@ -135,11 +128,9 @@
mock(NotifShadeEventSource.class),
mock(NotificationMediaManager.class),
mock(NotificationGutsManager.class),
- lockscreenGestureLogger,
mInitController,
mNotificationInterruptStateProvider,
mock(NotificationRemoteInputManager.class),
- mNotifPipelineFlags,
mock(NotificationRemoteInputManager.Callback.class),
mock(NotificationListContainer.class));
mInitController.executePostInitTasks();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c1239d5..502e0ec 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -256,7 +256,7 @@
public final class ActiveServices {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
private static final String TAG_MU = TAG + POSTFIX_MU;
- private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
+ static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
private static final String TAG_SERVICE_EXECUTING = TAG + POSTFIX_SERVICE_EXECUTING;
private static final boolean DEBUG_DELAYED_SERVICE = DEBUG_SERVICE;
@@ -850,8 +850,7 @@
// Service.startForeground()), at that point we will consult the BFSL check and the timeout
// and make the necessary decisions.
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
- backgroundStartPrivileges, false /* isBindService */,
- !fgRequired /* isStartService */);
+ backgroundStartPrivileges, false /* isBindService */);
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
@@ -894,7 +893,7 @@
if (fgRequired) {
logFgsBackgroundStart(r);
- if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) {
+ if (!r.isFgsAllowedStart() && isBgFgsRestrictionEnabled(r)) {
String msg = "startForegroundService() not allowed due to "
+ "mAllowStartForeground false: service "
+ r.shortInstanceName;
@@ -1060,7 +1059,7 @@
// Use that as a shortcut if possible to avoid having to recheck all the conditions.
final boolean whileInUseAllowsUiJobScheduling =
ActivityManagerService.doesReasonCodeAllowSchedulingUserInitiatedJobs(
- r.mAllowWhileInUsePermissionInFgsReason);
+ r.getFgsAllowWIU());
r.updateAllowUiJobScheduling(whileInUseAllowsUiJobScheduling
|| mAm.canScheduleUserInitiatedJobs(callingUid, callingPid, callingPackage));
} else {
@@ -2178,12 +2177,12 @@
// on a SHORT_SERVICE FGS.
// See if the app could start an FGS or not.
- r.mAllowStartForeground = REASON_DENIED;
+ r.clearFgsAllowStart();
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */, false /* isStartService */);
- if (r.mAllowStartForeground == REASON_DENIED) {
+ false /* isBindService */);
+ if (!r.isFgsAllowedStart()) {
Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: "
+ " BFSL DENIED.");
} else {
@@ -2191,13 +2190,13 @@
Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: "
+ " BFSL Allowed: "
+ PowerExemptionManager.reasonCodeToString(
- r.mAllowStartForeground));
+ r.getFgsAllowStart()));
}
}
final boolean fgsStartAllowed =
!isBgFgsRestrictionEnabledForService
- || (r.mAllowStartForeground != REASON_DENIED);
+ || r.isFgsAllowedStart();
if (fgsStartAllowed) {
if (isNewTypeShortFgs) {
@@ -2246,7 +2245,7 @@
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */, false /* isStartService */);
+ false /* isBindService */);
final String temp = "startForegroundDelayMs:" + delayMs;
if (r.mInfoAllowStartForeground != null) {
r.mInfoAllowStartForeground += "; " + temp;
@@ -2266,20 +2265,21 @@
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
BackgroundStartPrivileges.NONE,
- false /* isBindService */, false /* isStartService */);
+ false /* isBindService */);
}
// If the foreground service is not started from TOP process, do not allow it to
// have while-in-use location/camera/microphone access.
- if (!r.mAllowWhileInUsePermissionInFgs) {
+ if (!r.isFgsAllowedWIU()) {
Slog.w(TAG,
"Foreground service started from background can not have "
+ "location/camera/microphone access: service "
+ r.shortInstanceName);
}
+ r.maybeLogFgsLogicChange();
if (!bypassBfslCheck) {
logFgsBackgroundStart(r);
- if (r.mAllowStartForeground == REASON_DENIED
+ if (!r.isFgsAllowedStart()
&& isBgFgsRestrictionEnabledForService) {
final String msg = "Service.startForeground() not allowed due to "
+ "mAllowStartForeground false: service "
@@ -2378,9 +2378,9 @@
// The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could
// be deferred, make a copy of mAllowStartForeground and
// mAllowWhileInUsePermissionInFgs.
- r.mAllowStartForegroundAtEntering = r.mAllowStartForeground;
+ r.mAllowStartForegroundAtEntering = r.getFgsAllowStart();
r.mAllowWhileInUsePermissionInFgsAtEntering =
- r.mAllowWhileInUsePermissionInFgs;
+ r.isFgsAllowedWIU();
r.mStartForegroundCount++;
r.mFgsEnterTime = SystemClock.uptimeMillis();
if (!stopProcStatsOp) {
@@ -2558,7 +2558,7 @@
policy.getForegroundServiceTypePolicyInfo(type, defaultToType);
final @ForegroundServicePolicyCheckCode int code = policy.checkForegroundServiceTypePolicy(
mAm.mContext, r.packageName, r.app.uid, r.app.getPid(),
- r.mAllowWhileInUsePermissionInFgs, policyInfo);
+ r.isFgsAllowedWIU(), policyInfo);
RuntimeException exception = null;
switch (code) {
case FGS_TYPE_POLICY_CHECK_DEPRECATED: {
@@ -3744,8 +3744,7 @@
}
}
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
- BackgroundStartPrivileges.NONE, true /* isBindService */,
- false /* isStartService */);
+ BackgroundStartPrivileges.NONE, true /* isBindService */);
if (s.app != null) {
ProcessServiceRecord servicePsr = s.app.mServices;
@@ -7443,54 +7442,80 @@
* @param callingUid caller app's uid.
* @param intent intent to start/bind service.
* @param r the service to start.
- * @param isStartService True if it's called from Context.startService().
- * False if it's called from Context.startForegroundService() or
- * Service.startForeground().
+ * @param isBindService True if it's called from bindService().
* @return true if allow, false otherwise.
*/
private void setFgsRestrictionLocked(String callingPackage,
int callingPid, int callingUid, Intent intent, ServiceRecord r, int userId,
- BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService,
- boolean isStartService) {
- // Check DeviceConfig flag.
- if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
- if (!r.mAllowWhileInUsePermissionInFgs) {
- // BGFGS start restrictions are disabled. We're allowing while-in-use permissions.
- // Note REASON_OTHER since there's no other suitable reason.
- r.mAllowWhileInUsePermissionInFgsReason = REASON_OTHER;
- }
- r.mAllowWhileInUsePermissionInFgs = true;
+ BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) {
+
+ @ReasonCode int allowWIU;
+ @ReasonCode int allowStart;
+
+ // If called from bindService(), do not update the actual fields, but instead
+ // keep it in a separate set of fields.
+ if (isBindService) {
+ allowWIU = r.mAllowWIUInBindService;
+ allowStart = r.mAllowStartInBindService;
+ } else {
+ allowWIU = r.mAllowWhileInUsePermissionInFgsReasonNoBinding;
+ allowStart = r.mAllowStartForegroundNoBinding;
}
- if (!r.mAllowWhileInUsePermissionInFgs
- || (r.mAllowStartForeground == REASON_DENIED)) {
+ // Check DeviceConfig flag.
+ if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
+ if (allowWIU == REASON_DENIED) {
+ // BGFGS start restrictions are disabled. We're allowing while-in-use permissions.
+ // Note REASON_OTHER since there's no other suitable reason.
+ allowWIU = REASON_OTHER;
+ }
+ }
+
+ if ((allowWIU == REASON_DENIED)
+ || (allowStart == REASON_DENIED)) {
@ReasonCode final int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges);
// We store them to compare the old and new while-in-use logics to each other.
// (They're not used for any other purposes.)
- if (!r.mAllowWhileInUsePermissionInFgs) {
- r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED);
- r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse;
+ if (allowWIU == REASON_DENIED) {
+ allowWIU = allowWhileInUse;
}
- if (r.mAllowStartForeground == REASON_DENIED) {
- r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked(
+ if (allowStart == REASON_DENIED) {
+ allowStart = shouldAllowFgsStartForegroundWithBindingCheckLocked(
allowWhileInUse, callingPackage, callingPid, callingUid, intent, r,
backgroundStartPrivileges, isBindService);
}
}
+
+ if (isBindService) {
+ r.mAllowWIUInBindService = allowWIU;
+ r.mAllowStartInBindService = allowStart;
+ } else {
+ r.mAllowWhileInUsePermissionInFgsReasonNoBinding = allowWIU;
+ r.mAllowStartForegroundNoBinding = allowStart;
+
+ // Also do a binding client check, unless called from bindService().
+ if (r.mAllowWIUByBindings == REASON_DENIED) {
+ r.mAllowWIUByBindings =
+ shouldAllowFgsWhileInUsePermissionByBindingsLocked(callingUid);
+ }
+ if (r.mAllowStartByBindings == REASON_DENIED) {
+ r.mAllowStartByBindings = r.mAllowWIUByBindings;
+ }
+ }
}
/**
* Reset various while-in-use and BFSL related information.
*/
void resetFgsRestrictionLocked(ServiceRecord r) {
- r.mAllowWhileInUsePermissionInFgs = false;
- r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED;
- r.mAllowStartForeground = REASON_DENIED;
+ r.clearFgsAllowWIU();
+ r.clearFgsAllowStart();
+
r.mInfoAllowStartForeground = null;
r.mInfoTempFgsAllowListReason = null;
r.mLoggedInfoAllowStartForeground = false;
- r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs);
+ r.updateAllowUiJobScheduling(r.isFgsAllowedWIU());
}
boolean canStartForegroundServiceLocked(int callingPid, int callingUid, String callingPackage) {
@@ -8062,10 +8087,10 @@
*/
if (!r.mLoggedInfoAllowStartForeground) {
final String msg = "Background started FGS: "
- + ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ")
+ + (r.isFgsAllowedStart() ? "Allowed " : "Disallowed ")
+ r.mInfoAllowStartForeground
+ (r.isShortFgs() ? " (Called on SHORT_SERVICE)" : "");
- if (r.mAllowStartForeground != REASON_DENIED) {
+ if (r.isFgsAllowedStart()) {
if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName,
mAm.mConstants.mFgsStartAllowedLogSampleRate)) {
Slog.wtfQuiet(TAG, msg);
@@ -8105,8 +8130,8 @@
allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering;
fgsStartReasonCode = r.mAllowStartForegroundAtEntering;
} else {
- allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgs;
- fgsStartReasonCode = r.mAllowStartForeground;
+ allowWhileInUsePermissionInFgs = r.isFgsAllowedWIU();
+ fgsStartReasonCode = r.getFgsAllowStart();
}
final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;
@@ -8295,8 +8320,7 @@
r.mFgsEnterTime = SystemClock.uptimeMillis();
r.foregroundServiceType = options.mForegroundServiceTypes;
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, intent, r, userId,
- BackgroundStartPrivileges.NONE, false /* isBindService */,
- false /* isStartService */);
+ BackgroundStartPrivileges.NONE, false /* isBindService */);
final ProcessServiceRecord psr = callerApp.mServices;
final boolean newService = psr.startService(r);
// updateOomAdj.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7ba720e..81858ee 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -559,6 +559,10 @@
// How long we wait for a launched process to attach to the activity manager
// before we decide it's never going to come up for real.
static final int PROC_START_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
+
+ // How long we wait for a launched process to complete its app startup before we ANR.
+ static final int BIND_APPLICATION_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
+
// How long we wait to kill an application zygote, after the last process using
// it has gone away.
static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000;
@@ -1624,6 +1628,7 @@
static final int UPDATE_CACHED_APP_HIGH_WATERMARK = 79;
static final int ADD_UID_TO_OBSERVER_MSG = 80;
static final int REMOVE_UID_FROM_OBSERVER_MSG = 81;
+ static final int BIND_APPLICATION_TIMEOUT_MSG = 82;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1976,6 +1981,16 @@
case UPDATE_CACHED_APP_HIGH_WATERMARK: {
mAppProfiler.mCachedAppsWatermarkData.updateCachedAppsSnapshot((long) msg.obj);
} break;
+ case BIND_APPLICATION_TIMEOUT_MSG: {
+ ProcessRecord app = (ProcessRecord) msg.obj;
+
+ final String anrMessage;
+ synchronized (app) {
+ anrMessage = "Process " + app + " failed to complete startup";
+ }
+
+ mAnrHelper.appNotResponding(app, TimeoutRecord.forAppStart(anrMessage));
+ } break;
}
}
}
@@ -4734,6 +4749,12 @@
app.getDisabledCompatChanges(), serializedSystemFontMap,
app.getStartElapsedTime(), app.getStartUptime());
}
+
+ Message msg = mHandler.obtainMessage(BIND_APPLICATION_TIMEOUT_MSG);
+ msg.obj = app;
+ mHandler.sendMessageDelayed(msg, BIND_APPLICATION_TIMEOUT);
+ mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+
if (profilerInfo != null) {
profilerInfo.closeFd();
profilerInfo = null;
@@ -4808,7 +4829,7 @@
}
if (app != null && app.getStartUid() == uid && app.getStartSeq() == startSeq) {
- mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+ mHandler.removeMessages(BIND_APPLICATION_TIMEOUT_MSG, app);
} else {
Slog.wtf(TAG, "Mismatched or missing ProcessRecord: " + app + ". Pid: " + pid
+ ". Uid: " + uid);
diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
index 38e7371..4f5b5e1 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
@@ -479,8 +479,8 @@
r.appInfo.uid,
r.shortInstanceName,
fgsState, // FGS State
- r.mAllowWhileInUsePermissionInFgs, // allowWhileInUsePermissionInFgs
- r.mAllowStartForeground, // fgsStartReasonCode
+ r.isFgsAllowedWIU(), // allowWhileInUsePermissionInFgs
+ r.getFgsAllowStart(), // fgsStartReasonCode
r.appInfo.targetSdkVersion,
r.mRecentCallingUid,
0, // callerTargetSdkVersion
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a682c85..459c6ff 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2222,7 +2222,7 @@
if (s.isForeground) {
final int fgsType = s.foregroundServiceType;
- if (s.mAllowWhileInUsePermissionInFgs) {
+ if (s.isFgsAllowedWIU()) {
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 50fe6d7..aabab61 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -21,9 +21,11 @@
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
import static android.os.PowerExemptionManager.REASON_DENIED;
+import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.server.am.ActiveServices.TAG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -172,11 +174,11 @@
private BackgroundStartPrivileges mBackgroundStartPrivilegesByStartMerged =
BackgroundStartPrivileges.NONE;
- // allow while-in-use permissions in foreground service or not.
+ // Reason code for allow while-in-use permissions in foreground service.
+ // If it's not DENIED, while-in-use permissions are allowed.
// while-in-use permissions in FGS started from background might be restricted.
- boolean mAllowWhileInUsePermissionInFgs;
@PowerExemptionManager.ReasonCode
- int mAllowWhileInUsePermissionInFgsReason = REASON_DENIED;
+ int mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED;
// A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state.
boolean mAllowWhileInUsePermissionInFgsAtEntering;
@@ -205,15 +207,114 @@
// allow the service becomes foreground service? Service started from background may not be
// allowed to become a foreground service.
- @PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED;
+ @PowerExemptionManager.ReasonCode
+ int mAllowStartForegroundNoBinding = REASON_DENIED;
// A copy of mAllowStartForeground's value when the service is entering FGS state.
- @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED;
+ @PowerExemptionManager.ReasonCode
+ int mAllowStartForegroundAtEntering = REASON_DENIED;
// Debug info why mAllowStartForeground is allowed or denied.
String mInfoAllowStartForeground;
// Debug info if mAllowStartForeground is allowed because of a temp-allowlist.
ActivityManagerService.FgsTempAllowListItem mInfoTempFgsAllowListReason;
// Is the same mInfoAllowStartForeground string has been logged before? Used for dedup.
boolean mLoggedInfoAllowStartForeground;
+
+ @PowerExemptionManager.ReasonCode
+ int mAllowWIUInBindService = REASON_DENIED;
+
+ @PowerExemptionManager.ReasonCode
+ int mAllowWIUByBindings = REASON_DENIED;
+
+ @PowerExemptionManager.ReasonCode
+ int mAllowStartInBindService = REASON_DENIED;
+
+ @PowerExemptionManager.ReasonCode
+ int mAllowStartByBindings = REASON_DENIED;
+
+ @PowerExemptionManager.ReasonCode
+ int getFgsAllowWIU() {
+ return mAllowWhileInUsePermissionInFgsReasonNoBinding != REASON_DENIED
+ ? mAllowWhileInUsePermissionInFgsReasonNoBinding
+ : mAllowWIUInBindService;
+ }
+
+ boolean isFgsAllowedWIU() {
+ return getFgsAllowWIU() != REASON_DENIED;
+ }
+
+ @PowerExemptionManager.ReasonCode
+ int getFgsAllowStart() {
+ return mAllowStartForegroundNoBinding != REASON_DENIED
+ ? mAllowStartForegroundNoBinding
+ : mAllowStartInBindService;
+ }
+
+ boolean isFgsAllowedStart() {
+ return getFgsAllowStart() != REASON_DENIED;
+ }
+
+ void clearFgsAllowWIU() {
+ mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED;
+ mAllowWIUInBindService = REASON_DENIED;
+ mAllowWIUByBindings = REASON_DENIED;
+ }
+
+ void clearFgsAllowStart() {
+ mAllowStartForegroundNoBinding = REASON_DENIED;
+ mAllowStartInBindService = REASON_DENIED;
+ mAllowStartByBindings = REASON_DENIED;
+ }
+
+ @PowerExemptionManager.ReasonCode
+ int reasonOr(@PowerExemptionManager.ReasonCode int first,
+ @PowerExemptionManager.ReasonCode int second) {
+ return first != REASON_DENIED ? first : second;
+ }
+
+ boolean allowedChanged(@PowerExemptionManager.ReasonCode int first,
+ @PowerExemptionManager.ReasonCode int second) {
+ return (first == REASON_DENIED) != (second == REASON_DENIED);
+ }
+
+ String changeMessage(@PowerExemptionManager.ReasonCode int first,
+ @PowerExemptionManager.ReasonCode int second) {
+ return reasonOr(first, second) == REASON_DENIED ? "DENIED"
+ : ("ALLOWED ("
+ + reasonCodeToString(first)
+ + "+"
+ + reasonCodeToString(second)
+ + ")");
+ }
+
+ void maybeLogFgsLogicChange() {
+ final int origWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding,
+ mAllowWIUInBindService);
+ final int newWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding,
+ mAllowWIUByBindings);
+ final int origStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartInBindService);
+ final int newStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartByBindings);
+
+ final boolean wiuChanged = allowedChanged(origWiu, newWiu);
+ final boolean startChanged = allowedChanged(origStart, newStart);
+
+ if (!wiuChanged && !startChanged) {
+ return;
+ }
+ final String message = "FGS logic changed:"
+ + (wiuChanged ? " [WIU changed]" : "")
+ + (startChanged ? " [BFSL changed]" : "")
+ + " OW:" // Orig-WIU
+ + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding,
+ mAllowWIUInBindService)
+ + " NW:" // New-WIU
+ + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUByBindings)
+ + " OS:" // Orig-start
+ + changeMessage(mAllowStartForegroundNoBinding, mAllowStartInBindService)
+ + " NS:" // New-start
+ + changeMessage(mAllowStartForegroundNoBinding, mAllowStartByBindings);
+ Slog.wtf(TAG_SERVICE, message);
+ }
+
// The number of times Service.startForeground() is called, after this service record is
// created. (i.e. due to "bound" or "start".) It never decreases, even when stopForeground()
// is called.
@@ -502,7 +603,7 @@
ProtoUtils.toDuration(proto, ServiceRecordProto.RESTART_TIME, restartTime, now);
proto.write(ServiceRecordProto.CREATED_FROM_FG, createdFromFg);
proto.write(ServiceRecordProto.ALLOW_WHILE_IN_USE_PERMISSION_IN_FGS,
- mAllowWhileInUsePermissionInFgs);
+ isFgsAllowedWIU());
if (startRequested || delayedStop || lastStartId != 0) {
long startToken = proto.start(ServiceRecordProto.START);
@@ -618,7 +719,13 @@
pw.println(mBackgroundStartPrivilegesByStartMerged);
}
pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason=");
- pw.println(PowerExemptionManager.reasonCodeToString(mAllowWhileInUsePermissionInFgsReason));
+ pw.println(PowerExemptionManager.reasonCodeToString(
+ mAllowWhileInUsePermissionInFgsReasonNoBinding));
+
+ pw.print(prefix); pw.print("mAllowWIUInBindService=");
+ pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUInBindService));
+ pw.print(prefix); pw.print("mAllowWIUByBindings=");
+ pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUByBindings));
pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling);
pw.print(prefix); pw.print("recentCallingPackage=");
@@ -626,7 +733,12 @@
pw.print(prefix); pw.print("recentCallingUid=");
pw.println(mRecentCallingUid);
pw.print(prefix); pw.print("allowStartForeground=");
- pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForeground));
+ pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForegroundNoBinding));
+ pw.print(prefix); pw.print("mAllowStartInBindService=");
+ pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartInBindService));
+ pw.print(prefix); pw.print("mAllowStartByBindings=");
+ pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartByBindings));
+
pw.print(prefix); pw.print("startForegroundCount=");
pw.println(mStartForegroundCount);
pw.print(prefix); pw.print("infoAllowStartForeground=");
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 0b04159..f8f0088 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -613,16 +613,26 @@
@Override
public boolean isCameraDisabled(int userId) {
- DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- if (dpm == null) {
- Slog.e(TAG, "Failed to get the device policy manager service");
+ if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
+ Slog.e(TAG, "Calling UID: " + Binder.getCallingUid()
+ + " doesn't match expected camera service UID!");
return false;
}
+ final long ident = Binder.clearCallingIdentity();
try {
- return dpm.getCameraDisabled(null, userId);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ if (dpm == null) {
+ Slog.e(TAG, "Failed to get the device policy manager service");
+ return false;
+ }
+ try {
+ return dpm.getCameraDisabled(null, userId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
};
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index ffecf2b..c5d0c17 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -141,6 +141,9 @@
private static final int MSG_STATSD_HBM_BRIGHTNESS = 13;
private static final int MSG_SWITCH_USER = 14;
private static final int MSG_BOOT_COMPLETED = 15;
+ private static final int MSG_SET_DWBC_STRONG_MODE = 16;
+ private static final int MSG_SET_DWBC_COLOR_OVERRIDE = 17;
+ private static final int MSG_SET_DWBC_LOGGING_ENABLED = 18;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -436,6 +439,7 @@
private final boolean mSkipScreenOnBrightnessRamp;
// Display white balance components.
+ // Critical methods must be called on DPC handler thread.
@Nullable
private final DisplayWhiteBalanceSettings mDisplayWhiteBalanceSettings;
@Nullable
@@ -680,9 +684,9 @@
DisplayWhiteBalanceController displayWhiteBalanceController = null;
if (mDisplayId == Display.DEFAULT_DISPLAY) {
try {
+ displayWhiteBalanceController = injector.getDisplayWhiteBalanceController(
+ mHandler, mSensorManager, resources);
displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
- displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
- mSensorManager, resources);
displayWhiteBalanceSettings.setCallbacks(this);
displayWhiteBalanceController.setCallbacks(this);
} catch (Exception e) {
@@ -1025,10 +1029,6 @@
Message msg = mHandler.obtainMessage(MSG_STOP);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setEnabled(false);
- }
-
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.stop();
}
@@ -1334,9 +1334,11 @@
mAutomaticBrightnessController.switchToInteractiveScreenBrightnessMode();
}
}
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
- }
+
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_STRONG_MODE;
+ msg.arg1 = isIdle ? 1 : 0;
+ mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@@ -1405,8 +1407,13 @@
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
}
+
+ if (mDisplayWhiteBalanceController != null) {
+ mDisplayWhiteBalanceController.setEnabled(false);
+ }
}
+ // Call from handler thread
private void updatePowerState() {
Trace.traceBegin(Trace.TRACE_TAG_POWER,
"DisplayPowerController#updatePowerState");
@@ -2058,6 +2065,32 @@
}
}
+ private void setDwbcOverride(float cct) {
+ if (mDisplayWhiteBalanceController != null) {
+ mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
+ // The ambient color temperature override is only applied when the ambient color
+ // temperature changes or is updated, so it doesn't necessarily change the screen color
+ // temperature immediately. So, let's make it!
+ // We can call this directly, since we're already on the handler thread.
+ updatePowerState();
+ }
+ }
+
+ private void setDwbcStrongMode(int arg) {
+ if (mDisplayWhiteBalanceController != null) {
+ final boolean isIdle = (arg == 1);
+ mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
+ }
+ }
+
+ private void setDwbcLoggingEnabled(int arg) {
+ if (mDisplayWhiteBalanceController != null) {
+ final boolean shouldEnable = (arg == 1);
+ mDisplayWhiteBalanceController.setLoggingEnabled(shouldEnable);
+ mDisplayWhiteBalanceSettings.setLoggingEnabled(shouldEnable);
+ }
+ }
+
@Override
public void updateBrightness() {
sendUpdatePowerState();
@@ -3331,6 +3364,19 @@
mBootCompleted = true;
updatePowerState();
break;
+
+ case MSG_SET_DWBC_STRONG_MODE:
+ setDwbcStrongMode(msg.arg1);
+ break;
+
+ case MSG_SET_DWBC_COLOR_OVERRIDE:
+ final float cct = Float.intBitsToFloat(msg.arg1);
+ setDwbcOverride(cct);
+ break;
+
+ case MSG_SET_DWBC_LOGGING_ENABLED:
+ setDwbcLoggingEnabled(msg.arg1);
+ break;
}
}
}
@@ -3398,21 +3444,18 @@
@Override
public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
- mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
- }
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
+ msg.arg1 = enabled ? 1 : 0;
+ msg.sendToTarget();
}
@Override
public void setAmbientColorTemperatureOverride(float cct) {
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
- // The ambient color temperature override is only applied when the ambient color
- // temperature changes or is updated, so it doesn't necessarily change the screen color
- // temperature immediately. So, let's make it!
- sendUpdatePowerState();
- }
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
+ msg.arg1 = Float.floatToIntBits(cct);
+ msg.sendToTarget();
}
@VisibleForTesting
@@ -3543,6 +3586,12 @@
displayUniqueId, brightnessMin, brightnessMax, hbmData, hdrBrightnessCfg,
hbmChangeCallback, hbmMetadata, context);
}
+
+ DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
+ SensorManager sensorManager, Resources resources) {
+ return DisplayWhiteBalanceFactory.create(handler,
+ sensorManager, resources);
+ }
}
static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 7417aeb..c2c0c0a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -142,6 +142,9 @@
private static final int MSG_STATSD_HBM_BRIGHTNESS = 11;
private static final int MSG_SWITCH_USER = 12;
private static final int MSG_BOOT_COMPLETED = 13;
+ private static final int MSG_SET_DWBC_STRONG_MODE = 14;
+ private static final int MSG_SET_DWBC_COLOR_OVERRIDE = 15;
+ private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16;
private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
@@ -368,6 +371,7 @@
private final boolean mSkipScreenOnBrightnessRamp;
// Display white balance components.
+ // Critical methods must be called on DPC2 handler thread.
@Nullable
private final DisplayWhiteBalanceSettings mDisplayWhiteBalanceSettings;
@Nullable
@@ -572,9 +576,9 @@
DisplayWhiteBalanceController displayWhiteBalanceController = null;
if (mDisplayId == Display.DEFAULT_DISPLAY) {
try {
+ displayWhiteBalanceController = mInjector.getDisplayWhiteBalanceController(
+ mHandler, mSensorManager, resources);
displayWhiteBalanceSettings = new DisplayWhiteBalanceSettings(mContext, mHandler);
- displayWhiteBalanceController = DisplayWhiteBalanceFactory.create(mHandler,
- mSensorManager, resources);
displayWhiteBalanceSettings.setCallbacks(this);
displayWhiteBalanceController.setCallbacks(this);
} catch (Exception e) {
@@ -850,10 +854,6 @@
Message msg = mHandler.obtainMessage(MSG_STOP);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setEnabled(false);
- }
-
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.stop();
}
@@ -1164,9 +1164,10 @@
mAutomaticBrightnessController.switchToInteractiveScreenBrightnessMode();
}
}
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
- }
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_STRONG_MODE;
+ msg.arg1 = isIdle ? 1 : 0;
+ mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@@ -1221,8 +1222,13 @@
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
}
+
+ if (mDisplayWhiteBalanceController != null) {
+ mDisplayWhiteBalanceController.setEnabled(false);
+ }
}
+ // Call from handler thread
private void updatePowerState() {
Trace.traceBegin(Trace.TRACE_TAG_POWER,
"DisplayPowerController#updatePowerState");
@@ -1726,6 +1732,32 @@
}
}
+ private void setDwbcOverride(float cct) {
+ if (mDisplayWhiteBalanceController != null) {
+ mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
+ // The ambient color temperature override is only applied when the ambient color
+ // temperature changes or is updated, so it doesn't necessarily change the screen color
+ // temperature immediately. So, let's make it!
+ // We can call this directly, since we're already on the handler thread.
+ updatePowerState();
+ }
+ }
+
+ private void setDwbcStrongMode(int arg) {
+ if (mDisplayWhiteBalanceController != null) {
+ final boolean isIdle = (arg == 1);
+ mDisplayWhiteBalanceController.setStrongModeEnabled(isIdle);
+ }
+ }
+
+ private void setDwbcLoggingEnabled(int arg) {
+ if (mDisplayWhiteBalanceController != null) {
+ final boolean enabled = (arg == 1);
+ mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
+ mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
+ }
+ }
+
@Override
public void updateBrightness() {
sendUpdatePowerState();
@@ -2755,6 +2787,19 @@
mBootCompleted = true;
updatePowerState();
break;
+
+ case MSG_SET_DWBC_STRONG_MODE:
+ setDwbcStrongMode(msg.arg1);
+ break;
+
+ case MSG_SET_DWBC_COLOR_OVERRIDE:
+ final float cct = Float.intBitsToFloat(msg.arg1);
+ setDwbcOverride(cct);
+ break;
+
+ case MSG_SET_DWBC_LOGGING_ENABLED:
+ setDwbcLoggingEnabled(msg.arg1);
+ break;
}
}
}
@@ -2805,21 +2850,18 @@
@Override
public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setLoggingEnabled(enabled);
- mDisplayWhiteBalanceSettings.setLoggingEnabled(enabled);
- }
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
+ msg.arg1 = enabled ? 1 : 0;
+ msg.sendToTarget();
}
@Override
public void setAmbientColorTemperatureOverride(float cct) {
- if (mDisplayWhiteBalanceController != null) {
- mDisplayWhiteBalanceController.setAmbientColorTemperatureOverride(cct);
- // The ambient color temperature override is only applied when the ambient color
- // temperature changes or is updated, so it doesn't necessarily change the screen color
- // temperature immediately. So, let's make it!
- sendUpdatePowerState();
- }
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
+ msg.arg1 = Float.floatToIntBits(cct);
+ msg.sendToTarget();
}
/** Functional interface for providing time. */
@@ -2946,6 +2988,12 @@
boolean isColorFadeEnabled() {
return !ActivityManager.isLowRamDeviceStatic();
}
+
+ DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
+ SensorManager sensorManager, Resources resources) {
+ return DisplayWhiteBalanceFactory.create(handler,
+ sensorManager, resources);
+ }
}
static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 5b772fc..4ad26c4 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -37,8 +37,11 @@
* - Uses the AmbientColorTemperatureSensor to detect changes in the ambient color temperature;
* - Uses the AmbientColorTemperatureFilter to average these changes over time, filter out the
* noise, and arrive at an estimate of the actual ambient color temperature;
- * - Uses the DisplayWhiteBalanceThrottler to decide whether the display color tempearture should
+ * - Uses the DisplayWhiteBalanceThrottler to decide whether the display color temperature should
* be updated, suppressing changes that are too frequent or too minor.
+ *
+ * Calls to this class must happen on the DisplayPowerController(2) handler, to ensure
+ * values do not get out of sync.
*/
public class DisplayWhiteBalanceController implements
AmbientSensor.AmbientBrightnessSensor.Callbacks,
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a96e4ad..0616f4e 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -844,6 +844,10 @@
getAuthSecretHal();
mDeviceProvisionedObserver.onSystemReady();
+ // Work around an issue in PropertyInvalidatedCache where the cache doesn't work until the
+ // first invalidation. This can be removed if PropertyInvalidatedCache is fixed.
+ LockPatternUtils.invalidateCredentialTypeCache();
+
// TODO: maybe skip this for split system user mode.
mStorage.prefetchUser(UserHandle.USER_SYSTEM);
mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index c710d1c..56f650e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -121,7 +121,8 @@
private PowerManager mPowerManagerMock;
@Mock
private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
-
+ @Mock
+ private DisplayWhiteBalanceController mDisplayWhiteBalanceControllerMock;
@Captor
private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
@@ -1089,6 +1090,18 @@
.getThermalBrightnessThrottlingDataMapByThrottlingId();
}
+ @Test
+ public void testDwbcCallsHappenOnHandler() {
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+
+ mHolder.dpc.setAutomaticScreenBrightnessMode(true);
+ verify(mDisplayWhiteBalanceControllerMock, never()).setStrongModeEnabled(true);
+
+ // dispatch handler looper
+ advanceTime(1);
+ verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
@@ -1378,5 +1391,11 @@
Context context) {
return mHighBrightnessModeController;
}
+
+ @Override
+ DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
+ SensorManager sensorManager, Resources resources) {
+ return mDisplayWhiteBalanceControllerMock;
+ }
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 7d26913..e2aeea3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -121,7 +121,8 @@
private PowerManager mPowerManagerMock;
@Mock
private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
-
+ @Mock
+ private DisplayWhiteBalanceController mDisplayWhiteBalanceControllerMock;
@Captor
private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
@@ -1092,6 +1093,18 @@
.getThermalBrightnessThrottlingDataMapByThrottlingId();
}
+ @Test
+ public void testDwbcCallsHappenOnHandler() {
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+
+ mHolder.dpc.setAutomaticScreenBrightnessMode(true);
+ verify(mDisplayWhiteBalanceControllerMock, never()).setStrongModeEnabled(true);
+
+ // dispatch handler looper
+ advanceTime(1);
+ verify(mDisplayWhiteBalanceControllerMock, times(1)).setStrongModeEnabled(true);
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
@@ -1351,5 +1364,11 @@
Context context) {
return mHighBrightnessModeController;
}
+
+ @Override
+ DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler,
+ SensorManager sensorManager, Resources resources) {
+ return mDisplayWhiteBalanceControllerMock;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 2d4bf14..32d0c98 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -44,8 +44,10 @@
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
@@ -140,8 +142,6 @@
@Mock
WindowMagnificationPromptController mWindowMagnificationPromptController;
@Mock
- AccessibilityManagerService mMockAccessibilityManagerService;
- @Mock
AccessibilityTraceManager mMockTraceManager;
@Rule
@@ -153,6 +153,8 @@
private long mLastDownTime = Integer.MIN_VALUE;
+ private float mOriginalMagnificationPersistedScale;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -166,6 +168,13 @@
when(mockController.newValueAnimator()).thenReturn(new ValueAnimator());
when(mockController.getAnimationDuration()).thenReturn(1000L);
when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
+ mOriginalMagnificationPersistedScale = Settings.Secure.getFloatForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
+ UserHandle.USER_SYSTEM);
+ Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
+ UserHandle.USER_SYSTEM);
mFullScreenMagnificationController = new FullScreenMagnificationController(
mockController,
new Object(),
@@ -192,6 +201,10 @@
mMgh.onDestroy();
mFullScreenMagnificationController.unregister(DISPLAY_0);
verify(mWindowMagnificationPromptController).onDestroy();
+ Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+ mOriginalMagnificationPersistedScale,
+ UserHandle.USER_SYSTEM);
}
@NonNull
@@ -525,10 +538,9 @@
final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
.CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
final float persistedScale = (1.0f + threshold) * scale + 1.0f;
- mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
- mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
+ UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
DEFAULT_Y, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
@@ -547,10 +559,9 @@
final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
.CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
final float persistedScale = (1.0f + threshold) * scale - 0.1f;
- mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
- mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
+ UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
DEFAULT_Y, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3c882dc8..a109d5c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -73,6 +73,7 @@
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_LOCKDOWN;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
@@ -2009,10 +2010,10 @@
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
sbn.getNotification(), sbn.getUserId());
- Thread.sleep(1); // make sure the system clock advances before the next step
+ mTestableLooper.moveTimeForward(1);
// THEN it is canceled
mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
- Thread.sleep(1); // here too
+ mTestableLooper.moveTimeForward(1);
// THEN it is posted again (before the cancel has a chance to finish)
mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(),
sbn.getNotification(), sbn.getUserId());
@@ -2303,7 +2304,7 @@
notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
mService.addNotification(notif);
mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
- notif.getUserId(), 0);
+ notif.getUserId(), REASON_CANCEL);
waitForIdle();
StatusBarNotification[] notifs =
mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
@@ -3041,7 +3042,7 @@
notif.getNotification().flags |= Notification.FLAG_NO_CLEAR;
mService.addNotification(notif);
mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0,
- Notification.FLAG_ONGOING_EVENT, notif.getUserId(), 0);
+ Notification.FLAG_ONGOING_EVENT, notif.getUserId(), REASON_CANCEL);
waitForIdle();
StatusBarNotification[] notifs =
mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
@@ -3069,7 +3070,7 @@
notif.getNotification().flags |= Notification.FLAG_ONGOING_EVENT;
mService.addNotification(notif);
mService.cancelAllNotificationsInt(mUid, 0, PKG, null, 0, 0,
- notif.getUserId(), 0);
+ notif.getUserId(), REASON_CANCEL);
waitForIdle();
StatusBarNotification[] notifs =
mBinderService.getActiveNotifications(notif.getSbn().getPackageName());
@@ -12208,7 +12209,7 @@
mOnPermissionChangeListener.onOpChanged(
AppOpsManager.OPSTR_POST_NOTIFICATION, PKG, 0);
waitForIdle();
- Thread.sleep(600);
+ mTestableLooper.moveTimeForward(500);
waitForIdle();
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
@@ -12227,7 +12228,7 @@
mOnPermissionChangeListener.onOpChanged(
AppOpsManager.OPSTR_POST_NOTIFICATION, PKG, 0);
waitForIdle();
- Thread.sleep(600);
+ mTestableLooper.moveTimeForward(500);
waitForIdle();
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
@@ -12261,7 +12262,7 @@
assertThat(mService.mNotificationList).hasSize(0);
- Thread.sleep(600);
+ mTestableLooper.moveTimeForward(500);
waitForIdle();
verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null));
}
diff --git a/tests/Internal/src/android/service/wallpaper/OWNERS b/tests/Internal/src/android/service/wallpaper/OWNERS
new file mode 100644
index 0000000..5a26d0e
--- /dev/null
+++ b/tests/Internal/src/android/service/wallpaper/OWNERS
@@ -0,0 +1,4 @@
+dupin@google.com
+santie@google.com
+pomini@google.com
+poultney@google.com
\ No newline at end of file
diff --git a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
index 153ca79..0c5e8d48 100644
--- a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
+++ b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
@@ -85,4 +85,17 @@
assertEquals("onAmbientModeChanged should have been called", 2, zoomChangedCount[0]);
}
+ @Test
+ public void testNotifyColorsOfDestroyedEngine_doesntCrash() {
+ WallpaperService service = new WallpaperService() {
+ @Override
+ public Engine onCreateEngine() {
+ return new Engine();
+ }
+ };
+ WallpaperService.Engine engine = service.onCreateEngine();
+ engine.detach();
+
+ engine.notifyColorsChanged();
+ }
}
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index edd6dd3..82e40b1 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -32,6 +32,7 @@
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* This is a wrapper around {@link TestLooperManager} to make it easier to manage
@@ -55,7 +56,6 @@
private MessageHandler mMessageHandler;
private Handler mHandler;
- private Runnable mEmptyMessage;
private TestLooperManager mQueueWrapper;
static {
@@ -121,8 +121,12 @@
* @param num Number of messages to parse
*/
public int processMessages(int num) {
+ return processMessagesInternal(num, null);
+ }
+
+ private int processMessagesInternal(int num, Runnable barrierRunnable) {
for (int i = 0; i < num; i++) {
- if (!parseMessageInt()) {
+ if (!processSingleMessage(barrierRunnable)) {
return i + 1;
}
}
@@ -130,6 +134,27 @@
}
/**
+ * Process up to a certain number of messages, not blocking if the queue has less messages than
+ * that
+ * @param num the maximum number of messages to process
+ * @return the number of messages processed. This will be at most {@code num}.
+ */
+
+ public int processMessagesNonBlocking(int num) {
+ final AtomicBoolean reachedBarrier = new AtomicBoolean(false);
+ Runnable barrierRunnable = () -> {
+ reachedBarrier.set(true);
+ };
+ mHandler.post(barrierRunnable);
+ waitForMessage(mQueueWrapper, mHandler, barrierRunnable);
+ try {
+ return processMessagesInternal(num, barrierRunnable) + (reachedBarrier.get() ? -1 : 0);
+ } finally {
+ mHandler.removeCallbacks(barrierRunnable);
+ }
+ }
+
+ /**
* Process messages in the queue until no more are found.
*/
public void processAllMessages() {
@@ -165,19 +190,20 @@
private int processQueuedMessages() {
int count = 0;
- mEmptyMessage = () -> { };
- mHandler.post(mEmptyMessage);
- waitForMessage(mQueueWrapper, mHandler, mEmptyMessage);
- while (parseMessageInt()) count++;
+ Runnable barrierRunnable = () -> { };
+ mHandler.post(barrierRunnable);
+ waitForMessage(mQueueWrapper, mHandler, barrierRunnable);
+ while (processSingleMessage(barrierRunnable)) count++;
return count;
}
- private boolean parseMessageInt() {
+ private boolean processSingleMessage(Runnable barrierRunnable) {
try {
Message result = mQueueWrapper.next();
if (result != null) {
// This is a break message.
- if (result.getCallback() == mEmptyMessage) {
+ if (result.getCallback() == barrierRunnable) {
+ mQueueWrapper.execute(result);
mQueueWrapper.recycle(result);
return false;
}
diff --git a/tests/testables/tests/src/android/testing/TestableLooperTest.java b/tests/testables/tests/src/android/testing/TestableLooperTest.java
index 0f491b8..a02eb6b 100644
--- a/tests/testables/tests/src/android/testing/TestableLooperTest.java
+++ b/tests/testables/tests/src/android/testing/TestableLooperTest.java
@@ -27,12 +27,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -40,6 +34,11 @@
import android.testing.TestableLooper.MessageHandler;
import android.testing.TestableLooper.RunWithLooper;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -240,4 +239,33 @@
inOrder.verify(handler).dispatchMessage(messageC);
}
+ @Test
+ public void testProcessMessagesNonBlocking_onlyArgNumber() {
+ Handler h = new Handler(mTestableLooper.getLooper());
+ Runnable r = mock(Runnable.class);
+
+ h.post(r);
+ h.post(r);
+ h.post(r);
+
+ int processed = mTestableLooper.processMessagesNonBlocking(2);
+
+ verify(r, times(2)).run();
+ assertEquals(2, processed);
+ }
+
+ @Test
+ public void testProcessMessagesNonBlocking_lessMessagesThanArg() {
+ Handler h = new Handler(mTestableLooper.getLooper());
+ Runnable r = mock(Runnable.class);
+
+ h.post(r);
+ h.post(r);
+ h.post(r);
+
+ int processed = mTestableLooper.processMessagesNonBlocking(5);
+
+ verify(r, times(3)).run();
+ assertEquals(3, processed);
+ }
}