summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/animation/AnimatorSet.java22
-rw-r--r--core/java/android/app/IGameManagerService.aidl3
-rw-r--r--core/java/android/app/IGameStateListener.aidl27
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java22
-rw-r--r--core/java/android/os/GraphicsEnvironment.java68
-rw-r--r--core/java/android/util/FeatureFlagUtils.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java34
-rw-r--r--core/java/android/widget/ScrollView.java2
-rw-r--r--core/java/android/window/TaskFragmentOperation.java10
-rw-r--r--core/jni/android_os_GraphicsEnvironment.cpp6
-rw-r--r--core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java65
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java5
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java27
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java71
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPinContainer.java47
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java16
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java83
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java45
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java2
-rw-r--r--libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.kt6
-rw-r--r--libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt10
-rw-r--r--libs/dream/lowlight/src/com/android/dream/lowlight/util/TruncatedInterpolator.kt54
-rw-r--r--libs/dream/lowlight/tests/Android.bp1
-rw-r--r--libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.kt15
-rw-r--r--libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.kt20
-rw-r--r--libs/dream/lowlight/tests/src/com/android/dream/lowlight/util/TruncatedInterpolatorTest.kt53
-rw-r--r--packages/SystemUI/res/layout/status_bar_wifi_group.xml28
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java541
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java192
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java26
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java11
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java249
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java136
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java149
-rw-r--r--packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto57
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt57
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt55
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt40
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java5
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java14
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java51
-rw-r--r--services/core/java/com/android/server/biometrics/Utils.java28
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java40
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/Transition.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java14
-rw-r--r--services/java/com/android/server/SystemServer.java11
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java186
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java66
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java41
130 files changed, 1799 insertions, 2141 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 70c3d7ae3f82..f33d2991329a 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1346,8 +1346,26 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
}
// Set the child animators to the right end:
if (mShouldResetValuesAtStart) {
- initChildren();
- skipToEndValue(!mReversing);
+ if (isInitialized()) {
+ skipToEndValue(!mReversing);
+ } else if (mReversing) {
+ // Reversing but haven't initialized all the children yet.
+ initChildren();
+ skipToEndValue(!mReversing);
+ } else {
+ // If not all children are initialized and play direction is forward
+ for (int i = mEvents.size() - 1; i >= 0; i--) {
+ if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ Animator anim = mEvents.get(i).mNode.mAnimation;
+ // Only reset the animations that have been initialized to start value,
+ // so that if they are defined without a start value, they will get the
+ // values set at the right time (i.e. the next animation run)
+ if (anim.isInitialized()) {
+ anim.skipToEndValue(true);
+ }
+ }
+ }
+ }
}
if (mReversing || mStartDelay == 0 || mSeekState.isActive()) {
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index 3d6ab6fd9478..9a818e49ae4a 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -20,6 +20,7 @@ import android.app.GameModeConfiguration;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
/**
* @hide
@@ -49,4 +50,6 @@ interface IGameManagerService {
void addGameModeListener(IGameModeListener gameModeListener);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)")
void removeGameModeListener(IGameModeListener gameModeListener);
+ void addGameStateListener(IGameStateListener gameStateListener);
+ void removeGameStateListener(IGameStateListener gameStateListener);
}
diff --git a/core/java/android/app/IGameStateListener.aidl b/core/java/android/app/IGameStateListener.aidl
new file mode 100644
index 000000000000..34cff489d077
--- /dev/null
+++ b/core/java/android/app/IGameStateListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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 android.app;
+
+import android.app.GameState;
+
+/** @hide */
+interface IGameStateListener {
+ /**
+ * Called when the state of the game has changed.
+ */
+ oneway void onGameStateChanged(String packageName, in GameState state, int userId);
+}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a9c4818393a8..e472a40617ee 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -103,11 +103,10 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
-import android.view.BatchedInputEventReceiver.SimpleBatchedInputEventReceiver;
-import android.view.Choreographer;
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -1052,17 +1051,22 @@ public class InputMethodService extends AbstractInputMethodService {
stylusEvents.forEach(InputMethodService.this::onStylusHandwritingMotionEvent);
// create receiver for channel
- mHandwritingEventReceiver = new SimpleBatchedInputEventReceiver(
- channel,
- Looper.getMainLooper(), Choreographer.getInstance(),
- event -> {
+ mHandwritingEventReceiver = new InputEventReceiver(channel, Looper.getMainLooper()) {
+ @Override
+ public void onInputEvent(InputEvent event) {
+ boolean handled = false;
+ try {
if (!(event instanceof MotionEvent)) {
- return false;
+ return;
}
onStylusHandwritingMotionEvent((MotionEvent) event);
scheduleHandwritingSessionTimeout();
- return true;
- });
+ handled = true;
+ } finally {
+ finishInputEvent(event, handled);
+ }
+ }
+ };
scheduleHandwritingSessionTimeout();
}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 7664bada2c28..e6bdfe1b95c4 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -112,17 +112,9 @@ public class GraphicsEnvironment {
private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0;
// Values for ANGLE_GL_DRIVER_SELECTION_VALUES
- private enum AngleDriverChoice {
- DEFAULT("default"),
- ANGLE("angle"),
- NATIVE("native");
-
- public final String choice;
-
- AngleDriverChoice(String choice) {
- this.choice = choice;
- }
- }
+ private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default";
+ private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle";
+ private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
@@ -203,16 +195,15 @@ public class GraphicsEnvironment {
}
/**
- * Query to determine the ANGLE driver choice.
+ * Query to determine if ANGLE should be used
*/
- private AngleDriverChoice queryAngleChoice(Context context, Bundle coreSettings,
- String packageName) {
+ private boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) {
if (TextUtils.isEmpty(packageName)) {
Log.v(TAG, "No package name specified; use the system driver");
- return AngleDriverChoice.DEFAULT;
+ return false;
}
- return queryAngleChoiceInternal(context, coreSettings, packageName);
+ return shouldUseAngleInternal(context, coreSettings, packageName);
}
private int getVulkanVersion(PackageManager pm) {
@@ -433,11 +424,10 @@ public class GraphicsEnvironment {
* forces a choice;
* 3) Use ANGLE if isAngleEnabledByGameMode() returns true;
*/
- private AngleDriverChoice queryAngleChoiceInternal(Context context, Bundle bundle,
- String packageName) {
+ private boolean shouldUseAngleInternal(Context context, Bundle bundle, String packageName) {
// Make sure we have a good package name
if (TextUtils.isEmpty(packageName)) {
- return AngleDriverChoice.DEFAULT;
+ return false;
}
// Check the semi-global switch (i.e. once system has booted enough) for whether ANGLE
@@ -452,7 +442,7 @@ public class GraphicsEnvironment {
}
if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) {
Log.v(TAG, "Turn on ANGLE for all applications.");
- return AngleDriverChoice.ANGLE;
+ return true;
}
// Get the per-application settings lists
@@ -475,7 +465,7 @@ public class GraphicsEnvironment {
+ optInPackages.size() + ", "
+ "number of values: "
+ optInValues.size());
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
// See if this application is listed in the per-application settings list
@@ -483,7 +473,7 @@ public class GraphicsEnvironment {
if (pkgIndex < 0) {
Log.v(TAG, packageName + " is not listed in per-application setting");
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
mAngleOptInIndex = pkgIndex;
@@ -493,14 +483,14 @@ public class GraphicsEnvironment {
Log.v(TAG,
"ANGLE Developer option for '" + packageName + "' "
+ "set to: '" + optInValue + "'");
- if (optInValue.equals(AngleDriverChoice.ANGLE.choice)) {
- return AngleDriverChoice.ANGLE;
- } else if (optInValue.equals(AngleDriverChoice.NATIVE.choice)) {
- return AngleDriverChoice.NATIVE;
+ if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) {
+ return true;
+ } else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) {
+ return false;
} else {
// The user either chose default or an invalid value; go with the default driver or what
// the game mode indicates
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
}
@@ -568,13 +558,7 @@ public class GraphicsEnvironment {
private boolean setupAngle(Context context, Bundle bundle, PackageManager packageManager,
String packageName) {
- final AngleDriverChoice angleDriverChoice = queryAngleChoice(context, bundle, packageName);
- if (angleDriverChoice == AngleDriverChoice.DEFAULT) {
- return false;
- }
-
- if (queryAngleChoice(context, bundle, packageName) == AngleDriverChoice.NATIVE) {
- nativeSetAngleInfo("", true, packageName, null);
+ if (!shouldUseAngle(context, bundle, packageName)) {
return false;
}
@@ -643,10 +627,10 @@ public class GraphicsEnvironment {
Log.d(TAG, "ANGLE package libs: " + paths);
}
- // If we make it to here, ANGLE apk will be used. Call nativeSetAngleInfo() with the
- // application package name and ANGLE features to use.
+ // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name,
+ // and features to use.
final String[] features = getAngleEglFeatures(context, bundle);
- nativeSetAngleInfo(paths, false, packageName, features);
+ setAngleInfo(paths, false, packageName, features);
return true;
}
@@ -668,10 +652,10 @@ public class GraphicsEnvironment {
return false;
}
- // If we make it to here, system ANGLE will be used. Call nativeSetAngleInfo() with
- // the application package name and ANGLE features to use.
+ // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name,
+ // and features to use.
final String[] features = getAngleEglFeatures(context, bundle);
- nativeSetAngleInfo("system", false, packageName, features);
+ setAngleInfo("", true, packageName, features);
return true;
}
@@ -952,8 +936,8 @@ public class GraphicsEnvironment {
private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion);
- private static native void nativeSetAngleInfo(String path, boolean useNativeDriver,
- String packageName, String[] features);
+ private static native void setAngleInfo(String path, boolean useSystemAngle, String packageName,
+ String[] features);
private static native boolean setInjectLayersPrSetDumpable();
private static native void nativeToggleAngleAsSystemDriver(boolean enabled);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 0071a0d00105..827600c83fae 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -149,6 +149,13 @@ public class FeatureFlagUtils {
*/
public static final String SETTINGS_BIOMETRICS2_ENROLLMENT = "settings_biometrics2_enrollment";
+ /**
+ * Flag to enable/disable FingerprintSettings v2
+ * @hide
+ */
+ public static final String SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS =
+ "settings_biometrics2_fingerprint";
+
/** Flag to enable/disable entire page in Accessibility -> Hearing aids
* @hide
*/
@@ -239,6 +246,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "true");
+ DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_FINGERPRINT_SETTINGS, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 3f308e6fccee..b3233141f126 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -50,6 +50,7 @@ import android.annotation.TestApi;
import android.annotation.UiThread;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
+import android.app.PropertyInvalidatedCache;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -536,6 +537,13 @@ public final class InputMethodManager {
@UnsupportedAppUsage
Rect mCursorRect = new Rect();
+ /** Cached value for {@link #isStylusHandwritingAvailable} for userId. */
+ @GuardedBy("mH")
+ private PropertyInvalidatedCache<Integer, Boolean> mStylusHandwritingAvailableCache;
+
+ private static final String CACHE_KEY_STYLUS_HANDWRITING_PROPERTY =
+ "cache_key.system_server.stylus_handwriting";
+
@GuardedBy("mH")
private int mCursorSelStart;
@GuardedBy("mH")
@@ -662,6 +670,15 @@ public final class InputMethodManager {
private static final int MSG_UPDATE_VIRTUAL_DISPLAY_TO_SCREEN_MATRIX = 30;
private static final int MSG_ON_SHOW_REQUESTED = 31;
+ /**
+ * Calling this will invalidate Local stylus handwriting availability Cache which
+ * forces the next query in any process to recompute the cache.
+ * @hide
+ */
+ public static void invalidateLocalStylusHandwritingAvailabilityCaches() {
+ PropertyInvalidatedCache.invalidateCache(CACHE_KEY_STYLUS_HANDWRITING_PROPERTY);
+ }
+
private static boolean isAutofillUIShowing(View servedView) {
AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
return afm != null && afm.isAutofillUiShowing();
@@ -1577,8 +1594,21 @@ public final class InputMethodManager {
if (fallbackContext == null) {
return false;
}
-
- return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(userId);
+ boolean isAvailable;
+ synchronized (mH) {
+ if (mStylusHandwritingAvailableCache == null) {
+ mStylusHandwritingAvailableCache = new PropertyInvalidatedCache<>(
+ 4 /* maxEntries */, CACHE_KEY_STYLUS_HANDWRITING_PROPERTY) {
+ @Override
+ public Boolean recompute(Integer userId) {
+ return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(
+ userId);
+ }
+ };
+ }
+ isAvailable = mStylusHandwritingAvailableCache.query(userId);
+ }
+ return isAvailable;
}
/**
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index b65c1a17e26b..cb5dbe6c5618 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1550,6 +1550,7 @@ public class ScrollView extends FrameLayout {
float deltaDistance = -unconsumed * FLING_DESTRETCH_FACTOR / size;
int consumed = Math.round(-size / FLING_DESTRETCH_FACTOR
* mEdgeGlowTop.onPullDistance(deltaDistance, 0.5f));
+ mEdgeGlowTop.onRelease();
if (consumed != unconsumed) {
mEdgeGlowTop.finish();
}
@@ -1560,6 +1561,7 @@ public class ScrollView extends FrameLayout {
float deltaDistance = unconsumed * FLING_DESTRETCH_FACTOR / size;
int consumed = Math.round(size / FLING_DESTRETCH_FACTOR
* mEdgeGlowBottom.onPullDistance(deltaDistance, 0.5f));
+ mEdgeGlowBottom.onRelease();
if (consumed != unconsumed) {
mEdgeGlowBottom.finish();
}
diff --git a/core/java/android/window/TaskFragmentOperation.java b/core/java/android/window/TaskFragmentOperation.java
index 413f0ccbc275..e153bb70a7ca 100644
--- a/core/java/android/window/TaskFragmentOperation.java
+++ b/core/java/android/window/TaskFragmentOperation.java
@@ -73,6 +73,13 @@ public final class TaskFragmentOperation implements Parcelable {
/** Sets the relative bounds with {@link WindowContainerTransaction#setRelativeBounds}. */
public static final int OP_TYPE_SET_RELATIVE_BOUNDS = 9;
+ /**
+ * Reorders the TaskFragment to be the front-most TaskFragment in the Task.
+ * Note that there could still have other WindowContainer on top of the front-most
+ * TaskFragment, such as a non-embedded Activity.
+ */
+ public static final int OP_TYPE_REORDER_TO_FRONT = 10;
+
@IntDef(prefix = { "OP_TYPE_" }, value = {
OP_TYPE_UNKNOWN,
OP_TYPE_CREATE_TASK_FRAGMENT,
@@ -84,7 +91,8 @@ public final class TaskFragmentOperation implements Parcelable {
OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT,
OP_TYPE_SET_COMPANION_TASK_FRAGMENT,
OP_TYPE_SET_ANIMATION_PARAMS,
- OP_TYPE_SET_RELATIVE_BOUNDS
+ OP_TYPE_SET_RELATIVE_BOUNDS,
+ OP_TYPE_REORDER_TO_FRONT
})
@Retention(RetentionPolicy.SOURCE)
public @interface OperationType {}
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 8fc30d1c248d..afc3cbd15f88 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -50,7 +50,7 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
appPackageNameChars.c_str(), vulkanVersion);
}
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useNativeDriver,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useSystemAngle,
jstring packageName, jobjectArray featuresObj) {
ScopedUtfChars pathChars(env, path);
ScopedUtfChars packageNameChars(env, packageName);
@@ -73,7 +73,7 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useN
}
}
- android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useNativeDriver,
+ android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useSystemAngle,
packageNameChars.c_str(), features);
}
@@ -118,7 +118,7 @@ const JNINativeMethod g_methods[] = {
reinterpret_cast<void*>(setGpuStats_native)},
{"setInjectLayersPrSetDumpable", "()Z",
reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)},
- {"nativeSetAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V",
+ {"setAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V",
reinterpret_cast<void*>(setAngleInfo_native)},
{"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V",
reinterpret_cast<void*>(setLayerPaths_native)},
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
index 0525443ecf82..0c0747060f48 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue;
import android.util.Property;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ActivityTestRule;
@@ -36,6 +37,8 @@ import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
@SmallTest
public class AnimatorSetActivityTest {
@@ -613,6 +616,68 @@ public class AnimatorSetActivityTest {
});
}
+ @Test
+ public void initAfterStartNotification() throws Throwable {
+ Property<int[], Integer> property = new Property<>(Integer.class, "firstValue") {
+ @Override
+ public Integer get(int[] target) {
+ throw new IllegalStateException("Shouldn't be called");
+ }
+
+ @Override
+ public void set(int[] target, Integer value) {
+ target[0] = value;
+ }
+ };
+ int[] target = new int[1];
+ ObjectAnimator animator1 = ObjectAnimator.ofInt(target, property, 0, 100);
+ ObjectAnimator animator2 = ObjectAnimator.ofInt(target, property, 0, 100);
+ ObjectAnimator animator3 = ObjectAnimator.ofInt(target, property, 0, 100);
+ animator1.setDuration(10);
+ animator2.setDuration(10);
+ animator3.setDuration(10);
+ AnimatorSet set = new AnimatorSet();
+ set.playSequentially(animator1, animator2, animator3);
+ final int[] values = new int[4];
+ animator2.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
+ values[0] = target[0];
+ animator2.setIntValues(target[0], target[0] + 100);
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+ values[1] = target[0];
+ }
+ });
+ animator3.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(@NonNull Animator animation, boolean isReverse) {
+ values[2] = target[0];
+ animator3.setIntValues(target[0], target[0] + 100);
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+ values[3] = target[0];
+ }
+ });
+ final CountDownLatch latch = new CountDownLatch(1);
+ set.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+ latch.countDown();
+ }
+ });
+ mActivityRule.runOnUiThread(() -> set.start());
+ assertTrue(latch.await(1, TimeUnit.SECONDS));
+ assertEquals(100, values[0]);
+ assertEquals(200, values[1]);
+ assertEquals(200, values[2]);
+ assertEquals(300, values[3]);
+ }
+
/**
* Check that the animator list contains exactly the given animators and nothing else.
*/
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index b73a87c8f0d9..48577416b3d0 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -884,12 +884,13 @@ public class ActivityThreadTest {
mConfig.setTo(config);
++mNumOfConfigChanges;
- if (mConfigLatch != null) {
+ final CountDownLatch configLatch = mConfigLatch;
+ if (configLatch != null) {
if (mTestLatch != null) {
mTestLatch.countDown();
}
try {
- mConfigLatch.await(TIMEOUT_SEC, TimeUnit.SECONDS);
+ configLatch.await(TIMEOUT_SEC, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index 76e0e1eb7a95..55eabb039c01 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -48,7 +48,7 @@ public class WindowExtensionsImpl implements WindowExtensions {
// TODO(b/241126279) Introduce constants to better version functionality
@Override
public int getVendorApiLevel() {
- return 3;
+ return 4;
}
@NonNull
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 18497ad249ee..381e9d472f0f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -32,7 +32,7 @@ import androidx.window.extensions.core.util.function.Function;
*/
class SplitContainer {
@NonNull
- private final TaskFragmentContainer mPrimaryContainer;
+ private TaskFragmentContainer mPrimaryContainer;
@NonNull
private final TaskFragmentContainer mSecondaryContainer;
@NonNull
@@ -46,17 +46,35 @@ class SplitContainer {
@NonNull
private final IBinder mToken;
+ /**
+ * Whether the selection of which container is primary can be changed at runtime. Runtime
+ * updates is currently possible only for {@link SplitPinContainer}
+ *
+ * @see SplitPinContainer
+ */
+ private final boolean mIsPrimaryContainerMutable;
+
SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
@NonNull Activity primaryActivity,
@NonNull TaskFragmentContainer secondaryContainer,
@NonNull SplitRule splitRule,
@NonNull SplitAttributes splitAttributes) {
+ this(primaryContainer, primaryActivity, secondaryContainer, splitRule, splitAttributes,
+ false /* isPrimaryContainerMutable */);
+ }
+
+ SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
+ @NonNull Activity primaryActivity,
+ @NonNull TaskFragmentContainer secondaryContainer,
+ @NonNull SplitRule splitRule,
+ @NonNull SplitAttributes splitAttributes, boolean isPrimaryContainerMutable) {
mPrimaryContainer = primaryContainer;
mSecondaryContainer = secondaryContainer;
mSplitRule = splitRule;
mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
mCurrentSplitAttributes = splitAttributes;
mToken = new Binder("SplitContainer");
+ mIsPrimaryContainerMutable = isPrimaryContainerMutable;
if (shouldFinishPrimaryWithSecondary(splitRule)) {
if (mPrimaryContainer.getRunningActivityCount() == 1
@@ -74,6 +92,13 @@ class SplitContainer {
}
}
+ void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
+ if (!mIsPrimaryContainerMutable) {
+ throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
+ }
+ mPrimaryContainer = primaryContainer;
+ }
+
@NonNull
TaskFragmentContainer getPrimaryContainer() {
return mPrimaryContainer;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 4cedd41e2d9a..a2f75e099465 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -213,6 +213,56 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
@Override
+ public boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) {
+ synchronized (mLock) {
+ final TaskContainer task = getTaskContainer(taskId);
+ if (task == null) {
+ Log.e(TAG, "Cannot find the task for id: " + taskId);
+ return false;
+ }
+
+ final TaskFragmentContainer topContainer =
+ task.getTopNonFinishingTaskFragmentContainer();
+ // Cannot pin the TaskFragment if no other TaskFragment behind it.
+ if (topContainer == null || task.indexOf(topContainer) <= 0) {
+ Log.w(TAG, "Cannot find an ActivityStack to pin or split");
+ return false;
+ }
+ // Abort if the top container is already pinned.
+ if (task.getSplitPinContainer() != null) {
+ Log.w(TAG, "There is already a pinned ActivityStack.");
+ return false;
+ }
+
+ // Find a valid adjacent TaskFragmentContainer
+ final TaskFragmentContainer primaryContainer =
+ task.getNonFinishingTaskFragmentContainerBelow(topContainer);
+ if (primaryContainer == null) {
+ Log.w(TAG, "Cannot find another ActivityStack to split");
+ return false;
+ }
+
+ // Registers a Split
+ final SplitPinContainer splitPinContainer = new SplitPinContainer(primaryContainer,
+ topContainer, splitPinRule, splitPinRule.getDefaultSplitAttributes());
+ task.addSplitContainer(splitPinContainer);
+
+ // Updates the Split
+ final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
+ mPresenter.updateSplitContainer(splitPinContainer, wct);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
+ updateCallbackIfNecessary();
+ return true;
+ }
+ }
+
+ @Override
+ public void unpinTopActivityStack(int taskId){
+ // TODO
+ }
+
+ @Override
public void setSplitAttributesCalculator(
@NonNull Function<SplitAttributesCalculatorParams, SplitAttributes> calculator) {
synchronized (mLock) {
@@ -672,7 +722,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (targetContainer == null) {
// When there is no embedding rule matched, try to place it in the top container
// like a normal launch.
- targetContainer = taskContainer.getTopTaskFragmentContainer();
+ targetContainer = taskContainer.getTopNonFinishingTaskFragmentContainer();
}
if (targetContainer == null) {
return;
@@ -791,7 +841,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
final TaskFragmentContainer container = getContainerWithActivity(activity);
if (!isOnReparent && container != null
- && container.getTaskContainer().getTopTaskFragmentContainer() != container) {
+ && container.getTaskContainer().getTopNonFinishingTaskFragmentContainer()
+ != container) {
// Do not resolve if the launched activity is not the top-most container in the Task.
return true;
}
@@ -888,7 +939,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (taskContainer == null) {
return;
}
- final TaskFragmentContainer targetContainer = taskContainer.getTopTaskFragmentContainer();
+ final TaskFragmentContainer targetContainer =
+ taskContainer.getTopNonFinishingTaskFragmentContainer();
if (targetContainer == null) {
return;
}
@@ -1213,11 +1265,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// 3. Whether the top activity (if any) should be split with the new activity intent.
final TaskContainer taskContainer = getTaskContainer(taskId);
- if (taskContainer == null || taskContainer.getTopTaskFragmentContainer() == null) {
+ if (taskContainer == null
+ || taskContainer.getTopNonFinishingTaskFragmentContainer() == null) {
// There is no other activity in the Task to check split with.
return null;
}
- final TaskFragmentContainer topContainer = taskContainer.getTopTaskFragmentContainer();
+ final TaskFragmentContainer topContainer =
+ taskContainer.getTopNonFinishingTaskFragmentContainer();
final Activity topActivity = topContainer.getTopNonFinishingActivity();
if (topActivity != null && topActivity != launchingActivity) {
final TaskFragmentContainer container = getSecondaryContainerForSplitIfAny(wct,
@@ -1567,6 +1621,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// background.
return;
}
+ final SplitContainer splitContainer = getActiveSplitForContainer(container);
+ if (splitContainer instanceof SplitPinContainer
+ && updateSplitContainerIfNeeded(splitContainer, wct, null /* splitAttributes */)) {
+ // A SplitPinContainer exists and is updated.
+ return;
+ }
if (launchPlaceholderIfNecessary(wct, container)) {
// Placeholder was launched, the positions will be updated when the activity is added
// to the secondary container.
@@ -1579,7 +1639,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// If the info is not available yet the task fragment will be expanded when it's ready
return;
}
- SplitContainer splitContainer = getActiveSplitForContainer(container);
if (splitContainer == null) {
return;
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPinContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPinContainer.java
new file mode 100644
index 000000000000..03c77a089012
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPinContainer.java
@@ -0,0 +1,47 @@
+/*
+ * 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 androidx.window.extensions.embedding;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Client-side descriptor of a split that holds two containers while the secondary
+ * container is pinned on top of the Task and the primary container is the container that is
+ * currently below the secondary container. The primary container could be updated to
+ * another container whenever the existing primary container is removed or no longer
+ * be the container that's right behind the secondary container.
+ */
+class SplitPinContainer extends SplitContainer {
+
+ SplitPinContainer(@NonNull TaskFragmentContainer primaryContainer,
+ @NonNull TaskFragmentContainer secondaryContainer,
+ @NonNull SplitPinRule splitPinRule,
+ @NonNull SplitAttributes splitAttributes) {
+ super(primaryContainer, primaryContainer.getTopNonFinishingActivity(), secondaryContainer,
+ splitPinRule, splitAttributes, true /* isPrimaryContainerMutable */);
+ }
+
+ @Override
+ public String toString() {
+ return "SplitPinContainer{"
+ + " primaryContainer=" + getPrimaryContainer()
+ + " secondaryContainer=" + getSecondaryContainer()
+ + " splitPinRule=" + getSplitRule()
+ + " splitAttributes" + getCurrentSplitAttributes()
+ + "}";
+ }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 53d39d9fa28e..4dafbd17f379 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -17,6 +17,7 @@
package androidx.window.extensions.embedding;
import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import android.app.Activity;
import android.app.ActivityThread;
@@ -39,6 +40,7 @@ import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.TaskFragmentAnimationParams;
import android.window.TaskFragmentCreationParams;
+import android.window.TaskFragmentOperation;
import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
@@ -336,10 +338,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
// value.
final SplitRule rule = splitContainer.getSplitRule();
final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer();
- final Activity activity = primaryContainer.getTopNonFinishingActivity();
- if (activity == null) {
- return;
- }
final TaskContainer taskContainer = splitContainer.getTaskContainer();
final TaskProperties taskProperties = taskContainer.getTaskProperties();
final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
@@ -424,6 +422,16 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
container.setLastRequestedBounds(fragmentOptions.getInitialRelativeBounds());
container.setLastRequestedWindowingMode(fragmentOptions.getWindowingMode());
super.createTaskFragment(wct, fragmentOptions);
+
+ // Reorders the pinned TaskFragment to front to ensure it is the front-most TaskFragment.
+ final SplitPinContainer pinnedContainer =
+ container.getTaskContainer().getSplitPinContainer();
+ if (pinnedContainer != null) {
+ final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
+ OP_TYPE_REORDER_TO_FRONT).build();
+ wct.addTaskFragmentOperation(
+ pinnedContainer.getSecondaryContainer().getTaskFragmentToken(), operation);
+ }
}
@Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 4580c9836168..969e3ed5b9b6 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -57,6 +57,10 @@ class TaskContainer {
@NonNull
private final List<SplitContainer> mSplitContainers = new ArrayList<>();
+ /** Active pin split pair in this Task. */
+ @Nullable
+ private SplitPinContainer mSplitPinContainer;
+
@NonNull
private final Configuration mConfiguration;
@@ -174,11 +178,28 @@ class TaskContainer {
}
@Nullable
- TaskFragmentContainer getTopTaskFragmentContainer() {
- if (mContainers.isEmpty()) {
- return null;
+ TaskFragmentContainer getTopNonFinishingTaskFragmentContainer() {
+ for (int i = mContainers.size() - 1; i >= 0; i--) {
+ final TaskFragmentContainer container = mContainers.get(i);
+ if (!container.isFinished()) {
+ return container;
+ }
+ }
+ return null;
+ }
+
+ /** Gets a non-finishing container below the given one. */
+ @Nullable
+ TaskFragmentContainer getNonFinishingTaskFragmentContainerBelow(
+ @NonNull TaskFragmentContainer current) {
+ final int index = mContainers.indexOf(current);
+ for (int i = index - 1; i >= 0; i--) {
+ final TaskFragmentContainer container = mContainers.get(i);
+ if (!container.isFinished()) {
+ return container;
+ }
}
- return mContainers.get(mContainers.size() - 1);
+ return null;
}
@Nullable
@@ -217,31 +238,57 @@ class TaskContainer {
}
void addSplitContainer(@NonNull SplitContainer splitContainer) {
+ if (splitContainer instanceof SplitPinContainer) {
+ mSplitPinContainer = (SplitPinContainer) splitContainer;
+ mSplitContainers.add(splitContainer);
+ return;
+ }
+
+ // Keeps the SplitPinContainer on the top of the list.
+ mSplitContainers.remove(mSplitPinContainer);
mSplitContainers.add(splitContainer);
+ if (mSplitPinContainer != null) {
+ mSplitContainers.add(mSplitPinContainer);
+ }
}
void removeSplitContainers(@NonNull List<SplitContainer> containers) {
mSplitContainers.removeAll(containers);
}
+ void removeSplitPinContainer() {
+ mSplitContainers.remove(mSplitPinContainer);
+ mSplitPinContainer = null;
+ }
+
+ @Nullable
+ SplitPinContainer getSplitPinContainer() {
+ return mSplitPinContainer;
+ }
+
void addTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
mContainers.add(taskFragmentContainer);
+ onTaskFragmentContainerUpdated();
}
void addTaskFragmentContainer(int index, @NonNull TaskFragmentContainer taskFragmentContainer) {
mContainers.add(index, taskFragmentContainer);
+ onTaskFragmentContainerUpdated();
}
void removeTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
mContainers.remove(taskFragmentContainer);
+ onTaskFragmentContainerUpdated();
}
void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
mContainers.removeAll(taskFragmentContainer);
+ onTaskFragmentContainerUpdated();
}
void clearTaskFragmentContainer() {
mContainers.clear();
+ onTaskFragmentContainerUpdated();
}
/**
@@ -254,6 +301,34 @@ class TaskContainer {
return mContainers;
}
+ private void onTaskFragmentContainerUpdated() {
+ if (mSplitPinContainer == null) {
+ return;
+ }
+
+ final TaskFragmentContainer pinnedContainer = mSplitPinContainer.getSecondaryContainer();
+ final int pinnedContainerIndex = mContainers.indexOf(pinnedContainer);
+ if (pinnedContainerIndex <= 0) {
+ removeSplitPinContainer();
+ return;
+ }
+
+ // Ensure the pinned container is top-most.
+ if (pinnedContainerIndex != mContainers.size() - 1) {
+ mContainers.remove(pinnedContainer);
+ mContainers.add(pinnedContainer);
+ }
+
+ // Update the primary container adjacent to the pinned container if needed.
+ final TaskFragmentContainer adjacentContainer =
+ getNonFinishingTaskFragmentContainerBelow(pinnedContainer);
+ if (adjacentContainer == null) {
+ removeSplitPinContainer();
+ } else if (mSplitPinContainer.getPrimaryContainer() != adjacentContainer) {
+ mSplitPinContainer.setPrimaryContainer(adjacentContainer);
+ }
+ }
+
/** Adds the descriptors of split states in this Task to {@code outSplitStates}. */
void getSplitStates(@NonNull List<SplitInfo> outSplitStates) {
for (SplitContainer container : mSplitContainers) {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 9e264726a65a..9af1fe916279 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -1462,6 +1462,51 @@ public class SplitControllerTest {
verify(testRecord).apply(eq(false));
}
+ @Test
+ public void testPinTopActivityStack() {
+ // Create two activities.
+ final Activity primaryActivity = createMockActivity();
+ final Activity secondaryActivity = createMockActivity();
+
+ // Unable to pin if not being embedded.
+ SplitPinRule splitPinRule = new SplitPinRule.Builder(new SplitAttributes.Builder().build(),
+ parentWindowMetrics -> true /* parentWindowMetricsPredicate */).build();
+ assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
+
+ // Split the two activities.
+ addSplitTaskFragments(primaryActivity, secondaryActivity);
+ final TaskFragmentContainer primaryContainer =
+ mSplitController.getContainerWithActivity(primaryActivity);
+ spyOn(primaryContainer);
+
+ // Unable to pin if no valid TaskFragment.
+ doReturn(true).when(primaryContainer).isFinished();
+ assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
+
+ // Otherwise, should pin successfully.
+ doReturn(false).when(primaryContainer).isFinished();
+ assertTrue(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
+
+ // Unable to pin if there is already a pinned TaskFragment
+ assertFalse(mSplitController.pinTopActivityStack(TASK_ID, splitPinRule));
+
+ // Unable to pin on an unknown Task.
+ assertFalse(mSplitController.pinTopActivityStack(TASK_ID + 1, splitPinRule));
+
+ // Gets the current size of all the SplitContainers.
+ final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
+ final int splitContainerCount = taskContainer.getSplitContainers().size();
+
+ // Create another activity and split with primary activity.
+ final Activity thirdActivity = createMockActivity();
+ addSplitTaskFragments(primaryActivity, thirdActivity);
+
+ // Ensure another SplitContainer is added and the pinned TaskFragment still on top
+ assertTrue(taskContainer.getSplitContainers().size() == splitContainerCount + +1);
+ assertTrue(mSplitController.getTopActiveContainer(TASK_ID).getTopNonFinishingActivity()
+ == secondaryActivity);
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
return createMockActivity(TASK_ID);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index 11af1d1f20e1..000c65a75c81 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -135,15 +135,15 @@ public class TaskContainerTest {
@Test
public void testGetTopTaskFragmentContainer() {
final TaskContainer taskContainer = createTestTaskContainer();
- assertNull(taskContainer.getTopTaskFragmentContainer());
+ assertNull(taskContainer.getTopNonFinishingTaskFragmentContainer());
final TaskFragmentContainer tf0 = new TaskFragmentContainer(null /* activity */,
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
- assertEquals(tf0, taskContainer.getTopTaskFragmentContainer());
+ assertEquals(tf0, taskContainer.getTopNonFinishingTaskFragmentContainer());
final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
new Intent(), taskContainer, mController, null /* pairedPrimaryContainer */);
- assertEquals(tf1, taskContainer.getTopTaskFragmentContainer());
+ assertEquals(tf1, taskContainer.getTopNonFinishingTaskFragmentContainer());
}
@Test
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 6385fd3fd811..8def8ff1ab01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1075,9 +1075,9 @@ public class BubbleController implements ConfigurationChangeListener,
* <p>This is used by external callers (launcher).
*/
@VisibleForTesting
- public void expandStackAndSelectBubbleFromLauncher(String key, int bubbleBarXCoordinate,
- int bubbleBarYCoordinate) {
- mBubblePositioner.setBubbleBarPosition(bubbleBarXCoordinate, bubbleBarYCoordinate);
+ public void expandStackAndSelectBubbleFromLauncher(String key, int bubbleBarOffsetX,
+ int bubbleBarOffsetY) {
+ mBubblePositioner.setBubbleBarPosition(bubbleBarOffsetX, bubbleBarOffsetY);
if (BubbleOverflow.KEY.equals(key)) {
mBubbleData.setSelectedBubbleFromLauncher(mBubbleData.getOverflow());
@@ -2088,10 +2088,10 @@ public class BubbleController implements ConfigurationChangeListener,
}
@Override
- public void showBubble(String key, int bubbleBarXCoordinate, int bubbleBarYCoordinate) {
+ public void showBubble(String key, int bubbleBarOffsetX, int bubbleBarOffsetY) {
mMainExecutor.execute(
() -> mController.expandStackAndSelectBubbleFromLauncher(
- key, bubbleBarXCoordinate, bubbleBarYCoordinate));
+ key, bubbleBarOffsetX, bubbleBarOffsetY));
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 6a5e3104fed5..ee6996d3d23d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -718,9 +718,16 @@ public class BubblePositioner {
mShowingInBubbleBar = showingInBubbleBar;
}
- /** Sets the position of the bubble bar in screen coordinates. */
- public void setBubbleBarPosition(int x, int y) {
- mBubbleBarPosition.set(x, y);
+ /**
+ * Sets the position of the bubble bar in screen coordinates.
+ *
+ * @param offsetX the offset of the bubble bar from the edge of the screen on the X axis
+ * @param offsetY the offset of the bubble bar from the edge of the screen on the Y axis
+ */
+ public void setBubbleBarPosition(int offsetX, int offsetY) {
+ mBubbleBarPosition.set(
+ getAvailableRect().width() - offsetX,
+ getAvailableRect().height() + mInsets.top + mInsets.bottom - offsetY);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 59332f4be627..351319f5fb5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -29,8 +29,7 @@ interface IBubbles {
oneway void unregisterBubbleListener(in IBubblesListener listener) = 2;
- oneway void showBubble(in String key, in int bubbleBarXCoordinate,
- in int bubbleBarYCoordinate) = 3;
+ oneway void showBubble(in String key, in int bubbleBarOffsetX, in int bubbleBarOffsetY) = 3;
oneway void removeBubble(in String key, in int reason) = 4;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index b14c3c10846b..08da4857a0b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -1927,6 +1927,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
pw.println(innerPrefix + "mLeash=" + mLeash);
pw.println(innerPrefix + "mState=" + mPipTransitionState.getTransitionState());
pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
+ mPipTransitionController.dump(pw, innerPrefix);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 73eb62ae47e9..e3d53fc415db 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -72,6 +72,7 @@ import com.android.wm.shell.transition.CounterRotatorHelper;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.TransitionUtil;
+import java.io.PrintWriter;
import java.util.Optional;
/**
@@ -451,6 +452,9 @@ public class PipTransition extends PipTransitionController {
@Override
public void forceFinishTransition() {
+ // mFinishCallback might be null with an outdated mCurrentPipTaskToken
+ // for example, when app crashes while in PiP and exit transition has not started
+ mCurrentPipTaskToken = null;
if (mFinishCallback == null) return;
mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
mFinishCallback = null;
@@ -1137,4 +1141,12 @@ public class PipTransition extends PipTransitionController {
PipMenuController.ALPHA_NO_CHANGE);
mPipMenuController.updateMenuBounds(destinationBounds);
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + TAG);
+ pw.println(innerPrefix + "mCurrentPipTaskToken=" + mCurrentPipTaskToken);
+ pw.println(innerPrefix + "mFinishCallback=" + mFinishCallback);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index e1bcd70c256b..63627938ec87 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -42,6 +42,7 @@ import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -283,4 +284,9 @@ public abstract class PipTransitionController implements Transitions.TransitionH
*/
void onPipTransitionCanceled(int direction);
}
+
+ /**
+ * Dumps internal states.
+ */
+ public void dump(PrintWriter pw, String prefix) {}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
index 5f54f58557d1..56c0d0e67cab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
@@ -38,8 +38,6 @@ public class ShellSharedConstants {
public static final String KEY_EXTRA_SHELL_RECENT_TASKS = "extra_shell_recent_tasks";
// See IBackAnimation.aidl
public static final String KEY_EXTRA_SHELL_BACK_ANIMATION = "extra_shell_back_animation";
- // See IFloatingTasks.aidl
- public static final String KEY_EXTRA_SHELL_FLOATING_TASKS = "extra_shell_floating_tasks";
// See IDesktopMode.aidl
public static final String KEY_EXTRA_SHELL_DESKTOP_MODE = "extra_shell_desktop_mode";
// See IDragAndDrop.aidl
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.kt
index 96bfb78eff0d..d1dd8df81a3e 100644
--- a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.kt
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.kt
@@ -23,6 +23,7 @@ import android.content.ComponentName
import android.util.Log
import com.android.dream.lowlight.dagger.LowLightDreamModule
import com.android.dream.lowlight.dagger.qualifiers.Application
+import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.TimeoutCancellationException
@@ -103,6 +104,11 @@ class LowLightDreamManager @Inject constructor(
)
} catch (ex: TimeoutCancellationException) {
Log.e(TAG, "timed out while waiting for low light animation", ex)
+ } catch (ex: CancellationException) {
+ Log.w(TAG, "low light transition animation cancelled")
+ // Catch the cancellation so that we still set the system dream component if the
+ // animation is cancelled, such as by a user tapping to wake as the transition to
+ // low light happens.
}
dreamManager.setSystemDreamComponent(
if (shouldEnterLowLight) lowLightDreamComponent else null
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt
index 473603002b21..de1aee598667 100644
--- a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.kt
@@ -110,15 +110,5 @@ class LowLightTransitionCoordinator @Inject constructor() {
}
}
animator.addListener(listener)
- continuation.invokeOnCancellation {
- try {
- animator.removeListener(listener)
- animator.cancel()
- } catch (exception: IndexOutOfBoundsException) {
- // TODO(b/285666217): remove this try/catch once a proper fix is implemented.
- // Cancelling the animator can cause an exception since we may be removing a
- // listener during the cancellation. See b/285666217 for more details.
- }
- }
}
}
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/util/TruncatedInterpolator.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/util/TruncatedInterpolator.kt
new file mode 100644
index 000000000000..f69c84dafbb2
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/util/TruncatedInterpolator.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.dream.lowlight.util
+
+import android.view.animation.Interpolator
+
+/**
+ * Interpolator wrapper that shortens another interpolator from its original duration to a portion
+ * of that duration.
+ *
+ * For example, an `originalDuration` of 1000 and a `newDuration` of 200 results in an animation
+ * that when played for 200ms is the exact same as the first 200ms of a 1000ms animation if using
+ * the original interpolator.
+ *
+ * This is useful for the transition between the user dream and the low light clock as some
+ * animations are defined in the spec to be longer than the total duration of the animation. For
+ * example, the low light clock exit translation animation is defined to last >1s while the actual
+ * fade out of the low light clock is only 250ms, meaning the clock isn't visible anymore after
+ * 250ms.
+ *
+ * Since the dream framework currently only allows one dream to be visible and running, we use this
+ * interpolator to play just the first 250ms of the translation animation. Simply reducing the
+ * duration of the animation would result in the text exiting much faster than intended, so a custom
+ * interpolator is needed.
+ */
+class TruncatedInterpolator(
+ private val baseInterpolator: Interpolator,
+ originalDuration: Float,
+ newDuration: Float
+) : Interpolator {
+ private val scaleFactor: Float
+
+ init {
+ scaleFactor = newDuration / originalDuration
+ }
+
+ override fun getInterpolation(input: Float): Float {
+ return baseInterpolator.getInterpolation(input * scaleFactor)
+ }
+}
diff --git a/libs/dream/lowlight/tests/Android.bp b/libs/dream/lowlight/tests/Android.bp
index 2d79090cd7d4..64b53cbb5c5a 100644
--- a/libs/dream/lowlight/tests/Android.bp
+++ b/libs/dream/lowlight/tests/Android.bp
@@ -27,6 +27,7 @@ android_test {
"androidx.test.runner",
"androidx.test.rules",
"androidx.test.ext.junit",
+ "animationlib",
"frameworks-base-testutils",
"junit",
"kotlinx_coroutines_test",
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.kt b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.kt
index 2a886bc31788..de84adb2e5c2 100644
--- a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.kt
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.kt
@@ -152,6 +152,21 @@ class LowLightDreamManagerTest {
verify(mDreamManager).setSystemDreamComponent(DREAM_COMPONENT)
}
+ @Test
+ fun setAmbientLightMode_animationCancelled_SetsSystemDream() = testScope.runTest {
+ mLowLightDreamManager.setAmbientLightMode(LowLightDreamManager.AMBIENT_LIGHT_MODE_LOW_LIGHT)
+ runCurrent()
+ cancelEnterAnimations()
+ runCurrent()
+ // Animation never finishes, but we should still set the system dream
+ verify(mDreamManager).setSystemDreamComponent(DREAM_COMPONENT)
+ }
+
+ private fun cancelEnterAnimations() {
+ val listener = withArgCaptor { verify(mEnterAnimator).addListener(capture()) }
+ listener.onAnimationCancel(mEnterAnimator)
+ }
+
private fun completeEnterAnimations() {
val listener = withArgCaptor { verify(mEnterAnimator).addListener(capture()) }
listener.onAnimationEnd(mEnterAnimator)
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.kt b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.kt
index 4c526a6ac69d..9ae304f9763a 100644
--- a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.kt
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.kt
@@ -158,26 +158,6 @@ class LowLightTransitionCoordinatorTest {
assertThat(job.isCancelled).isTrue()
}
- @Test
- fun shouldCancelAnimatorWhenJobCancelled() = testScope.runTest {
- whenever(mEnterListener.onBeforeEnterLowLight()).thenReturn(mAnimator)
- val coordinator = LowLightTransitionCoordinator()
- coordinator.setLowLightEnterListener(mEnterListener)
- val job = launch {
- coordinator.waitForLowLightTransitionAnimation(timeout = TIMEOUT, entering = true)
- }
- runCurrent()
- // Animator listener is added and the runnable is not run yet.
- verify(mAnimator).addListener(mAnimatorListenerCaptor.capture())
- verify(mAnimator, never()).cancel()
- assertThat(job.isCompleted).isFalse()
-
- job.cancel()
- // We should have removed the listener and cancelled the animator
- verify(mAnimator).removeListener(mAnimatorListenerCaptor.value)
- verify(mAnimator).cancel()
- }
-
companion object {
private val TIMEOUT = 1.toDuration(DurationUnit.SECONDS)
}
diff --git a/libs/dream/lowlight/tests/src/com/android/dream/lowlight/util/TruncatedInterpolatorTest.kt b/libs/dream/lowlight/tests/src/com/android/dream/lowlight/util/TruncatedInterpolatorTest.kt
new file mode 100644
index 000000000000..190f02e97136
--- /dev/null
+++ b/libs/dream/lowlight/tests/src/com/android/dream/lowlight/util/TruncatedInterpolatorTest.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.dream.lowlight.util
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TruncatedInterpolatorTest {
+ @Test
+ fun truncatedInterpolator_matchesRegularInterpolator() {
+ val originalInterpolator = Interpolators.EMPHASIZED
+ val truncatedInterpolator =
+ TruncatedInterpolator(originalInterpolator, ORIGINAL_DURATION_MS, NEW_DURATION_MS)
+
+ // Both interpolators should start at the same value.
+ var animationPercent = 0f
+ Truth.assertThat(truncatedInterpolator.getInterpolation(animationPercent))
+ .isEqualTo(originalInterpolator.getInterpolation(animationPercent))
+
+ animationPercent = 1f
+ Truth.assertThat(truncatedInterpolator.getInterpolation(animationPercent))
+ .isEqualTo(originalInterpolator.getInterpolation(animationPercent * DURATION_RATIO))
+
+ animationPercent = 0.25f
+ Truth.assertThat(truncatedInterpolator.getInterpolation(animationPercent))
+ .isEqualTo(originalInterpolator.getInterpolation(animationPercent * DURATION_RATIO))
+ }
+
+ companion object {
+ private const val ORIGINAL_DURATION_MS: Float = 1000f
+ private const val NEW_DURATION_MS: Float = 200f
+ private const val DURATION_RATIO: Float = NEW_DURATION_MS / ORIGINAL_DURATION_MS
+ }
+}
diff --git a/packages/SystemUI/res/layout/status_bar_wifi_group.xml b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
deleted file mode 100644
index 6cb6993bb762..000000000000
--- a/packages/SystemUI/res/layout/status_bar_wifi_group.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2018, 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.
-*/
--->
-<com.android.systemui.statusbar.StatusBarWifiView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wifi_combo"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical" >
-
- <include layout="@layout/status_bar_wifi_group_inner" />
-
-</com.android.systemui.statusbar.StatusBarWifiView> \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index 0fbeb1a054a7..f3296f0632bb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -32,7 +32,7 @@ open class RegionSampler
@JvmOverloads
constructor(
val sampledView: View,
- mainExecutor: Executor?,
+ val mainExecutor: Executor?,
val bgExecutor: Executor?,
val regionSamplingEnabled: Boolean,
val isLockscreen: Boolean = false,
@@ -166,7 +166,7 @@ constructor(
if (isLockscreen) WallpaperManager.FLAG_LOCK
else WallpaperManager.FLAG_SYSTEM
)
- onColorsChanged(sampledRegionWithOffset, initialSampling)
+ mainExecutor?.execute { onColorsChanged(sampledRegionWithOffset, initialSampling) }
}
)
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index ca064efd4f76..4b14d3cff718 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -42,8 +42,6 @@ public class QuickStepContract {
"com.google.android.apps.nexuslauncher.NexusLauncherActivity";
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
- public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
- public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
public static final String KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER = "extra_unfold_animation";
// See ISysuiUnlockAnimationController.aidl
public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation";
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
deleted file mode 100644
index 74c325dea15c..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.shared.system;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-import static android.view.WindowManager.TRANSIT_SLEEP;
-
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.app.IApplicationThread;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.view.IRecentsAnimationController;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl;
-import android.window.IRemoteTransition;
-import android.window.IRemoteTransitionFinishedCallback;
-import android.window.PictureInPictureSurfaceTransaction;
-import android.window.RemoteTransition;
-import android.window.TaskSnapshot;
-import android.window.TransitionInfo;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.wm.shell.util.TransitionUtil;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * Helper class to build {@link RemoteTransition} objects
- */
-public class RemoteTransitionCompat {
- private static final String TAG = "RemoteTransitionCompat";
-
- /** Constructor specifically for recents animation */
- public static RemoteTransition newRemoteTransition(RecentsAnimationListener recents,
- IApplicationThread appThread) {
- IRemoteTransition remote = new IRemoteTransition.Stub() {
- final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
- IBinder mToken = null;
-
- @Override
- public void startAnimation(IBinder transition, TransitionInfo info,
- SurfaceControl.Transaction t,
- IRemoteTransitionFinishedCallback finishedCallback) {
- // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
- mToken = transition;
- mRecentsSession.start(recents, mToken, info, t, finishedCallback);
- }
-
- @Override
- public void mergeAnimation(IBinder transition, TransitionInfo info,
- SurfaceControl.Transaction t, IBinder mergeTarget,
- IRemoteTransitionFinishedCallback finishedCallback) {
- if (mergeTarget.equals(mToken) && mRecentsSession.merge(info, t)) {
- try {
- finishedCallback.onTransitionFinished(null /* wct */, null /* sct */);
- } catch (RemoteException e) {
- Log.e(TAG, "Error merging transition.", e);
- }
- // commit taskAppeared after merge transition finished.
- mRecentsSession.commitTasksAppearedIfNeeded();
- } else {
- t.close();
- info.releaseAllSurfaces();
- }
- }
- };
- return new RemoteTransition(remote, appThread, "Recents");
- }
-
- /**
- * Wrapper to hook up parts of recents animation to shell transition.
- * TODO(b/177438007): Remove this once Launcher handles shell transitions directly.
- */
- @VisibleForTesting
- static class RecentsControllerWrap extends IRecentsAnimationController.Default {
- private RecentsAnimationListener mListener = null;
- private IRemoteTransitionFinishedCallback mFinishCB = null;
-
- /**
- * List of tasks that we are switching away from via this transition. Upon finish, these
- * pausing tasks will become invisible.
- * These need to be ordered since the order must be restored if there is no task-switch.
- */
- private ArrayList<TaskState> mPausingTasks = null;
-
- /**
- * List of tasks that we are switching to. Upon finish, these will remain visible and
- * on top.
- */
- private ArrayList<TaskState> mOpeningTasks = null;
-
- private WindowContainerToken mPipTask = null;
- private WindowContainerToken mRecentsTask = null;
- private int mRecentsTaskId = 0;
- private TransitionInfo mInfo = null;
- private boolean mOpeningSeparateHome = false;
- private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
- private PictureInPictureSurfaceTransaction mPipTransaction = null;
- private IBinder mTransition = null;
- private boolean mKeyguardLocked = false;
- private RemoteAnimationTarget[] mAppearedTargets;
- private boolean mWillFinishToHome = false;
-
- /** The animation is idle, waiting for the user to choose a task to switch to. */
- private static final int STATE_NORMAL = 0;
-
- /** The user chose a new task to switch to and the animation is animating to it. */
- private static final int STATE_NEW_TASK = 1;
-
- /** The latest state that the recents animation is operating in. */
- private int mState = STATE_NORMAL;
-
- void start(RecentsAnimationListener listener,
- IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
- IRemoteTransitionFinishedCallback finishedCallback) {
- if (mInfo != null) {
- throw new IllegalStateException("Trying to run a new recents animation while"
- + " recents is already active.");
- }
- mListener = listener;
- mInfo = info;
- mFinishCB = finishedCallback;
- mPausingTasks = new ArrayList<>();
- mOpeningTasks = new ArrayList<>();
- mPipTask = null;
- mRecentsTask = null;
- mRecentsTaskId = -1;
- mLeashMap = new ArrayMap<>();
- mTransition = transition;
- mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;
- mState = STATE_NORMAL;
-
- final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
- final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
- TransitionUtil.LeafTaskFilter leafTaskFilter = new TransitionUtil.LeafTaskFilter();
- // About layering: we divide up the "layer space" into 3 regions (each the size of
- // the change count). This lets us categorize things into above/below/between
- // while maintaining their relative ordering.
- for (int i = 0; i < info.getChanges().size(); ++i) {
- final TransitionInfo.Change change = info.getChanges().get(i);
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (TransitionUtil.isWallpaper(change)) {
- final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
- // wallpapers go into the "below" layer space
- info.getChanges().size() - i, info, t, mLeashMap);
- wallpapers.add(target);
- // Make all the wallpapers opaque since we want them visible from the start
- t.setAlpha(target.leash, 1);
- } else if (leafTaskFilter.test(change)) {
- // start by putting everything into the "below" layer space.
- final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
- info.getChanges().size() - i, info, t, mLeashMap);
- apps.add(target);
- if (TransitionUtil.isClosingType(change.getMode())) {
- // raise closing (pausing) task to "above" layer so it isn't covered
- t.setLayer(target.leash, info.getChanges().size() * 3 - i);
- mPausingTasks.add(new TaskState(change, target.leash));
- if (taskInfo.pictureInPictureParams != null
- && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
- mPipTask = taskInfo.token;
- }
- } else if (taskInfo != null
- && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
- // There's a 3p launcher, so make sure recents goes above that.
- t.setLayer(target.leash, info.getChanges().size() * 3 - i);
- mRecentsTask = taskInfo.token;
- mRecentsTaskId = taskInfo.taskId;
- } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- mRecentsTask = taskInfo.token;
- mRecentsTaskId = taskInfo.taskId;
- } else if (TransitionUtil.isOpeningType(change.getMode())) {
- mOpeningTasks.add(new TaskState(change, target.leash));
- }
- }
- }
- t.apply();
- mListener.onAnimationStart(new RecentsAnimationControllerCompat(this),
- apps.toArray(new RemoteAnimationTarget[apps.size()]),
- wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
- new Rect(0, 0, 0, 0), new Rect());
- }
-
- @SuppressLint("NewApi")
- boolean merge(TransitionInfo info, SurfaceControl.Transaction t) {
- if (info.getType() == TRANSIT_SLEEP) {
- // A sleep event means we need to stop animations immediately, so cancel here.
- mListener.onAnimationCanceled(new HashMap<>());
- finish(mWillFinishToHome, false /* userLeaveHint */);
- return false;
- }
- ArrayList<TransitionInfo.Change> openingTasks = null;
- ArrayList<TransitionInfo.Change> closingTasks = null;
- mAppearedTargets = null;
- mOpeningSeparateHome = false;
- TransitionInfo.Change recentsOpening = null;
- boolean foundRecentsClosing = false;
- boolean hasChangingApp = false;
- final TransitionUtil.LeafTaskFilter leafTaskFilter =
- new TransitionUtil.LeafTaskFilter();
- for (int i = 0; i < info.getChanges().size(); ++i) {
- final TransitionInfo.Change change = info.getChanges().get(i);
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- final boolean isLeafTask = leafTaskFilter.test(change);
- if (TransitionUtil.isOpeningType(change.getMode())) {
- if (mRecentsTask.equals(change.getContainer())) {
- recentsOpening = change;
- } else if (isLeafTask) {
- if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- // This is usually a 3p launcher
- mOpeningSeparateHome = true;
- }
- if (openingTasks == null) {
- openingTasks = new ArrayList<>();
- }
- openingTasks.add(change);
- }
- } else if (TransitionUtil.isClosingType(change.getMode())) {
- if (mRecentsTask.equals(change.getContainer())) {
- foundRecentsClosing = true;
- } else if (isLeafTask) {
- if (closingTasks == null) {
- closingTasks = new ArrayList<>();
- }
- closingTasks.add(change);
- }
- } else if (change.getMode() == TRANSIT_CHANGE) {
- // Finish recents animation if the display is changed, so the default
- // transition handler can play the animation such as rotation effect.
- if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
- mListener.onSwitchToScreenshot(() -> finish(false /* toHome */,
- false /* userLeaveHint */));
- return false;
- }
- hasChangingApp = true;
- }
- }
- if (hasChangingApp && foundRecentsClosing) {
- // This happens when a visible app is expanding (usually PiP). In this case,
- // that transition probably has a special-purpose animation, so finish recents
- // now and let it do its animation (since recents is going to be occluded).
- if (!mListener.onSwitchToScreenshot(
- () -> finish(true /* toHome */, false /* userLeaveHint */))) {
- Log.w(TAG, "Recents callback doesn't support support switching to screenshot"
- + ", there might be a flicker.");
- finish(true /* toHome */, false /* userLeaveHint */);
- }
- return false;
- }
- if (recentsOpening != null) {
- // the recents task re-appeared. This happens if the user gestures before the
- // task-switch (NEW_TASK) animation finishes.
- if (mState == STATE_NORMAL) {
- Log.e(TAG, "Returning to recents while recents is already idle.");
- }
- if (closingTasks == null || closingTasks.size() == 0) {
- Log.e(TAG, "Returning to recents without closing any opening tasks.");
- }
- // Setup may hide it initially since it doesn't know that overview was still active.
- t.show(recentsOpening.getLeash());
- t.setAlpha(recentsOpening.getLeash(), 1.f);
- mState = STATE_NORMAL;
- }
- boolean didMergeThings = false;
- if (closingTasks != null) {
- // Cancelling a task-switch. Move the tasks back to mPausing from mOpening
- for (int i = 0; i < closingTasks.size(); ++i) {
- final TransitionInfo.Change change = closingTasks.get(i);
- int openingIdx = TaskState.indexOf(mOpeningTasks, change);
- if (openingIdx < 0) {
- Log.e(TAG, "Back to existing recents animation from an unrecognized "
- + "task: " + change.getTaskInfo().taskId);
- continue;
- }
- mPausingTasks.add(mOpeningTasks.remove(openingIdx));
- didMergeThings = true;
- }
- }
- if (openingTasks != null && openingTasks.size() > 0) {
- // Switching to some new tasks, add to mOpening and remove from mPausing. Also,
- // enter NEW_TASK state since this will start the switch-to animation.
- final int layer = mInfo.getChanges().size() * 3;
- final RemoteAnimationTarget[] targets =
- new RemoteAnimationTarget[openingTasks.size()];
- for (int i = 0; i < openingTasks.size(); ++i) {
- final TransitionInfo.Change change = openingTasks.get(i);
- int pausingIdx = TaskState.indexOf(mPausingTasks, change);
- if (pausingIdx >= 0) {
- // Something is showing/opening a previously-pausing app.
- targets[i] = TransitionUtil.newTarget(change, layer,
- mPausingTasks.get(pausingIdx).mLeash);
- mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
- // Setup hides opening tasks initially, so make it visible again (since we
- // are already showing it).
- t.show(change.getLeash());
- t.setAlpha(change.getLeash(), 1.f);
- } else {
- // We are receiving new opening tasks, so convert to onTasksAppeared.
- targets[i] = TransitionUtil.newTarget(change, layer, info, t, mLeashMap);
- // reparent into the original `mInfo` since that's where we are animating.
- final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
- t.reparent(targets[i].leash, mInfo.getRoot(rootIdx).getLeash());
- t.setLayer(targets[i].leash, layer);
- mOpeningTasks.add(new TaskState(change, targets[i].leash));
- }
- }
- didMergeThings = true;
- mState = STATE_NEW_TASK;
- mAppearedTargets = targets;
- }
- if (!didMergeThings) {
- // Didn't recognize anything in incoming transition so don't merge it.
- Log.w(TAG, "Don't know how to merge this transition.");
- return false;
- }
- t.apply();
- // not using the incoming anim-only surfaces
- info.releaseAnimSurfaces();
- return true;
- }
-
- private void commitTasksAppearedIfNeeded() {
- if (mAppearedTargets != null) {
- mListener.onTasksAppeared(mAppearedTargets);
- mAppearedTargets = null;
- }
- }
-
- @Override public TaskSnapshot screenshotTask(int taskId) {
- try {
- return ActivityTaskManager.getService().takeTaskSnapshot(taskId,
- true /* updateCache */);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to screenshot task", e);
- }
- return null;
- }
-
- @Override public void setInputConsumerEnabled(boolean enabled) {
- if (!enabled) return;
- // transient launches don't receive focus automatically. Since we are taking over
- // the gesture now, take focus explicitly.
- // This also moves recents back to top if the user gestured before a switch
- // animation finished.
- try {
- ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to set focused task", e);
- }
- }
-
- @Override public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
- }
-
- @Override public void setFinishTaskTransaction(int taskId,
- PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
- mPipTransaction = finishTransaction;
- }
-
- @Override
- @SuppressLint("NewApi")
- public void finish(boolean toHome, boolean sendUserLeaveHint) {
- if (mFinishCB == null) {
- Log.e(TAG, "Duplicate call to finish", new RuntimeException());
- return;
- }
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- final WindowContainerTransaction wct = new WindowContainerTransaction();
-
- if (mKeyguardLocked && mRecentsTask != null) {
- if (toHome) wct.reorder(mRecentsTask, true /* toTop */);
- else wct.restoreTransientOrder(mRecentsTask);
- }
- if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
- // The gesture is returning to the pausing-task(s) rather than continuing with
- // recents, so end the transition by moving the app back to the top (and also
- // re-showing it's task).
- for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
- // reverse order so that index 0 ends up on top
- wct.reorder(mPausingTasks.get(i).mToken, true /* onTop */);
- t.show(mPausingTasks.get(i).mTaskSurface);
- }
- if (!mKeyguardLocked && mRecentsTask != null) {
- wct.restoreTransientOrder(mRecentsTask);
- }
- } else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
- // Special situation where 3p launcher was changed during recents (this happens
- // during tapltests...). Here we get both "return to home" AND "home opening".
- // This is basically going home, but we have to restore the recents and home order.
- for (int i = 0; i < mOpeningTasks.size(); ++i) {
- final TaskState state = mOpeningTasks.get(i);
- if (state.mTaskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- // Make sure it is on top.
- wct.reorder(state.mToken, true /* onTop */);
- }
- t.show(state.mTaskSurface);
- }
- for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
- t.hide(mPausingTasks.get(i).mTaskSurface);
- }
- if (!mKeyguardLocked && mRecentsTask != null) {
- wct.restoreTransientOrder(mRecentsTask);
- }
- } else {
- // The general case: committing to recents, going home, or switching tasks.
- for (int i = 0; i < mOpeningTasks.size(); ++i) {
- t.show(mOpeningTasks.get(i).mTaskSurface);
- }
- for (int i = 0; i < mPausingTasks.size(); ++i) {
- if (!sendUserLeaveHint) {
- // This means recents is not *actually* finishing, so of course we gotta
- // do special stuff in WMCore to accommodate.
- wct.setDoNotPip(mPausingTasks.get(i).mToken);
- }
- // Since we will reparent out of the leashes, pre-emptively hide the child
- // surface to match the leash. Otherwise, there will be a flicker before the
- // visibility gets committed in Core when using split-screen (in splitscreen,
- // the leaf-tasks are not "independent" so aren't hidden by normal setup).
- t.hide(mPausingTasks.get(i).mTaskSurface);
- }
- if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) {
- t.show(mInfo.getChange(mPipTask).getLeash());
- PictureInPictureSurfaceTransaction.apply(mPipTransaction,
- mInfo.getChange(mPipTask).getLeash(), t);
- mPipTask = null;
- mPipTransaction = null;
- }
- }
- try {
- mFinishCB.onTransitionFinished(wct.isEmpty() ? null : wct, t);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to call animation finish callback", e);
- t.apply();
- }
- // Only release the non-local created surface references. The animator is responsible
- // for releasing the leashes created by local.
- mInfo.releaseAllSurfaces();
- // Reset all members.
- mListener = null;
- mFinishCB = null;
- mPausingTasks = null;
- mOpeningTasks = null;
- mAppearedTargets = null;
- mInfo = null;
- mOpeningSeparateHome = false;
- mLeashMap = null;
- mTransition = null;
- mState = STATE_NORMAL;
- }
-
- @Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
- }
-
- @Override public void cleanupScreenshot() {
- }
-
- @Override public void setWillFinishToHome(boolean willFinishToHome) {
- mWillFinishToHome = willFinishToHome;
- }
-
- /**
- * @see IRecentsAnimationController#removeTask
- */
- @Override public boolean removeTask(int taskId) {
- return false;
- }
-
- /**
- * @see IRecentsAnimationController#detachNavigationBarFromApp
- */
- @Override public void detachNavigationBarFromApp(boolean moveHomeToTop) {
- try {
- ActivityTaskManager.getService().detachNavigationBarFromApp(mTransition);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to detach the navigation bar from app", e);
- }
- }
-
- /**
- * @see IRecentsAnimationController#animateNavigationBarToApp(long)
- */
- @Override public void animateNavigationBarToApp(long duration) {
- }
- }
-
- /** Utility class to track the state of a task as-seen by recents. */
- private static class TaskState {
- WindowContainerToken mToken;
- ActivityManager.RunningTaskInfo mTaskInfo;
-
- /** The surface/leash of the task provided by Core. */
- SurfaceControl mTaskSurface;
-
- /** The (local) animation-leash created for this task. */
- SurfaceControl mLeash;
-
- TaskState(TransitionInfo.Change change, SurfaceControl leash) {
- mToken = change.getContainer();
- mTaskInfo = change.getTaskInfo();
- mTaskSurface = change.getLeash();
- mLeash = leash;
- }
-
- static int indexOf(ArrayList<TaskState> list, TransitionInfo.Change change) {
- for (int i = list.size() - 1; i >= 0; --i) {
- if (list.get(i).mToken.equals(change.getContainer())) {
- return i;
- }
- }
- return -1;
- }
-
- public String toString() {
- return "" + mToken + " : " + mLeash;
- }
- }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
deleted file mode 100644
index 98212e1d91b6..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.shared.tracing;
-
-import android.os.Trace;
-import android.util.Log;
-import android.view.Choreographer;
-
-import com.android.internal.util.TraceBuffer;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Queue;
-import java.util.function.Consumer;
-
-/**
- * A proto tracer implementation that can be updated directly (upon state change), or on the next
- * scheduled frame.
- *
- * @param <P> The class type of the proto provider
- * @param <S> The proto class type of the encapsulating proto
- * @param <T> The proto class type of the individual proto entries in the buffer
- * @param <R> The proto class type of the entry root proto in the buffer
- */
-public class FrameProtoTracer<P, S extends P, T extends P, R>
- implements Choreographer.FrameCallback {
-
- private static final String TAG = "FrameProtoTracer";
- private static final int BUFFER_CAPACITY = 1024 * 1024;
-
- private final Object mLock = new Object();
- private final TraceBuffer<P, S, T> mBuffer;
- private final File mTraceFile;
- private final ProtoTraceParams<P, S, T, R> mParams;
- private Choreographer mChoreographer;
- private final Queue<T> mPool = new ArrayDeque<>();
- private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>();
- private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>();
-
- private volatile boolean mEnabled;
- private boolean mFrameScheduled;
-
- private final TraceBuffer.ProtoProvider<P, S, T> mProvider =
- new TraceBuffer.ProtoProvider<P, S, T>() {
- @Override
- public int getItemSize(P proto) {
- return mParams.getProtoSize(proto);
- }
-
- @Override
- public byte[] getBytes(P proto) {
- return mParams.getProtoBytes(proto);
- }
-
- @Override
- public void write(S encapsulatingProto, Queue<T> buffer, OutputStream os)
- throws IOException {
- os.write(mParams.serializeEncapsulatingProto(encapsulatingProto, buffer));
- }
- };
-
- public interface ProtoTraceParams<P, S, T, R> {
- File getTraceFile();
- S getEncapsulatingTraceProto();
- T updateBufferProto(T reuseObj, ArrayList<ProtoTraceable<R>> traceables);
- byte[] serializeEncapsulatingProto(S encapsulatingProto, Queue<T> buffer);
- byte[] getProtoBytes(P proto);
- int getProtoSize(P proto);
- }
-
- public FrameProtoTracer(ProtoTraceParams<P, S, T, R> params) {
- mParams = params;
- mBuffer = new TraceBuffer<>(BUFFER_CAPACITY, mProvider, new Consumer<T>() {
- @Override
- public void accept(T t) {
- onProtoDequeued(t);
- }
- });
- mTraceFile = params.getTraceFile();
- }
-
- public void start() {
- synchronized (mLock) {
- if (mEnabled) {
- return;
- }
- mBuffer.resetBuffer();
- mEnabled = true;
- }
- logState();
- }
-
- public void stop() {
- synchronized (mLock) {
- if (!mEnabled) {
- return;
- }
- mEnabled = false;
- }
- writeToFile();
- }
-
- public boolean isEnabled() {
- return mEnabled;
- }
-
- public void add(ProtoTraceable<R> traceable) {
- synchronized (mLock) {
- mTraceables.add(traceable);
- }
- }
-
- public void remove(ProtoTraceable<R> traceable) {
- synchronized (mLock) {
- mTraceables.remove(traceable);
- }
- }
-
- public void scheduleFrameUpdate() {
- if (!mEnabled || mFrameScheduled) {
- return;
- }
-
- // Schedule an update on the next frame
- if (mChoreographer == null) {
- mChoreographer = Choreographer.getMainThreadInstance();
- }
- mChoreographer.postFrameCallback(this);
- mFrameScheduled = true;
- }
-
- public void update() {
- if (!mEnabled) {
- return;
- }
-
- logState();
- }
-
- public float getBufferUsagePct() {
- return (float) mBuffer.getBufferSize() / BUFFER_CAPACITY;
- }
-
- @Override
- public void doFrame(long frameTimeNanos) {
- logState();
- }
-
- private void onProtoDequeued(T proto) {
- mPool.add(proto);
- }
-
- private void logState() {
- synchronized (mLock) {
- mTmpTraceables.addAll(mTraceables);
- }
-
- mBuffer.add(mParams.updateBufferProto(mPool.poll(), mTmpTraceables));
- mTmpTraceables.clear();
- mFrameScheduled = false;
- }
-
- private void writeToFile() {
- try {
- Trace.beginSection("ProtoTracer.writeToFile");
- mBuffer.writeTraceToFile(mTraceFile, mParams.getEncapsulatingTraceProto());
- } catch (IOException e) {
- Log.e(TAG, "Unable to write buffer to file", e);
- } finally {
- Trace.endSection();
- }
- }
-}
-
-
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
deleted file mode 100644
index e05b0b074449..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 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.shared.tracing;
-
-/**
- * @see FrameProtoTracer
- */
-public interface ProtoTraceable<T> {
-
- /**
- * NOTE: Implementations should update all fields in this proto.
- */
- void writeToProto(T proto);
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 794e6941c2bb..b3e08c0bc69f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -165,15 +165,18 @@ public class KeyguardPinViewController
* Responsible for identifying if PIN hinting is to be enabled or not
*/
private boolean isPinHinting() {
- return mLockPatternUtils.getPinLength(KeyguardUpdateMonitor.getCurrentUser())
- == DEFAULT_PIN_LENGTH;
+ return mPinLength == DEFAULT_PIN_LENGTH;
}
/**
- * Responsible for identifying if auto confirm is enabled or not in Settings
+ * Responsible for identifying if auto confirm is enabled or not in Settings and
+ * a valid PIN_LENGTH is stored on the device (though the latter check is only to make it more
+ * robust since we only allow enabling PIN confirmation if the user has a valid PIN length
+ * saved on device)
*/
private boolean isAutoPinConfirmEnabledInSettings() {
//Checks if user has enabled the auto confirm in Settings
- return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser());
+ return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser())
+ && mPinLength != LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
index a7d4455b43c2..87627698597f 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
@@ -20,6 +20,7 @@ import com.android.keyguard.CarrierText;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
import dagger.Module;
@@ -44,6 +45,13 @@ public abstract class KeyguardStatusBarViewModule {
/** */
@Provides
@KeyguardStatusBarViewScope
+ static StatusBarLocation getStatusBarLocation() {
+ return StatusBarLocation.KEYGUARD;
+ }
+
+ /** */
+ @Provides
+ @KeyguardStatusBarViewScope
static StatusBarUserSwitcherContainer getUserSwitcherContainer(KeyguardStatusBarView view) {
return view.findViewById(R.id.user_switcher_container);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 1f1b154ef1c8..04acd0b91173 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -123,7 +123,6 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.systemui.telephony.TelephonyListenerManager;
-import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.DeviceConfigProxy;
@@ -335,7 +334,6 @@ public class Dependency {
@Inject Lazy<IWallpaperManager> mWallpaperManager;
@Inject Lazy<CommandQueue> mCommandQueue;
@Inject Lazy<RecordingController> mRecordingController;
- @Inject Lazy<ProtoTracer> mProtoTracer;
@Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
@Inject Lazy<DeviceConfigProxy> mDeviceConfigProxy;
@Inject Lazy<TelephonyListenerManager> mTelephonyListenerManager;
@@ -528,7 +526,6 @@ public class Dependency {
mProviders.put(DozeParameters.class, mDozeParameters::get);
mProviders.put(IWallpaperManager.class, mWallpaperManager::get);
mProviders.put(CommandQueue.class, mCommandQueue::get);
- mProviders.put(ProtoTracer.class, mProtoTracer::get);
mProviders.put(DeviceConfigProxy.class, mDeviceConfigProxy::get);
mProviders.put(TelephonyListenerManager.class, mTelephonyListenerManager::get);
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index 43fb3630bd19..444491f53629 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -144,12 +144,7 @@ constructor(
private val lockPatternUtils: LockPatternUtils,
) : AuthenticationRepository {
- override val isUnlocked: StateFlow<Boolean> =
- keyguardRepository.isKeyguardUnlocked.stateIn(
- scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = false,
- )
+ override val isUnlocked: StateFlow<Boolean> = keyguardRepository.isKeyguardUnlocked
override suspend fun isLockscreenEnabled(): Boolean {
return withContext(backgroundDispatcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt b/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt
index b52ddc1dbc42..b34f1b45d763 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/battery/AccessorizedBatteryDrawable.kt
@@ -87,6 +87,10 @@ class AccessorizedBatteryDrawable(
}
var displayShield: Boolean = false
+ set(value) {
+ field = value
+ postInvalidate()
+ }
private fun updateSizes() {
val b = bounds
@@ -204,4 +208,11 @@ class AccessorizedBatteryDrawable(
val shieldPathString = context.resources.getString(R.string.config_batterymeterShieldPath)
shieldPath.set(PathParser.createPathFromPathData(shieldPathString))
}
+
+ private val invalidateRunnable: () -> Unit = { invalidateSelf() }
+
+ private fun postInvalidate() {
+ unscheduleSelf(invalidateRunnable)
+ scheduleSelf(invalidateRunnable, 0)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index c1238d911ecf..4e8383c3e39e 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -464,9 +464,11 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
public void dump(PrintWriter pw, String[] args) {
String powerSave = mDrawable == null ? null : mDrawable.getPowerSaveEnabled() + "";
+ String displayShield = mDrawable == null ? null : mDrawable.getDisplayShield() + "";
CharSequence percent = mBatteryPercentView == null ? null : mBatteryPercentView.getText();
pw.println(" BatteryMeterView:");
pw.println(" mDrawable.getPowerSave: " + powerSave);
+ pw.println(" mDrawable.getDisplayShield: " + displayShield);
pw.println(" mBatteryPercentView.getText(): " + percent);
pw.println(" mTextColor: #" + Integer.toHexString(mTextColor));
pw.println(" mBatteryStateUnknown: " + mBatteryStateUnknown);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index f6a10bd4af4a..6a5749cc5571 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -30,16 +30,18 @@ import android.view.View;
import androidx.annotation.NonNull;
+import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
+import java.io.PrintWriter;
+
import javax.inject.Inject;
/** Controller for {@link BatteryMeterView}. **/
@@ -53,6 +55,7 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
private final String mSlotBattery;
private final SettingObserver mSettingObserver;
private final UserTracker mUserTracker;
+ private final StatusBarLocation mLocation;
private final ConfigurationController.ConfigurationListener mConfigurationListener =
new ConfigurationController.ConfigurationListener() {
@@ -94,6 +97,13 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
public void onIsBatteryDefenderChanged(boolean isBatteryDefender) {
mView.onIsBatteryDefenderChanged(isBatteryDefender);
}
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.print(super.toString());
+ pw.println(" location=" + mLocation);
+ mView.dump(pw, args);
+ }
};
private final UserTracker.Callback mUserChangedCallback =
@@ -113,14 +123,15 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
@Inject
public BatteryMeterViewController(
BatteryMeterView view,
+ StatusBarLocation location,
UserTracker userTracker,
ConfigurationController configurationController,
TunerService tunerService,
@Main Handler mainHandler,
ContentResolver contentResolver,
- FeatureFlags featureFlags,
BatteryController batteryController) {
super(view);
+ mLocation = location;
mUserTracker = userTracker;
mConfigurationController = configurationController;
mTunerService = tunerService;
@@ -129,7 +140,8 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
mBatteryController = batteryController;
mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
- mView.setDisplayShieldEnabled(featureFlags.isEnabled(Flags.BATTERY_SHIELD_ICON));
+ mView.setDisplayShieldEnabled(
+ getContext().getResources().getBoolean(R.bool.flag_battery_shield_icon));
mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
mSettingObserver = new SettingObserver(mMainHandler);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
index a90980fddfb0..046ccf165d07 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
@@ -18,6 +18,7 @@ package com.android.systemui.dagger;
import com.android.systemui.globalactions.ShutdownUiModule;
import com.android.systemui.keyguard.CustomizationProvider;
+import com.android.systemui.shade.ShadeModule;
import com.android.systemui.statusbar.NotificationInsetsModule;
import com.android.systemui.statusbar.QsFrameTranslateModule;
@@ -32,6 +33,7 @@ import dagger.Subcomponent;
DependencyProvider.class,
NotificationInsetsModule.class,
QsFrameTranslateModule.class,
+ ShadeModule.class,
ShutdownUiModule.class,
SystemUIBinder.class,
SystemUIModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 3b897394c515..3c42a29451ca 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -82,7 +82,6 @@ import com.android.systemui.screenshot.dagger.ScreenshotModule;
import com.android.systemui.security.data.repository.SecurityRepositoryModule;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.ShadeModule;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
import com.android.systemui.shared.condition.Monitor;
@@ -199,7 +198,6 @@ import javax.inject.Named;
SecurityRepositoryModule.class,
ScreenRecordModule.class,
SettingsUtilModule.class,
- ShadeModule.class,
SmartRepliesInflationModule.class,
SmartspaceModule.class,
StatusBarPipelineModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index ee046c27d72e..484bf3d51f36 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -26,6 +26,7 @@ import androidx.core.animation.doOnEnd
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
+import com.android.dream.lowlight.util.TruncatedInterpolator
import com.android.systemui.R
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.complication.ComplicationLayoutParams
@@ -204,31 +205,28 @@ constructor(
translationYAnimator(
from = 0f,
to = -mDreamInTranslationYDistance.toFloat(),
- durationMs = mDreamInTranslationYDurationMs,
+ durationMs = mDreamInComplicationsAnimDurationMs,
delayMs = 0,
- interpolator = Interpolators.EMPHASIZED
+ // Truncate the animation from the full duration to match the alpha
+ // animation so that the whole animation ends at the same time.
+ interpolator =
+ TruncatedInterpolator(
+ Interpolators.EMPHASIZED,
+ /*originalDuration=*/ mDreamInTranslationYDurationMs.toFloat(),
+ /*newDuration=*/ mDreamInComplicationsAnimDurationMs.toFloat()
+ )
),
alphaAnimator(
- from =
- mCurrentAlphaAtPosition.getOrDefault(
- key = POSITION_BOTTOM,
- defaultValue = 1f
- ),
- to = 0f,
- durationMs = mDreamInComplicationsAnimDurationMs,
- delayMs = 0,
- positions = POSITION_BOTTOM
- )
- .apply {
- doOnEnd {
- // The logical end of the animation is once the alpha and blur
- // animations finish, end the animation so that any listeners are
- // notified. The Y translation animation is much longer than all of
- // the other animations due to how the spec is defined, but is not
- // expected to run to completion.
- mAnimator?.end()
- }
- },
+ from =
+ mCurrentAlphaAtPosition.getOrDefault(
+ key = POSITION_BOTTOM,
+ defaultValue = 1f
+ ),
+ to = 0f,
+ durationMs = mDreamInComplicationsAnimDurationMs,
+ delayMs = 0,
+ positions = POSITION_BOTTOM
+ ),
alphaAnimator(
from =
mCurrentAlphaAtPosition.getOrDefault(
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index a5a799565eaf..83c1c7100761 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -290,12 +290,17 @@ object Flags {
/** Migrate the lock icon view to the new keyguard root view. */
// TODO(b/286552209): Tracking bug.
@JvmField
- val MIGRATE_LOCK_ICON = unreleasedFlag(240, "migrate_lock_icon")
+ val MIGRATE_LOCK_ICON = unreleasedFlag(240, "migrate_lock_icon", teamfood = true)
// TODO(b/288276738): Tracking bug.
@JvmField
val WIDGET_ON_KEYGUARD = unreleasedFlag(241, "widget_on_keyguard")
+ /** Migrate the NSSL to the a sibling to both the panel and keyguard root view. */
+ // TODO(b/288074305): Tracking bug.
+ @JvmField
+ val MIGRATE_NSSL = unreleasedFlag(242, "migrate_nssl")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -367,22 +372,10 @@ object Flags {
// TODO(b/256614753): Tracking Bug
val NEW_STATUS_BAR_MOBILE_ICONS = releasedFlag(606, "new_status_bar_mobile_icons")
- // TODO(b/256614210): Tracking Bug
- val NEW_STATUS_BAR_WIFI_ICON = releasedFlag(607, "new_status_bar_wifi_icon")
-
// TODO(b/256614751): Tracking Bug
val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND =
unreleasedFlag(608, "new_status_bar_mobile_icons_backend", teamfood = true)
- // TODO(b/256613548): Tracking Bug
- val NEW_STATUS_BAR_WIFI_ICON_BACKEND =
- unreleasedFlag(609, "new_status_bar_wifi_icon_backend", teamfood = true)
-
- // TODO(b/256623670): Tracking Bug
- @JvmField
- val BATTERY_SHIELD_ICON =
- resourceBooleanFlag(610, R.bool.flag_battery_shield_icon, "battery_shield_icon")
-
// TODO(b/260881289): Tracking Bug
val NEW_STATUS_BAR_ICONS_DEBUG_COLORING =
unreleasedFlag(611, "new_status_bar_icons_debug_coloring")
@@ -799,4 +792,11 @@ object Flags {
// TODO(b/285174336): Tracking Bug
@JvmField
val USE_REPOS_FOR_BOUNCER_SHOWING = unreleasedFlag(2900, "use_repos_for_bouncer_showing")
+
+ // 3100 - Haptic interactions
+
+ // TODO(b/290213663): Tracking Bug
+ @JvmField
+ val ONE_WAY_HAPTICS_API_MIGRATION =
+ unreleasedFlag(3100, "oneway_haptics_api_migration")
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index e7704d625168..d119920e1a42 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -87,7 +87,7 @@ interface KeyguardRepository {
val isKeyguardShowing: Flow<Boolean>
/** Is the keyguard in a unlocked state? */
- val isKeyguardUnlocked: Flow<Boolean>
+ val isKeyguardUnlocked: StateFlow<Boolean>
/** Is an activity showing over the keyguard? */
val isKeyguardOccluded: Flow<Boolean>
@@ -299,7 +299,7 @@ constructor(
}
.distinctUntilChanged()
- override val isKeyguardUnlocked: Flow<Boolean> =
+ override val isKeyguardUnlocked: StateFlow<Boolean> =
conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
@@ -330,7 +330,11 @@ constructor(
awaitClose { keyguardStateController.removeCallback(callback) }
}
- .distinctUntilChanged()
+ .stateIn(
+ scope = scope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = keyguardStateController.isUnlocked,
+ )
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index a8af67a9fc97..b21b0017208c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -88,11 +88,7 @@ import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
-import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.tracing.ProtoTracer;
-import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
-import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.systemui.util.Assert;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.desktopmode.DesktopMode;
@@ -115,8 +111,7 @@ import javax.inject.Provider;
/**
* Utility class to handle edge swipes for back gesture
*/
-public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBackPlugin>,
- ProtoTraceable<SystemUiTraceProto> {
+public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBackPlugin> {
private static final String TAG = "EdgeBackGestureHandler";
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -192,7 +187,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private Consumer<Boolean> mButtonForcedVisibleCallback;
private final PluginManager mPluginManager;
- private final ProtoTracer mProtoTracer;
private final NavigationModeController mNavigationModeController;
private final BackPanelController.Factory mBackPanelControllerFactory;
private final ViewConfiguration mViewConfiguration;
@@ -402,7 +396,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
@Main Handler handler,
@Background Executor backgroundExecutor,
UserTracker userTracker,
- ProtoTracer protoTracer,
NavigationModeController navigationModeController,
BackPanelController.Factory backPanelControllerFactory,
ViewConfiguration viewConfiguration,
@@ -425,7 +418,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mOverviewProxyService = overviewProxyService;
mSysUiState = sysUiState;
mPluginManager = pluginManager;
- mProtoTracer = protoTracer;
mNavigationModeController = navigationModeController;
mBackPanelControllerFactory = backPanelControllerFactory;
mViewConfiguration = viewConfiguration;
@@ -557,7 +549,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
*/
public void onNavBarAttached() {
mIsAttached = true;
- mProtoTracer.add(this);
mOverviewProxyService.addCallback(mQuickSwitchListener);
mSysUiState.addCallback(mSysUiStateCallback);
if (mIsTrackpadGestureFeaturesEnabled) {
@@ -576,7 +567,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
*/
public void onNavBarDetached() {
mIsAttached = false;
- mProtoTracer.remove(this);
mOverviewProxyService.removeCallback(mQuickSwitchListener);
mSysUiState.removeCallback(mSysUiStateCallback);
mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
@@ -1135,8 +1125,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
dispatchToBackAnimation(ev);
}
}
-
- mProtoTracer.scheduleFrameUpdate();
}
private boolean isButtonPressFromTrackpad(MotionEvent ev) {
@@ -1285,14 +1273,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
return topActivity != null && mGestureBlockingActivities.contains(topActivity);
}
- @Override
- public void writeToProto(SystemUiTraceProto proto) {
- if (proto.edgeBackGestureHandler == null) {
- proto.edgeBackGestureHandler = new EdgeBackGestureHandlerProto();
- }
- proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
- }
-
public void setBackAnimation(BackAnimation backAnimation) {
mBackAnimation = backAnimation;
updateBackAnimationThresholds();
@@ -1319,7 +1299,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private final Handler mHandler;
private final Executor mBackgroundExecutor;
private final UserTracker mUserTracker;
- private final ProtoTracer mProtoTracer;
private final NavigationModeController mNavigationModeController;
private final BackPanelController.Factory mBackPanelControllerFactory;
private final ViewConfiguration mViewConfiguration;
@@ -1343,7 +1322,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
@Main Handler handler,
@Background Executor backgroundExecutor,
UserTracker userTracker,
- ProtoTracer protoTracer,
NavigationModeController navigationModeController,
BackPanelController.Factory backPanelControllerFactory,
ViewConfiguration viewConfiguration,
@@ -1365,7 +1343,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mHandler = handler;
mBackgroundExecutor = backgroundExecutor;
mUserTracker = userTracker;
- mProtoTracer = protoTracer;
mNavigationModeController = navigationModeController;
mBackPanelControllerFactory = backPanelControllerFactory;
mViewConfiguration = viewConfiguration;
@@ -1392,7 +1369,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mHandler,
mBackgroundExecutor,
mUserTracker,
- mProtoTracer,
mNavigationModeController,
mBackPanelControllerFactory,
mViewConfiguration,
diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
index c13476fbbe08..eb1ca66f6ca8 100644
--- a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt
@@ -20,6 +20,7 @@ package com.android.systemui.power.domain.interactor
import android.os.PowerManager
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.data.repository.PowerRepository
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
@@ -32,6 +33,7 @@ class PowerInteractor
@Inject
constructor(
private val repository: PowerRepository,
+ private val keyguardRepository: KeyguardRepository,
private val falsingCollector: FalsingCollector,
private val screenOffAnimationController: ScreenOffAnimationController,
private val statusBarStateController: StatusBarStateController,
@@ -54,4 +56,21 @@ constructor(
falsingCollector.onScreenOnFromTouch()
}
}
+
+ /**
+ * Wakes up the device if the device was dozing or going to sleep in order to display a
+ * full-screen intent.
+ */
+ fun wakeUpForFullScreenIntent() {
+ if (
+ keyguardRepository.wakefulness.value.isStartingToSleep() ||
+ statusBarStateController.isDozing
+ ) {
+ repository.wakeUp(why = FSI_WAKE_WHY, wakeReason = PowerManager.WAKE_REASON_APPLICATION)
+ }
+ }
+
+ companion object {
+ private const val FSI_WAKE_WHY = "full_screen_intent"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index e7dde6617964..207cc1398279 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -25,11 +25,9 @@ import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
@@ -173,8 +171,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private boolean mInputFocusTransferStarted;
private float mInputFocusTransferStartY;
private long mInputFocusTransferStartMillis;
- private float mWindowCornerRadius;
- private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
@VisibleForTesting
@@ -454,8 +450,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
Bundle params = new Bundle();
params.putBinder(KEY_EXTRA_SYSUI_PROXY, mSysUiProxy.asBinder());
- params.putFloat(KEY_EXTRA_WINDOW_CORNER_RADIUS, mWindowCornerRadius);
- params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
params.putBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER,
mSysuiUnlockAnimationController.asBinder());
mUnfoldTransitionProgressForwarder.ifPresent(
@@ -588,9 +582,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
com.android.internal.R.string.config_recentsComponentName));
mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(mRecentsComponentName.getPackageName());
- mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
- mSupportsRoundedCornersOnWindows = ScreenDecorationsUtils
- .supportsRoundedCornersOnWindows(mContext.getResources());
mSysUiState = sysUiState;
mSysUiState.addCallback(this::notifySystemUiStateFlags);
mUiEventLogger = uiEventLogger;
@@ -1084,8 +1075,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
pw.print(" mInputFocusTransferStarted="); pw.println(mInputFocusTransferStarted);
pw.print(" mInputFocusTransferStartY="); pw.println(mInputFocusTransferStartY);
pw.print(" mInputFocusTransferStartMillis="); pw.println(mInputFocusTransferStartMillis);
- pw.print(" mWindowCornerRadius="); pw.println(mWindowCornerRadius);
- pw.print(" mSupportsRoundedCornersOnWindows="); pw.println(mSupportsRoundedCornersOnWindows);
pw.print(" mActiveNavBarRegion="); pw.println(mActiveNavBarRegion);
pw.print(" mNavigationBarSurface="); pw.println(mNavigationBarSurface);
pw.print(" mNavBarMode="); pw.println(mNavBarMode);
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
index 59f82f034723..285ff74f8b2e 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
@@ -22,6 +22,8 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
@@ -45,6 +47,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
private val sceneInteractor: SceneInteractor,
private val authenticationInteractor: AuthenticationInteractor,
+ private val keyguardInteractor: KeyguardInteractor,
private val featureFlags: FeatureFlags,
) : CoreStartable {
@@ -78,7 +81,7 @@ constructor(
when {
isUnlocked ->
when (currentSceneKey) {
- // When the device becomes unlocked in Bouncer, go to the Gone.
+ // When the device becomes unlocked in Bouncer, go to Gone.
is SceneKey.Bouncer -> SceneKey.Gone
// When the device becomes unlocked in Lockscreen, go to Gone if
// bypass is enabled.
@@ -101,15 +104,30 @@ constructor(
}
}
.filterNotNull()
- .collect { targetSceneKey ->
- sceneInteractor.setCurrentScene(
- containerName = CONTAINER_NAME,
- scene = SceneModel(targetSceneKey),
- )
+ .collect { targetSceneKey -> switchToScene(targetSceneKey) }
+ }
+
+ applicationScope.launch {
+ keyguardInteractor.wakefulnessModel
+ .map { it.state == WakefulnessState.ASLEEP }
+ .distinctUntilChanged()
+ .collect { isAsleep ->
+ if (isAsleep) {
+ // When the device goes to sleep, reset the current scene.
+ val isUnlocked = authenticationInteractor.isUnlocked.value
+ switchToScene(if (isUnlocked) SceneKey.Gone else SceneKey.Lockscreen)
+ }
}
}
}
+ private fun switchToScene(targetSceneKey: SceneKey) {
+ sceneInteractor.setCurrentScene(
+ containerName = CONTAINER_NAME,
+ scene = SceneModel(targetSceneKey),
+ )
+ }
+
companion object {
private const val CONTAINER_NAME = SceneContainerNames.SYSTEM_UI_DEFAULT
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d97db3b27c87..ea15035a6c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1076,6 +1076,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mTapAgainViewController.init();
mShadeHeaderController.init();
+ mShadeHeaderController.setShadeCollapseAction(
+ () -> collapse(/* delayed= */ false , /* speedUpFactor= */ 1.0f));
mKeyguardUnfoldTransition.ifPresent(u -> u.setup(mView));
mNotificationPanelUnfoldAnimationController.ifPresent(controller ->
controller.setup(mNotificationContainerParent));
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
index ebb98883c679..02f337a8752a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
@@ -18,6 +18,7 @@ package com.android.systemui.shade;
import android.view.MotionEvent;
+import com.android.systemui.CoreStartable;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
@@ -31,7 +32,7 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
* these are coordinated with {@link StatusBarKeyguardViewManager} via
* {@link com.android.systemui.keyguard.KeyguardViewMediator} and others.
*/
-public interface ShadeController {
+public interface ShadeController extends CoreStartable {
/** Make our window larger and the shade expanded */
void instantExpandShade();
@@ -164,17 +165,14 @@ public interface ShadeController {
void onLaunchAnimationEnd(boolean launchIsFullScreen);
/** Sets the listener for when the visibility of the shade changes. */
- default void setVisibilityListener(ShadeVisibilityListener listener) {};
+ default void setVisibilityListener(ShadeVisibilityListener listener) {}
/** */
- default void setNotificationPresenter(NotificationPresenter presenter) {};
+ default void setNotificationPresenter(NotificationPresenter presenter) {}
/** */
default void setNotificationShadeWindowViewController(
- NotificationShadeWindowViewController notificationShadeWindowViewController) {};
-
- /** */
- default void setShadeViewController(ShadeViewController shadeViewController) {};
+ NotificationShadeWindowViewController notificationShadeWindowViewController) {}
/** Listens for shade visibility changes. */
interface ShadeVisibilityListener {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
index 4d0500786ca3..5f95bcae030e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
@@ -1,3 +1,19 @@
+/*
+ * 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
@@ -7,6 +23,7 @@ import javax.inject.Inject
/** Empty implementation of ShadeController for variants of Android without shades. */
@SysUISingleton
open class ShadeControllerEmptyImpl @Inject constructor() : ShadeController {
+ override fun start() {}
override fun instantExpandShade() {}
override fun instantCollapseShade() {}
override fun animateCollapseShade(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index af74a8d7dca1..22c638177a48 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -63,6 +63,7 @@ public final class ShadeControllerImpl implements ShadeController {
private final StatusBarWindowController mStatusBarWindowController;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final Lazy<ShadeViewController> mShadeViewControllerLazy;
private final Lazy<AssistManager> mAssistManagerLazy;
private final Lazy<NotificationGutsManager> mGutsManager;
@@ -70,8 +71,6 @@ public final class ShadeControllerImpl implements ShadeController {
private boolean mExpandedVisible;
- // TODO(b/237661616): Rename this variable to mShadeViewController.
- private ShadeViewController mNotificationPanelViewController;
private NotificationPresenter mPresenter;
private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
private ShadeVisibilityListener mShadeVisibilityListener;
@@ -87,11 +86,13 @@ public final class ShadeControllerImpl implements ShadeController {
DeviceProvisionedController deviceProvisionedController,
NotificationShadeWindowController notificationShadeWindowController,
WindowManager windowManager,
+ Lazy<ShadeViewController> shadeViewControllerLazy,
Lazy<AssistManager> assistManagerLazy,
Lazy<NotificationGutsManager> gutsManager
) {
mCommandQueue = commandQueue;
mMainExecutor = mainExecutor;
+ mShadeViewControllerLazy = shadeViewControllerLazy;
mStatusBarStateController = statusBarStateController;
mStatusBarWindowController = statusBarWindowController;
mDeviceProvisionedController = deviceProvisionedController;
@@ -107,7 +108,7 @@ public final class ShadeControllerImpl implements ShadeController {
public void instantExpandShade() {
// Make our window larger and the panel expanded.
makeExpandedVisible(true /* force */);
- mNotificationPanelViewController.expand(false /* animate */);
+ getShadeViewController().expand(false /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, false /* animate */);
}
@@ -123,13 +124,13 @@ public final class ShadeControllerImpl implements ShadeController {
"animateCollapse(): mExpandedVisible=" + mExpandedVisible + "flags=" + flags);
}
if (getNotificationShadeWindowView() != null
- && mNotificationPanelViewController.canBeCollapsed()
+ && getShadeViewController().canBeCollapsed()
&& (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
// release focus immediately to kick off focus change transition
mNotificationShadeWindowController.setNotificationShadeFocusable(false);
mNotificationShadeWindowViewController.cancelExpandHelper();
- mNotificationPanelViewController.collapse(true, delayed, speedUpFactor);
+ getShadeViewController().collapse(true, delayed, speedUpFactor);
}
}
@@ -138,7 +139,7 @@ public final class ShadeControllerImpl implements ShadeController {
if (!mCommandQueue.panelsEnabled()) {
return;
}
- mNotificationPanelViewController.expandToNotifications();
+ getShadeViewController().expandToNotifications();
}
@Override
@@ -149,12 +150,12 @@ public final class ShadeControllerImpl implements ShadeController {
// Settings are not available in setup
if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
- mNotificationPanelViewController.expandToQs();
+ getShadeViewController().expandToQs();
}
@Override
public boolean closeShadeIfOpen() {
- if (!mNotificationPanelViewController.isFullyCollapsed()) {
+ if (!getShadeViewController().isFullyCollapsed()) {
mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
notifyVisibilityChanged(false);
@@ -170,12 +171,12 @@ public final class ShadeControllerImpl implements ShadeController {
@Override
public boolean isShadeFullyOpen() {
- return mNotificationPanelViewController.isShadeFullyExpanded();
+ return getShadeViewController().isShadeFullyExpanded();
}
@Override
public boolean isExpandingOrCollapsing() {
- return mNotificationPanelViewController.isExpandingOrCollapsing();
+ return getShadeViewController().isExpandingOrCollapsing();
}
@Override
public void postAnimateCollapseShade() {
@@ -194,13 +195,13 @@ public final class ShadeControllerImpl implements ShadeController {
@Override
public void postOnShadeExpanded(Runnable executable) {
- mNotificationPanelViewController.addOnGlobalLayoutListener(
+ getShadeViewController().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getNotificationShadeWindowView().isVisibleToUser()) {
- mNotificationPanelViewController.removeOnGlobalLayoutListener(this);
- mNotificationPanelViewController.postToView(executable);
+ getShadeViewController().removeOnGlobalLayoutListener(this);
+ getShadeViewController().postToView(executable);
}
}
});
@@ -224,7 +225,7 @@ public final class ShadeControllerImpl implements ShadeController {
@Override
public boolean collapseShade() {
- if (!mNotificationPanelViewController.isFullyCollapsed()) {
+ if (!getShadeViewController().isFullyCollapsed()) {
// close the shade if it was open
animateCollapseShadeForcedDelayed();
notifyVisibilityChanged(false);
@@ -252,10 +253,10 @@ public final class ShadeControllerImpl implements ShadeController {
@Override
public void cancelExpansionAndCollapseShade() {
- if (mNotificationPanelViewController.isTracking()) {
+ if (getShadeViewController().isTracking()) {
mNotificationShadeWindowViewController.cancelCurrentTouch();
}
- if (mNotificationPanelViewController.isPanelExpanded()
+ if (getShadeViewController().isPanelExpanded()
&& mStatusBarStateController.getState() == StatusBarState.SHADE) {
animateCollapseShade();
}
@@ -311,7 +312,7 @@ public final class ShadeControllerImpl implements ShadeController {
@Override
public void instantCollapseShade() {
- mNotificationPanelViewController.instantCollapse();
+ getShadeViewController().instantCollapse();
runPostCollapseRunnables();
}
@@ -342,7 +343,7 @@ public final class ShadeControllerImpl implements ShadeController {
}
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
- mNotificationPanelViewController.collapse(false, false, 1.0f);
+ getShadeViewController().collapse(false, false, 1.0f);
mExpandedVisible = false;
notifyVisibilityChanged(false);
@@ -364,7 +365,7 @@ public final class ShadeControllerImpl implements ShadeController {
notifyExpandedVisibleChanged(false);
mCommandQueue.recomputeDisableFlags(
mDisplayId,
- mNotificationPanelViewController.shouldHideStatusBarIconsWhenExpanded());
+ getShadeViewController().shouldHideStatusBarIconsWhenExpanded());
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -406,11 +407,14 @@ public final class ShadeControllerImpl implements ShadeController {
return mNotificationShadeWindowViewController.getView();
}
+ private ShadeViewController getShadeViewController() {
+ return mShadeViewControllerLazy.get();
+ }
+
@Override
- public void setShadeViewController(ShadeViewController shadeViewController) {
- mNotificationPanelViewController = shadeViewController;
- mNotificationPanelViewController.setTrackingStartedListener(this::runPostCollapseRunnables);
- mNotificationPanelViewController.setOpenCloseListener(
+ public void start() {
+ getShadeViewController().setTrackingStartedListener(this::runPostCollapseRunnables);
+ getShadeViewController().setOpenCloseListener(
new OpenCloseListener() {
@Override
public void onClosingFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 411f91f0cb07..8b89ff49f418 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -122,6 +122,8 @@ constructor(
}
}
+ var shadeCollapseAction: Runnable? = null
+
private lateinit var iconManager: StatusBarIconController.TintedIconManager
private lateinit var carrierIconSlots: List<String>
private lateinit var mShadeCarrierGroupController: ShadeCarrierGroupController
@@ -469,9 +471,11 @@ constructor(
if (largeScreenActive) {
logInstantEvent("Large screen constraints set")
header.setTransition(LARGE_SCREEN_HEADER_TRANSITION_ID)
+ systemIcons.setOnClickListener { shadeCollapseAction?.run() }
} else {
logInstantEvent("Small screen constraints set")
header.setTransition(HEADER_TRANSITION_ID)
+ systemIcons.setOnClickListener(null)
}
header.jumpToState(header.startState)
updatePosition()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 8ae9e5e1fb8c..8ec8d115de78 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -50,6 +50,7 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC
import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
+import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.TapAgainView
import com.android.systemui.statusbar.policy.BatteryController
@@ -64,7 +65,7 @@ import javax.inject.Named
import javax.inject.Provider
/** Module for classes related to the notification shade. */
-@Module
+@Module(includes = [StartShadeModule::class])
abstract class ShadeModule {
@Binds
@@ -281,17 +282,16 @@ abstract class ShadeModule {
tunerService: TunerService,
@Main mainHandler: Handler,
contentResolver: ContentResolver,
- featureFlags: FeatureFlags,
batteryController: BatteryController,
): BatteryMeterViewController {
return BatteryMeterViewController(
batteryMeterView,
+ StatusBarLocation.QS,
userTracker,
configurationController,
tunerService,
mainHandler,
contentResolver,
- featureFlags,
batteryController,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt
new file mode 100644
index 000000000000..c50693c30533
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import com.android.systemui.CoreStartable
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+
+@Module
+internal abstract class StartShadeModule {
+ @Binds
+ @IntoMap
+ @ClassKey(ShadeController::class)
+ abstract fun bind(shadeController: ShadeController): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
index ce730baeed0d..5d06f8d083d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
@@ -21,8 +21,8 @@ import android.widget.FrameLayout
/**
* A temporary base class that's shared between our old status bar connectivity view implementations
- * ([StatusBarWifiView], [StatusBarMobileView]) and our new status bar implementations (
- * [ModernStatusBarWifiView], [ModernStatusBarMobileView]).
+ * ([StatusBarMobileView]) and our new status bar implementations ([ModernStatusBarWifiView],
+ * [ModernStatusBarMobileView]).
*
* Once our refactor is over, we should be able to delete this go-between class and the old view
* class.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a532195c5b9f..92df78bac17f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -73,7 +73,6 @@ import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.statusbar.policy.CallbackController;
-import com.android.systemui.tracing.ProtoTracer;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -190,7 +189,6 @@ public class CommandQueue extends IStatusBar.Stub implements
*/
private int mLastUpdatedImeDisplayId = INVALID_DISPLAY;
private final DisplayTracker mDisplayTracker;
- private ProtoTracer mProtoTracer;
private final @Nullable CommandRegistry mRegistry;
private final @Nullable DumpHandler mDumpHandler;
@@ -504,18 +502,16 @@ public class CommandQueue extends IStatusBar.Stub implements
@VisibleForTesting
public CommandQueue(Context context, DisplayTracker displayTracker) {
- this(context, displayTracker, null, null, null);
+ this(context, displayTracker, null, null);
}
public CommandQueue(
Context context,
DisplayTracker displayTracker,
- ProtoTracer protoTracer,
CommandRegistry registry,
DumpHandler dumpHandler
) {
mDisplayTracker = displayTracker;
- mProtoTracer = protoTracer;
mRegistry = registry;
mDumpHandler = dumpHandler;
mDisplayTracker.addDisplayChangeCallback(new DisplayTracker.Callback() {
@@ -1160,9 +1156,6 @@ public class CommandQueue extends IStatusBar.Stub implements
@Override
public void startTracing() {
synchronized (mLock) {
- if (mProtoTracer != null) {
- mProtoTracer.start();
- }
mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, true).sendToTarget();
}
}
@@ -1170,9 +1163,6 @@ public class CommandQueue extends IStatusBar.Stub implements
@Override
public void stopTracing() {
synchronized (mLock) {
- if (mProtoTracer != null) {
- mProtoTracer.stop();
- }
mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, false).sendToTarget();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
deleted file mode 100644
index 8d7214d6bd75..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2018 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;
-
-import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-
-import java.util.ArrayList;
-
-/**
- * Start small: StatusBarWifiView will be able to layout from a WifiIconState
- */
-public class StatusBarWifiView extends BaseStatusBarFrameLayout implements DarkReceiver {
- private static final String TAG = "StatusBarWifiView";
-
- /// Used to show etc dots
- private StatusBarIconView mDotView;
- /// Contains the main icon layout
- private LinearLayout mWifiGroup;
- private ImageView mWifiIcon;
- private ImageView mIn;
- private ImageView mOut;
- private View mInoutContainer;
- private View mSignalSpacer;
- private View mAirplaneSpacer;
- private WifiIconState mState;
- private String mSlot;
- @StatusBarIconView.VisibleState
- private int mVisibleState = STATE_HIDDEN;
-
- public static StatusBarWifiView fromContext(Context context, String slot) {
- LayoutInflater inflater = LayoutInflater.from(context);
- StatusBarWifiView v = (StatusBarWifiView) inflater.inflate(R.layout.status_bar_wifi_group, null);
- v.setSlot(slot);
- v.init();
- v.setVisibleState(STATE_ICON);
- return v;
- }
-
- public StatusBarWifiView(Context context) {
- super(context);
- }
-
- public StatusBarWifiView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public StatusBarWifiView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public void setSlot(String slot) {
- mSlot = slot;
- }
-
- @Override
- public void setStaticDrawableColor(int color) {
- ColorStateList list = ColorStateList.valueOf(color);
- mWifiIcon.setImageTintList(list);
- mIn.setImageTintList(list);
- mOut.setImageTintList(list);
- mDotView.setDecorColor(color);
- }
-
- @Override
- public void setDecorColor(int color) {
- mDotView.setDecorColor(color);
- }
-
- @Override
- public String getSlot() {
- return mSlot;
- }
-
- @Override
- public boolean isIconVisible() {
- return mState != null && mState.visible;
- }
-
- @Override
- public void setVisibleState(@StatusBarIconView.VisibleState int state, boolean animate) {
- if (state == mVisibleState) {
- return;
- }
- mVisibleState = state;
-
- switch (state) {
- case STATE_ICON:
- mWifiGroup.setVisibility(View.VISIBLE);
- mDotView.setVisibility(View.GONE);
- break;
- case STATE_DOT:
- mWifiGroup.setVisibility(View.GONE);
- mDotView.setVisibility(View.VISIBLE);
- break;
- case STATE_HIDDEN:
- default:
- mWifiGroup.setVisibility(View.GONE);
- mDotView.setVisibility(View.GONE);
- break;
- }
- }
-
- @Override
- @StatusBarIconView.VisibleState
- public int getVisibleState() {
- return mVisibleState;
- }
-
- @Override
- public void getDrawingRect(Rect outRect) {
- super.getDrawingRect(outRect);
- float translationX = getTranslationX();
- float translationY = getTranslationY();
- outRect.left += translationX;
- outRect.right += translationX;
- outRect.top += translationY;
- outRect.bottom += translationY;
- }
-
- private void init() {
- mWifiGroup = findViewById(R.id.wifi_group);
- mWifiIcon = findViewById(R.id.wifi_signal);
- mIn = findViewById(R.id.wifi_in);
- mOut = findViewById(R.id.wifi_out);
- mSignalSpacer = findViewById(R.id.wifi_signal_spacer);
- mAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
- mInoutContainer = findViewById(R.id.inout_container);
-
- initDotView();
- }
-
- private void initDotView() {
- mDotView = new StatusBarIconView(mContext, mSlot, null);
- mDotView.setVisibleState(STATE_DOT);
-
- int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size_sp);
- LayoutParams lp = new LayoutParams(width, width);
- lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
- addView(mDotView, lp);
- }
-
- public void applyWifiState(WifiIconState state) {
- boolean requestLayout = false;
-
- if (state == null) {
- requestLayout = getVisibility() != View.GONE;
- setVisibility(View.GONE);
- mState = null;
- } else if (mState == null) {
- requestLayout = true;
- mState = state.copy();
- initViewState();
- } else if (!mState.equals(state)) {
- requestLayout = updateState(state.copy());
- }
-
- if (requestLayout) {
- requestLayout();
- }
- }
-
- private boolean updateState(WifiIconState state) {
- setContentDescription(state.contentDescription);
- if (mState.resId != state.resId && state.resId >= 0) {
- mWifiIcon.setImageDrawable(mContext.getDrawable(state.resId));
- }
-
- mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
- mOut.setVisibility(state.activityOut ? View.VISIBLE : View.GONE);
- mInoutContainer.setVisibility(
- (state.activityIn || state.activityOut) ? View.VISIBLE : View.GONE);
- mAirplaneSpacer.setVisibility(state.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
- mSignalSpacer.setVisibility(state.signalSpacerVisible ? View.VISIBLE : View.GONE);
-
- boolean needsLayout = state.activityIn != mState.activityIn
- ||state.activityOut != mState.activityOut;
-
- if (mState.visible != state.visible) {
- needsLayout |= true;
- setVisibility(state.visible ? View.VISIBLE : View.GONE);
- }
-
- mState = state;
- return needsLayout;
- }
-
- private void initViewState() {
- setContentDescription(mState.contentDescription);
- if (mState.resId >= 0) {
- mWifiIcon.setImageDrawable(mContext.getDrawable(mState.resId));
- }
-
- mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
- mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE);
- mInoutContainer.setVisibility(
- (mState.activityIn || mState.activityOut) ? View.VISIBLE : View.GONE);
- mAirplaneSpacer.setVisibility(mState.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
- mSignalSpacer.setVisibility(mState.signalSpacerVisible ? View.VISIBLE : View.GONE);
- setVisibility(mState.visible ? View.VISIBLE : View.GONE);
- }
-
- @Override
- public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
- int areaTint = getTint(areas, this, tint);
- ColorStateList color = ColorStateList.valueOf(areaTint);
- mWifiIcon.setImageTintList(color);
- mIn.setImageTintList(color);
- mOut.setImageTintList(color);
- mDotView.setDecorColor(areaTint);
- mDotView.setIconColor(areaTint, false);
- }
-
-
- @Override
- public String toString() {
- return "StatusBarWifiView(slot=" + mSlot + " state=" + mState + ")";
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 73f181b8c734..9aa28c31cfd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -18,10 +18,6 @@ package com.android.systemui.statusbar.connectivity;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.Nullable;
@@ -557,10 +553,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
mBroadcastDispatcher.unregisterReceiver(this);
}
- public int getConnectedWifiLevel() {
- return mWifiSignalController.getState().level;
- }
-
@Override
public AccessPointController getAccessPointController() {
return mAccessPoints;
@@ -654,14 +646,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
return mWifiSignalController.isCarrierMergedWifi(subId);
}
- boolean hasDefaultNetwork() {
- return !mNoDefaultNetwork;
- }
-
- boolean isNonCarrierWifiNetworkAvailable() {
- return !mNoNetworksAvailable;
- }
-
boolean isEthernetDefault() {
return mConnectedTransports.get(NetworkCapabilities.TRANSPORT_ETHERNET);
}
@@ -1242,15 +1226,12 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
private boolean mDemoInetCondition;
- private WifiState mDemoWifiState;
@Override
public void onDemoModeStarted() {
if (DEBUG) Log.d(TAG, "Entering demo mode");
unregisterListeners();
mDemoInetCondition = mInetCondition;
- mDemoWifiState = mWifiSignalController.getState();
- mDemoWifiState.ssid = "DemoMode";
}
@Override
@@ -1300,41 +1281,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
controller.updateConnectivity(connected, connected);
}
}
- String wifi = args.getString("wifi");
- if (wifi != null && !mStatusBarPipelineFlags.runNewWifiIconBackend()) {
- boolean show = wifi.equals("show");
- String level = args.getString("level");
- if (level != null) {
- mDemoWifiState.level = level.equals("null") ? -1
- : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
- mDemoWifiState.connected = mDemoWifiState.level >= 0;
- }
- String activity = args.getString("activity");
- if (activity != null) {
- switch (activity) {
- case "inout":
- mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
- break;
- case "in":
- mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
- break;
- case "out":
- mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
- break;
- default:
- mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
- break;
- }
- } else {
- mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
- }
- String ssid = args.getString("ssid");
- if (ssid != null) {
- mDemoWifiState.ssid = ssid;
- }
- mDemoWifiState.enabled = show;
- mWifiSignalController.notifyListeners();
- }
String sims = args.getString("sims");
if (sims != null && !mStatusBarPipelineFlags.useNewMobileIcons()) {
int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 035fa0454bfc..e5ba3ce1fdae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -78,7 +78,6 @@ import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
-import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.SystemClock;
@@ -195,11 +194,10 @@ public interface CentralSurfacesDependenciesModule {
static CommandQueue provideCommandQueue(
Context context,
DisplayTracker displayTracker,
- ProtoTracer protoTracer,
CommandRegistry registry,
DumpHandler dumpHandler
) {
- return new CommandQueue(context, displayTracker, protoTracer, registry, dumpHandler);
+ return new CommandQueue(context, displayTracker, registry, dumpHandler);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index 212f2c215989..1cf9c1e1f299 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -3,7 +3,10 @@ package com.android.systemui.statusbar.notification
import android.util.FloatProperty
import android.view.View
import androidx.annotation.FloatRange
+import com.android.systemui.Dependency
import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import kotlin.math.abs
@@ -20,6 +23,8 @@ interface Roundable {
/** Properties required for a Roundable */
val roundableState: RoundableState
+ val clipHeight: Int
+
/** Current top roundness */
@get:FloatRange(from = 0.0, to = 1.0)
@JvmDefault
@@ -40,12 +45,16 @@ interface Roundable {
/** Current top corner in pixel, based on [topRoundness] and [maxRadius] */
@JvmDefault
val topCornerRadius: Float
- get() = topRoundness * maxRadius
+ get() =
+ if (roundableState.newHeadsUpAnimFlagEnabled) roundableState.topCornerRadius
+ else topRoundness * maxRadius
/** Current bottom corner in pixel, based on [bottomRoundness] and [maxRadius] */
@JvmDefault
val bottomCornerRadius: Float
- get() = bottomRoundness * maxRadius
+ get() =
+ if (roundableState.newHeadsUpAnimFlagEnabled) roundableState.bottomCornerRadius
+ else bottomRoundness * maxRadius
/** Get and update the current radii */
@JvmDefault
@@ -320,14 +329,20 @@ interface Roundable {
* @param roundable Target of the radius animation
* @param maxRadius Max corner radius in pixels
*/
-class RoundableState(
+class RoundableState
+@JvmOverloads
+constructor(
internal val targetView: View,
private val roundable: Roundable,
maxRadius: Float,
+ private val featureFlags: FeatureFlags = Dependency.get(FeatureFlags::class.java)
) {
internal var maxRadius = maxRadius
private set
+ internal val newHeadsUpAnimFlagEnabled
+ get() = featureFlags.isEnabled(Flags.IMPROVED_HUN_ANIMATIONS)
+
/** Animatable for top roundness */
private val topAnimatable = topAnimatable(roundable)
@@ -344,6 +359,41 @@ class RoundableState(
internal var bottomRoundness = 0f
private set
+ internal val topCornerRadius: Float
+ get() {
+ val height = roundable.clipHeight
+ val topRadius = topRoundness * maxRadius
+ val bottomRadius = bottomRoundness * maxRadius
+
+ if (height == 0) {
+ return 0f
+ } else if (topRadius + bottomRadius > height) {
+ // The sum of top and bottom corner radii should be at max the clipped height
+ val overShoot = topRadius + bottomRadius - height
+ return topRadius - (overShoot * topRoundness / (topRoundness + bottomRoundness))
+ }
+
+ return topRadius
+ }
+
+ internal val bottomCornerRadius: Float
+ get() {
+ val height = roundable.clipHeight
+ val topRadius = topRoundness * maxRadius
+ val bottomRadius = bottomRoundness * maxRadius
+
+ if (height == 0) {
+ return 0f
+ } else if (topRadius + bottomRadius > height) {
+ // The sum of top and bottom corner radii should be at max the clipped height
+ val overShoot = topRadius + bottomRadius - height
+ return bottomRadius -
+ (overShoot * bottomRoundness / (topRoundness + bottomRoundness))
+ }
+
+ return bottomRadius
+ }
+
/** Last requested top roundness associated by [SourceType] */
internal val topRoundnessMap = mutableMapOf<SourceType, Float>()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 27510d47b5ab..908c11a1d076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -566,12 +566,20 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
@Override
public float getTopCornerRadius() {
+ if (isNewHeadsUpAnimFlagEnabled()) {
+ return super.getTopCornerRadius();
+ }
+
float fraction = getInterpolatedAppearAnimationFraction();
return MathUtils.lerp(0, super.getTopCornerRadius(), fraction);
}
@Override
public float getBottomCornerRadius() {
+ if (isNewHeadsUpAnimFlagEnabled()) {
+ return super.getBottomCornerRadius();
+ }
+
float fraction = getInterpolatedAppearAnimationFraction();
return MathUtils.lerp(0, super.getBottomCornerRadius(), fraction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 9aa50e989ff1..7f23c1b89b51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -28,7 +28,10 @@ import android.util.IndentingPrintWriter;
import android.view.View;
import android.view.ViewOutlineProvider;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.notification.RoundableState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.util.DumpUtilsKt;
@@ -47,12 +50,14 @@ public abstract class ExpandableOutlineView extends ExpandableView {
private float mOutlineAlpha = -1f;
private boolean mAlwaysRoundBothCorners;
private Path mTmpPath = new Path();
+ private final FeatureFlags mFeatureFlags;
/**
* {@code false} if the children views of the {@link ExpandableOutlineView} are translated when
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
*/
protected boolean mDismissUsingRowTranslationX = true;
+
private float[] mTmpCornerRadii = new float[8];
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@@ -81,6 +86,15 @@ public abstract class ExpandableOutlineView extends ExpandableView {
return mRoundableState;
}
+ @Override
+ public int getClipHeight() {
+ if (mCustomOutline) {
+ return mOutlineRect.height();
+ }
+
+ return super.getClipHeight();
+ }
+
protected Path getClipPath(boolean ignoreTranslation) {
int left;
int top;
@@ -112,7 +126,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
return EMPTY_PATH;
}
float bottomRadius = mAlwaysRoundBothCorners ? getMaxRadius() : getBottomCornerRadius();
- if (topRadius + bottomRadius > height) {
+ if (!isNewHeadsUpAnimFlagEnabled() && (topRadius + bottomRadius > height)) {
float overShoot = topRadius + bottomRadius - height;
float currentTopRoundness = getTopRoundness();
float currentBottomRoundness = getBottomRoundness();
@@ -153,6 +167,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
super(context, attrs);
setOutlineProvider(mProvider);
initDimens();
+ mFeatureFlags = Dependency.get(FeatureFlags.class);
}
@Override
@@ -360,4 +375,9 @@ public abstract class ExpandableOutlineView extends ExpandableView {
}
});
}
+
+ // TODO(b/290365128) replace with ViewRefactorFlag
+ protected boolean isNewHeadsUpAnimFlagEnabled() {
+ return mFeatureFlags.isEnabled(Flags.IMPROVED_HUN_ANIMATIONS);
+ }
}
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 f98624409e56..c4c116ba0613 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
@@ -93,6 +93,12 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro
return mRoundableState;
}
+ @Override
+ public int getClipHeight() {
+ int clipHeight = Math.max(mActualHeight - mClipTopAmount - mClipBottomAmount, 0);
+ return Math.max(clipHeight, mMinimumHeightForClipping);
+ }
+
private void initDimens() {
mContentShift = getResources().getDimensionPixelSize(
R.dimen.shelf_transform_content_shift);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index ef5e86f06ef0..87205e2df9c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -120,6 +120,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple
}
@Override
+ public int getClipHeight() {
+ return mView.getHeight();
+ }
+
+ @Override
public void applyRoundnessAndInvalidate() {
if (mRoundnessChangedListener != null) {
// We cannot apply the rounded corner to this View, so our parents (in drawChild()) will
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
index 04308b47abc9..a8d8a8e03ed5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
@@ -30,8 +30,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableView
*/
class MediaContainerView(context: Context, attrs: AttributeSet?) : ExpandableView(context, attrs) {
+ override var clipHeight = 0
var cornerRadius = 0f
- var clipHeight = 0
var clipRect = RectF()
var clipPath = Path()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index dad806418f2d..626f851d9d11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -192,6 +192,11 @@ public class NotificationChildrenContainer extends ViewGroup
}
@Override
+ public int getClipHeight() {
+ return Math.max(mActualHeight - mClipBottomAmount, 0);
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount =
Math.min(mAttachedChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
index 730ef57f1972..26b51a95acad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -37,6 +37,7 @@ import com.android.systemui.animation.DelegateLaunchAnimatorController
import com.android.systemui.assist.AssistManager
import com.android.systemui.camera.CameraIntents.Companion.isInsecureCameraIntent
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.DisplayId
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardViewMediator
import com.android.systemui.keyguard.WakefulnessLifecycle
@@ -72,6 +73,7 @@ constructor(
private val notifShadeWindowControllerLazy: Lazy<NotificationShadeWindowController>,
private val activityLaunchAnimator: ActivityLaunchAnimator,
private val context: Context,
+ @DisplayId private val displayId: Int,
private val lockScreenUserManager: NotificationLockscreenUserManager,
private val statusBarWindowController: StatusBarWindowController,
private val wakefulnessLifecycle: WakefulnessLifecycle,
@@ -471,9 +473,7 @@ constructor(
intent.getPackage()
) { adapter: RemoteAnimationAdapter? ->
val options =
- ActivityOptions(
- CentralSurfaces.getActivityOptions(centralSurfaces!!.displayId, adapter)
- )
+ ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter))
// We know that the intent of the caller is to dismiss the keyguard and
// this runnable is called right after the keyguard is solved, so we tell
@@ -596,7 +596,7 @@ constructor(
val options =
ActivityOptions(
CentralSurfaces.getActivityOptions(
- centralSurfaces!!.displayId,
+ displayId,
animationAdapter
)
)
@@ -762,7 +762,7 @@ constructor(
TaskStackBuilder.create(context)
.addNextIntent(intent)
.startActivities(
- CentralSurfaces.getActivityOptions(centralSurfaces!!.displayId, adapter),
+ CentralSurfaces.getActivityOptions(displayId, adapter),
userHandle
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 478baf2f58d6..2b9c3d33e9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -355,15 +355,11 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
void updateNotificationPanelTouchState();
- int getDisplayId();
-
int getRotation();
@VisibleForTesting
void setBarStateForTest(int state);
- void wakeUpForFullScreenIntent();
-
void showTransientUnchecked();
void clearTransient();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 8902a186c43a..62e98f934888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1613,7 +1613,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
// (Right now, there's a circular dependency.)
mNotificationShadeWindowController.setWindowRootView(windowRootView);
mNotificationShadeWindowViewController.setupExpandedStatusBar();
- mShadeController.setShadeViewController(mShadeSurface);
mShadeController.setNotificationShadeWindowViewController(
mNotificationShadeWindowViewController);
mBackActionInteractor.setup(mQsController, mShadeSurface);
@@ -1773,7 +1772,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
try {
EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
sbn.getKey());
- wakeUpForFullScreenIntent();
+ mPowerInteractor.wakeUpForFullScreenIntent();
ActivityOptions opts = ActivityOptions.makeBasic();
opts.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
@@ -1786,16 +1785,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mHeadsUpManager.releaseAllImmediately();
}
- @Override
- public void wakeUpForFullScreenIntent() {
- if (isGoingToSleep() || mDozing) {
- mPowerManager.wakeUp(
- SystemClock.uptimeMillis(),
- PowerManager.WAKE_REASON_APPLICATION,
- "com.android.systemui:full_screen_intent");
- }
- }
-
/**
* Called when another window is about to transfer it's input focus.
*/
@@ -2108,11 +2097,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
@Override
- public int getDisplayId() {
- return mDisplayId;
- }
-
- @Override
public void readyForKeyguardDone() {
mStatusBarKeyguardViewManager.readyForKeyguardDone();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 39b5b5a4cef8..8e9f382d8c00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -35,11 +35,9 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
@@ -58,7 +56,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
private final ArrayList<ModernStatusBarMobileView> mModernMobileViews = new ArrayList<>();
private final int mIconSize;
- private StatusBarWifiView mWifiView;
private ModernStatusBarWifiView mModernWifiView;
private boolean mDemoMode;
private int mColor;
@@ -238,36 +235,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
addView(v, 0, createLayoutParams());
}
- public void addDemoWifiView(WifiIconState state) {
- Log.d(TAG, "addDemoWifiView: ");
- StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);
-
- int viewIndex = getChildCount();
- // If we have mobile views, put wifi before them
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof StatusBarMobileView
- || child instanceof ModernStatusBarMobileView) {
- viewIndex = i;
- break;
- }
- }
-
- mWifiView = view;
- mWifiView.applyWifiState(state);
- mWifiView.setStaticDrawableColor(mColor);
- addView(view, viewIndex, createLayoutParams());
- }
-
- public void updateWifiState(WifiIconState state) {
- Log.d(TAG, "updateWifiState: ");
- if (mWifiView == null) {
- addDemoWifiView(state);
- } else {
- mWifiView.applyWifiState(state);
- }
- }
-
/**
* Add a new mobile icon view
*/
@@ -352,10 +319,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
public void onRemoveIcon(StatusIconDisplayable view) {
if (view.getSlot().equals("wifi")) {
- if (view instanceof StatusBarWifiView) {
- removeView(mWifiView);
- mWifiView = null;
- } else if (view instanceof ModernStatusBarWifiView) {
+ if (view instanceof ModernStatusBarWifiView) {
Log.d(TAG, "onRemoveIcon: removing modern wifi view");
removeView(mModernWifiView);
mModernWifiView = null;
@@ -409,9 +373,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
setColor(DarkIconDispatcher.getTint(areas, mStatusIcons, tint));
- if (mWifiView != null) {
- mWifiView.onDarkChanged(areas, darkIntensity, tint);
- }
if (mModernWifiView != null) {
mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 59583ddf3e34..42b0a4f13e0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -17,7 +17,6 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW;
import android.annotation.Nullable;
@@ -43,12 +42,10 @@ import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.BaseStatusBarFrameLayout;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
@@ -97,16 +94,9 @@ public interface StatusBarIconController {
*/
void setIcon(String slot, int resourceId, CharSequence contentDescription);
- /** */
- void setWifiIcon(String slot, WifiIconState state);
-
/**
* Sets up a wifi icon using the new data pipeline. No effect if the wifi icon has already been
* set up (inflated and added to the view hierarchy).
- *
- * This method completely replaces {@link #setWifiIcon} with the information from the new wifi
- * data pipeline. Icons will automatically keep their state up to date, so we don't have to
- * worry about funneling state objects through anymore.
*/
void setNewWifiIcon();
@@ -408,13 +398,7 @@ public interface StatusBarIconController {
mMobileIconsViewModel = null;
}
- if (statusBarPipelineFlags.runNewWifiIconBackend()) {
- // This starts the flow for the new pipeline, and will notify us of changes if
- // {@link StatusBarPipelineFlags#useNewWifiIcon} is also true.
- mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
- } else {
- mWifiViewModel = null;
- }
+ mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
}
public boolean isDemoable() {
@@ -462,9 +446,6 @@ public interface StatusBarIconController {
case TYPE_ICON:
return addIcon(index, slot, blocked, holder.getIcon());
- case TYPE_WIFI:
- return addWifiIcon(index, slot, holder.getWifiState());
-
case TYPE_WIFI_NEW:
return addNewWifiIcon(index, slot);
@@ -487,29 +468,7 @@ public interface StatusBarIconController {
return view;
}
- @VisibleForTesting
- protected StatusIconDisplayable addWifiIcon(int index, String slot, WifiIconState state) {
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- throw new IllegalStateException("Attempting to add a wifi icon while the new "
- + "icons are enabled is not supported");
- }
-
- final StatusBarWifiView view = onCreateStatusBarWifiView(slot);
- view.applyWifiState(state);
- mGroup.addView(view, index, onCreateLayoutParams());
-
- if (mIsInDemoMode) {
- mDemoStatusIcons.addDemoWifiView(state);
- }
- return view;
- }
-
protected StatusIconDisplayable addNewWifiIcon(int index, String slot) {
- if (!mStatusBarPipelineFlags.useNewWifiIcon()) {
- throw new IllegalStateException("Attempting to add a wifi icon using the new"
- + "pipeline, but the enabled flag is false.");
- }
-
ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
mGroup.addView(view, index, onCreateLayoutParams());
@@ -573,11 +532,6 @@ public interface StatusBarIconController {
return new StatusBarIconView(mContext, slot, null, blocked);
}
- private StatusBarWifiView onCreateStatusBarWifiView(String slot) {
- StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot);
- return view;
- }
-
private ModernStatusBarWifiView onCreateModernStatusBarWifiView(String slot) {
return ModernStatusBarWifiView.constructAndBind(mContext, slot, mWifiViewModel);
}
@@ -640,9 +594,6 @@ public interface StatusBarIconController {
case TYPE_ICON:
onSetIcon(viewIndex, holder.getIcon());
return;
- case TYPE_WIFI:
- onSetWifiIcon(viewIndex, holder.getWifiState());
- return;
case TYPE_MOBILE:
onSetMobileIcon(viewIndex, holder.getMobileState());
return;
@@ -655,23 +606,6 @@ public interface StatusBarIconController {
}
}
- public void onSetWifiIcon(int viewIndex, WifiIconState state) {
- View view = mGroup.getChildAt(viewIndex);
- if (view instanceof StatusBarWifiView) {
- ((StatusBarWifiView) view).applyWifiState(state);
- } else if (view instanceof ModernStatusBarWifiView) {
- // ModernStatusBarWifiView will automatically apply state based on its callbacks, so
- // we don't need to call applyWifiState.
- } else {
- throw new IllegalStateException("View at " + viewIndex + " must be of type "
- + "StatusBarWifiView or ModernStatusBarWifiView");
- }
-
- if (mIsInDemoMode) {
- mDemoStatusIcons.updateWifiState(state);
- }
- }
-
public void onSetMobileIcon(int viewIndex, MobileIconState state) {
View view = mGroup.getChildAt(viewIndex);
if (view instanceof StatusBarMobileView) {
@@ -703,9 +637,7 @@ public interface StatusBarIconController {
mIsInDemoMode = true;
if (mDemoStatusIcons == null) {
mDemoStatusIcons = createDemoStatusIcons();
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- mDemoStatusIcons.addModernWifiView(mWifiViewModel);
- }
+ mDemoStatusIcons.addModernWifiView(mWifiViewModel);
}
mDemoStatusIcons.onDemoModeStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 80d5651a65dc..d1a02d6cd611 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -40,7 +40,6 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -202,35 +201,7 @@ public class StatusBarIconControllerImpl implements Tunable,
}
@Override
- public void setWifiIcon(String slot, WifiIconState state) {
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- Log.d(TAG, "ignoring old pipeline callback because the new wifi icon is enabled");
- return;
- }
-
- if (state == null) {
- removeIcon(slot, 0);
- return;
- }
-
- StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, 0);
- if (holder == null) {
- holder = StatusBarIconHolder.fromWifiIconState(state);
- setIcon(slot, holder);
- } else {
- holder.setWifiState(state);
- handleSet(slot, holder);
- }
- }
-
-
- @Override
public void setNewWifiIcon() {
- if (!mStatusBarPipelineFlags.useNewWifiIcon()) {
- Log.d(TAG, "ignoring new pipeline callback because the new wifi icon is disabled");
- return;
- }
-
String slot = mContext.getString(com.android.internal.R.string.status_bar_wifi);
StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, /* tag= */ 0);
if (holder == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index 833cb93f62e9..01fd247f54bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -25,7 +25,6 @@ import android.os.UserHandle;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel;
import java.lang.annotation.Retention;
@@ -36,7 +35,6 @@ import java.lang.annotation.RetentionPolicy;
*/
public class StatusBarIconHolder {
public static final int TYPE_ICON = 0;
- public static final int TYPE_WIFI = 1;
public static final int TYPE_MOBILE = 2;
/**
* TODO (b/249790733): address this once the new pipeline is in place
@@ -65,7 +63,6 @@ public class StatusBarIconHolder {
@IntDef({
TYPE_ICON,
- TYPE_WIFI,
TYPE_MOBILE,
TYPE_MOBILE_NEW,
TYPE_WIFI_NEW
@@ -74,7 +71,6 @@ public class StatusBarIconHolder {
@interface IconType {}
private StatusBarIcon mIcon;
- private WifiIconState mWifiState;
private MobileIconState mMobileState;
private @IconType int mType = TYPE_ICON;
private int mTag = 0;
@@ -83,7 +79,6 @@ public class StatusBarIconHolder {
public static String getTypeString(@IconType int type) {
switch(type) {
case TYPE_ICON: return "ICON";
- case TYPE_WIFI: return "WIFI_OLD";
case TYPE_MOBILE: return "MOBILE_OLD";
case TYPE_MOBILE_NEW: return "MOBILE_NEW";
case TYPE_WIFI_NEW: return "WIFI_NEW";
@@ -101,25 +96,6 @@ public class StatusBarIconHolder {
return wrapper;
}
- /** */
- public static StatusBarIconHolder fromResId(
- Context context,
- int resId,
- CharSequence contentDescription) {
- StatusBarIconHolder holder = new StatusBarIconHolder();
- holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
- Icon.createWithResource( context, resId), 0, 0, contentDescription);
- return holder;
- }
-
- /** */
- public static StatusBarIconHolder fromWifiIconState(WifiIconState state) {
- StatusBarIconHolder holder = new StatusBarIconHolder();
- holder.mWifiState = state;
- holder.mType = TYPE_WIFI;
- return holder;
- }
-
/** Creates a new holder with for the new wifi icon. */
public static StatusBarIconHolder forNewWifiIcon() {
StatusBarIconHolder holder = new StatusBarIconHolder();
@@ -178,15 +154,6 @@ public class StatusBarIconHolder {
}
@Nullable
- public WifiIconState getWifiState() {
- return mWifiState;
- }
-
- public void setWifiState(WifiIconState state) {
- mWifiState = state;
- }
-
- @Nullable
public MobileIconState getMobileState() {
return mMobileState;
}
@@ -199,8 +166,6 @@ public class StatusBarIconHolder {
switch (mType) {
case TYPE_ICON:
return mIcon.visible;
- case TYPE_WIFI:
- return mWifiState.visible;
case TYPE_MOBILE:
return mMobileState.visible;
case TYPE_MOBILE_NEW:
@@ -223,10 +188,6 @@ public class StatusBarIconHolder {
mIcon.visible = visible;
break;
- case TYPE_WIFI:
- mWifiState.visible = visible;
- break;
-
case TYPE_MOBILE:
mMobileState.visible = visible;
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index f79a08173bf2..ec0c00e26c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -54,8 +54,10 @@ import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.EventLogTags;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeViewController;
@@ -94,6 +96,7 @@ import javax.inject.Inject;
class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
private final Context mContext;
+ private final int mDisplayId;
private final Handler mMainThreadHandler;
private final Executor mUiBgExecutor;
@@ -120,12 +123,12 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
private final MetricsLogger mMetricsLogger;
private final StatusBarNotificationActivityStarterLogger mLogger;
- private final CentralSurfaces mCentralSurfaces;
private final NotificationPresenter mPresenter;
private final ShadeViewController mShadeViewController;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
+ private final PowerInteractor mPowerInteractor;
private final UserTracker mUserTracker;
private final OnUserInteractionCallback mOnUserInteractionCallback;
@@ -134,6 +137,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
@Inject
StatusBarNotificationActivityStarter(
Context context,
+ @DisplayId int displayId,
Handler mainThreadHandler,
Executor uiBgExecutor,
NotificationVisibilityProvider visibilityProvider,
@@ -156,16 +160,17 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
MetricsLogger metricsLogger,
StatusBarNotificationActivityStarterLogger logger,
OnUserInteractionCallback onUserInteractionCallback,
- CentralSurfaces centralSurfaces,
NotificationPresenter presenter,
ShadeViewController shadeViewController,
NotificationShadeWindowController notificationShadeWindowController,
ActivityLaunchAnimator activityLaunchAnimator,
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
LaunchFullScreenIntentProvider launchFullScreenIntentProvider,
+ PowerInteractor powerInteractor,
FeatureFlags featureFlags,
UserTracker userTracker) {
mContext = context;
+ mDisplayId = displayId;
mMainThreadHandler = mainThreadHandler;
mUiBgExecutor = uiBgExecutor;
mVisibilityProvider = visibilityProvider;
@@ -190,12 +195,11 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mMetricsLogger = metricsLogger;
mLogger = logger;
mOnUserInteractionCallback = onUserInteractionCallback;
- // TODO: use KeyguardStateController#isOccluded to remove this dependency
- mCentralSurfaces = centralSurfaces;
mPresenter = presenter;
mShadeViewController = shadeViewController;
mActivityLaunchAnimator = activityLaunchAnimator;
mNotificationAnimationProvider = notificationAnimationProvider;
+ mPowerInteractor = powerInteractor;
mUserTracker = userTracker;
launchFullScreenIntentProvider.registerListener(entry -> launchFullScreenIntent(entry));
@@ -280,7 +284,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mShadeController.addPostCollapseAction(runnable);
mShadeController.collapseShade(true /* animate */);
} else if (mKeyguardStateController.isShowing()
- && mCentralSurfaces.isOccluded()) {
+ && mKeyguardStateController.isOccluded()) {
mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
mShadeController.collapseShade();
} else {
@@ -452,11 +456,11 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
long eventTime = row.getAndResetLastActionUpTime();
Bundle options = eventTime > 0
? getActivityOptions(
- mCentralSurfaces.getDisplayId(),
+ mDisplayId,
adapter,
mKeyguardStateController.isShowing(),
eventTime)
- : getActivityOptions(mCentralSurfaces.getDisplayId(), adapter);
+ : getActivityOptions(mDisplayId, adapter);
int result = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, options);
mLogger.logSendPendingIntent(entry, intent, result);
@@ -491,7 +495,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
- mCentralSurfaces.getDisplayId(),
+ mDisplayId,
adapter),
new UserHandle(UserHandle.getUserId(appUid))));
});
@@ -539,7 +543,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate,
intent.getPackage(),
(adapter) -> tsb.startActivities(
- getActivityOptions(mCentralSurfaces.getDisplayId(), adapter),
+ getActivityOptions(mDisplayId, adapter),
mUserTracker.getUserHandle()));
});
return true;
@@ -592,7 +596,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
entry.getKey());
- mCentralSurfaces.wakeUpForFullScreenIntent();
+ mPowerInteractor.wakeUpForFullScreenIntent();
ActivityOptions options = ActivityOptions.makeBasic();
options.setPendingIntentBackgroundActivityStartMode(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index d731f8886536..69199966dea6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -30,7 +30,6 @@ import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
-import com.android.systemui.statusbar.connectivity.WifiIndicators;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -51,7 +50,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
private final String mSlotAirplane;
private final String mSlotMobile;
- private final String mSlotWifi;
private final String mSlotEthernet;
private final String mSlotVpn;
private final String mSlotNoCalling;
@@ -67,17 +65,14 @@ public class StatusBarSignalPolicy implements SignalCallback,
private boolean mHideAirplane;
private boolean mHideMobile;
- private boolean mHideWifi;
private boolean mHideEthernet;
private boolean mActivityEnabled;
// Track as little state as possible, and only for padding purposes
private boolean mIsAirplaneMode = false;
- private boolean mIsWifiEnabled = false;
private ArrayList<MobileIconState> mMobileStates = new ArrayList<>();
private ArrayList<CallIndicatorIconState> mCallIndicatorStates = new ArrayList<>();
- private WifiIconState mWifiIconState = new WifiIconState();
private boolean mInitialized;
@Inject
@@ -99,7 +94,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane);
mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile);
- mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
@@ -154,15 +148,13 @@ public class StatusBarSignalPolicy implements SignalCallback,
ArraySet<String> hideList = StatusBarIconController.getIconHideList(mContext, newValue);
boolean hideAirplane = hideList.contains(mSlotAirplane);
boolean hideMobile = hideList.contains(mSlotMobile);
- boolean hideWifi = hideList.contains(mSlotWifi);
boolean hideEthernet = hideList.contains(mSlotEthernet);
if (hideAirplane != mHideAirplane || hideMobile != mHideMobile
- || hideEthernet != mHideEthernet || hideWifi != mHideWifi) {
+ || hideEthernet != mHideEthernet) {
mHideAirplane = hideAirplane;
mHideMobile = hideMobile;
mHideEthernet = hideEthernet;
- mHideWifi = hideWifi;
// Re-register to get new callbacks.
mNetworkController.removeCallback(this);
mNetworkController.addCallback(this);
@@ -170,56 +162,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
@Override
- public void setWifiIndicators(@NonNull WifiIndicators indicators) {
- if (DEBUG) {
- Log.d(TAG, "setWifiIndicators: " + indicators);
- }
- boolean visible = indicators.statusIcon.visible && !mHideWifi;
- boolean in = indicators.activityIn && mActivityEnabled && visible;
- boolean out = indicators.activityOut && mActivityEnabled && visible;
- mIsWifiEnabled = indicators.enabled;
-
- WifiIconState newState = mWifiIconState.copy();
-
- if (mWifiIconState.noDefaultNetwork && mWifiIconState.noNetworksAvailable
- && !mIsAirplaneMode) {
- newState.visible = true;
- newState.resId = R.drawable.ic_qs_no_internet_unavailable;
- } else if (mWifiIconState.noDefaultNetwork && !mWifiIconState.noNetworksAvailable
- && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) {
- newState.visible = true;
- newState.resId = R.drawable.ic_qs_no_internet_available;
- } else {
- newState.visible = visible;
- newState.resId = indicators.statusIcon.icon;
- newState.activityIn = in;
- newState.activityOut = out;
- newState.contentDescription = indicators.statusIcon.contentDescription;
- MobileIconState first = getFirstMobileState();
- newState.signalSpacerVisible = first != null && first.typeId != 0;
- }
- newState.slot = mSlotWifi;
- newState.airplaneSpacerVisible = mIsAirplaneMode;
- updateWifiIconWithState(newState);
- mWifiIconState = newState;
- }
-
- private void updateShowWifiSignalSpacer(WifiIconState state) {
- MobileIconState first = getFirstMobileState();
- state.signalSpacerVisible = first != null && first.typeId != 0;
- }
-
- private void updateWifiIconWithState(WifiIconState state) {
- if (DEBUG) Log.d(TAG, "WifiIconState: " + state == null ? "" : state.toString());
- if (state.visible && state.resId > 0) {
- mIconController.setWifiIcon(mSlotWifi, state);
- mIconController.setIconVisibility(mSlotWifi, true);
- } else {
- mIconController.setIconVisibility(mSlotWifi, false);
- }
- }
-
- @Override
public void setCallIndicator(@NonNull IconState statusIcon, int subId) {
if (DEBUG) {
Log.d(TAG, "setCallIndicator: "
@@ -257,10 +199,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
return;
}
- // Visibility of the data type indicator changed
- boolean typeChanged = indicators.statusType != state.typeId
- && (indicators.statusType == 0 || state.typeId == 0);
-
state.visible = indicators.statusIcon.visible && !mHideMobile;
state.strengthId = indicators.statusIcon.icon;
state.typeId = indicators.statusType;
@@ -277,15 +215,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
// Always send a copy to maintain value type semantics
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
-
- if (typeChanged) {
- WifiIconState wifiCopy = mWifiIconState.copy();
- updateShowWifiSignalSpacer(wifiCopy);
- if (!Objects.equals(wifiCopy, mWifiIconState)) {
- updateWifiIconWithState(wifiCopy);
- mWifiIconState = wifiCopy;
- }
- }
}
private CallIndicatorIconState getNoCallingState(int subId) {
@@ -308,15 +237,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
return null;
}
- private MobileIconState getFirstMobileState() {
- if (mMobileStates.size() > 0) {
- return mMobileStates.get(0);
- }
-
- return null;
- }
-
-
/**
* It is expected that a call to setSubs will be immediately followed by setMobileDataIndicators
* so we don't have to update the icon manager at this point, just remove the old ones
@@ -504,60 +424,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
}
- public static class WifiIconState extends SignalIconState{
- public int resId;
- public boolean airplaneSpacerVisible;
- public boolean signalSpacerVisible;
- public boolean noDefaultNetwork;
- public boolean noValidatedNetwork;
- public boolean noNetworksAvailable;
-
- @Override
- public boolean equals(Object o) {
- // Skipping reference equality bc this should be more of a value type
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- if (!super.equals(o)) {
- return false;
- }
- WifiIconState that = (WifiIconState) o;
- return resId == that.resId
- && airplaneSpacerVisible == that.airplaneSpacerVisible
- && signalSpacerVisible == that.signalSpacerVisible
- && noDefaultNetwork == that.noDefaultNetwork
- && noValidatedNetwork == that.noValidatedNetwork
- && noNetworksAvailable == that.noNetworksAvailable;
- }
-
- public void copyTo(WifiIconState other) {
- super.copyTo(other);
- other.resId = resId;
- other.airplaneSpacerVisible = airplaneSpacerVisible;
- other.signalSpacerVisible = signalSpacerVisible;
- other.noDefaultNetwork = noDefaultNetwork;
- other.noValidatedNetwork = noValidatedNetwork;
- other.noNetworksAvailable = noNetworksAvailable;
- }
-
- public WifiIconState copy() {
- WifiIconState newState = new WifiIconState();
- copyTo(newState);
- return newState;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(),
- resId, airplaneSpacerVisible, signalSpacerVisible, noDefaultNetwork,
- noValidatedNetwork, noNetworksAvailable);
- }
-
- @Override public String toString() {
- return "WifiIconState(resId=" + resId + ", visible=" + visible + ")";
- }
- }
-
/**
* A little different. This one delegates to SignalDrawable instead of a specific resId
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index 97a1bd1851d9..c8e73d33c452 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -26,6 +26,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
import com.android.systemui.statusbar.phone.StatusBarBoundsProvider;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.phone.SystemBarAttributesListener;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
@@ -72,6 +73,13 @@ public interface StatusBarFragmentModule {
/** */
@Provides
@StatusBarFragmentScope
+ static StatusBarLocation getStatusBarLocation() {
+ return StatusBarLocation.HOME;
+ }
+
+ /** */
+ @Provides
+ @StatusBarFragmentScope
@Named(START_SIDE_CONTENT)
static View startSideContent(@RootView PhoneStatusBarView view) {
return view.findViewById(R.id.status_bar_start_side_content);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
index 4a684d9f8e36..29829e46cda7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
@@ -45,18 +45,6 @@ constructor(
fun runNewMobileIconsBackend(): Boolean =
featureFlags.isEnabled(Flags.NEW_STATUS_BAR_MOBILE_ICONS_BACKEND) || useNewMobileIcons()
- /** True if we should display the wifi icon using the new status bar data pipeline. */
- fun useNewWifiIcon(): Boolean = featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON)
-
- /**
- * True if we should run the new wifi icon backend to get the logging.
- *
- * Does *not* affect whether we render the wifi icon using the new backend data. See
- * [useNewWifiIcon] for that.
- */
- fun runNewWifiIconBackend(): Boolean =
- featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON_BACKEND) || useNewWifiIcon()
-
/**
* Returns true if we should apply some coloring to the icons that were rendered with the new
* pipeline to help with debugging.
@@ -71,5 +59,5 @@ constructor(
* @return true if this icon is controlled by any of the status bar pipeline flags
*/
fun isIconControlledByFlags(slotName: String): Boolean =
- slotName == wifiSlot && useNewWifiIcon() || slotName == mobileSlot && useNewMobileIcons()
+ slotName == wifiSlot || (slotName == mobileSlot && useNewMobileIcons())
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
index 83738544ee84..a1b96dd327e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
@@ -101,12 +101,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) :
this.binding = bindingCreator.invoke()
}
- /**
- * Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view.
- *
- * Mostly duplicated from [com.android.systemui.statusbar.StatusBarWifiView] and
- * [com.android.systemui.statusbar.StatusBarMobileView].
- */
+ /** Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view. */
private fun initDotView() {
// TODO(b/238425913): Could we just have this dot view be part of the layout with a dot
// drawable so we don't need to inflate it manually? Would that not work with animations?
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
index 174298ab6490..6d7182376fab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
@@ -68,12 +68,7 @@ constructor(
launch {
locationViewModel.wifiIcon.collect { wifiIcon ->
// Only notify the icon controller if we want to *render* the new icon.
- // Note that this flow may still run if
- // [statusBarPipelineFlags.runNewWifiIconBackend] is true because we may
- // want to get the logging data without rendering.
- if (
- wifiIcon is WifiIcon.Visible && statusBarPipelineFlags.useNewWifiIcon()
- ) {
+ if (wifiIcon is WifiIcon.Visible) {
iconController.setNewWifiIcon()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 3d165912a09c..7df083afcd19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -19,6 +19,9 @@ package com.android.systemui.statusbar.policy;
import android.annotation.Nullable;
import android.view.View;
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -136,7 +139,7 @@ public interface BatteryController extends DemoMode,
* A listener that will be notified whenever a change in battery level or power save mode has
* occurred.
*/
- interface BatteryStateChangeCallback {
+ interface BatteryStateChangeCallback extends Dumpable {
default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
}
@@ -158,6 +161,11 @@ public interface BatteryController extends DemoMode,
default void onIsBatteryDefenderChanged(boolean isBatteryDefender) {
}
+
+ @Override
+ default void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
+ pw.println(this);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index e69d86c31abc..d5d8f4d7598e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -22,6 +22,7 @@ import static android.os.BatteryManager.EXTRA_CHARGING_STATUS;
import static android.os.BatteryManager.EXTRA_PRESENT;
import static com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_QS;
+import static com.android.systemui.util.DumpUtilsKt.asIndenting;
import android.annotation.WorkerThread;
import android.content.BroadcastReceiver;
@@ -33,6 +34,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerSaveState;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.View;
@@ -157,15 +159,29 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
@Override
- public void dump(PrintWriter pw, String[] args) {
- pw.println("BatteryController state:");
- pw.print(" mLevel="); pw.println(mLevel);
- pw.print(" mPluggedIn="); pw.println(mPluggedIn);
- pw.print(" mCharging="); pw.println(mCharging);
- pw.print(" mCharged="); pw.println(mCharged);
- pw.print(" mIsBatteryDefender="); pw.println(mIsBatteryDefender);
- pw.print(" mPowerSave="); pw.println(mPowerSave);
- pw.print(" mStateUnknown="); pw.println(mStateUnknown);
+ public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
+ IndentingPrintWriter ipw = asIndenting(pw);
+ ipw.println("BatteryController state:");
+ ipw.increaseIndent();
+ ipw.print("mHasReceivedBattery="); ipw.println(mHasReceivedBattery);
+ ipw.print("mLevel="); ipw.println(mLevel);
+ ipw.print("mPluggedIn="); ipw.println(mPluggedIn);
+ ipw.print("mCharging="); ipw.println(mCharging);
+ ipw.print("mCharged="); ipw.println(mCharged);
+ ipw.print("mIsBatteryDefender="); ipw.println(mIsBatteryDefender);
+ ipw.print("mPowerSave="); ipw.println(mPowerSave);
+ ipw.print("mStateUnknown="); ipw.println(mStateUnknown);
+ ipw.println("Callbacks:------------------");
+ // Since the above lines are already indented, we need to indent twice for the callbacks.
+ ipw.increaseIndent();
+ synchronized (mChangeCallbacks) {
+ final int n = mChangeCallbacks.size();
+ for (int i = 0; i < n; i++) {
+ mChangeCallbacks.get(i).dump(ipw, args);
+ }
+ }
+ ipw.decreaseIndent();
+ ipw.println("------------------");
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index 3e1c13c1cba8..c1ac800b8159 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -64,9 +64,9 @@ constructor(
// These values must only be accessed on the handler.
private var batteryCapacity = 1.0f
private var suppressed = false
- private var inputDeviceId: Int? = null
private var instanceId: InstanceId? = null
-
+ @VisibleForTesting var inputDeviceId: Int? = null
+ private set
@VisibleForTesting var instanceIdSequence = InstanceIdSequence(1 shl 13)
fun init() {
@@ -110,10 +110,10 @@ constructor(
fun updateBatteryState(deviceId: Int, batteryState: BatteryState) {
handler.post updateBattery@{
+ inputDeviceId = deviceId
if (batteryState.capacity == batteryCapacity || batteryState.capacity <= 0f)
return@updateBattery
- inputDeviceId = deviceId
batteryCapacity = batteryState.capacity
debugLog {
"Updating notification battery state to $batteryCapacity " +
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
deleted file mode 100644
index b54d1566eba3..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.tracing;
-
-import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_H;
-import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_L;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.shared.tracing.FrameProtoTracer;
-import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
-import com.android.systemui.shared.tracing.ProtoTraceable;
-import com.android.systemui.tracing.nano.SystemUiTraceEntryProto;
-import com.android.systemui.tracing.nano.SystemUiTraceFileProto;
-import com.android.systemui.tracing.nano.SystemUiTraceProto;
-
-import com.google.protobuf.nano.MessageNano;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Queue;
-
-import javax.inject.Inject;
-
-/**
- * Controller for coordinating winscope proto tracing.
- */
-@SysUISingleton
-public class ProtoTracer implements
- Dumpable,
- ProtoTraceParams<
- MessageNano,
- SystemUiTraceFileProto,
- SystemUiTraceEntryProto,
- SystemUiTraceProto> {
-
- private static final String TAG = "ProtoTracer";
- private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
-
- private final Context mContext;
- private final FrameProtoTracer<MessageNano, SystemUiTraceFileProto, SystemUiTraceEntryProto,
- SystemUiTraceProto> mProtoTracer;
-
- @Inject
- public ProtoTracer(Context context, DumpManager dumpManager) {
- mContext = context;
- mProtoTracer = new FrameProtoTracer<>(this);
- dumpManager.registerDumpable(this);
- }
-
- @Override
- public File getTraceFile() {
- return new File(mContext.getFilesDir(), "sysui_trace.pb");
- }
-
- @Override
- public SystemUiTraceFileProto getEncapsulatingTraceProto() {
- return new SystemUiTraceFileProto();
- }
-
- @Override
- public SystemUiTraceEntryProto updateBufferProto(SystemUiTraceEntryProto reuseObj,
- ArrayList<ProtoTraceable<SystemUiTraceProto>> traceables) {
- SystemUiTraceEntryProto proto = reuseObj != null
- ? reuseObj
- : new SystemUiTraceEntryProto();
- proto.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
- proto.systemUi = proto.systemUi != null ? proto.systemUi : new SystemUiTraceProto();
- for (ProtoTraceable t : traceables) {
- t.writeToProto(proto.systemUi);
- }
- return proto;
- }
-
- @Override
- public byte[] serializeEncapsulatingProto(SystemUiTraceFileProto encapsulatingProto,
- Queue<SystemUiTraceEntryProto> buffer) {
- encapsulatingProto.magicNumber = MAGIC_NUMBER_VALUE;
- encapsulatingProto.entry = buffer.toArray(new SystemUiTraceEntryProto[0]);
- return MessageNano.toByteArray(encapsulatingProto);
- }
-
- @Override
- public byte[] getProtoBytes(MessageNano proto) {
- return MessageNano.toByteArray(proto);
- }
-
- @Override
- public int getProtoSize(MessageNano proto) {
- return proto.getCachedSize();
- }
-
- public void start() {
- mProtoTracer.start();
- }
-
- public void stop() {
- mProtoTracer.stop();
- }
-
- public boolean isEnabled() {
- return mProtoTracer.isEnabled();
- }
-
- public void add(ProtoTraceable<SystemUiTraceProto> traceable) {
- mProtoTracer.add(traceable);
- }
-
- public void remove(ProtoTraceable<SystemUiTraceProto> traceable) {
- mProtoTracer.remove(traceable);
- }
-
- public void scheduleFrameUpdate() {
- mProtoTracer.scheduleFrameUpdate();
- }
-
- public void update() {
- mProtoTracer.update();
- }
-
- @Override
- public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- pw.println("ProtoTracer:");
- pw.print(" "); pw.println("enabled: " + mProtoTracer.isEnabled());
- pw.print(" "); pw.println("usagePct: " + mProtoTracer.getBufferUsagePct());
- pw.print(" "); pw.println("file: " + getTraceFile());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
deleted file mode 100644
index d940a6b5c460..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto2";
-
-package com.android.systemui.tracing;
-
-option java_multiple_files = true;
-
-message SystemUiTraceProto {
-
- optional EdgeBackGestureHandlerProto edge_back_gesture_handler = 1;
-}
-
-message EdgeBackGestureHandlerProto {
-
- optional bool allow_gesture = 1;
-}
-
-/* represents a file full of system ui trace entries.
- Encoded, it should start with 0x9 0x53 0x59 0x53 0x55 0x49 0x54 0x52 0x43 (.SYSUITRC), such
- that they can be easily identified. */
-message SystemUiTraceFileProto {
-
- /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
- (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
- constants into .proto files. */
- enum MagicNumber {
- INVALID = 0;
- MAGIC_NUMBER_L = 0x55535953; /* SYSU (little-endian ASCII) */
- MAGIC_NUMBER_H = 0x43525449; /* ITRC (little-endian ASCII) */
- }
-
- optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */
- repeated SystemUiTraceEntryProto entry = 2;
-}
-
-/* one system ui trace entry. */
-message SystemUiTraceEntryProto {
- /* required: elapsed realtime in nanos since boot of when this entry was logged */
- optional fixed64 elapsed_realtime_nanos = 1;
-
- optional SystemUiTraceProto system_ui = 3;
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index d9a8e0cfb53a..38226ec45910 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -45,7 +45,7 @@ import com.android.systemui.screenshot.ReferenceScreenshotModule;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.ShadeControllerImpl;
+import com.android.systemui.shade.ShadeControllerEmptyImpl;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationListener;
@@ -138,7 +138,7 @@ public abstract class TvSystemUIModule {
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
- abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
+ abstract ShadeController provideShadeController(ShadeControllerEmptyImpl shadeController);
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 93622200ad46..349f3684659c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -168,6 +168,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
/** Volume dialog slider animation. */
private static final String TYPE_UPDATE = "update";
+ /**
+ * TODO(b/290612381): remove lingering animations or tolerate them
+ * When false, this will cause this class to not listen to animator events and not record jank
+ * events. This should never be false in production code, and only is false for unit tests for
+ * this class. This flag should be true in Scenario/Integration tests.
+ */
+ private final boolean mShouldListenForJank;
private final int mDialogShowAnimationDurationMs;
private final int mDialogHideAnimationDurationMs;
private int mDialogWidth;
@@ -304,6 +311,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
VolumePanelFactory volumePanelFactory,
ActivityStarter activityStarter,
InteractionJankMonitor interactionJankMonitor,
+ boolean shouldListenForJank,
CsdWarningDialog.Factory csdWarningDialogFactory,
DevicePostureController devicePostureController,
Looper looper,
@@ -311,6 +319,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mContext =
new ContextThemeWrapper(context, R.style.volume_dialog_theme);
mHandler = new H(looper);
+
+ mShouldListenForJank = shouldListenForJank;
mController = volumeDialogController;
mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -1368,7 +1378,10 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
}
private Animator.AnimatorListener getJankListener(View v, String type, long timeout) {
- return new Animator.AnimatorListener() {
+ if (!mShouldListenForJank) {
+ // TODO(b/290612381): temporary fix to prevent null pointers on leftover JankMonitors
+ return null;
+ } else return new Animator.AnimatorListener() {
@Override
public void onAnimationStart(@NonNull Animator animation) {
if (!v.isAttachedToWindow()) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index aa4ee545a500..d0edc6e7ce4c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -72,6 +72,7 @@ public interface VolumeModule {
volumePanelFactory,
activityStarter,
interactionJankMonitor,
+ true, /* should listen for jank */
csdFactory,
devicePostureController,
Looper.getMainLooper(),
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 5144d1966222..943e906a1ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -51,15 +51,11 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.notetask.NoteTaskInitializer;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.tracing.ProtoTracer;
-import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
-import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
@@ -94,8 +90,7 @@ import javax.inject.Inject;
@SysUISingleton
public final class WMShell implements
CoreStartable,
- CommandQueue.Callbacks,
- ProtoTraceable<SystemUiTraceProto> {
+ CommandQueue.Callbacks {
private static final String TAG = WMShell.class.getName();
private static final int INVALID_SYSUI_STATE_MASK =
SYSUI_STATE_DIALOG_SHOWING
@@ -122,7 +117,6 @@ public final class WMShell implements
private final ScreenLifecycle mScreenLifecycle;
private final SysUiState mSysUiState;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private final ProtoTracer mProtoTracer;
private final UserTracker mUserTracker;
private final DisplayTracker mDisplayTracker;
private final NoteTaskInitializer mNoteTaskInitializer;
@@ -184,7 +178,6 @@ public final class WMShell implements
KeyguardUpdateMonitor keyguardUpdateMonitor,
ScreenLifecycle screenLifecycle,
SysUiState sysUiState,
- ProtoTracer protoTracer,
WakefulnessLifecycle wakefulnessLifecycle,
UserTracker userTracker,
DisplayTracker displayTracker,
@@ -203,7 +196,6 @@ public final class WMShell implements
mOneHandedOptional = oneHandedOptional;
mDesktopModeOptional = desktopMode;
mWakefulnessLifecycle = wakefulnessLifecycle;
- mProtoTracer = protoTracer;
mUserTracker = userTracker;
mDisplayTracker = displayTracker;
mNoteTaskInitializer = noteTaskInitializer;
@@ -223,7 +215,6 @@ public final class WMShell implements
// Subscribe to user changes
mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());
- mProtoTracer.add(this);
mCommandQueue.addCallback(this);
mPipOptional.ifPresent(this::initPip);
mSplitScreenOptional.ifPresent(this::initSplitScreen);
@@ -361,12 +352,6 @@ public final class WMShell implements
}
@Override
- public void writeToProto(SystemUiTraceProto proto) {
- // Dump to WMShell proto here
- // TODO: Figure out how we want to synchronize while dumping to proto
- }
-
- @Override
public void dump(PrintWriter pw, String[] args) {
// Handle commands if provided
if (mShell.handleCommand(args, pw)) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index fa32835c2695..677d3ff3df69 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -187,9 +187,7 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
@Test
public void testLockedOut_verifyPasswordAndUnlock_doesNotEnableViewInput() {
- mKeyguardAbsKeyInputViewController.handleAttemptLockout(
- SystemClock.elapsedRealtime() + 1000);
- mKeyguardAbsKeyInputViewController.verifyPasswordAndUnlock();
+ mKeyguardAbsKeyInputViewController.handleAttemptLockout(SystemClock.elapsedRealtime());
verify(mAbsKeyInputView).setPasswordEntryInputEnabled(false);
verify(mAbsKeyInputView).setPasswordEntryEnabled(false);
verify(mAbsKeyInputView, never()).setPasswordEntryInputEnabled(true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 9db267c2c929..d256ee163877 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -105,6 +105,7 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
`when`(keyguardPinView.findViewById<View>(R.id.key_enter)).thenReturn(enterButton)
// For posture tests:
`when`(keyguardPinView.buttons).thenReturn(arrayOf())
+ `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
pinViewController =
KeyguardPinViewController(
@@ -167,7 +168,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation_withAutoPinConfirmationFailedPasswordAttemptsLessThan5() {
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
- `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(3)
`when`(passwordTextView.text).thenReturn("")
@@ -182,7 +182,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation_withAutoPinConfirmationFailedPasswordAttemptsMoreThan5() {
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
- `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(6)
`when`(passwordTextView.text).thenReturn("")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
index 1482f291b57a..40b572934f74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -33,10 +33,10 @@ import android.provider.Settings;
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
@@ -61,7 +61,6 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
private Handler mHandler;
@Mock
private ContentResolver mContentResolver;
- private FakeFeatureFlags mFeatureFlags;
@Mock
private BatteryController mBatteryController;
@@ -74,8 +73,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
when(mBatteryMeterView.getContext()).thenReturn(mContext);
when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
- mFeatureFlags = new FakeFeatureFlags();
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, false);
}
@Test
@@ -134,7 +133,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
@Test
public void shieldFlagDisabled_viewNotified() {
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, false);
initController();
@@ -143,7 +143,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
@Test
public void shieldFlagEnabled_viewNotified() {
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, true);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, true);
initController();
@@ -153,12 +154,12 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
private void initController() {
mController = new BatteryMeterViewController(
mBatteryMeterView,
+ StatusBarLocation.HOME,
mUserTracker,
mConfigurationController,
mTunerService,
mHandler,
mContentResolver,
- mFeatureFlags,
mBatteryController
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
index 023ed061c642..45bb9313264c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt
@@ -21,6 +21,10 @@ import android.os.PowerManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.shared.model.WakeSleepReason
+import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
@@ -44,6 +48,7 @@ class PowerInteractorTest : SysuiTestCase() {
private lateinit var underTest: PowerInteractor
private lateinit var repository: FakePowerRepository
+ private val keyguardRepository = FakeKeyguardRepository()
@Mock private lateinit var falsingCollector: FalsingCollector
@Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController
@Mock private lateinit var statusBarStateController: StatusBarStateController
@@ -59,6 +64,7 @@ class PowerInteractorTest : SysuiTestCase() {
underTest =
PowerInteractor(
repository,
+ keyguardRepository,
falsingCollector,
screenOffAnimationController,
statusBarStateController,
@@ -125,6 +131,57 @@ class PowerInteractorTest : SysuiTestCase() {
verify(falsingCollector).onScreenOnFromTouch()
}
+ @Test
+ fun wakeUpForFullScreenIntent_notGoingToSleepAndNotDozing_notWoken() {
+ keyguardRepository.setWakefulnessModel(
+ WakefulnessModel(
+ state = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ )
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+
+ underTest.wakeUpForFullScreenIntent()
+
+ assertThat(repository.lastWakeWhy).isNull()
+ assertThat(repository.lastWakeReason).isNull()
+ }
+
+ @Test
+ fun wakeUpForFullScreenIntent_startingToSleep_woken() {
+ keyguardRepository.setWakefulnessModel(
+ WakefulnessModel(
+ state = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ )
+ whenever(statusBarStateController.isDozing).thenReturn(false)
+
+ underTest.wakeUpForFullScreenIntent()
+
+ assertThat(repository.lastWakeWhy).isNotNull()
+ assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_APPLICATION)
+ }
+
+ @Test
+ fun wakeUpForFullScreenIntent_dozing_woken() {
+ whenever(statusBarStateController.isDozing).thenReturn(true)
+ keyguardRepository.setWakefulnessModel(
+ WakefulnessModel(
+ state = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ )
+
+ underTest.wakeUpForFullScreenIntent()
+
+ assertThat(repository.lastWakeWhy).isNotNull()
+ assertThat(repository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_APPLICATION)
+ }
+
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
index df5e7bcd16be..3e9ddcb06389 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
@@ -20,6 +20,9 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.WakeSleepReason
+import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
@@ -47,12 +50,18 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
utils.authenticationInteractor(
repository = authenticationRepository,
)
+ private val keyguardRepository = utils.keyguardRepository()
+ private val keyguardInteractor =
+ utils.keyguardInteractor(
+ repository = keyguardRepository,
+ )
private val underTest =
SystemUiDefaultSceneContainerStartable(
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
+ keyguardInteractor = keyguardInteractor,
featureFlags = featureFlags,
)
@@ -280,6 +289,94 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
+ @Test
+ fun switchToGoneWhenDeviceSleepsUnlocked_featureEnabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Shade,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ underTest.start()
+
+ keyguardRepository.setWakefulnessModel(ASLEEP)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ }
+
+ @Test
+ fun switchToGoneWhenDeviceSleepsUnlocked_featureDisabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Shade,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ underTest.start()
+
+ keyguardRepository.setWakefulnessModel(ASLEEP)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ }
+
+ @Test
+ fun switchToLockscreenWhenDeviceSleepsLocked_featureEnabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = false,
+ initialSceneKey = SceneKey.Shade,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ underTest.start()
+
+ keyguardRepository.setWakefulnessModel(ASLEEP)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ }
+
+ @Test
+ fun switchToLockscreenWhenDeviceSleepsLocked_featureDisabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = false,
+ initialSceneKey = SceneKey.Shade,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ underTest.start()
+
+ keyguardRepository.setWakefulnessModel(ASLEEP)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+ }
+
private fun prepareState(
isFeatureEnabled: Boolean = true,
isDeviceUnlocked: Boolean = false,
@@ -293,4 +390,13 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
sceneInteractor.setCurrentScene(SceneContainerNames.SYSTEM_UI_DEFAULT, SceneModel(it))
}
}
+
+ companion object {
+ private val ASLEEP =
+ WakefulnessModel(
+ state = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.POWER_BUTTON
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
index a4fab1dbac57..77a22ac9b092 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
@@ -28,6 +28,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dock.DockManager
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.data.repository.FakePowerRepository
@@ -89,6 +90,7 @@ class PulsingGestureListenerTest : SysuiTestCase() {
dockManager,
PowerInteractor(
powerRepository,
+ FakeKeyguardRepository(),
falsingCollector,
screenOffAnimationController,
statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
index 729c4a9145c2..52e0c9c9936b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -78,11 +78,11 @@ class ShadeControllerImplTest : SysuiTestCase() {
deviceProvisionedController,
notificationShadeWindowController,
windowManager,
+ Lazy { shadeViewController },
Lazy { assistManager },
Lazy { gutsManager },
)
shadeController.setNotificationShadeWindowViewController(nswvc)
- shadeController.setShadeViewController(shadeViewController)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index f542ab099517..bf25f2975253 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -29,6 +29,7 @@ import android.view.DisplayCutout
import android.view.View
import android.view.ViewPropertyAnimator
import android.view.WindowInsets
+import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -127,6 +128,7 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
var viewVisibility = View.GONE
var viewAlpha = 1f
+ private val systemIcons = LinearLayout(context)
private lateinit var shadeHeaderController: ShadeHeaderController
private lateinit var carrierIconSlots: List<String>
private val configurationController = FakeConfigurationController()
@@ -146,6 +148,7 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
.thenReturn(batteryMeterView)
whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
+ whenever<View>(view.findViewById(R.id.shade_header_system_icons)).thenReturn(systemIcons)
viewContext = Mockito.spy(context)
whenever(view.context).thenReturn(viewContext)
@@ -451,6 +454,17 @@ class ShadeHeaderControllerTest : SysuiTestCase() {
}
@Test
+ fun testLargeScreenActive_collapseActionRun_onSystemIconsClick() {
+ shadeHeaderController.largeScreenActive = true
+ var wasRun = false
+ shadeHeaderController.shadeCollapseAction = Runnable { wasRun = true }
+
+ systemIcons.performClick()
+
+ assertThat(wasRun).isTrue()
+ }
+
+ @Test
fun testShadeExpandedFraction() {
// View needs to be visible for this to actually take effect
shadeHeaderController.qsVisible = true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index ff2f1065049b..4a2518ae6f7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -101,16 +101,18 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Mock lateinit var activityStarter: ActivityStarter
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
private val disableFlagsRepository = FakeDisableFlagsRepository()
+ private val keyguardRepository = FakeKeyguardRepository()
private val shadeInteractor = ShadeInteractor(
testScope.backgroundScope,
disableFlagsRepository,
- keyguardRepository = FakeKeyguardRepository(),
+ keyguardRepository,
userSetupRepository = FakeUserSetupRepository(),
deviceProvisionedController = mock(),
userInteractor = mock(),
)
private val powerInteractor = PowerInteractor(
FakePowerRepository(),
+ keyguardRepository,
FalsingCollectorFake(),
screenOffAnimationController = mock(),
statusBarStateController = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
index 89faa239c5a2..a56fb2c515a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
@@ -3,7 +3,11 @@ package com.android.systemui.statusbar.notification
import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -15,8 +19,9 @@ import org.mockito.Mockito.verify
@SmallTest
@RunWith(JUnit4::class)
class RoundableTest : SysuiTestCase() {
- val targetView: View = mock()
- val roundable = FakeRoundable(targetView)
+ private val targetView: View = mock()
+ private val featureFlags = FakeFeatureFlags()
+ private val roundable = FakeRoundable(targetView = targetView, featureFlags = featureFlags)
@Test
fun defaultConfig_shouldNotHaveRoundedCorner() {
@@ -144,16 +149,62 @@ class RoundableTest : SysuiTestCase() {
assertEquals(0.2f, roundable.roundableState.bottomRoundness)
}
+ @Test
+ fun getCornerRadii_radius_maxed_to_height() {
+ whenever(targetView.height).thenReturn(10)
+ featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
+ roundable.requestRoundness(1f, 1f, SOURCE1)
+
+ assertCornerRadiiEquals(5f, 5f)
+ }
+
+ @Test
+ fun getCornerRadii_topRadius_maxed_to_height() {
+ whenever(targetView.height).thenReturn(5)
+ featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
+ roundable.requestRoundness(1f, 0f, SOURCE1)
+
+ assertCornerRadiiEquals(5f, 0f)
+ }
+
+ @Test
+ fun getCornerRadii_bottomRadius_maxed_to_height() {
+ whenever(targetView.height).thenReturn(5)
+ featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
+ roundable.requestRoundness(0f, 1f, SOURCE1)
+
+ assertCornerRadiiEquals(0f, 5f)
+ }
+
+ @Test
+ fun getCornerRadii_radii_kept() {
+ whenever(targetView.height).thenReturn(100)
+ featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
+ roundable.requestRoundness(1f, 1f, SOURCE1)
+
+ assertCornerRadiiEquals(MAX_RADIUS, MAX_RADIUS)
+ }
+
+ private fun assertCornerRadiiEquals(top: Float, bottom: Float) {
+ assertEquals("topCornerRadius", top, roundable.topCornerRadius)
+ assertEquals("bottomCornerRadius", bottom, roundable.bottomCornerRadius)
+ }
+
class FakeRoundable(
targetView: View,
radius: Float = MAX_RADIUS,
+ featureFlags: FeatureFlags
) : Roundable {
override val roundableState =
RoundableState(
targetView = targetView,
roundable = this,
maxRadius = radius,
+ featureFlags = featureFlags
)
+
+ override val clipHeight: Int
+ get() = roundableState.targetView.height
}
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
index a87dd2d3d670..8881f42783fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/domain/interactor/NotificationShelfInteractorTest.kt
@@ -58,6 +58,7 @@ class NotificationShelfInteractorTest : SysuiTestCase() {
private val powerInteractor =
PowerInteractor(
powerRepository,
+ keyguardRepository,
FalsingCollectorFake(),
screenOffAnimationController,
statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
index 7ae150231b98..6221f3e89ad6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt
@@ -69,6 +69,7 @@ class NotificationShelfViewModelTest : SysuiTestCase() {
private val powerInteractor by lazy {
PowerInteractor(
powerRepository,
+ keyguardRepository,
FalsingCollectorFake(),
screenOffAnimationController,
statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
index 442ba0977cf6..5e0e140563cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -95,6 +95,7 @@ class ActivityStarterImplTest : SysuiTestCase() {
Lazy { notifShadeWindowController },
activityLaunchAnimator,
context,
+ DISPLAY_ID,
lockScreenUserManager,
statusBarWindowController,
wakefulnessLifecycle,
@@ -274,4 +275,8 @@ class ActivityStarterImplTest : SysuiTestCase() {
mainExecutor.runAllReady()
verify(statusBarStateController).setLeaveOpenOnKeyguardHide(true)
}
+
+ private companion object {
+ private const val DISPLAY_ID = 0
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 88d8dfc50b47..3d35233ad646 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -447,10 +447,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mDeviceProvisionedController,
mNotificationShadeWindowController,
mContext.getSystemService(WindowManager.class),
+ () -> mNotificationPanelViewController,
() -> mAssistManager,
() -> mNotificationGutsManager
));
- mShadeController.setShadeViewController(mNotificationPanelViewController);
mShadeController.setNotificationShadeWindowViewController(
mNotificationShadeWindowViewController);
mShadeController.setNotificationPresenter(mNotificationPresenter);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index 8aaa57ffe2cb..9157cd9e4f43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -16,7 +16,6 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
import static junit.framework.Assert.assertTrue;
@@ -41,13 +40,11 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
@@ -156,13 +153,9 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
assertTrue("Expected StatusBarIconView",
(manager.getViewAt(0) instanceof StatusBarIconView));
- holder = holderForType(TYPE_WIFI);
- manager.onIconAdded(1, "test_wifi", false, holder);
- assertTrue(manager.getViewAt(1) instanceof StatusBarWifiView);
-
holder = holderForType(TYPE_MOBILE);
- manager.onIconAdded(2, "test_mobile", false, holder);
- assertTrue(manager.getViewAt(2) instanceof StatusBarMobileView);
+ manager.onIconAdded(1, "test_mobile", false, holder);
+ assertTrue(manager.getViewAt(1) instanceof StatusBarMobileView);
}
private StatusBarIconHolder holderForType(int type) {
@@ -170,9 +163,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
case TYPE_MOBILE:
return StatusBarIconHolder.fromMobileIconState(mock(MobileIconState.class));
- case TYPE_WIFI:
- return StatusBarIconHolder.fromWifiIconState(mock(WifiIconState.class));
-
case TYPE_ICON:
default:
return StatusBarIconHolder.fromIcon(mock(StatusBarIcon.class));
@@ -214,13 +204,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
}
@Override
- protected StatusBarWifiView addWifiIcon(int index, String slot, WifiIconState state) {
- StatusBarWifiView mock = mock(StatusBarWifiView.class);
- mGroup.addView(mock, index);
- return mock;
- }
-
- @Override
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
StatusBarMobileView mock = mock(StatusBarMobileView.class);
mGroup.addView(mock, index);
@@ -254,13 +237,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
}
@Override
- protected StatusBarWifiView addWifiIcon(int index, String slot, WifiIconState state) {
- StatusBarWifiView mock = mock(StatusBarWifiView.class);
- mGroup.addView(mock, index);
- return mock;
- }
-
- @Override
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
StatusBarMobileView mock = mock(StatusBarMobileView.class);
mGroup.addView(mock, index);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index d44af885a27e..9c7f6190de44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -21,6 +21,8 @@ import static android.service.notification.NotificationListenerService.REASON_CL
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -61,10 +63,14 @@ import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.data.repository.FakePowerRepository;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeControllerImpl;
@@ -110,6 +116,8 @@ import java.util.Optional;
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
+ private static final int DISPLAY_ID = 0;
+
@Mock
private AssistManager mAssistManager;
@Mock
@@ -118,13 +126,12 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private NotificationClickNotifier mClickNotifier;
@Mock
private StatusBarStateController mStatusBarStateController;
+ @Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private NotificationRemoteInputManager mRemoteInputManager;
@Mock
- private CentralSurfaces mCentralSurfaces;
- @Mock
private KeyguardStateController mKeyguardStateController;
@Mock
private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
@@ -150,6 +157,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock
private InteractionJankMonitor mJankMonitor;
+ private FakePowerRepository mPowerRepository;
+ private PowerInteractor mPowerInteractor;
@Mock
private UserTracker mUserTracker;
private final FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -199,6 +208,14 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(mUserTracker.getUserHandle()).thenReturn(
UserHandle.of(ActivityManager.getCurrentUser()));
+ mPowerRepository = new FakePowerRepository();
+ mPowerInteractor = new PowerInteractor(
+ mPowerRepository,
+ new FakeKeyguardRepository(),
+ new FalsingCollectorFake(),
+ mScreenOffAnimationController,
+ mStatusBarStateController);
+
HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
new NotificationLaunchAnimatorControllerProvider(
@@ -209,6 +226,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mNotificationActivityStarter =
new StatusBarNotificationActivityStarter(
getContext(),
+ DISPLAY_ID,
mHandler,
mUiBgExecutor,
mVisibilityProvider,
@@ -231,13 +249,13 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mock(MetricsLogger.class),
mock(StatusBarNotificationActivityStarterLogger.class),
mOnUserInteractionCallback,
- mCentralSurfaces,
mock(NotificationPresenter.class),
mock(ShadeViewController.class),
mock(NotificationShadeWindowController.class),
mActivityLaunchAnimator,
notificationAnimationProvider,
mock(LaunchFullScreenIntentProvider.class),
+ mPowerInteractor,
mock(FeatureFlags.class),
mUserTracker
);
@@ -274,7 +292,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
notification.flags |= Notification.FLAG_AUTO_CANCEL;
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mCentralSurfaces.isOccluded()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
// When
mNotificationActivityStarter.onNotificationClicked(entry, mNotificationRow);
@@ -340,7 +358,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
// Given
sbn.getNotification().contentIntent = null;
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mCentralSurfaces.isOccluded()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
// When
mNotificationActivityStarter.onNotificationClicked(entry, mBubbleNotificationRow);
@@ -368,7 +386,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
// Given
sbn.getNotification().contentIntent = mContentIntent;
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mCentralSurfaces.isOccluded()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
// When
mNotificationActivityStarter.onNotificationClicked(entry, mBubbleNotificationRow);
@@ -402,11 +420,13 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
when(entry.getSbn()).thenReturn(sbn);
- // WHEN
+ // WHEN the intent is launched while dozing
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
mNotificationActivityStarter.launchFullScreenIntent(entry);
// THEN display should try wake up for the full screen intent
- verify(mCentralSurfaces).wakeUpForFullScreenIntent();
+ assertThat(mPowerRepository.getLastWakeReason()).isNotNull();
+ assertThat(mPowerRepository.getLastWakeWhy()).isNotNull();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
index 90821bdef0be..d212c026d66e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
@@ -126,6 +126,16 @@ class StylusUsiPowerUiTest : SysuiTestCase() {
}
@Test
+ fun updateBatteryState_capacitySame_inputDeviceChanges_updatesInputDeviceId() {
+ stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
+ stylusUsiPowerUi.updateBatteryState(1, FixedCapacityBatteryState(0.1f))
+
+ assertThat(stylusUsiPowerUi.inputDeviceId).isEqualTo(1)
+ verify(notificationManager, times(1))
+ .notify(eq(R.string.stylus_battery_low_percentage), any())
+ }
+
+ @Test
fun updateBatteryState_existingNotification_capacityAboveThreshold_cancelsNotification() {
stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.8f))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 8f725bebfb16..0c77529377ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -142,6 +142,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor,
+ false,
mCsdWarningDialogFactory,
mPostureController,
mTestableLooper.getLooper(),
@@ -378,6 +379,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor,
+ false,
mCsdWarningDialogFactory,
devicePostureController,
mTestableLooper.getLooper(),
@@ -397,6 +399,8 @@ public class VolumeDialogImplTest extends SysuiTestCase {
int gravity = dialog.getWindowGravity();
assertEquals(Gravity.TOP, gravity & Gravity.VERTICAL_GRAVITY_MASK);
+
+ cleanUp(dialog);
}
@Test
@@ -415,6 +419,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor,
+ false,
mCsdWarningDialogFactory,
devicePostureController,
mTestableLooper.getLooper(),
@@ -433,6 +438,8 @@ public class VolumeDialogImplTest extends SysuiTestCase {
int gravity = dialog.getWindowGravity();
assertEquals(Gravity.CENTER_VERTICAL, gravity & Gravity.VERTICAL_GRAVITY_MASK);
+
+ cleanUp(dialog);
}
@Test
@@ -451,6 +458,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor,
+ false,
mCsdWarningDialogFactory,
devicePostureController,
mTestableLooper.getLooper(),
@@ -469,6 +477,8 @@ public class VolumeDialogImplTest extends SysuiTestCase {
int gravity = dialog.getWindowGravity();
assertEquals(Gravity.CENTER_VERTICAL, gravity & Gravity.VERTICAL_GRAVITY_MASK);
+
+ cleanUp(dialog);
}
@Test
@@ -489,18 +499,19 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mVolumePanelFactory,
mActivityStarter,
mInteractionJankMonitor,
+ false,
mCsdWarningDialogFactory,
mPostureController,
mTestableLooper.getLooper(),
- mDumpManager
- );
+ mDumpManager);
dialog.init(0, null);
verify(mPostureController, never()).removeCallback(any());
-
dialog.destroy();
verify(mPostureController).removeCallback(any());
+
+ cleanUp(dialog);
}
private void setOrientation(int orientation) {
@@ -513,14 +524,18 @@ public class VolumeDialogImplTest extends SysuiTestCase {
@After
public void teardown() {
- if (mDialog != null) {
- mDialog.clearInternalHandlerAfterTest();
- }
+ cleanUp(mDialog);
setOrientation(mOriginalOrientation);
mTestableLooper.processAllMessages();
reset(mPostureController);
}
+ private void cleanUp(VolumeDialogImpl dialog) {
+ if (dialog != null) {
+ dialog.clearInternalHandlerAfterTest();
+ }
+ }
+
/*
@Test
public void testContentDescriptions() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 9de7a87c8b82..ef0adbb91a63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -34,7 +34,6 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
@@ -76,7 +75,6 @@ public class WMShellTest extends SysuiTestCase {
@Mock SplitScreen mSplitScreen;
@Mock OneHanded mOneHanded;
@Mock WakefulnessLifecycle mWakefulnessLifecycle;
- @Mock ProtoTracer mProtoTracer;
@Mock UserTracker mUserTracker;
@Mock ShellExecutor mSysUiMainExecutor;
@Mock NoteTaskInitializer mNoteTaskInitializer;
@@ -99,7 +97,6 @@ public class WMShellTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mScreenLifecycle,
mSysUiState,
- mProtoTracer,
mWakefulnessLifecycle,
mUserTracker,
displayTracker,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 60a4951735c5..63097401bc5a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -48,7 +48,7 @@ class FakeKeyguardRepository : KeyguardRepository {
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
private val _isKeyguardUnlocked = MutableStateFlow(false)
- override val isKeyguardUnlocked: Flow<Boolean> = _isKeyguardUnlocked
+ override val isKeyguardUnlocked: StateFlow<Boolean> = _isKeyguardUnlocked.asStateFlow()
private val _isKeyguardOccluded = MutableStateFlow(false)
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index d797962bae8b..47e1daf4008c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -22,11 +22,20 @@ import com.android.systemui.authentication.data.repository.AuthenticationReposit
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.bouncer.data.repository.BouncerRepository
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
+import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
+import com.android.systemui.keyguard.shared.model.WakeSleepReason
+import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerConfig
@@ -53,7 +62,11 @@ class SceneTestUtils(
) {
val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)
- val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) }
+ val featureFlags =
+ FakeFeatureFlags().apply {
+ set(Flags.SCENE_CONTAINER, true)
+ set(Flags.FACE_AUTH_REFACTOR, false)
+ }
private val userRepository: UserRepository by lazy {
FakeUserRepository().apply {
val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
@@ -67,6 +80,17 @@ class SceneTestUtils(
currentTime = { testScope.currentTime },
)
}
+ val keyguardRepository: FakeKeyguardRepository by lazy {
+ FakeKeyguardRepository().apply {
+ setWakefulnessModel(
+ WakefulnessModel(
+ WakefulnessState.AWAKE,
+ WakeSleepReason.OTHER,
+ WakeSleepReason.OTHER,
+ )
+ )
+ }
+ }
private val context = test.context
fun fakeSceneContainerRepository(
@@ -122,6 +146,20 @@ class SceneTestUtils(
)
}
+ fun keyguardRepository(): FakeKeyguardRepository {
+ return keyguardRepository
+ }
+
+ fun keyguardInteractor(repository: KeyguardRepository): KeyguardInteractor {
+ return KeyguardInteractor(
+ repository = repository,
+ commandQueue = FakeCommandQueue(),
+ featureFlags = featureFlags,
+ bouncerRepository = FakeKeyguardBouncerRepository(),
+ configurationRepository = FakeConfigurationRepository()
+ )
+ }
+
fun bouncerInteractor(
authenticationInteractor: AuthenticationInteractor,
sceneInteractor: SceneInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index c664c99cf2a7..56837e8cc7ef 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -21,7 +21,6 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -62,10 +61,6 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
}
@Override
- public void setWifiIcon(String slot, WifiIconState state) {
- }
-
- @Override
public void setNewWifiIcon() {
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index e51fc0a2cef7..a682c85f03b2 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1713,6 +1713,11 @@ public class OomAdjuster {
}
}
+ private boolean isScreenOnOrAnimatingLocked(ProcessStateRecord state) {
+ return mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
+ || state.isRunningRemoteAnimation();
+ }
+
@GuardedBy({"mService", "mProcLock"})
private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
@@ -1794,8 +1799,7 @@ public class OomAdjuster {
state.setSystemNoUi(false);
}
if (!state.isSystemNoUi()) {
- if (mService.mWakefulness.get() == PowerManagerInternal.WAKEFULNESS_AWAKE
- || state.isRunningRemoteAnimation()) {
+ if (isScreenOnOrAnimatingLocked(state)) {
// screen on or animating, promote UI
state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
state.setCurrentSchedulingGroup(SCHED_GROUP_TOP_APP);
@@ -3281,8 +3285,10 @@ public class OomAdjuster {
} else {
setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
}
- initialSchedGroup = SCHED_GROUP_TOP_APP;
- initialProcState = PROCESS_STATE_TOP;
+ if (isScreenOnOrAnimatingLocked(state)) {
+ initialSchedGroup = SCHED_GROUP_TOP_APP;
+ initialProcState = PROCESS_STATE_TOP;
+ }
initialCapability = PROCESS_CAPABILITY_ALL;
initialCached = false;
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index ca15dd79adbc..c6d6122aeed6 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -40,6 +40,7 @@ import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameManagerService;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
import android.app.StatsManager;
import android.app.UidObserver;
import android.content.BroadcastReceiver;
@@ -148,6 +149,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
private final Object mLock = new Object();
private final Object mDeviceConfigLock = new Object();
private final Object mGameModeListenerLock = new Object();
+ private final Object mGameStateListenerLock = new Object();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
final Handler mHandler;
private final PackageManager mPackageManager;
@@ -164,6 +166,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
// listener to caller uid map
@GuardedBy("mGameModeListenerLock")
private final ArrayMap<IGameModeListener, Integer> mGameModeListeners = new ArrayMap<>();
+ @GuardedBy("mGameStateListenerLock")
+ private final ArrayMap<IGameStateListener, Integer> mGameStateListeners = new ArrayMap<>();
@Nullable
private final GameServiceController mGameServiceController;
private final Object mUidObserverLock = new Object();
@@ -352,6 +356,16 @@ public final class GameManagerService extends IGameManagerService.Stub {
loadingBoostDuration);
}
}
+ synchronized (mGameStateListenerLock) {
+ for (IGameStateListener listener : mGameStateListeners.keySet()) {
+ try {
+ listener.onGameStateChanged(packageName, gameState, userId);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Cannot notify game state change for listener added by "
+ + mGameStateListeners.get(listener));
+ }
+ }
+ }
break;
}
case CANCEL_GAME_LOADING_MODE: {
@@ -1474,6 +1488,43 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
/**
+ * Adds a game state listener.
+ */
+ @Override
+ public void addGameStateListener(@NonNull IGameStateListener listener) {
+ try {
+ final IBinder listenerBinder = listener.asBinder();
+ listenerBinder.linkToDeath(new DeathRecipient() {
+ @Override public void binderDied() {
+ removeGameStateListenerUnchecked(listener);
+ listenerBinder.unlinkToDeath(this, 0 /*flags*/);
+ }
+ }, 0 /*flags*/);
+ synchronized (mGameStateListenerLock) {
+ mGameStateListeners.put(listener, Binder.getCallingUid());
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG,
+ "Failed to link death recipient for IGameStateListener from caller "
+ + Binder.getCallingUid() + ", abandoned its listener registration", ex);
+ }
+ }
+
+ /**
+ * Removes a game state listener.
+ */
+ @Override
+ public void removeGameStateListener(@NonNull IGameStateListener listener) {
+ removeGameStateListenerUnchecked(listener);
+ }
+
+ private void removeGameStateListenerUnchecked(IGameStateListener listener) {
+ synchronized (mGameStateListenerLock) {
+ mGameStateListeners.remove(listener);
+ }
+ }
+
+ /**
* Notified when boot is completed.
*/
@VisibleForTesting
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 06417d725e7e..f51b62d77ab9 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -66,7 +66,6 @@ import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.biometrics.sensors.BaseClientMonitor;
-import java.util.ArrayList;
import java.util.List;
public class Utils {
@@ -98,33 +97,6 @@ public class Utils {
}
/**
- * Get the enabled HAL instances. If virtual is enabled and available it will be returned as
- * the only instance, otherwise all other instances will be returned.
- *
- * @param context system context
- * @param declaredInstances known instances
- * @return filtered list of enabled instances
- */
- @NonNull
- public static List<String> filterAvailableHalInstances(@NonNull Context context,
- @NonNull List<String> declaredInstances) {
- if (declaredInstances.size() <= 1) {
- return declaredInstances;
- }
-
- final int virtualAt = declaredInstances.indexOf("virtual");
- if (isVirtualEnabled(context) && virtualAt != -1) {
- return List.of(declaredInstances.get(virtualAt));
- }
-
- declaredInstances = new ArrayList<>(declaredInstances);
- if (virtualAt != -1) {
- declaredInstances.remove(virtualAt);
- }
- return declaredInstances;
- }
-
- /**
* Combines {@link PromptInfo#setDeviceCredentialAllowed(boolean)} with
* {@link PromptInfo#setAuthenticators(int)}, as the former is not flexible enough.
*/
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 28cb7d9445ee..7cc6940f4b9d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -871,19 +871,22 @@ public class FingerprintService extends SystemService {
super.registerAuthenticators_enforcePermission();
mRegistry.registerAll(() -> {
- final List<ServiceProvider> providers = new ArrayList<>();
- providers.addAll(getHidlProviders(hidlSensors));
List<String> aidlSensors = new ArrayList<>();
final String[] instances = mAidlInstanceNameSupplier.get();
if (instances != null) {
aidlSensors.addAll(Lists.newArrayList(instances));
}
- providers.addAll(getAidlProviders(
- Utils.filterAvailableHalInstances(getContext(), aidlSensors)));
+
+ final Pair<List<FingerprintSensorPropertiesInternal>, List<String>>
+ filteredInstances = filterAvailableHalInstances(hidlSensors, aidlSensors);
+
+ final List<ServiceProvider> providers = new ArrayList<>();
+ providers.addAll(getHidlProviders(filteredInstances.first));
+ providers.addAll(getAidlProviders(filteredInstances.second));
+
return providers;
});
}
-
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void addAuthenticatorsRegisteredCallback(
@@ -1038,6 +1041,33 @@ public class FingerprintService extends SystemService {
});
}
+ private Pair<List<FingerprintSensorPropertiesInternal>, List<String>>
+ filterAvailableHalInstances(
+ @NonNull List<FingerprintSensorPropertiesInternal> hidlInstances,
+ @NonNull List<String> aidlInstances) {
+ if ((hidlInstances.size() + aidlInstances.size()) <= 1) {
+ return new Pair(hidlInstances, aidlInstances);
+ }
+
+ final int virtualAt = aidlInstances.indexOf("virtual");
+ if (Utils.isVirtualEnabled(getContext())) {
+ if (virtualAt != -1) {
+ //only virtual instance should be returned
+ return new Pair(new ArrayList<>(), List.of(aidlInstances.get(virtualAt)));
+ } else {
+ Slog.e(TAG, "Could not find virtual interface while it is enabled");
+ return new Pair(hidlInstances, aidlInstances);
+ }
+ } else {
+ //remove virtual instance
+ aidlInstances = new ArrayList<>(aidlInstances);
+ if (virtualAt != -1) {
+ aidlInstances.remove(virtualAt);
+ }
+ return new Pair(hidlInstances, aidlInstances);
+ }
+ }
+
@NonNull
private List<ServiceProvider> getHidlProviders(
@NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 02ee96a04b1f..7bda2c1fa5ab 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1175,6 +1175,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE), false, this, userId);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ STYLUS_HANDWRITING_ENABLED), false, this);
mRegistered = true;
}
@@ -1183,6 +1185,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
final Uri accessibilityRequestingNoImeUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
+ final Uri stylusHandwritingEnabledUri = Settings.Secure.getUriFor(
+ STYLUS_HANDWRITING_ENABLED);
synchronized (ImfLock.class) {
if (showImeUri.equals(uri)) {
mMenuController.updateKeyboardFromSettingsLocked();
@@ -1200,6 +1204,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
showCurrentInputImplicitLocked(mCurFocusedWindow,
SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE);
}
+ } else if (stylusHandwritingEnabledUri.equals(uri)) {
+ InputMethodManager.invalidateLocalStylusHandwritingAvailabilityCaches();
} else {
boolean enabledChanged = false;
String newEnabled = mSettings.getEnabledInputMethodsStr();
@@ -2363,7 +2369,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mCurVirtualDisplayToScreenMatrix = null;
ImeTracker.forLogging().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
-
+ InputMethodManager.invalidateLocalStylusHandwritingAvailabilityCaches();
mMenuController.hideInputMethodMenuLocked();
}
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index db3b267529e6..0c7d007dc48a 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -723,6 +723,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mFlags |= WindowManager.TRANSIT_FLAG_INVISIBLE;
return;
}
+ // Activity doesn't need to capture snapshot if the starting window has associated to task.
+ if (wc.asActivityRecord() != null) {
+ final ActivityRecord activityRecord = wc.asActivityRecord();
+ if (activityRecord.mStartingData != null
+ && activityRecord.mStartingData.mAssociatedTask != null) {
+ return;
+ }
+ }
if (mContainerFreezer == null) {
mContainerFreezer = new ScreenshotFreezer();
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index d1b00a38701d..4ce150e03558 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -24,6 +24,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
+import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
@@ -1335,6 +1336,19 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
taskFragment.setAnimationParams(animationParams);
break;
}
+ case OP_TYPE_REORDER_TO_FRONT: {
+ final Task task = taskFragment.getTask();
+ if (task != null) {
+ final TaskFragment topTaskFragment = task.getTaskFragment(
+ tf -> tf.asTask() == null);
+ if (topTaskFragment != null && topTaskFragment != taskFragment) {
+ final int index = task.mChildren.indexOf(topTaskFragment);
+ task.mChildren.remove(taskFragment);
+ task.mChildren.add(index, taskFragment);
+ }
+ }
+ break;
+ }
}
return effects;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 991248aceb4b..6960da74dd1a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -434,6 +434,10 @@ public final class SystemServer implements Dumpable {
+ "OnDevicePersonalizationSystemService$Lifecycle";
private static final String UPDATABLE_DEVICE_CONFIG_SERVICE_CLASS =
"com.android.server.deviceconfig.DeviceConfigInit$Lifecycle";
+ private static final String DEVICE_LOCK_SERVICE_CLASS =
+ "com.android.server.devicelock.DeviceLockService";
+ private static final String DEVICE_LOCK_APEX_PATH =
+ "/apex/com.android.devicelock/javalib/service-devicelock.jar";
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
@@ -2864,6 +2868,13 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(HEALTHCONNECT_MANAGER_SERVICE_CLASS);
t.traceEnd();
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_LOCK)) {
+ t.traceBegin("DeviceLockService");
+ mSystemServiceManager.startServiceFromJar(DEVICE_LOCK_SERVICE_CLASS,
+ DEVICE_LOCK_APEX_PATH);
+ t.traceEnd();
+ }
+
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 4aba30a661ad..f660b42457db 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -16,7 +16,9 @@
package com.android.server.midi;
+import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.BroadcastReceiver;
@@ -48,6 +50,7 @@ import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.EventLog;
import android.util.Log;
@@ -81,6 +84,11 @@ import java.util.concurrent.atomic.AtomicLong;
// 2. synchronized (mDeviceConnections)
//TODO Introduce a single lock object to lock the whole state and avoid the requirement above.
+// All users should be able to connect to USB and Bluetooth MIDI devices.
+// All users can create can install an app that provides, a Virtual MIDI Device Service.
+// Users can not open virtual MIDI devices created by other users.
+// getDevices() surfaces devices that can be opened by that user.
+// openDevice() rejects devices that are cannot be opened by that user.
public class MidiService extends IMidiManager.Stub {
public static class Lifecycle extends SystemService {
@@ -97,10 +105,21 @@ public class MidiService extends IMidiManager.Stub {
}
@Override
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
+ public void onUserStarting(@NonNull TargetUser user) {
+ mMidiService.onStartOrUnlockUser(user, false /* matchDirectBootUnaware */);
+ }
+
+ @Override
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
public void onUserUnlocking(@NonNull TargetUser user) {
- if (user.getUserIdentifier() == UserHandle.USER_SYSTEM) {
- mMidiService.onUnlockUser();
- }
+ mMidiService.onStartOrUnlockUser(user, true /* matchDirectBootUnaware */);
}
}
@@ -134,6 +153,7 @@ public class MidiService extends IMidiManager.Stub {
private int mNextDeviceId = 1;
private final PackageManager mPackageManager;
+ private final UserManager mUserManager;
private static final String MIDI_LEGACY_STRING = "MIDI 1.0";
private static final String MIDI_UNIVERSAL_STRING = "MIDI 2.0";
@@ -159,21 +179,24 @@ public class MidiService extends IMidiManager.Stub {
private final HashSet<ParcelUuid> mNonMidiUUIDs = new HashSet<ParcelUuid>();
// PackageMonitor for listening to package changes
+ // uid is the uid of the package so use getChangingUserId() to fetch the userId.
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public void onPackageAdded(String packageName, int uid) {
- addPackageDeviceServers(packageName);
+ addPackageDeviceServers(packageName, getChangingUserId());
}
@Override
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public void onPackageModified(String packageName) {
- removePackageDeviceServers(packageName);
- addPackageDeviceServers(packageName);
+ removePackageDeviceServers(packageName, getChangingUserId());
+ addPackageDeviceServers(packageName, getChangingUserId());
}
@Override
public void onPackageRemoved(String packageName, int uid) {
- removePackageDeviceServers(packageName);
+ removePackageDeviceServers(packageName, getChangingUserId());
}
};
@@ -202,6 +225,10 @@ public class MidiService extends IMidiManager.Stub {
return mUid;
}
+ private int getUserId() {
+ return UserHandle.getUserId(mUid);
+ }
+
public void addListener(IMidiDeviceListener listener) {
if (mListeners.size() >= MAX_LISTENERS_PER_CLIENT) {
throw new SecurityException(
@@ -219,8 +246,12 @@ public class MidiService extends IMidiManager.Stub {
}
}
- public void addDeviceConnection(Device device, IMidiDeviceOpenCallback callback) {
- Log.d(TAG, "addDeviceConnection() device:" + device);
+ @RequiresPermission(anyOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ Manifest.permission.INTERACT_ACROSS_PROFILES})
+ public void addDeviceConnection(Device device, IMidiDeviceOpenCallback callback,
+ int userId) {
+ Log.d(TAG, "addDeviceConnection() device:" + device + " userId:" + userId);
if (mDeviceConnections.size() >= MAX_CONNECTIONS_PER_CLIENT) {
Log.i(TAG, "too many MIDI connections for UID = " + mUid);
throw new SecurityException(
@@ -228,7 +259,7 @@ public class MidiService extends IMidiManager.Stub {
}
DeviceConnection connection = new DeviceConnection(device, this, callback);
mDeviceConnections.put(connection.getToken(), connection);
- device.addDeviceConnection(connection);
+ device.addDeviceConnection(connection, userId);
}
// called from MidiService.closeDevice()
@@ -251,8 +282,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceAdded(Device device) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
@@ -265,8 +296,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceRemoved(Device device) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
@@ -279,8 +310,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceStatusChanged(Device device, MidiDeviceStatus status) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
try {
for (IMidiDeviceListener listener : mListeners.values()) {
@@ -354,6 +385,8 @@ public class MidiService extends IMidiManager.Stub {
private final ServiceInfo mServiceInfo;
// UID of device implementation
private final int mUid;
+ // User Id of the app. Only used for virtual devices
+ private final int mUserId;
// ServiceConnection for implementing Service (virtual devices only)
// mServiceConnection is non-null when connected or attempting to connect to the service
@@ -375,19 +408,24 @@ public class MidiService extends IMidiManager.Stub {
private AtomicInteger mTotalOutputBytes = new AtomicInteger();
public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo,
- ServiceInfo serviceInfo, int uid) {
+ ServiceInfo serviceInfo, int uid, int userId) {
mDeviceInfo = deviceInfo;
mServiceInfo = serviceInfo;
mUid = uid;
+ mUserId = userId;
mBluetoothDevice = (BluetoothDevice)deviceInfo.getProperties().getParcelable(
MidiDeviceInfo.PROPERTY_BLUETOOTH_DEVICE, android.bluetooth.BluetoothDevice.class);;
setDeviceServer(server);
}
+ @RequiresPermission(anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
public Device(BluetoothDevice bluetoothDevice) {
mBluetoothDevice = bluetoothDevice;
mServiceInfo = null;
mUid = mBluetoothServiceUid;
+ mUserId = mUserManager.getMainUser().getIdentifier();
}
private void setDeviceServer(IMidiDeviceServer server) {
@@ -468,11 +506,22 @@ public class MidiService extends IMidiManager.Stub {
return mUid;
}
+ public int getUserId() {
+ return mUserId;
+ }
+
public boolean isUidAllowed(int uid) {
return (!mDeviceInfo.isPrivate() || mUid == uid);
}
- public void addDeviceConnection(DeviceConnection connection) {
+ public boolean isUserIdAllowed(int userId) {
+ return (mDeviceInfo.getType() != MidiDeviceInfo.TYPE_VIRTUAL || mUserId == userId);
+ }
+
+ @RequiresPermission(anyOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ Manifest.permission.INTERACT_ACROSS_PROFILES})
+ public void addDeviceConnection(DeviceConnection connection, int userId) {
Log.d(TAG, "addDeviceConnection() [A] connection:" + connection);
synchronized (mDeviceConnections) {
mDeviceConnectionsAdded.incrementAndGet();
@@ -537,8 +586,8 @@ public class MidiService extends IMidiManager.Stub {
new ComponentName(mServiceInfo.packageName, mServiceInfo.name));
}
- if (!mContext.bindService(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE)) {
+ if (!mContext.bindServiceAsUser(intent, mServiceConnection,
+ Context.BIND_AUTO_CREATE, UserHandle.of(mUserId))) {
Log.e(TAG, "Unable to bind service: " + intent);
setDeviceServer(null);
mServiceConnection = null;
@@ -886,6 +935,8 @@ public class MidiService extends IMidiManager.Stub {
public MidiService(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
// TEMPORARY - Disable BTL-MIDI
//FIXME - b/25689266
@@ -913,32 +964,41 @@ public class MidiService extends IMidiManager.Stub {
// mNonMidiUUIDs.add(BluetoothUuid.BATTERY);
}
- private void onUnlockUser() {
- mPackageMonitor.register(mContext, null, true);
-
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
+ private void onStartOrUnlockUser(TargetUser user, boolean matchDirectBootUnaware) {
+ Log.d(TAG, "onStartOrUnlockUser " + user.getUserIdentifier() + " matchDirectBootUnaware: "
+ + matchDirectBootUnaware);
Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
- List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent,
- PackageManager.GET_META_DATA);
+ int resolveFlags = PackageManager.GET_META_DATA;
+ if (matchDirectBootUnaware) {
+ resolveFlags |= PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ }
+ List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServicesAsUser(intent,
+ resolveFlags, user.getUserIdentifier());
if (resolveInfos != null) {
int count = resolveInfos.size();
for (int i = 0; i < count; i++) {
ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
if (serviceInfo != null) {
- addPackageDeviceServer(serviceInfo);
+ addPackageDeviceServer(serviceInfo, user.getUserIdentifier());
}
}
}
- PackageInfo info;
- try {
- info = mPackageManager.getPackageInfo(MidiManager.BLUETOOTH_MIDI_SERVICE_PACKAGE, 0);
- } catch (PackageManager.NameNotFoundException e) {
- info = null;
- }
- if (info != null && info.applicationInfo != null) {
- mBluetoothServiceUid = info.applicationInfo.uid;
- } else {
- mBluetoothServiceUid = -1;
+ if (user.getUserIdentifier() == mUserManager.getMainUser().getIdentifier()) {
+ PackageInfo info;
+ try {
+ info = mPackageManager.getPackageInfoAsUser(
+ MidiManager.BLUETOOTH_MIDI_SERVICE_PACKAGE, 0, user.getUserIdentifier());
+ } catch (PackageManager.NameNotFoundException e) {
+ info = null;
+ }
+ if (info != null && info.applicationInfo != null) {
+ mBluetoothServiceUid = info.applicationInfo.uid;
+ }
}
}
@@ -960,10 +1020,11 @@ public class MidiService extends IMidiManager.Stub {
// Inform listener of the status of all known devices.
private void updateStickyDeviceStatus(int uid, IMidiDeviceListener listener) {
+ int userId = UserHandle.getUserId(uid);
synchronized (mDevicesByInfo) {
for (Device device : mDevicesByInfo.values()) {
- // ignore private devices that our client cannot access
- if (device.isUidAllowed(uid)) {
+ // ignore devices that our client cannot access
+ if (device.isUidAllowed(uid) && device.isUserIdAllowed(userId)) {
try {
MidiDeviceStatus status = device.getDeviceStatus();
if (status != null) {
@@ -989,10 +1050,11 @@ public class MidiService extends IMidiManager.Stub {
public MidiDeviceInfo[] getDevicesForTransport(int transport) {
ArrayList<MidiDeviceInfo> deviceInfos = new ArrayList<MidiDeviceInfo>();
int uid = Binder.getCallingUid();
+ int userId = getCallingUserId();
synchronized (mDevicesByInfo) {
for (Device device : mDevicesByInfo.values()) {
- if (device.isUidAllowed(uid)) {
+ if (device.isUidAllowed(uid) && device.isUserIdAllowed(userId)) {
// UMP devices have protocols that are not PROTOCOL_UNKNOWN
if (transport == MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS) {
if (device.getDeviceInfo().getDefaultProtocol()
@@ -1029,6 +1091,9 @@ public class MidiService extends IMidiManager.Stub {
if (!device.isUidAllowed(Binder.getCallingUid())) {
throw new SecurityException("Attempt to open private device with wrong UID");
}
+ if (!device.isUserIdAllowed(getCallingUserId())) {
+ throw new SecurityException("Attempt to open virtual device with wrong user id");
+ }
}
if (deviceInfo.getType() == MidiDeviceInfo.TYPE_USB) {
@@ -1044,7 +1109,7 @@ public class MidiService extends IMidiManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
Log.i(TAG, "addDeviceConnection() [B] device:" + device);
- client.addDeviceConnection(device, callback);
+ client.addDeviceConnection(device, callback, getCallingUserId());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1106,7 +1171,7 @@ public class MidiService extends IMidiManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
Log.i(TAG, "addDeviceConnection() [C] device:" + device);
- client.addDeviceConnection(device, callback);
+ client.addDeviceConnection(device, callback, getCallingUserId());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1124,6 +1189,7 @@ public class MidiService extends IMidiManager.Stub {
int numOutputPorts, String[] inputPortNames, String[] outputPortNames,
Bundle properties, int type, int defaultProtocol) {
int uid = Binder.getCallingUid();
+ int userId = getCallingUserId();
if (type == MidiDeviceInfo.TYPE_USB && uid != Process.SYSTEM_UID) {
throw new SecurityException("only system can create USB devices");
} else if (type == MidiDeviceInfo.TYPE_BLUETOOTH && uid != mBluetoothServiceUid) {
@@ -1133,7 +1199,7 @@ public class MidiService extends IMidiManager.Stub {
synchronized (mDevicesByInfo) {
return addDeviceLocked(type, numInputPorts, numOutputPorts, inputPortNames,
outputPortNames, properties, server, null, false, uid,
- defaultProtocol);
+ defaultProtocol, userId);
}
}
@@ -1210,7 +1276,8 @@ public class MidiService extends IMidiManager.Stub {
private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts,
String[] inputPortNames, String[] outputPortNames, Bundle properties,
IMidiDeviceServer server, ServiceInfo serviceInfo,
- boolean isPrivate, int uid, int defaultProtocol) {
+ boolean isPrivate, int uid, int defaultProtocol, int userId) {
+ Log.d(TAG, "addDeviceLocked()" + uid + " type:" + type);
// Limit the number of devices per app.
int deviceCountForApp = 0;
@@ -1250,7 +1317,7 @@ public class MidiService extends IMidiManager.Stub {
}
}
if (device == null) {
- device = new Device(server, deviceInfo, serviceInfo, uid);
+ device = new Device(server, deviceInfo, serviceInfo, uid, userId);
}
mDevicesByInfo.put(deviceInfo, device);
if (bluetoothDevice != null) {
@@ -1281,12 +1348,14 @@ public class MidiService extends IMidiManager.Stub {
}
}
- private void addPackageDeviceServers(String packageName) {
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ private void addPackageDeviceServers(String packageName, int userId) {
PackageInfo info;
try {
- info = mPackageManager.getPackageInfo(packageName,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ info = mPackageManager.getPackageInfoAsUser(packageName,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e);
return;
@@ -1295,13 +1364,14 @@ public class MidiService extends IMidiManager.Stub {
ServiceInfo[] services = info.services;
if (services == null) return;
for (int i = 0; i < services.length; i++) {
- addPackageDeviceServer(services[i]);
+ addPackageDeviceServer(services[i], userId);
}
}
private static final String[] EMPTY_STRING_ARRAY = new String[0];
- private void addPackageDeviceServer(ServiceInfo serviceInfo) {
+ private void addPackageDeviceServer(ServiceInfo serviceInfo, int userId) {
+ Log.d(TAG, "addPackageDeviceServer()" + userId);
XmlResourceParser parser = null;
try {
@@ -1404,8 +1474,8 @@ public class MidiService extends IMidiManager.Stub {
int uid;
try {
- ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
- serviceInfo.packageName, 0);
+ ApplicationInfo appInfo = mPackageManager.getApplicationInfoAsUser(
+ serviceInfo.packageName, 0, userId);
uid = appInfo.uid;
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "could not fetch ApplicationInfo for "
@@ -1419,7 +1489,7 @@ public class MidiService extends IMidiManager.Stub {
inputPortNames.toArray(EMPTY_STRING_ARRAY),
outputPortNames.toArray(EMPTY_STRING_ARRAY),
properties, null, serviceInfo, isPrivate, uid,
- MidiDeviceInfo.PROTOCOL_UNKNOWN);
+ MidiDeviceInfo.PROTOCOL_UNKNOWN, userId);
}
// setting properties to null signals that we are no longer
// processing a <device>
@@ -1437,12 +1507,13 @@ public class MidiService extends IMidiManager.Stub {
}
}
- private void removePackageDeviceServers(String packageName) {
+ private void removePackageDeviceServers(String packageName, int userId) {
synchronized (mDevicesByInfo) {
Iterator<Device> iterator = mDevicesByInfo.values().iterator();
while (iterator.hasNext()) {
Device device = iterator.next();
- if (packageName.equals(device.getPackageName())) {
+ if (packageName.equals(device.getPackageName())
+ && (device.getUserId() == userId)) {
iterator.remove();
removeDeviceLocked(device);
}
@@ -1571,4 +1642,11 @@ public class MidiService extends IMidiManager.Stub {
String extractUsbDeviceTag(String propertyName) {
return propertyName.substring(propertyName.length() - MIDI_LEGACY_STRING.length());
}
+
+ /**
+ * @return the user id of the calling user.
+ */
+ private int getCallingUserId() {
+ return UserHandle.getUserId(Binder.getCallingUid());
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index 212a243c6a9e..cd3a78ed5e17 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -52,6 +52,7 @@ import android.app.GameModeConfiguration;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -1578,6 +1579,71 @@ public class GameManagerServiceTests {
assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
}
+ @Test
+ public void testAddGameStateListener() throws Exception {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ mockDeviceConfigAll();
+ startUser(gameManagerService, USER_ID_1);
+
+ IGameStateListener mockListener = Mockito.mock(IGameStateListener.class);
+ IBinder binder = Mockito.mock(IBinder.class);
+ when(mockListener.asBinder()).thenReturn(binder);
+ gameManagerService.addGameStateListener(mockListener);
+ verify(binder).linkToDeath(mDeathRecipientCaptor.capture(), anyInt());
+
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO);
+ GameState gameState = new GameState(true, GameState.MODE_NONE);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME);
+ gameState = new GameState(true, GameState.MODE_NONE);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener).onGameStateChanged(mPackageName, gameState, USER_ID_1);
+ reset(mockListener);
+
+ gameState = new GameState(false, GameState.MODE_CONTENT);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ mTestLooper.dispatchAll();
+ verify(mockListener).onGameStateChanged(mPackageName, gameState, USER_ID_1);
+ reset(mockListener);
+
+ mDeathRecipientCaptor.getValue().binderDied();
+ verify(binder).unlinkToDeath(eq(mDeathRecipientCaptor.getValue()), anyInt());
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+ }
+
+ @Test
+ public void testRemoveGameStateListener() throws Exception {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ mockDeviceConfigAll();
+ startUser(gameManagerService, USER_ID_1);
+
+ IGameStateListener mockListener = Mockito.mock(IGameStateListener.class);
+ IBinder binder = Mockito.mock(IBinder.class);
+ when(mockListener.asBinder()).thenReturn(binder);
+
+ gameManagerService.addGameStateListener(mockListener);
+ gameManagerService.removeGameStateListener(mockListener);
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME);
+ GameState gameState = new GameState(false, GameState.MODE_CONTENT);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+ }
+
private List<String> readGameModeInterventionList() throws Exception {
final File interventionFile = new File(InstrumentationRegistry.getContext().getFilesDir(),
"system/game_mode_intervention.list");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 99ab715ab987..54b935132957 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -26,6 +26,7 @@ import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
+import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_FRONT;
import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS;
import static android.window.TaskFragmentOperation.OP_TYPE_SET_ANIMATION_PARAMS;
@@ -1590,6 +1591,46 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
assertEquals(taskFragmentBounds, mTaskFragment.getBounds());
}
+ @Test
+ public void testApplyTransaction_reorderTaskFragmentToFront() {
+ final Task task = createTask(mDisplayContent);
+ // Create a TaskFragment.
+ final IBinder token0 = new Binder();
+ final TaskFragment tf0 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(token0)
+ .setOrganizer(mOrganizer)
+ .createActivityCount(1)
+ .build();
+ // Create another TaskFragment
+ final IBinder token1 = new Binder();
+ final TaskFragment tf1 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setFragmentToken(token1)
+ .setOrganizer(mOrganizer)
+ .createActivityCount(1)
+ .build();
+ // Create a non-embedded Activity on top.
+ final ActivityRecord topActivity = new ActivityBuilder(mAtm)
+ .setTask(task)
+ .build();
+ mWindowOrganizerController.mLaunchTaskFragments.put(token0, tf0);
+ mWindowOrganizerController.mLaunchTaskFragments.put(token1, tf1);
+
+ // Reorder TaskFragment to front
+ final TaskFragmentOperation operation = new TaskFragmentOperation.Builder(
+ OP_TYPE_REORDER_TO_FRONT).build();
+ mTransaction.addTaskFragmentOperation(token0, operation);
+ assertApplyTransactionAllowed(mTransaction);
+
+ // Ensure the non-embedded activity still on top.
+ assertEquals(topActivity, task.getTopChild().asActivityRecord());
+
+ // Ensure the TaskFragment is moved to front.
+ final TaskFragment frontMostTaskFragment = task.getTaskFragment(tf -> tf.asTask() == null);
+ assertEquals(frontMostTaskFragment, tf0);
+ }
+
/**
* Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
* {@link WindowOrganizerController#applyTransaction(WindowContainerTransaction)} to apply the