diff options
35 files changed, 874 insertions, 195 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 49b152b85ca1..c30164c065af 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -41,6 +41,7 @@ aconfig_srcjars = [ ":android.app.flags-aconfig-java{.generated_srcjars}", ":android.credentials.flags-aconfig-java{.generated_srcjars}", ":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}", + ":android.service.voice.flags-aconfig-java{.generated_srcjars}", ] filegroup { @@ -402,3 +403,16 @@ java_aconfig_library { aconfig_declarations: "android.view.contentprotection.flags-aconfig", defaults: ["framework-minus-apex-aconfig-java-defaults"], } + +// Voice +aconfig_declarations { + name: "android.service.voice.flags-aconfig", + package: "android.service.voice.flags", + srcs: ["core/java/android/service/voice/flags/*.aconfig"], +} + +java_aconfig_library { + name: "android.service.voice.flags-aconfig-java", + aconfig_declarations: "android.service.voice.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} diff --git a/core/api/current.txt b/core/api/current.txt index a304080f7579..96a959572949 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -42982,7 +42982,6 @@ package android.telephony { field public static final String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array"; field public static final String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool"; field public static final String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool"; - field @Deprecated public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool"; field public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool"; field public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool"; field public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL = "hide_lte_plus_data_icon_bool"; diff --git a/core/api/removed.txt b/core/api/removed.txt index 57e2e73854c1..5a4be65ef559 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -472,6 +472,10 @@ package android.speech.tts { package android.telephony { + public class CarrierConfigManager { + field @Deprecated public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool"; + } + public class NetworkScan { method @Deprecated public void stop() throws android.os.RemoteException; } diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java index a6a57cd5745a..37111e931d71 100644 --- a/core/java/android/app/ApplicationStartInfo.java +++ b/core/java/android/app/ApplicationStartInfo.java @@ -473,9 +473,8 @@ public final class ApplicationStartInfo implements Parcelable { * available. * For {@link #STARTUP_STATE_ERROR}, no additional timestamps are guaranteed available. * For {@link #STARTUP_STATE_FIRST_FRAME_DRAWN}, timestamps - * {@link #START_TIMESTAMP_JAVA_CLASSLOADING_COMPLETE}, {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, - * {@link #START_TIMESTAMP_BIND_APPLICATION}, and {@link #START_TIMESTAMP_FIRST_FRAME} will - * additionally be available. + * {@link #START_TIMESTAMP_APPLICATION_ONCREATE}, {@link #START_TIMESTAMP_BIND_APPLICATION}, + * and {@link #START_TIMESTAMP_FIRST_FRAME} will additionally be available. * * Timestamp {@link #START_TIMESTAMP_FULLY_DRAWN} is never guaranteed to be available as it is * dependant on devloper calling {@link Activity#reportFullyDrawn}. diff --git a/core/java/android/app/GrammaticalInflectionManager.java b/core/java/android/app/GrammaticalInflectionManager.java index bc6fe6146764..a55121aaa12c 100644 --- a/core/java/android/app/GrammaticalInflectionManager.java +++ b/core/java/android/app/GrammaticalInflectionManager.java @@ -100,7 +100,7 @@ public class GrammaticalInflectionManager { /** * Sets the current grammatical gender for all privileged applications. The value will be - * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int) + * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)} * * @param grammaticalGender the terms of address the user preferred in system. * @@ -121,8 +121,7 @@ public class GrammaticalInflectionManager { } /** - * Get the current grammatical gender of privileged application from the encrypted file, - * which is stored under {@link android.os.Environment#getDataSystemCeDirectory(int)}. + * Get the current grammatical gender of privileged application from the encrypted file. * * @return the value of grammatical gender * diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 93c2b5ad4d86..dd7db23d668b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -9195,6 +9195,12 @@ public class Notification implements Parcelable * You can opt-out of this behavior by using {@link Notification.Builder#setColorized(boolean)}. * <p> * + * <p> + * Starting at {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM Android V} the + * {@link Notification#FLAG_NO_CLEAR NO_CLEAR flag} will be set for valid MediaStyle + * notifications. + * <p> + * * To use this style with your Notification, feed it to * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so: * <pre class="prettyprint"> diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d09f0a831f30..b414ed4faea2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5664,6 +5664,37 @@ public final class Settings { public static final String SHOW_ROTARY_INPUT = "show_rotary_input"; /** + * The screen backlight brightness for automatic mode. + * + * <p>Value should be one of: + * <ul> + * <li>SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT + * <li>SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL + * <li>SCREEN_BRIGHTNESS_AUTOMATIC_DIM + * </ul> + * @hide + */ + public static final String SCREEN_BRIGHTNESS_FOR_ALS = "screen_brightness_for_als"; + + /** + * SCREEN_BRIGHTNESS_FOR_ALS value for automatic bright. + * @hide + */ + public static final int SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT = 1; + + /** + * SCREEN_BRIGHTNESS_FOR_ALS value for automatic normal. + * @hide + */ + public static final int SCREEN_BRIGHTNESS_AUTOMATIC_NORMAL = 2; + + /** + * SCREEN_BRIGHTNESS_FOR_ALS value for automatic dim. + * @hide + */ + public static final int SCREEN_BRIGHTNESS_AUTOMATIC_DIM = 3; + + /** * Log raw orientation data from * {@link com.android.server.policy.WindowOrientationListener} for use with the * orientationplot.py tool. diff --git a/core/java/android/service/voice/flags/flags.aconfig b/core/java/android/service/voice/flags/flags.aconfig new file mode 100644 index 000000000000..c414ef8a6826 --- /dev/null +++ b/core/java/android/service/voice/flags/flags.aconfig @@ -0,0 +1,8 @@ +package: "android.service.voice.flags" + +flag { + name: "allow_training_data_egress_from_hds" + namespace: "machine_learning" + description: "This flag allows the hotword detection service to egress training data to the default assistant." + bug: "296074924" +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt new file mode 100644 index 000000000000..4f27ceddd705 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt @@ -0,0 +1,64 @@ +/* + * 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.wm.shell.flicker.pip + +import android.platform.test.annotations.Presubmit +import android.tools.common.Rotation +import android.tools.device.flicker.junit.FlickerParametersRunnerFactory +import android.tools.device.flicker.legacy.FlickerBuilder +import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import com.android.wm.shell.flicker.pip.common.PipTransition +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** Test changing aspect ratio of pip. */ +@RunWith(Parameterized::class) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class PipAspectRatioChangeTest(flicker: LegacyFlickerTest) : PipTransition(flicker) { + override val thisTransition: FlickerBuilder.() -> Unit = { + transitions { + pipApp.changeAspectRatio() + } + } + + @Presubmit + @Test + fun pipAspectRatioChangesProperly() { + flicker.assertLayersStart { this.visibleRegion(pipApp).isSameAspectRatio(16, 9) } + flicker.assertLayersEnd { this.visibleRegion(pipApp).isSameAspectRatio(1, 2) } + } + + companion object { + /** + * Creates the test configurations. + * + * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and + * navigation modes. + */ + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams() = + LegacyFlickerTestFactory.nonRotationTests( + supportedRotations = listOf(Rotation.ROTATION_0) + ) + } +} diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS index 6ca991d8b294..bc174599a4d3 100644 --- a/libs/hwui/OWNERS +++ b/libs/hwui/OWNERS @@ -4,9 +4,8 @@ alecmouri@google.com djsollen@google.com jreck@google.com njawad@google.com -reed@google.com scroggo@google.com -stani@google.com +sumir@google.com # For text, e.g. Typeface, Font, Minikin, etc. nona@google.com diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index 17ce7c7cc435..29f27f74bca4 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -120,6 +120,11 @@ public class SystemSettingsValidators { VALIDATORS.put(System.DISPLAY_COLOR_MODE_VENDOR_HINT, ANY_STRING_VALIDATOR); VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(System.SCREEN_BRIGHTNESS_MODE, BOOLEAN_VALIDATOR); + VALIDATORS.put( + System.SCREEN_BRIGHTNESS_FOR_ALS, + new InclusiveIntegerRangeValidator( + System.SCREEN_BRIGHTNESS_AUTOMATIC_BRIGHT, + System.SCREEN_BRIGHTNESS_AUTOMATIC_DIM)); VALIDATORS.put(System.ADAPTIVE_SLEEP, BOOLEAN_VALIDATOR); VALIDATORS.put(System.MODE_RINGER_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR); diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index c0f62313cb39..9ddc976af7e2 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -101,6 +101,7 @@ public class SettingsBackupTest { Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities Settings.System.SCREEN_BRIGHTNESS_FLOAT, + Settings.System.SCREEN_BRIGHTNESS_FOR_ALS, Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, Settings.System.WEAR_TTS_PREWARM_ENABLED, Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index a81069a1f7db..9b00b5f2aaf2 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -25,6 +25,7 @@ import static com.android.keyguard.LockIconView.ICON_UNLOCK; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1; import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; +import static com.android.systemui.flags.Flags.NEW_AOD_TRANSITION; import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; @@ -99,6 +100,8 @@ public class LockIconViewController implements Dumpable { private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); + private static final long FADE_OUT_DURATION_MS = 250L; + private final long mLongPressTimeout; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final KeyguardViewController mKeyguardViewController; @@ -388,6 +391,16 @@ public class LockIconViewController implements Dumpable { mView.updateIcon(ICON_LOCK, true); mView.setContentDescription(mLockedLabel); mView.setVisibility(View.VISIBLE); + } else if (mIsDozing && mFeatureFlags.isEnabled(NEW_AOD_TRANSITION)) { + mView.animate() + .alpha(0f) + .setDuration(FADE_OUT_DURATION_MS) + .withEndAction(() -> { + mView.clearIcon(); + mView.setVisibility(View.INVISIBLE); + mView.setContentDescription(null); + }) + .start(); } else { mView.clearIcon(); mView.setVisibility(View.INVISIBLE); diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java b/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java index e3cc2b02177c..bf9018a1f99c 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java @@ -177,6 +177,13 @@ public class FlagCommand implements Command { || (flag instanceof SysPropFlag); } + private Boolean isTeamfoodFlag(Flag<?> flag) { + if (!(flag instanceof BooleanFlag)) { + return null; + } + return flag.getTeamfood(); + } + private boolean isBooleanFlagEnabled(Flag<?> flag) { if (flag instanceof ReleasedFlag) { return mFeatureFlags.isEnabled((ReleasedFlag) flag); @@ -232,11 +239,13 @@ public class FlagCommand implements Command { for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) { pw.print(" "); } - pw.println(" Value"); + pw.print(" Value "); + pw.println(" Teamfood?"); for (int i = 0; i < longestFieldName; i++) { pw.print("="); } - pw.println(" ========"); + pw.println(" ======= ==========="); + for (String fieldName : fields.keySet()) { Flag<?> flag = fields.get(fieldName); if (!mAllFlags.containsKey(flag.getName())) { @@ -249,7 +258,19 @@ public class FlagCommand implements Command { } pw.print(" "); if (isBooleanFlag(flag)) { - pw.println(isBooleanFlagEnabled(flag)); + boolean enabled = isBooleanFlagEnabled(flag); + pw.print(enabled); + if (enabled) { + pw.print(" "); + } else { + pw.print(" "); + } + Boolean teamfood = isTeamfoodFlag(flag); + if (teamfood != null) { + pw.print(teamfood); + } + pw.println(); + } else if (isStringFlag(flag)) { pw.println(getStringFlag(flag)); } else if (isIntFlag(flag)) { diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index e33878e8c62d..bdd245ed7b7f 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -176,7 +176,11 @@ object Flags { */ // TODO(b/281655028): Tracking bug @JvmField - val LIGHT_REVEAL_MIGRATION = unreleasedFlag("light_reveal_migration", teamfood = false) + val LIGHT_REVEAL_MIGRATION = unreleasedFlag("light_reveal_migration", teamfood = true) + + // TODO(b/301915812): Tracking Bug + @JvmField + val NEW_AOD_TRANSITION = unreleasedFlag("new_aod_transition", teamfood = true) /** Flag to control the migration of face auth to modern architecture. */ // TODO(b/262838215): Tracking bug diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt index 1c43609aa551..fbe26de4e9ba 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt @@ -34,16 +34,17 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.OFF import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep +import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.stateIn -import javax.inject.Inject /** Encapsulates business-logic related to the keyguard transitions. */ @SysUISingleton @@ -176,18 +177,17 @@ constructor( .map { step -> step.to } .stateIn(scope, SharingStarted.Eagerly, LOCKSCREEN) - /** * Whether we're currently in a transition to a new [KeyguardState] and haven't yet completed * it. */ val isInTransitionToAnyState = - combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - startedStep.to != finishedState - } + combine( + startedKeyguardTransitionStep, + finishedKeyguardState, + ) { startedStep, finishedState -> + startedStep.to != finishedState + } /** * The amount of transition into or out of the given [KeyguardState]. @@ -236,14 +236,9 @@ constructor( /** Whether we're in a transition to the given [KeyguardState], but haven't yet completed it. */ fun isInTransitionToState( - state: KeyguardState, + state: KeyguardState, ): Flow<Boolean> { - return combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - startedStep.to == state && finishedState != state - } + return isInTransitionToStateWhere { it == state } } /** @@ -251,28 +246,18 @@ constructor( * haven't yet completed it. */ fun isInTransitionToStateWhere( - stateMatcher: (KeyguardState) -> Boolean, + stateMatcher: (KeyguardState) -> Boolean, ): Flow<Boolean> { - return combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - stateMatcher(startedStep.to) && finishedState != startedStep.from - } + return isInTransitionWhere(fromStatePredicate = { true }, toStatePredicate = stateMatcher) } /** * Whether we're in a transition out of the given [KeyguardState], but haven't yet completed it. */ fun isInTransitionFromState( - state: KeyguardState, + state: KeyguardState, ): Flow<Boolean> { - return combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - startedStep.from == state && finishedState != state - } + return isInTransitionFromStateWhere { it == state } } /** @@ -280,14 +265,9 @@ constructor( * haven't yet completed it. */ fun isInTransitionFromStateWhere( - stateMatcher: (KeyguardState) -> Boolean, + stateMatcher: (KeyguardState) -> Boolean, ): Flow<Boolean> { - return combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - stateMatcher(startedStep.from) && finishedState != startedStep.from - } + return isInTransitionWhere(fromStatePredicate = stateMatcher, toStatePredicate = { true }) } /** @@ -299,26 +279,23 @@ constructor( toStatePredicate: (KeyguardState) -> Boolean, ): Flow<Boolean> { return combine( - startedKeyguardTransitionStep, - finishedKeyguardState, - ) { startedStep, finishedState -> - fromStatePredicate(startedStep.from) - && toStatePredicate(startedStep.to) - && finishedState != startedStep.from - } + startedKeyguardTransitionStep, + finishedKeyguardState, + ) { startedStep, finishedState -> + fromStatePredicate(startedStep.from) && + toStatePredicate(startedStep.to) && + finishedState != startedStep.to + } + .distinctUntilChanged() } - /** - * Whether we've FINISHED a transition to a state that matches the given predicate. - */ + /** Whether we've FINISHED a transition to a state that matches the given predicate. */ fun isFinishedInStateWhere(stateMatcher: (KeyguardState) -> Boolean): Flow<Boolean> { - return finishedKeyguardState.map { stateMatcher(it) } + return finishedKeyguardState.map { stateMatcher(it) }.distinctUntilChanged() } - /** - * Whether we've FINISHED a transition to a state that matches the given predicate. - */ - fun isFinishedInState(state: KeyguardState) : Flow<Boolean> { - return finishedKeyguardState.map { it == state } + /** Whether we've FINISHED a transition to a state that matches the given predicate. */ + fun isFinishedInState(state: KeyguardState): Flow<Boolean> { + return finishedKeyguardState.map { it == state }.distinctUntilChanged() } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt index aa76702dc3d4..f0d118cbe20f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt @@ -134,7 +134,14 @@ object KeyguardQuickAffordanceViewBinder { vibratorHelper: VibratorHelper?, ) { if (!viewModel.isVisible) { - view.isInvisible = true + view.alpha = 1f + view + .animate() + .alpha(0f) + .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN) + .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS) + .withEndAction { view.isInvisible = true } + .start() return } @@ -142,11 +149,9 @@ object KeyguardQuickAffordanceViewBinder { view.isVisible = true if (viewModel.animateReveal) { view.alpha = 0f - view.translationY = view.height / 2f view .animate() .alpha(1f) - .translationY(0f) .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) .setDuration(EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS) .start() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt index 20241c323ab6..5cc5e751ca8e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt @@ -35,6 +35,7 @@ import com.android.systemui.demomode.DemoMode import com.android.systemui.demomode.DemoModeController import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.flags.Flags.NEW_AOD_TRANSITION import com.android.systemui.flags.ViewRefactorFlag import com.android.systemui.plugins.DarkIconDispatcher import com.android.systemui.plugins.statusbar.StatusBarStateController @@ -88,7 +89,7 @@ constructor( private val bubblesOptional: Optional<Bubbles>, demoModeController: DemoModeController, darkIconDispatcher: DarkIconDispatcher, - featureFlags: FeatureFlags, + private val featureFlags: FeatureFlags, private val statusBarWindowController: StatusBarWindowController, private val screenOffAnimationController: ScreenOffAnimationController, private val shelfIconsViewModel: NotificationIconContainerShelfViewModel, @@ -299,9 +300,12 @@ constructor( var animate = true if (!bypassController.bypassEnabled) { animate = dozeParameters.alwaysOn && !dozeParameters.displayNeedsBlanking - // We only want the appear animations to happen when the notifications get fully hidden, - // since otherwise the unhide animation overlaps - animate = animate and isFullyHidden + if (!featureFlags.isEnabled(NEW_AOD_TRANSITION)) { + // We only want the appear animations to happen when the notifications get fully + // hidden, + // since otherwise the unhide animation overlaps + animate = animate and isFullyHidden + } } updateAodIconsVisibility(animate, false /* force */) updateAodNotificationIcons() @@ -657,23 +661,34 @@ constructor( aodIconsVisible = visible aodIcons!!.animate().cancel() if (animate) { - val wasFullyInvisible = aodIcons!!.visibility != View.VISIBLE - if (aodIconsVisible) { - if (wasFullyInvisible) { - // No fading here, let's just appear the icons instead! - aodIcons!!.visibility = View.VISIBLE - aodIcons!!.alpha = 1.0f - appearAodIcons() + if (featureFlags.isEnabled(NEW_AOD_TRANSITION)) { + // Let's make sure the icon are translated to 0, since we cancelled it above + animateInAodIconTranslation() + if (aodIconsVisible) { + CrossFadeHelper.fadeIn(aodIcons) + } else { + CrossFadeHelper.fadeOut(aodIcons) + } + } else { + val wasFullyInvisible = aodIcons!!.visibility != View.VISIBLE + if (aodIconsVisible) { + if (wasFullyInvisible) { + // No fading here, let's just appear the icons instead! + aodIcons!!.visibility = View.VISIBLE + aodIcons!!.alpha = 1.0f + appearAodIcons() + } else { + // Let's make sure the icon are translated to 0, since we cancelled it + // above + animateInAodIconTranslation() + // We were fading out, let's fade in instead + CrossFadeHelper.fadeIn(aodIcons) + } } else { // Let's make sure the icon are translated to 0, since we cancelled it above animateInAodIconTranslation() - // We were fading out, let's fade in instead - CrossFadeHelper.fadeIn(aodIcons) + CrossFadeHelper.fadeOut(aodIcons) } - } else { - // Let's make sure the icon are translated to 0, since we cancelled it above - animateInAodIconTranslation() - CrossFadeHelper.fadeOut(aodIcons) } } else { aodIcons!!.alpha = 1.0f diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d18f9919604d..061132ff4f19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -772,6 +772,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView /** * @return if the view is in heads up state, i.e either still heads upped or it's disappearing. */ + @Override public boolean isHeadsUpState() { return mIsHeadsUp || mHeadsupDisappearRunning; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java index 5aae48899bc9..f2f55a87ba3f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java @@ -621,6 +621,10 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro return false; } + public boolean isHeadsUpState() { + return false; + } + public boolean isChildInGroup() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 28f0a0c5fd78..9f95c0924c64 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -203,6 +203,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private final ViewRefactorFlag mAnimatedInsets; private final ViewRefactorFlag mShelfRefactor; + private final boolean mNewAodTransition; + private int mContentHeight; private float mIntrinsicContentHeight; private int mPaddingBetweenElements; @@ -632,6 +634,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mIsSmallLandscapeLockscreenEnabled = featureFlags.isEnabled( Flags.LOCKSCREEN_ENABLE_LANDSCAPE); mDebugLines = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES); + mNewAodTransition = featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION); mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION); mSensitiveRevealAnimEndabled = featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM); mAnimatedInsets = @@ -1432,12 +1435,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @VisibleForTesting public void updateStackHeight(float endHeight, float fraction) { - // During the (AOD<=>LS) transition where dozeAmount is changing, - // apply dozeAmount to stack height instead of expansionFraction - // to unfurl notifications on AOD=>LS wakeup (and furl up on LS=>AOD sleep) - final float dozeAmount = mAmbientState.getDozeAmount(); - if (0f < dozeAmount && dozeAmount < 1f) { - fraction = 1f - dozeAmount; + if (!mNewAodTransition) { + // During the (AOD<=>LS) transition where dozeAmount is changing, + // apply dozeAmount to stack height instead of expansionFraction + // to unfurl notifications on AOD=>LS wakeup (and furl up on LS=>AOD sleep) + final float dozeAmount = mAmbientState.getDozeAmount(); + if (0f < dozeAmount && dozeAmount < 1f) { + fraction = 1f - dozeAmount; + } } mAmbientState.setStackHeight( MathUtils.lerp(endHeight * StackScrollAlgorithm.START_FRACTION, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index f2d5394e0aee..8ca18521de63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -142,7 +142,15 @@ public class StackScrollAlgorithm { viewState.setAlpha(1f); } else if (ambientState.isOnKeyguard()) { // Adjust alpha for wakeup to lockscreen. - viewState.setAlpha(1f - ambientState.getHideAmount()); + if (view.isHeadsUpState()) { + // Pulsing HUN should be visible on AOD and stay visible during + // AOD=>lockscreen transition + viewState.setAlpha(1f - ambientState.getHideAmount()); + } else { + // Normal notifications are hidden on AOD and should fade in during + // AOD=>lockscreen transition + viewState.setAlpha(1f - ambientState.getDozeAmount()); + } } else if (ambientState.isExpansionChanging()) { // Adjust alpha for shade open & close. float expansion = ambientState.getExpansionFraction(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java index 660aa3f641c4..1b9e5b304635 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java @@ -15,6 +15,8 @@ */ package com.android.systemui.statusbar.phone; +import static com.android.systemui.flags.Flags.NEW_AOD_TRANSITION; + import android.content.Context; import android.content.res.Resources; import android.graphics.Color; @@ -109,6 +111,8 @@ public class LegacyNotificationIconAreaControllerImpl implements private final ViewRefactorFlag mShelfRefactor; + private final boolean mNewAodTransition; + private int mAodIconAppearTranslation; private boolean mAnimationsEnabled; @@ -147,6 +151,7 @@ public class LegacyNotificationIconAreaControllerImpl implements mContext = context; mStatusBarStateController = statusBarStateController; mShelfRefactor = new ViewRefactorFlag(featureFlags, Flags.NOTIFICATION_SHELF_REFACTOR); + mNewAodTransition = featureFlags.isEnabled(NEW_AOD_TRANSITION); mStatusBarStateController.addCallback(this); mMediaManager = notificationMediaManager; mDozeParameters = dozeParameters; @@ -609,9 +614,11 @@ public class LegacyNotificationIconAreaControllerImpl implements boolean animate = true; if (!mBypassController.getBypassEnabled()) { animate = mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking(); - // We only want the appear animations to happen when the notifications get fully hidden, - // since otherwise the unhide animation overlaps - animate &= fullyHidden; + if (!mNewAodTransition) { + // We only want the appear animations to happen when the notifications get fully + // hidden, since otherwise the unhide animation overlaps + animate &= fullyHidden; + } } updateAodIconsVisibility(animate, false /* force */); updateAodNotificationIcons(); @@ -647,23 +654,34 @@ public class LegacyNotificationIconAreaControllerImpl implements mAodIconsVisible = visible; mAodIcons.animate().cancel(); if (animate) { - boolean wasFullyInvisible = mAodIcons.getVisibility() != View.VISIBLE; - if (mAodIconsVisible) { - if (wasFullyInvisible) { - // No fading here, let's just appear the icons instead! - mAodIcons.setVisibility(View.VISIBLE); - mAodIcons.setAlpha(1.0f); - appearAodIcons(); + if (mNewAodTransition) { + // Let's make sure the icon are translated to 0, since we cancelled it above + animateInAodIconTranslation(); + if (mAodIconsVisible) { + CrossFadeHelper.fadeIn(mAodIcons); + } else { + CrossFadeHelper.fadeOut(mAodIcons); + } + } else { + boolean wasFullyInvisible = mAodIcons.getVisibility() != View.VISIBLE; + if (mAodIconsVisible) { + if (wasFullyInvisible) { + // No fading here, let's just appear the icons instead! + mAodIcons.setVisibility(View.VISIBLE); + mAodIcons.setAlpha(1.0f); + appearAodIcons(); + } else { + // Let's make sure the icon are translated to 0, since we cancelled it + // above + animateInAodIconTranslation(); + // We were fading out, let's fade in instead + CrossFadeHelper.fadeIn(mAodIcons); + } } else { // Let's make sure the icon are translated to 0, since we cancelled it above animateInAodIconTranslation(); - // We were fading out, let's fade in instead - CrossFadeHelper.fadeIn(mAodIcons); + CrossFadeHelper.fadeOut(mAodIcons); } - } else { - // Let's make sure the icon are translated to 0, since we cancelled it above - animateInAodIconTranslation(); - CrossFadeHelper.fadeOut(mAodIcons); } } else { mAodIcons.setAlpha(1.0f); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java index a2dc7763d0ea..7b920939263e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java @@ -17,9 +17,11 @@ package com.android.keyguard; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; + import static com.android.keyguard.LockIconView.ICON_LOCK; import static com.android.keyguard.LockIconView.ICON_UNLOCK; import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; @@ -41,6 +43,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.biometrics.UdfpsController; import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams; import com.android.systemui.doze.util.BurnInHelperKt; +import com.android.systemui.statusbar.StatusBarState; import org.junit.Test; import org.junit.runner.RunWith; @@ -180,13 +183,14 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest { } @Test - public void testLockIcon_clearsIconOnAod_whenUdfpsNotEnrolled() { + public void testLockIcon_clearsIconWhenUnlocked() { // GIVEN udfps not enrolled setupUdfps(); when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(false); // GIVEN starting state for the lock icon setupShowLockIcon(); + when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); // GIVEN lock icon controller is initialized and view is attached init(/* useMigrationFlag= */false); @@ -194,7 +198,7 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest { reset(mLockIconView); // WHEN the dozing state changes - mStatusBarStateListener.onDozingChanged(true /* isDozing */); + mStatusBarStateListener.onDozingChanged(false /* isDozing */); // THEN the icon is cleared verify(mLockIconView).clearIcon(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt index c372f4555f61..12135182ac15 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.statusbar.StatusBarState import com.android.systemui.util.mockito.whenever import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking @@ -42,7 +43,7 @@ class LockIconViewControllerWithCoroutinesTest : LockIconViewControllerBaseTest( /** After migration, replaces LockIconViewControllerTest version */ @Test - fun testLockIcon_clearsIconOnAod_whenUdfpsNotEnrolled() = + fun testLockIcon_clearsIconWhenUnlocked() = runBlocking(IMMEDIATE) { // GIVEN udfps not enrolled setupUdfps() @@ -50,14 +51,14 @@ class LockIconViewControllerWithCoroutinesTest : LockIconViewControllerBaseTest( // GIVEN starting state for the lock icon setupShowLockIcon() + whenever(mStatusBarStateController.state).thenReturn(StatusBarState.SHADE) // GIVEN lock icon controller is initialized and view is attached init(/* useMigrationFlag= */ true) reset(mLockIconView) // WHEN the dozing state changes - mUnderTest.mIsDozingCallback.accept(true) - + mUnderTest.mIsDozingCallback.accept(false) // THEN the icon is cleared verify(mLockIconView).clearIcon() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt index 9e9c25eafa33..fa93253642e3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt @@ -230,4 +230,432 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() { assertThat(startedSteps).isEqualTo(listOf(0f, 0.5f, 1f, 1f, 0.5f, 0f)) } + + @Test + fun isInTransitionToState() = testScope.runTest { + val results by collectValues(underTest.isInTransitionToState(GONE)) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + TransitionStep(GONE, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + @Test + fun isInTransitionFromState() = testScope.runTest { + val results by collectValues(underTest.isInTransitionFromState(DOZING)) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + TransitionStep(GONE, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + @Test + fun isInTransitionFromStateWhere() = testScope.runTest { + val results by collectValues(underTest.isInTransitionFromStateWhere { + it == DOZING + }) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + TransitionStep(GONE, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + @Test + fun isInTransitionWhere() = testScope.runTest { + val results by collectValues(underTest.isInTransitionWhere( + fromStatePredicate = { it == DOZING }, + toStatePredicate = { it == GONE }, + )) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + TransitionStep(GONE, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + @Test + fun isFinishedInStateWhere() = testScope.runTest { + val results by collectValues(underTest.isFinishedInStateWhere { it == GONE } ) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, // Finished in DOZING, not GONE. + )) + + sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED)) + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING)) + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps(TransitionStep(GONE, DOZING, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + @Test + fun isFinishedInState() = testScope.runTest { + val results by collectValues(underTest.isFinishedInState(GONE)) + + sendSteps( + TransitionStep(AOD, DOZING, 0f, STARTED), + TransitionStep(AOD, DOZING, 0.5f, RUNNING), + TransitionStep(AOD, DOZING, 1f, FINISHED), + ) + + assertThat(results).isEqualTo(listOf( + false, // Finished in DOZING, not GONE. + )) + + sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED)) + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING)) + + assertThat(results).isEqualTo(listOf( + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps( + TransitionStep(GONE, DOZING, 0f, STARTED), + TransitionStep(GONE, DOZING, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + )) + + sendSteps(TransitionStep(GONE, DOZING, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps( + TransitionStep(DOZING, GONE, 0f, STARTED), + TransitionStep(DOZING, GONE, 0f, RUNNING), + ) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + )) + + sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED)) + + assertThat(results).isEqualTo(listOf( + false, + true, + false, + true, + )) + } + + private suspend fun sendSteps(vararg steps: TransitionStep) { + steps.forEach { + repository.sendTransitionStep(it) + testScope.runCurrent() + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 3a820e8087a8..236bcb416573 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -163,6 +163,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mFeatureFlags.setDefault(Flags.SENSITIVE_REVEAL_ANIM); mFeatureFlags.setDefault(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS); mFeatureFlags.setDefault(Flags.NOTIFICATION_SHELF_REFACTOR); + mFeatureFlags.setDefault(Flags.NEW_AOD_TRANSITION); // Inject dependencies before initializing the layout mDependency.injectTestDependency(FeatureFlags.class, mFeatureFlags); @@ -247,25 +248,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - public void testUpdateStackHeight_withDozeAmount_whenDozeChanging() { - final float dozeAmount = 0.5f; - mAmbientState.setDozeAmount(dozeAmount); - - final float endHeight = 8f; - final float expansionFraction = 1f; - float expected = MathUtils.lerp( - endHeight * StackScrollAlgorithm.START_FRACTION, - endHeight, dozeAmount); - - mStackScroller.updateStackHeight(endHeight, expansionFraction); - assertThat(mAmbientState.getStackHeight()).isEqualTo(expected); - } - - @Test public void testUpdateStackHeight_withExpansionAmount_whenDozeNotChanging() { - final float dozeAmount = 1f; - mAmbientState.setDozeAmount(dozeAmount); - final float endHeight = 8f; final float expansionFraction = 0.5f; final float expected = MathUtils.lerp( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index a52466d2fa41..93faa77bef5c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -241,6 +241,8 @@ class StackScrollAlgorithmTest : SysuiTestCase() { fun resetViewStates_isOnKeyguard_viewBecomesTransparent() { ambientState.setStatusBarState(StatusBarState.KEYGUARD) ambientState.hideAmount = 0.25f + whenever(notificationRow.isHeadsUpState).thenReturn(true) + stackScrollAlgorithm.initView(context) stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) @@ -283,17 +285,20 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val row2 = mockExpandableNotificationRow() hostView.addView(row2) + whenever(row1.isHeadsUpState).thenReturn(true) + whenever(row2.isHeadsUpState).thenReturn(false) + ambientState.setStatusBarState(StatusBarState.KEYGUARD) ambientState.hideAmount = 0.25f + ambientState.dozeAmount = 0.33f notificationShelf.viewState.hidden = true ambientState.shelf = notificationShelf stackScrollAlgorithm.initView(context) stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) - val expected = 1f - ambientState.hideAmount - assertThat(row1.viewState.alpha).isEqualTo(expected) - assertThat(row2.viewState.alpha).isEqualTo(expected) + assertThat(row1.viewState.alpha).isEqualTo(1f - ambientState.hideAmount) + assertThat(row2.viewState.alpha).isEqualTo(1f - ambientState.dozeAmount) } @Test diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 55130e4cbbe6..987507fe7f03 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -16,9 +16,6 @@ per-file UserspaceRebootLogger.java = ioffe@google.com, dvander@google.com # ServiceWatcher per-file ServiceWatcher.java = sooniln@google.com -# Health -per-file BatteryService.java = file:platform/hardware/interfaces:/health/aidl/OWNERS - per-file *Accessibility* = file:/services/accessibility/OWNERS per-file *Alarm* = file:/apex/jobscheduler/OWNERS per-file *AppOp* = file:/core/java/android/permission/OWNERS @@ -39,7 +36,7 @@ per-file MmsServiceBroker.java = file:/telephony/OWNERS per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS per-file PinnerService.java = file:/apct-tests/perftests/OWNERS -per-file RescueParty.java = fdunlap@google.com, shuc@google.com, ancr@google.com, harshitmahajan@google.com +per-file RescueParty.java = shuc@google.com, ancr@google.com, harshitmahajan@google.com per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS per-file TelephonyRegistry.java = file:/telephony/OWNERS diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index a3c71c2e0218..db69d93583d4 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -541,6 +541,13 @@ public class NotificationManagerService extends SystemService { @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) private static final long NOTIFICATION_LOG_ASSISTANT_CANCEL = 195579280L; + /** + * NO_CLEAR flag will be set for any media notification. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + static final long ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION = 264179692L; + private static final Duration POST_WAKE_LOCK_TIMEOUT = Duration.ofSeconds(30); private IActivityManager mAm; @@ -7189,6 +7196,12 @@ public class NotificationManagerService extends SystemService { + "MEDIA_CONTENT_CONTROL permission"); } } + + // Enforce NO_CLEAR flag on MediaStyle notification for apps with targetSdk >= V. + if (CompatChanges.isChangeEnabled(ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION, + notificationUid)) { + notification.flags |= Notification.FLAG_NO_CLEAR; + } } // Ensure only allowed packages have a substitute app name diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp index 2dacda0af7f4..1d37f9da8d7a 100644 --- a/services/tests/uiservicestests/Android.bp +++ b/services/tests/uiservicestests/Android.bp @@ -31,6 +31,7 @@ android_test { "androidx.test.rules", "hamcrest-library", "mockito-target-inline-minus-junit4", + "platform-compat-test-rules", "platform-test-annotations", "platformprotosnano", "statsdprotolite", 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 9543a2de1e13..c98d2359b2f9 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -164,6 +164,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.usage.UsageStatsManagerInternal; import android.companion.AssociationInfo; import android.companion.ICompanionDeviceManager; +import android.compat.testing.PlatformCompatChangeRule; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentUris; @@ -270,11 +271,15 @@ import com.android.server.wm.WindowManagerInternal; import com.google.android.collect.Lists; import com.google.common.collect.ImmutableList; +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; @@ -317,6 +322,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { private final int mUid = Binder.getCallingUid(); private final @UserIdInt int mUserId = UserHandle.getUserId(mUid); + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + private TestableNotificationManagerService mService; private INotificationManager mBinderService; private NotificationManagerInternal mInternalService; @@ -4828,6 +4836,62 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + @EnableCompatChanges({NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION}) + public void testMediaStyle_enforceNoClearFlagEnabled() throws RemoteException { + Notification.MediaStyle style = new Notification.MediaStyle(); + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setStyle(style); + + NotificationRecord posted = createAndPostNotification(nb, "testMediaStyleSetNoClearFlag"); + + assertThat(posted.getFlags() & FLAG_NO_CLEAR).isEqualTo(FLAG_NO_CLEAR); + } + + @Test + @EnableCompatChanges({NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION}) + public void testCustomMediaStyle_enforceNoClearFlagEnabled() throws RemoteException { + Notification.DecoratedMediaCustomViewStyle style = + new Notification.DecoratedMediaCustomViewStyle(); + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setStyle(style); + + NotificationRecord posted = createAndPostNotification(nb, + "testCustomMediaStyleSetNoClearFlag"); + + assertThat(posted.getFlags() & FLAG_NO_CLEAR).isEqualTo(FLAG_NO_CLEAR); + } + + @Test + @DisableCompatChanges(NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION) + public void testMediaStyle_enforceNoClearFlagDisabled() throws RemoteException { + Notification.MediaStyle style = new Notification.MediaStyle(); + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setStyle(style); + + NotificationRecord posted = createAndPostNotification(nb, "testMediaStyleSetNoClearFlag"); + + assertThat(posted.getFlags() & FLAG_NO_CLEAR).isNotEqualTo(FLAG_NO_CLEAR); + } + + @Test + @DisableCompatChanges(NotificationManagerService.ENFORCE_NO_CLEAR_FLAG_ON_MEDIA_NOTIFICATION) + public void testCustomMediaStyle_enforceNoClearFlagDisabled() throws RemoteException { + Notification.DecoratedMediaCustomViewStyle style = + new Notification.DecoratedMediaCustomViewStyle(); + Notification.Builder nb = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setStyle(style); + + NotificationRecord posted = createAndPostNotification(nb, + "testCustomMediaStyleSetNoClearFlag"); + + assertThat(posted.getFlags() & FLAG_NO_CLEAR).isNotEqualTo(FLAG_NO_CLEAR); + } + + @Test public void testMediaStyleRemote_hasPermission() throws RemoteException { String deviceName = "device"; mContext.getTestablePermissions().setPermission( @@ -4838,17 +4902,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mTestNotificationChannel.getId()) .setStyle(style); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testMediaStyleRemoteHasPermission", mUid, 0, - nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), - nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); - waitForIdle(); - - NotificationRecord posted = mService.findNotificationLocked( - PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + NotificationRecord posted = createAndPostNotification(nb, + "testMediaStyleRemoteHasPermission"); Bundle extras = posted.getNotification().extras; assertTrue(extras.containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); @@ -4866,17 +4921,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mTestNotificationChannel.getId()) .setStyle(style); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testMediaStyleRemoteNoPermission", mUid, 0, - nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), - nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); - waitForIdle(); - - NotificationRecord posted = mService.findNotificationLocked( - PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + NotificationRecord posted = createAndPostNotification(nb, + "testMediaStyleRemoteNoPermission"); assertFalse(posted.getNotification().extras .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); @@ -4899,17 +4945,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mTestNotificationChannel.getId()) .setStyle(style); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testCustomMediaStyleRemoteNoPermission", mUid, 0, - nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), - nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); - waitForIdle(); - - NotificationRecord posted = mService.findNotificationLocked( - PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + NotificationRecord posted = createAndPostNotification(nb, + "testCustomMediaStyleRemoteNoPermission"); assertFalse(posted.getNotification().extras .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE)); @@ -4929,16 +4966,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { Notification.Builder nb = new Notification.Builder(mContext, mTestNotificationChannel.getId()) .addExtras(extras); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testSubstituteAppNamePermission", mUid, 0, - nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), - nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); - waitForIdle(); - NotificationRecord posted = mService.findNotificationLocked( - PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + NotificationRecord posted = createAndPostNotification(nb, + "testSubstituteAppNameHasPermission"); assertTrue(posted.getNotification().extras .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); @@ -4955,16 +4985,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { Notification.Builder nb = new Notification.Builder(mContext, mTestNotificationChannel.getId()) .addExtras(extras); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, - "testSubstituteAppNamePermission", mUid, 0, - nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); - NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), - nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); - waitForIdle(); - NotificationRecord posted = mService.findNotificationLocked( - PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + NotificationRecord posted = createAndPostNotification(nb, + "testSubstituteAppNameNoPermission"); assertFalse(posted.getNotification().extras .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)); @@ -12656,6 +12679,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(service, times(1)).setDNDMigrationDone(user.id); } + private NotificationRecord createAndPostNotification(Notification.Builder nb, String testName) + throws RemoteException { + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, testName, mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), + nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); + waitForIdle(); + + return mService.findNotificationLocked( + PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId()); + } + private static <T extends Parcelable> T parcelAndUnparcel(T source, Parcelable.Creator<T> creator) { Parcel parcel = Parcel.obtain(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index a5e0638fec95..98bbb40282c9 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -519,8 +519,6 @@ public class CarrierConfigManager { /** * Used in the Preferred Network Types menu to determine if the 2G option is displayed. * Value defaults to false as of Android T to discourage the use of insecure 2G protocols. - * - * @see #KEY_HIDE_ENABLE_2G */ public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool"; @@ -9541,9 +9539,9 @@ public class CarrierConfigManager { * Used to trade privacy/security against potentially reduced carrier coverage for some * carriers. * - * @deprecated Future versions of Android will disallow carriers from hiding this toggle - * because disabling 2g is a security feature that users should always have access to at - * their discretion. + * @removed This config option is no longer supported as it was hiding a security feature + * from users. Setting this option will not change the behavior of the Settings menu starting + * in Android V. */ @Deprecated public static final String KEY_HIDE_ENABLE_2G = "hide_enable_2g_bool"; diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index c30786f4e1c4..da51eff24dc1 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -17,6 +17,7 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation +import android.content.Intent import android.media.session.MediaController import android.media.session.MediaSessionManager import android.tools.common.datatypes.Rect @@ -267,6 +268,11 @@ open class PipAppHelper(instrumentation: Instrumentation) : fun exitPipToFullScreenViaIntent(wmHelper: WindowManagerStateHelper) = launchViaIntent(wmHelper) + fun changeAspectRatio() { + val intent = Intent("com.android.wm.shell.flicker.testapp.ASPECT_RATIO") + context.sendBroadcast(intent) + } + fun clickEnterPipButton(wmHelper: WindowManagerStateHelper) { clickObject(ENTER_PIP_BUTTON_ID) diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java index cdb1d42bd4f2..12eaad108fc6 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/PipActivity.java @@ -82,6 +82,8 @@ public class PipActivity extends Activity { "com.android.wm.shell.flicker.testapp.SWITCH_OFF"; private static final String ACTION_SWITCH_ON = "com.android.wm.shell.flicker.testapp.SWITCH_ON"; private static final String ACTION_CLEAR = "com.android.wm.shell.flicker.testapp.CLEAR"; + private static final String ACTION_ASPECT_RATIO = + "com.android.wm.shell.flicker.testapp.ASPECT_RATIO"; private final PictureInPictureParams.Builder mPipParamsBuilder = new PictureInPictureParams.Builder() @@ -109,6 +111,9 @@ public class PipActivity extends Activity { case ACTION_CLEAR: mPipParamsBuilder.setActions(Collections.emptyList()); break; + case ACTION_ASPECT_RATIO: + mPipParamsBuilder.setAspectRatio(RATIO_TALL); + break; case ACTION_NO_OP: return; default: @@ -190,6 +195,7 @@ public class PipActivity extends Activity { filter.addAction(ACTION_CLEAR); filter.addAction(ACTION_SET_REQUESTED_ORIENTATION); filter.addAction(ACTION_ENTER_PIP); + filter.addAction(ACTION_ASPECT_RATIO); registerReceiver(mBroadcastReceiver, filter); handleIntentExtra(getIntent()); |