summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java10
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java1
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java10
-rw-r--r--apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java6
-rw-r--r--apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java6
-rw-r--r--apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java20
-rw-r--r--apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java14
-rw-r--r--apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java6
-rw-r--r--apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java35
-rw-r--r--apct-tests/perftests/core/src/android/text/TextPerfUtils.java19
-rw-r--r--apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java6
-rw-r--r--apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java37
-rwxr-xr-xapi/current.txt4
-rw-r--r--api/system-current.txt1
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java2
-rw-r--r--cmds/am/src/com/android/commands/am/Instrument.java16
-rw-r--r--cmds/incidentd/Android.mk6
-rw-r--r--cmds/statsd/src/atoms.proto105
-rw-r--r--config/preloaded-classes6
-rw-r--r--core/java/android/app/ActivityManager.java11
-rw-r--r--core/java/android/app/WallpaperInfo.java24
-rw-r--r--core/java/android/content/Intent.java16
-rw-r--r--core/java/android/inputmethodservice/IInputMethodSessionWrapper.java11
-rw-r--r--core/java/android/os/PowerManager.java6
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/view/GhostView.java6
-rw-r--r--core/java/android/view/IWindowManager.aidl41
-rw-r--r--core/java/android/view/RenderNodeAnimator.java8
-rw-r--r--core/java/android/view/RenderNodeAnimatorSetHelper.java6
-rw-r--r--core/java/android/view/Surface.java4
-rw-r--r--core/java/android/view/SurfaceView.java1
-rw-r--r--core/java/android/view/TextureLayer.java2
-rw-r--r--core/java/android/view/TextureView.java5
-rw-r--r--core/java/android/view/ThreadedRenderer.java8
-rw-r--r--core/java/android/view/View.java10
-rw-r--r--core/java/android/view/ViewAnimationHostBridge.java2
-rw-r--r--core/java/android/view/ViewDebug.java4
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java1
-rw-r--r--core/java/android/view/ViewRootImpl.java6
-rw-r--r--core/java/android/view/WindowCallbacks.java3
-rw-r--r--core/java/android/webkit/WebViewDelegate.java10
-rw-r--r--core/java/android/widget/Editor.java14
-rw-r--r--core/java/android/widget/Magnifier.java10
-rw-r--r--core/java/com/android/internal/policy/BackdropFrameRenderer.java8
-rw-r--r--core/java/com/android/internal/policy/DecorView.java97
-rw-r--r--core/java/com/android/internal/view/IInputMethodSession.aidl4
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java10
-rw-r--r--core/jni/android_opengl_EGL15.cpp75
-rw-r--r--core/jni/android_view_DisplayListCanvas.cpp2
-rw-r--r--core/jni/android_view_RenderNode.cpp6
-rw-r--r--core/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java17
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--graphics/java/android/graphics/BaseCanvas.java2
-rw-r--r--graphics/java/android/graphics/Bitmap.java4
-rw-r--r--graphics/java/android/graphics/Picture.java3
-rw-r--r--graphics/java/android/graphics/RecordingCanvas.java (renamed from core/java/android/view/DisplayListCanvas.java)62
-rw-r--r--graphics/java/android/graphics/RenderNode.java (renamed from core/java/android/view/RenderNode.java)100
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java10
-rw-r--r--graphics/java/android/graphics/drawable/RippleComponent.java7
-rw-r--r--graphics/java/android/graphics/drawable/RippleForeground.java10
-rw-r--r--libs/hwui/Android.bp3
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp24
-rw-r--r--libs/hwui/tests/macrobench/main.cpp2
-rw-r--r--opengl/java/android/opengl/EGL15.java18
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java11
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java53
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java10
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java32
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java45
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskDescriptionCompat.java40
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowCallbacksCompat.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/InitController.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeHost.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java513
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java551
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java291
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java104
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java147
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java1246
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java672
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java252
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java120
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java89
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java115
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java5
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto5
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MagnificationController.java1076
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java148
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java4
-rw-r--r--services/core/java/com/android/server/am/ActiveUids.java74
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java94
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityTaskManagerService.java129
-rw-r--r--services/core/java/com/android/server/am/PendingTempWhitelists.java59
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java76
-rw-r--r--services/core/java/com/android/server/am/UidRecord.java30
-rw-r--r--services/core/java/com/android/server/am/WindowProcessController.java49
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/Settings.java34
-rw-r--r--services/core/java/com/android/server/pm/SharedUserSetting.java26
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java31
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java21
-rw-r--r--services/core/java/com/android/server/power/BatterySaverPolicy.java14
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java77
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java73
-rw-r--r--services/core/java/com/android/server/wm/DisplaySettings.java163
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java64
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java4
-rw-r--r--services/tests/mockingservicestests/Android.mk2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java270
-rw-r--r--services/tests/servicestests/Android.mk3
-rw-r--r--services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java38
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java11
-rw-r--r--services/tests/servicestests/test-apps/SuspendTestApp/Android.mk2
-rw-r--r--services/tests/wmtests/Android.mk2
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java6
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java12
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java8
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java3
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java6
-rw-r--r--tests/Internal/res/xml/livewallpaper.xml3
-rw-r--r--tests/Internal/src/android/app/WallpaperInfoTest.java27
-rw-r--r--tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java2
-rw-r--r--tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java31
-rw-r--r--tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java7
-rw-r--r--wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl5
-rw-r--r--wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java53
221 files changed, 6052 insertions, 3379 deletions
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
index eed1db032d9f..c742df3b882b 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java
@@ -17,14 +17,14 @@
package android.graphics.perftests;
import android.graphics.Bitmap;
-import android.graphics.Color;
import android.graphics.Bitmap.Config;
+import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
@@ -43,7 +43,7 @@ public class CanvasPerfTest {
RenderNode child = RenderNode.create("child", null);
child.setLeftTopRightBottom(50, 50, 100, 100);
- DisplayListCanvas canvas = node.start(100, 100);
+ RecordingCanvas canvas = node.start(100, 100);
node.end(canvas);
canvas = child.start(50, 50);
canvas.drawColor(Color.WHITE);
@@ -70,7 +70,7 @@ public class CanvasPerfTest {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
RenderNode node = RenderNode.create("benchmark", null);
- DisplayListCanvas canvas = node.start(100, 100);
+ RecordingCanvas canvas = node.start(100, 100);
node.end(canvas);
Bitmap bitmap = Bitmap.createBitmap(80, 80, Config.ARGB_8888);
Paint paint = new Paint();
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java
index 3a4fc7206712..f9c375804599 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java
@@ -20,7 +20,6 @@ import android.graphics.Outline;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index a283e0664bc6..d18aa51bfcd3 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -17,17 +17,15 @@
package android.graphics.perftests;
import android.graphics.Outline;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
-import java.util.ArrayList;
-
@LargeTest
public class RenderNodePerfTest {
@Rule
@@ -73,7 +71,7 @@ public class RenderNodePerfTest {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
RenderNode node = RenderNode.create("LinearLayout", null);
while (state.keepRunning()) {
- DisplayListCanvas canvas = node.start(100, 100);
+ RecordingCanvas canvas = node.start(100, 100);
node.end(canvas);
}
}
@@ -82,7 +80,7 @@ public class RenderNodePerfTest {
public void testStartEndDeepHierarchy() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
RenderNode[] nodes = new RenderNode[30];
- DisplayListCanvas[] canvases = new DisplayListCanvas[nodes.length];
+ RecordingCanvas[] canvases = new RecordingCanvas[nodes.length];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = RenderNode.create("LinearLayout", null);
}
diff --git a/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
index 64f2800ee112..9245c1ba59e4 100644
--- a/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/BoringLayoutCreateDrawPerfTest.java
@@ -18,12 +18,12 @@ package android.text;
import static android.text.Layout.Alignment.ALIGN_NORMAL;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
import android.text.NonEditableTextGenerator.TextType;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
@@ -120,7 +120,7 @@ public class BoringLayoutCreateDrawPerfTest {
while (state.keepRunning()) {
state.pauseTiming();
- final DisplayListCanvas canvas = node.start(1200, 200);
+ final RecordingCanvas canvas = node.start(1200, 200);
final int save = canvas.save();
if (!mCached) Canvas.freeTextLayoutCaches();
state.resumeTiming();
diff --git a/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
index ad5a34e44997..a7972f59f382 100644
--- a/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/PaintMeasureDrawPerfTest.java
@@ -17,11 +17,11 @@ package android.text;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
@@ -107,7 +107,7 @@ public class PaintMeasureDrawPerfTest {
while (state.keepRunning()) {
state.pauseTiming();
- final DisplayListCanvas canvas = node.start(1200, 200);
+ final RecordingCanvas canvas = node.start(1200, 200);
final int save = canvas.save();
if (!mCached) Canvas.freeTextLayoutCaches();
state.resumeTiming();
diff --git a/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
index d98df059e2d3..00a626750c79 100644
--- a/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
+++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextMemoryUsageTest.java
@@ -16,32 +16,16 @@
package android.text;
-import static android.text.TextDirectionHeuristics.LTR;
-
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
-
import android.app.Activity;
import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Typeface;
-import android.text.Layout;
-import android.text.style.TextAppearanceSpan;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.nio.CharBuffer;
-import java.util.Random;
import java.util.Locale;
@LargeTest
diff --git a/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
index 1cd0ae13069b..33b1a47413c8 100644
--- a/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/PrecomputedTextPerfTest.java
@@ -16,30 +16,16 @@
package android.text;
-import static android.text.TextDirectionHeuristics.LTR;
-
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
-
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Typeface;
-import android.text.Layout;
-import android.text.style.TextAppearanceSpan;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.nio.CharBuffer;
-import java.util.Random;
-
@LargeTest
@RunWith(AndroidJUnit4.class)
public class PrecomputedTextPerfTest {
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
index deb2b0a74aaa..b40dd6b9dbb7 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutCreateDrawPerfTest.java
@@ -18,12 +18,12 @@ package android.text;
import static android.text.Layout.Alignment.ALIGN_NORMAL;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
import android.text.NonEditableTextGenerator.TextType;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
@@ -119,7 +119,7 @@ public class StaticLayoutCreateDrawPerfTest {
while (state.keepRunning()) {
state.pauseTiming();
- final DisplayListCanvas canvas = node.start(1200, 200);
+ final RecordingCanvas canvas = node.start(1200, 200);
int save = canvas.save();
if (!mCached) Canvas.freeTextLayoutCaches();
state.resumeTiming();
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index e1a38a0956d7..e224fa39422c 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -16,30 +16,19 @@
package android.text;
-import static android.text.TextDirectionHeuristics.LTR;
-
+import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
-
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Typeface;
-import android.text.Layout;
-import android.text.style.TextAppearanceSpan;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.nio.CharBuffer;
-import java.util.Random;
-
@LargeTest
@RunWith(AndroidJUnit4.class)
public class StaticLayoutPerfTest {
@@ -256,7 +245,7 @@ public class StaticLayoutPerfTest {
state.pauseTiming();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -272,7 +261,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -288,7 +277,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -304,7 +293,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -321,7 +310,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -339,7 +328,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -356,7 +345,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -373,7 +362,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -391,7 +380,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final DisplayListCanvas c = node.start(1200, 200);
+ final RecordingCanvas c = node.start(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
diff --git a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
index aa505b533f26..22e516abe926 100644
--- a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
+++ b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
@@ -16,32 +16,15 @@
package android.text;
-import static android.text.TextDirectionHeuristics.LTR;
-
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
-
import android.content.res.ColorStateList;
-import android.graphics.Canvas;
import android.graphics.Typeface;
import android.icu.text.UnicodeSet;
import android.icu.text.UnicodeSetIterator;
-import android.text.Layout;
import android.text.style.TextAppearanceSpan;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
import java.nio.CharBuffer;
-import java.util.Random;
import java.util.ArrayList;
+import java.util.Random;
public class TextPerfUtils {
diff --git a/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java b/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
index 4bbe4049ba35..25cc7078762a 100644
--- a/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/TextViewSetTextMeasurePerfTest.java
@@ -19,13 +19,13 @@ import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.UNSPECIFIED;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.text.NonEditableTextGenerator.TextType;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import android.widget.TextView;
import org.junit.Rule;
@@ -128,7 +128,7 @@ public class TextViewSetTextMeasurePerfTest {
while (state.keepRunning()) {
state.pauseTiming();
- final DisplayListCanvas canvas = node.start(1200, 200);
+ final RecordingCanvas canvas = node.start(1200, 200);
int save = canvas.save();
textView.setTextLocale(Locale.UK);
textView.setTextLocale(Locale.US);
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index dc34b7fe057c..434b8e56dd36 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -16,46 +16,29 @@
package android.widget;
-import static android.view.View.MeasureSpec.AT_MOST;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.UNSPECIFIED;
+import static android.widget.TextView.UNKNOWN_BORING;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Typeface;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
-import android.text.PrecomputedText;
-import android.text.Layout;
import android.text.BoringLayout;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
+import android.text.Layout;
+import android.text.PrecomputedText;
import android.text.TextPaint;
-import android.text.style.TextAppearanceSpan;
-import android.view.LayoutInflater;
import android.text.TextPerfUtils;
import android.view.View.MeasureSpec;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-
-import com.android.perftests.core.R;
-
-import java.util.Random;
-import java.util.Locale;
import org.junit.Before;
-import org.junit.Test;
import org.junit.Rule;
+import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertTrue;
-
-import static android.widget.TextView.UNKNOWN_BORING;
-
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TextViewPrecomputedTextPerfTest {
@@ -360,7 +343,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final DisplayListCanvas c = node.start(
+ final RecordingCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -386,7 +369,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final DisplayListCanvas c = node.start(
+ final RecordingCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -414,7 +397,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final DisplayListCanvas c = node.start(
+ final RecordingCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -443,7 +426,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final DisplayListCanvas c = node.start(
+ final RecordingCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
diff --git a/api/current.txt b/api/current.txt
index 21bab7cf5d1e..1c3ee82dbba0 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -1199,6 +1199,7 @@ package android {
field public static final deprecated int selectedWeekBackgroundColor = 16843586; // 0x1010342
field public static final int sessionService = 16843837; // 0x101043d
field public static final int settingsActivity = 16843301; // 0x1010225
+ field public static final int settingsSliceUri = 16844179; // 0x1010593
field public static final int setupActivity = 16843766; // 0x10103f6
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
@@ -6321,6 +6322,7 @@ package android.app {
method public android.content.pm.ServiceInfo getServiceInfo();
method public java.lang.String getServiceName();
method public java.lang.String getSettingsActivity();
+ method public android.net.Uri getSettingsSliceUri();
method public boolean getShowMetadataInPreview();
method public java.lang.CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
method public java.lang.CharSequence loadContextDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
@@ -29743,9 +29745,11 @@ package android.opengl {
public class EGL15 {
ctor public EGL15();
method public static int eglClientWaitSync(android.opengl.EGLDisplay, android.opengl.EGLSync, int, long);
+ method public static android.opengl.EGLImage eglCreateImage(android.opengl.EGLDisplay, android.opengl.EGLContext, int, long, long[], int);
method public static android.opengl.EGLSurface eglCreatePlatformPixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.nio.Buffer, long[], int);
method public static android.opengl.EGLSurface eglCreatePlatformWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.nio.Buffer, long[], int);
method public static android.opengl.EGLSync eglCreateSync(android.opengl.EGLDisplay, int, long[], int);
+ method public static boolean eglDestroyImage(android.opengl.EGLDisplay, android.opengl.EGLImage);
method public static boolean eglDestroySync(android.opengl.EGLDisplay, android.opengl.EGLSync);
method public static android.opengl.EGLDisplay eglGetPlatformDisplay(int, long, long[], int);
method public static boolean eglGetSyncAttrib(android.opengl.EGLDisplay, android.opengl.EGLSync, int, long[], int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 26036ea9c281..7e510827b6ff 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -987,6 +987,7 @@ package android.content {
field public static final java.lang.String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
+ field public static final java.lang.String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
field public static final java.lang.String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index c04e61b77274..41d546f6d603 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -174,6 +174,8 @@ public class Am extends BaseCommand {
instrument.noWindowAnimation = true;
} else if (opt.equals("--no-hidden-api-checks")) {
instrument.disableHiddenApiChecks = true;
+ } else if (opt.equals("--no-isolated-storage")) {
+ instrument.disableIsolatedStorage = true;
} else if (opt.equals("--user")) {
instrument.userId = parseUserArg(nextArgRequired());
} else if (opt.equals("--abi")) {
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 0dade0b2ba81..70baa8702ba9 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -16,6 +16,9 @@
package com.android.commands.am;
+import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
+import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
+
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
import android.app.Instrumentation;
@@ -74,16 +77,13 @@ public class Instrument {
String logPath = null;
public boolean noWindowAnimation = false;
public boolean disableHiddenApiChecks = false;
+ public boolean disableIsolatedStorage = false;
public String abi = null;
public int userId = UserHandle.USER_CURRENT;
public Bundle args = new Bundle();
// Required
public String componentNameArg;
- // Disable hidden API checks for the newly started instrumentation.
- // Must be kept in sync with ActivityManagerService.
- private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
-
/**
* Construct the instrument command runner.
*/
@@ -480,7 +480,13 @@ public class Instrument {
}
// Start the instrumentation
- int flags = disableHiddenApiChecks ? INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS : 0;
+ int flags = 0;
+ if (disableHiddenApiChecks) {
+ flags |= INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
+ }
+ if (disableIsolatedStorage) {
+ flags |= INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
+ }
if (!mAm.startInstrumentation(cn, profileFile, flags, args, watcher, connection, userId,
abi)) {
throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index db864aed6bdc..eba558653b04 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -33,6 +33,9 @@ LOCAL_SRC_FILES := $(call all-cpp-files-under, src) \
LOCAL_CFLAGS += \
-Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
+# Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
+LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
+
ifeq (debug,)
LOCAL_CFLAGS += \
-g -O0
@@ -100,6 +103,9 @@ LOCAL_MODULE_TAGS := tests
LOCAL_CFLAGS := -Werror -Wall -Wno-unused-variable -Wunused-parameter
+# Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
+LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
+
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call all-cpp-files-under, tests) \
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c2fed66eea41..869c3a3c5ea7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -144,6 +144,7 @@ message Atom {
PhoneServiceStateChanged phone_service_state_changed = 94;
PhoneStateChanged phone_state_changed = 95;
UserRestrictionChanged user_restriction_changed = 96;
+ SettingsUIChanged settings_ui_changed = 97;
}
// Pulled events will start at field 10000.
@@ -1437,6 +1438,79 @@ message PhoneStateChanged {
}
/**
+ * Logs when Settings UI has changed.
+ *
+ * Logged from:
+ * packages/apps/Settings
+ */
+message SettingsUIChanged {
+ /**
+ * The action performed in this event
+ */
+ enum Action {
+ ACTION_UNKNOWN = 0;
+ PAGE_VISIBLE = 1;
+ PAGE_HIDE = 2;
+ PREF_CHANGE = 3;
+ }
+
+ /**
+ * Id for Settings pages. Each page must have its own unique Id.
+ */
+ enum PageId {
+ // Unknown page. Should not be used in production code.
+ PAGE_UNKNOWN = 0;
+
+ // OPEN: Settings homepage
+ SETTINGS_HOMEPAGE = 1502;
+
+ // OPEN: Settings > System > Input & Gesture > Wake screen
+ SETTINGS_GESTURE_WAKE_SCREEN = 1570;
+
+ // OPEN: Settings > Network & internet > Mobile network
+ MOBILE_NETWORK = 1571;
+
+ // OPEN: Settings > Network & internet > Mobile network > Choose network
+ MOBILE_NETWORK_SELECT = 1581;
+
+ // OPEN: Settings > Network & internet > Mobile network > Mobile Data > Dialog
+ MOBILE_DATA_DIALOG = 1582;
+
+ // OPEN: Settings > Network & internet > Mobile network > Data roaming > Dialog
+ MOBILE_ROAMING_DIALOG = 1583;
+
+ // Settings > Display > Lock screen display > On lock screen
+ LOCK_SCREEN_NOTIFICATION_CONTENT = 1584;
+ }
+
+ /**
+ * Where this SettingsUIChange event comes from. For example, if
+ * it's a PAGE_VISIBLE event, where the page is opened from.
+ */
+ optional PageId attribution = 1;
+
+ /**
+ * What the UI action is.
+ */
+ optional Action action = 2;
+
+ /**
+ * Where the action is happening
+ */
+ optional PageId pageId = 3;
+
+ /**
+ * What preference changed in this event.
+ */
+ optional string changedPreferenceKey = 4;
+
+ /**
+ * The new value of the changed preference.
+ */
+ optional int64 changedPreferenceIntValue = 5;
+}
+
+/**
* Logs that a setting was updated.
* Logged from:
* frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -2051,25 +2125,34 @@ message Notification {
optional int32 importance = 7;
// ID for the notification channel.
- optional int32 channel_id = 8;
+ optional string channel_id = 8;
// Importance for the notification channel.
optional int32 channel_importance = 9;
+ // Application-supplied ID associated with the notifications group.
+ optional string group_id = 10;
+
// Whether notification was a group summary.
- optional bool group_summary = 10;
+ optional bool group_summary = 11;
- // Time since notification was created in milliseconds.
- optional int64 since_create_millis = 11;
+ // Reason for dismissal of a notification. This field is only meaningful for
+ // TYPE_DISMISS events.
+ optional int32 dismiss_reason = 12;
- // Time since notification was interrupted in milliseconds.
- optional int64 since_interruption_millis = 12;
+ // The first post time of notification, stable across updates.
+ optional int64 creation_millis = 13;
- // Time since notification was updated in milliseconds.
- optional int64 since_update_millis = 13;
+ // The most recent interruption time, or the creation time if no updates.
+ // Differs from update_millis because updates are filtered based on whether
+ // they actually interrupted the user.
+ optional int64 interruption_millis = 14;
- // Time since notification was visible in milliseconds.
- optional int64 since_visible_millis = 14;
+ // The most recent update time, or the creation time if no updates.
+ optional int64 update_millis = 15;
+
+ // The most recent visibility event.
+ optional int64 visible_millis = 16;
}
@@ -3046,4 +3129,4 @@ message UserRestrictionChanged {
optional string restriction = 1;
// Whether the restriction is enabled or disabled.
optional bool enabled = 2;
-} \ No newline at end of file
+}
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 1a8a32ec574f..95bcf0ecf132 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3227,7 +3227,7 @@ android.view.DisplayCutout$ParcelableWrapper$1
android.view.DisplayEventReceiver
android.view.DisplayInfo
android.view.DisplayInfo$1
-android.view.DisplayListCanvas
+android.graphics.RecordingCanvas
android.view.FallbackEventHandler
android.view.FocusFinder
android.view.FocusFinder$1
@@ -3305,8 +3305,8 @@ android.view.OrientationEventListener
android.view.OrientationEventListener$SensorEventListenerImpl
android.view.PointerIcon
android.view.PointerIcon$1
-android.view.RenderNode
-android.view.RenderNode$NoImagePreloadHolder
+android.graphics.RenderNode
+android.graphics.RenderNode$NoImagePreloadHolder
android.view.RenderNodeAnimator
android.view.RenderNodeAnimator$1
android.view.RenderNodeAnimatorSetHelper
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 14b8ae45d989..7330da323f47 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -137,6 +137,17 @@ public class ActivityManager {
private static final int FIRST_START_NON_FATAL_ERROR_CODE = 100;
private static final int LAST_START_NON_FATAL_ERROR_CODE = 199;
+ /**
+ * Disable hidden API checks for the newly started instrumentation.
+ * @hide
+ */
+ public static final int INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
+ /**
+ * Mount full external storage for the newly started instrumentation.
+ * @hide
+ */
+ public static final int INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL = 1 << 1;
+
static final class UidObserver extends IUidObserver.Stub {
final OnUidImportanceListener mListener;
final Context mContext;
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 9873a8152b3f..e33d1fed4b4c 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.slice.Slice;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -77,6 +78,7 @@ public final class WallpaperInfo implements Parcelable {
final int mContextDescriptionResource;
final boolean mShowMetadataInPreview;
final boolean mSupportsAmbientMode;
+ final String mSettingsSliceUri;
/**
* Constructor.
@@ -118,7 +120,6 @@ public final class WallpaperInfo implements Parcelable {
com.android.internal.R.styleable.Wallpaper);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.Wallpaper_settingsActivity);
-
mThumbnailResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_thumbnail,
-1);
@@ -140,6 +141,8 @@ public final class WallpaperInfo implements Parcelable {
mSupportsAmbientMode = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_supportsAmbientMode,
false);
+ mSettingsSliceUri = sa.getString(
+ com.android.internal.R.styleable.Wallpaper_settingsSliceUri);
sa.recycle();
} catch (NameNotFoundException e) {
@@ -159,6 +162,7 @@ public final class WallpaperInfo implements Parcelable {
mContextDescriptionResource = source.readInt();
mShowMetadataInPreview = source.readInt() != 0;
mSupportsAmbientMode = source.readInt() != 0;
+ mSettingsSliceUri = source.readString();
mService = ResolveInfo.CREATOR.createFromParcel(source);
}
@@ -332,13 +336,28 @@ public final class WallpaperInfo implements Parcelable {
* explicit {@link android.content.ComponentName}
* composed of {@link #getPackageName} and the class name returned here.
*
- * <p>A null will be returned if there is no settings activity associated
+ * <p>{@code null} will be returned if there is no settings activity associated
* with the wallpaper.
*/
public String getSettingsActivity() {
return mSettingsActivityName;
}
+ /**
+ * Returns an URI that provides a settings {@link Slice} for this wallpaper.
+ *
+ * <p>{@code null} will be returned if there is no settings Slice URI associated
+ * with the wallpaper.
+ *
+ * @return The URI.
+ */
+ public Uri getSettingsSliceUri() {
+ if (mSettingsSliceUri == null) {
+ return null;
+ }
+ return Uri.parse(mSettingsSliceUri);
+ }
+
public void dump(Printer pw, String prefix) {
pw.println(prefix + "Service:");
mService.dump(pw, prefix + " ");
@@ -367,6 +386,7 @@ public final class WallpaperInfo implements Parcelable {
dest.writeInt(mContextDescriptionResource);
dest.writeInt(mShowMetadataInPreview ? 1 : 0);
dest.writeInt(mSupportsAmbientMode ? 1 : 0);
+ dest.writeString(mSettingsSliceUri);
mService.writeToParcel(dest, flags);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c0463e9ae7af..ea1a2fe758af 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1908,6 +1908,22 @@ public class Intent implements Parcelable, Cloneable {
@SystemApi
public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
+ /**
+ * Activity action: Launch UI to review app uses of permissions.
+ * <p>
+ * Input: Nothing
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REVIEW_PERMISSION_USAGE =
+ "android.intent.action.REVIEW_PERMISSION_USAGE";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent broadcast actions (see action variable).
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 0982d65ee4c9..843db6d28d30 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -41,8 +41,7 @@ import com.android.internal.view.IInputMethodSession;
class IInputMethodSessionWrapper extends IInputMethodSession.Stub
implements HandlerCaller.Callback {
private static final String TAG = "InputMethodWrapper";
-
- private static final int DO_FINISH_INPUT = 60;
+
private static final int DO_DISPLAY_COMPLETIONS = 65;
private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
private static final int DO_UPDATE_SELECTION = 90;
@@ -89,9 +88,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
}
switch (msg.what) {
- case DO_FINISH_INPUT:
- mInputMethodSession.finishInput();
- return;
case DO_DISPLAY_COMPLETIONS:
mInputMethodSession.displayCompletions((CompletionInfo[])msg.obj);
return;
@@ -150,11 +146,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
}
@Override
- public void finishInput() {
- mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
- }
-
- @Override
public void displayCompletions(CompletionInfo[] completions) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(
DO_DISPLAY_COMPLETIONS, completions));
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8ea061e4a8d0..e0b2c7853eba 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -557,6 +557,7 @@ public final class PowerManager {
ServiceType.FORCE_ALL_APPS_STANDBY,
ServiceType.OPTIONAL_SENSORS,
ServiceType.AOD,
+ ServiceType.QUICK_DOZE,
})
public @interface ServiceType {
int NULL = 0;
@@ -586,6 +587,11 @@ public final class PowerManager {
* Whether to disable non-essential sensors. (e.g. edge sensors.)
*/
int OPTIONAL_SENSORS = 13;
+
+ /**
+ * Whether to go into Deep Doze as soon as the screen turns off or not.
+ */
+ int QUICK_DOZE = 15;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ad640219a6a5..80e8f78ec92b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10907,6 +10907,7 @@ public final class Settings {
* idle_pending_to (long)
* max_idle_pending_to (long)
* idle_pending_factor (float)
+ * quick_doze_delay_to (long)
* idle_to (long)
* max_idle_to (long)
* idle_factor (float)
@@ -10940,6 +10941,11 @@ public final class Settings {
* gps_mode (int)
* adjust_brightness_disabled (boolean)
* adjust_brightness_factor (float)
+ * force_all_apps_standby (boolean)
+ * force_background_check (boolean)
+ * optional_sensors_disabled (boolean)
+ * aod_disabled (boolean)
+ * quick_doze_enabled (boolean)
* </pre>
* @hide
* @see com.android.server.power.BatterySaverPolicy
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index fa7b067deb20..98ed21735e62 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -18,6 +18,8 @@ package android.view;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.widget.FrameLayout;
import java.util.ArrayList;
@@ -46,8 +48,8 @@ public class GhostView extends View {
@Override
protected void onDraw(Canvas canvas) {
- if (canvas instanceof DisplayListCanvas) {
- DisplayListCanvas dlCanvas = (DisplayListCanvas) canvas;
+ if (canvas instanceof RecordingCanvas) {
+ RecordingCanvas dlCanvas = (RecordingCanvas) canvas;
mView.mRecreateDisplayList = true;
RenderNode renderNode = mView.updateDisplayListIfDirty();
if (renderNode.isValid()) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 3e559d9e106f..0c3a2957e1bc 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -226,25 +226,50 @@ interface IWindowManager
int getPreferredOptionsPanelGravity(int displayId);
/**
- * Lock the device orientation to the specified rotation, or to the
- * current rotation if -1. Sensor input will be ignored until
- * thawRotation() is called.
- * @hide
+ * Equivalent to calling {@link #freezeDisplayRotation(int, int)} with {@link
+ * android.view.Display#DEFAULT_DISPLAY} and given rotation.
*/
void freezeRotation(int rotation);
/**
- * Release the orientation lock imposed by freezeRotation().
- * @hide
+ * Equivalent to calling {@link #thawDisplayRotation(int)} with {@link
+ * android.view.Display#DEFAULT_DISPLAY}.
*/
void thawRotation();
/**
- * Gets whether the rotation is frozen.
+ * Equivelant to call {@link #isDisplayRotationFrozen(int)} with {@link
+ * android.view.Display#DEFAULT_DISPLAY}.
+ */
+ boolean isRotationFrozen();
+
+ /**
+ * Lock the display orientation to the specified rotation, or to the current
+ * rotation if -1. Sensor input will be ignored until thawRotation() is called.
*
+ * @param displayId the ID of display which rotation should be frozen.
+ * @param rotation one of {@link android.view.Surface#ROTATION_0},
+ * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
+ * {@link android.view.Surface#ROTATION_270} or -1 to freeze it to current rotation.
+ * @hide
+ */
+ void freezeDisplayRotation(int displayId, int rotation);
+
+ /**
+ * Release the orientation lock imposed by freezeRotation() on the display.
+ *
+ * @param displayId the ID of display which rotation should be thawed.
+ * @hide
+ */
+ void thawDisplayRotation(int displayId);
+
+ /**
+ * Gets whether the rotation is frozen on the display.
+ *
+ * @param displayId the ID of display which frozen is needed.
* @return Whether the rotation is frozen.
*/
- boolean isRotationFrozen();
+ boolean isDisplayRotationFrozen(int displayId);
/**
* Screenshot the current wallpaper layer, including the whole screen.
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index e48bcfdb7203..9d31bd16b452 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -22,6 +22,8 @@ import android.animation.ValueAnimator;
import android.annotation.UnsupportedAppUsage;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import android.util.SparseIntArray;
import com.android.internal.util.VirtualRefBasePtr;
@@ -286,8 +288,8 @@ public class RenderNodeAnimator extends Animator {
setTarget(mViewTarget.mRenderNode);
}
- /** Sets the animation target to the owning view of the DisplayListCanvas */
- public void setTarget(DisplayListCanvas canvas) {
+ /** Sets the animation target to the owning view of the RecordingCanvas */
+ public void setTarget(RecordingCanvas canvas) {
setTarget(canvas.mNode);
}
@@ -405,7 +407,7 @@ public class RenderNodeAnimator extends Animator {
return listeners;
}
- long getNativeAnimator() {
+ public long getNativeAnimator() {
return mNativePtr.get();
}
diff --git a/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java
index e1ef05941394..d222e0739fa2 100644
--- a/core/java/android/view/RenderNodeAnimatorSetHelper.java
+++ b/core/java/android/view/RenderNodeAnimatorSetHelper.java
@@ -16,6 +16,8 @@
package android.view;
import android.animation.TimeInterpolator;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
import com.android.internal.view.animation.FallbackLUTInterpolator;
import com.android.internal.view.animation.NativeInterpolatorFactory;
@@ -29,10 +31,12 @@ import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
*/
public class RenderNodeAnimatorSetHelper {
- public static RenderNode getTarget(DisplayListCanvas recordingCanvas) {
+ /** checkstyle @hide */
+ public static RenderNode getTarget(RecordingCanvas recordingCanvas) {
return recordingCanvas.mNode;
}
+ /** checkstyle @hide */
public static long createNativeInterpolator(TimeInterpolator interpolator, long
duration) {
if (interpolator == null) {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6fb1bbabddc2..f17a45800aeb 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -22,7 +22,9 @@ import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.graphics.SurfaceTexture;
import android.os.Parcel;
import android.os.Parcelable;
@@ -889,7 +891,7 @@ public class Surface implements Parcelable {
private final class HwuiContext {
private final RenderNode mRenderNode;
private long mHwuiRenderer;
- private DisplayListCanvas mCanvas;
+ private RecordingCanvas mCanvas;
private final boolean mIsWideColorGamut;
HwuiContext(boolean isWideColorGamut) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index e71182c33c12..67f9399e678a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -30,6 +30,7 @@ import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.RenderNode;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index 35a886fa27a3..d89d634c6a25 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -31,7 +31,7 @@ import com.android.internal.util.VirtualRefBasePtr;
*
* @hide
*/
-final class TextureLayer {
+public final class TextureLayer {
private ThreadedRenderer mRenderer;
private VirtualRefBasePtr mFinalizer;
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 997e48fe61ac..0175ba201dd1 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -23,6 +23,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.Drawable;
@@ -343,7 +344,7 @@ public class TextureView extends View {
properties (alpha, layer paint) affect all of the content of a TextureView. */
if (canvas.isHardwareAccelerated()) {
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
TextureLayer layer = getTextureLayer();
if (layer != null) {
@@ -351,7 +352,7 @@ public class TextureView extends View {
applyTransformMatrix();
mLayer.setLayerPaint(mLayerPaint); // ensure layer paint is up to date
- displayListCanvas.drawTextureLayer(layer);
+ recordingCanvas.drawTextureLayer(layer);
}
}
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 42690cef9da3..c1ab4d4b895e 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -24,7 +24,9 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -693,7 +695,7 @@ public final class ThreadedRenderer {
updateViewTreeDisplayList(view);
if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
- DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+ RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
@@ -770,7 +772,7 @@ public final class ThreadedRenderer {
*
* @param canvas The Canvas used to render the view.
*/
- void onPreDraw(DisplayListCanvas canvas);
+ void onPreDraw(RecordingCanvas canvas);
/**
* Invoked after a view is drawn by a threaded renderer.
@@ -778,7 +780,7 @@ public final class ThreadedRenderer {
*
* @param canvas The Canvas used to render the view.
*/
- void onPostDraw(DisplayListCanvas canvas);
+ void onPostDraw(RecordingCanvas canvas);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cc58b8928f6e..c82918249531 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -57,9 +57,11 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
+import android.graphics.RenderNode;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -19233,7 +19235,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int height = mBottom - mTop;
int layerType = getLayerType();
- final DisplayListCanvas canvas = renderNode.start(width, height);
+ final RecordingCanvas canvas = renderNode.start(width, height);
try {
if (layerType == LAYER_TYPE_SOFTWARE) {
@@ -20250,7 +20252,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!drawingWithDrawingCache) {
if (drawingWithRenderNode) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
- ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
+ ((RecordingCanvas) canvas).drawRenderNode(renderNode);
} else {
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
@@ -20581,7 +20583,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final RenderNode renderNode = mBackgroundRenderNode;
if (renderNode != null && renderNode.isValid()) {
setBackgroundRenderNodeProperties(renderNode);
- ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
+ ((RecordingCanvas) canvas).drawRenderNode(renderNode);
return;
}
}
@@ -20633,7 +20635,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final Rect bounds = drawable.getBounds();
final int width = bounds.width();
final int height = bounds.height();
- final DisplayListCanvas canvas = renderNode.start(width, height);
+ final RecordingCanvas canvas = renderNode.start(width, height);
// Reverse left/top translation done by drawable canvas, which will
// instead be applied by rendernode's LTRB bounds below. This way, the
diff --git a/core/java/android/view/ViewAnimationHostBridge.java b/core/java/android/view/ViewAnimationHostBridge.java
index 58f555dfa305..e0fae21bbdf6 100644
--- a/core/java/android/view/ViewAnimationHostBridge.java
+++ b/core/java/android/view/ViewAnimationHostBridge.java
@@ -16,6 +16,8 @@
package android.view;
+import android.graphics.RenderNode;
+
/**
* Maps a View to a RenderNode's AnimationHost
*
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 8dd03476a2b8..292e933c3f7e 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -23,7 +23,9 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.os.Debug;
import android.os.Handler;
import android.os.RemoteException;
@@ -601,7 +603,7 @@ public class ViewDebug {
}
if (view.isHardwareAccelerated()) {
- DisplayListCanvas canvas = node.start(dm.widthPixels, dm.heightPixels);
+ RecordingCanvas canvas = node.start(dm.widthPixels, dm.heightPixels);
try {
return profileViewOperation(view, () -> view.draw(canvas));
} finally {
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index e3e2069422fc..a0ab362f3985 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -19,6 +19,7 @@ package android.view;
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.graphics.RenderNode;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bef8e8fedfdf..7da31ebe4a17 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -51,8 +51,10 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.RenderNode;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -3120,7 +3122,7 @@ public final class ViewRootImpl implements ViewParent,
int mHardwareYOffset;
@Override
- public void onPreDraw(DisplayListCanvas canvas) {
+ public void onPreDraw(RecordingCanvas canvas) {
// If mCurScrollY is not 0 then this influences the hardwareYOffset. The end result is we
// can apply offsets that are not handled by anything else, resulting in underdraw as
// the View is shifted (thus shifting the window background) exposing unpainted
@@ -3134,7 +3136,7 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void onPostDraw(DisplayListCanvas canvas) {
+ public void onPostDraw(RecordingCanvas canvas) {
drawAccessibilityFocusedDrawableIfNeeded(canvas);
if (mUseMTRenderer) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java
index b2dc1e91bdf7..a99730205136 100644
--- a/core/java/android/view/WindowCallbacks.java
+++ b/core/java/android/view/WindowCallbacks.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
/**
@@ -82,5 +83,5 @@ public interface WindowCallbacks {
*
* @param canvas The canvas to draw on.
*/
- void onPostDraw(DisplayListCanvas canvas);
+ void onPostDraw(RecordingCanvas canvas);
}
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index ba665713fb21..6ab7f66aedd3 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -27,11 +27,11 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.Trace;
import android.util.SparseArray;
-import android.view.DisplayListCanvas;
import android.view.View;
import android.view.ViewRootImpl;
@@ -107,12 +107,12 @@ public final class WebViewDelegate {
* @throws IllegalArgumentException if the canvas is not hardware accelerated
*/
public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
- if (!(canvas instanceof DisplayListCanvas)) {
+ if (!(canvas instanceof RecordingCanvas)) {
// Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas.
throw new IllegalArgumentException(canvas.getClass().getName()
+ " is not a DisplayList canvas");
}
- ((DisplayListCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, null);
+ ((RecordingCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, null);
}
/**
@@ -129,12 +129,12 @@ public final class WebViewDelegate {
*/
public void callDrawGlFunction(@NonNull Canvas canvas, long nativeDrawGLFunctor,
@Nullable Runnable releasedRunnable) {
- if (!(canvas instanceof DisplayListCanvas)) {
+ if (!(canvas instanceof RecordingCanvas)) {
// Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas.
throw new IllegalArgumentException(canvas.getClass().getName()
+ " is not a DisplayList canvas");
}
- ((DisplayListCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, releasedRunnable);
+ ((RecordingCanvas) canvas).drawGLFunctor2(nativeDrawGLFunctor, releasedRunnable);
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8027dd7cdb10..48c164f726bc 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -42,8 +42,10 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.RenderNode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -83,7 +85,6 @@ import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.ContextMenu;
import android.view.ContextThemeWrapper;
-import android.view.DisplayListCanvas;
import android.view.DragAndDropPermissions;
import android.view.DragEvent;
import android.view.Gravity;
@@ -93,7 +94,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import android.view.RenderNode;
import android.view.SubMenu;
import android.view.View;
import android.view.View.DragShadowBuilder;
@@ -1941,18 +1941,18 @@ public class Editor {
// Rebuild display list if it is invalid
if (blockDisplayListIsInvalid) {
- final DisplayListCanvas displayListCanvas = blockDisplayList.start(
+ final RecordingCanvas recordingCanvas = blockDisplayList.start(
right - left, bottom - top);
try {
// drawText is always relative to TextView's origin, this translation
// brings this range of text back to the top left corner of the viewport
- displayListCanvas.translate(-left, -top);
- layout.drawText(displayListCanvas, blockBeginLine, blockEndLine);
+ recordingCanvas.translate(-left, -top);
+ layout.drawText(recordingCanvas, blockBeginLine, blockEndLine);
mTextRenderNodes[blockIndex].isDirty = false;
// No need to untranslate, previous context is popped after
// drawDisplayList
} finally {
- blockDisplayList.end(displayListCanvas);
+ blockDisplayList.end(recordingCanvas);
// Same as drawDisplayList below, handled by our TextView's parent
blockDisplayList.setClipToBounds(false);
}
@@ -1962,7 +1962,7 @@ public class Editor {
blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
mTextRenderNodes[blockIndex].needsToBeShifted = false;
}
- ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList);
+ ((RecordingCanvas) canvas).drawRenderNode(blockDisplayList);
return startIndexToFindAvailableRenderNode;
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 16ddd0fc8247..6a3fc0fad4dd 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -33,15 +33,15 @@ import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.ContextThemeWrapper;
import android.view.Display;
-import android.view.DisplayListCanvas;
import android.view.PixelCopy;
-import android.view.RenderNode;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
@@ -704,7 +704,7 @@ public final class Magnifier {
cornerRadius
);
- final DisplayListCanvas canvas = mRenderer.getRootNode().start(width, height);
+ final RecordingCanvas canvas = mRenderer.getRootNode().start(width, height);
try {
canvas.insertReorderBarrier();
canvas.drawRenderNode(mBitmapRenderNode);
@@ -736,7 +736,7 @@ public final class Magnifier {
bitmapRenderNode.setClipToOutline(true);
// Create a dummy draw, which will be replaced later with real drawing.
- final DisplayListCanvas canvas = bitmapRenderNode.start(mContentWidth, mContentHeight);
+ final RecordingCanvas canvas = bitmapRenderNode.start(mContentWidth, mContentHeight);
try {
canvas.drawColor(0xFF00FF00);
} finally {
@@ -817,7 +817,7 @@ public final class Magnifier {
return;
}
- final DisplayListCanvas canvas =
+ final RecordingCanvas canvas =
mBitmapRenderNode.start(mContentWidth, mContentHeight);
try {
canvas.drawColor(Color.WHITE);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index a70209c705c0..f14007bd7ac6 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -16,13 +16,13 @@
package com.android.internal.policy;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.view.Choreographer;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import android.view.ThreadedRenderer;
/**
@@ -339,7 +339,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
// Draw the caption and content backdrops in to our render node.
- DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
+ RecordingCanvas canvas = mFrameAndBackdropNode.start(width, height);
final Drawable drawable = mUserCaptionBackgroundDrawable != null
? mUserCaptionBackgroundDrawable : mCaptionBackgroundDrawable;
@@ -368,7 +368,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
if (mSystemBarBackgroundNode == null) {
return;
}
- DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
+ RecordingCanvas canvas = mSystemBarBackgroundNode.start(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
if (mStatusBarColor != null) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 469726613513..94140ab7f440 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -16,52 +16,60 @@
package com.android.internal.policy;
-import android.annotation.Nullable;
-import android.annotation.TestApi;
-import android.app.WindowConfiguration;
-import android.graphics.Outline;
-import android.graphics.drawable.InsetDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.util.Pair;
-import android.view.ViewOutlineProvider;
-import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.internal.R;
-import com.android.internal.policy.PhoneWindow.PanelFeatureState;
-import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
-import com.android.internal.view.FloatingActionMode;
-import com.android.internal.view.RootViewSurfaceTaker;
-import com.android.internal.view.StandaloneActionMode;
-import com.android.internal.view.menu.ContextMenuBuilder;
-import com.android.internal.view.menu.MenuHelper;
-import com.android.internal.widget.ActionBarContextView;
-import com.android.internal.widget.BackgroundFallback;
-import com.android.internal.widget.DecorCaptionView;
-import com.android.internal.widget.FloatingToolbar;
+import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.N;
+import static android.view.View.MeasureSpec.AT_MOST;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.getMode;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.Window.DECOR_CAPTION_SHADE_DARK;
+import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
-import java.util.List;
+import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.app.WindowConfiguration;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
+import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.graphics.drawable.LayerDrawable;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
-import android.view.DisplayListCanvas;
import android.view.Gravity;
import android.view.InputQueue;
import android.view.KeyEvent;
@@ -73,6 +81,7 @@ import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.Window;
@@ -81,34 +90,26 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
-import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.os.Build.VERSION_CODES.M;
-import static android.os.Build.VERSION_CODES.N;
-import static android.view.View.MeasureSpec.AT_MOST;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.getMode;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.Window.DECOR_CAPTION_SHADE_DARK;
-import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
-import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
-import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
+import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow.PanelFeatureState;
+import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
+import com.android.internal.view.FloatingActionMode;
+import com.android.internal.view.RootViewSurfaceTaker;
+import com.android.internal.view.StandaloneActionMode;
+import com.android.internal.view.menu.ContextMenuBuilder;
+import com.android.internal.view.menu.MenuHelper;
+import com.android.internal.widget.ActionBarContextView;
+import com.android.internal.widget.BackgroundFallback;
+import com.android.internal.widget.DecorCaptionView;
+import com.android.internal.widget.FloatingToolbar;
+
+import java.util.List;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -2134,7 +2135,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
@Override
- public void onPostDraw(DisplayListCanvas canvas) {
+ public void onPostDraw(RecordingCanvas canvas) {
drawResizingShadowIfNeeded(canvas);
}
@@ -2152,7 +2153,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
new float[] { 0f, 0.3f, 1f }, Shader.TileMode.CLAMP));
}
- private void drawResizingShadowIfNeeded(DisplayListCanvas canvas) {
+ private void drawResizingShadowIfNeeded(RecordingCanvas canvas) {
if (mResizeMode != RESIZE_MODE_DOCKED_DIVIDER || mWindow.mIsFloating
|| mWindow.isTranslucent()
|| mWindow.isShowingWallpaper()) {
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 367b713ed78f..794238a3826e 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -29,10 +29,8 @@ import android.view.inputmethod.ExtractedText;
* {@hide}
*/
oneway interface IInputMethodSession {
- void finishInput();
-
void updateExtractedText(int token, in ExtractedText text);
-
+
void updateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
int candidatesStart, int candidatesEnd);
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 9263b579ee02..97896f0f6028 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -24,23 +24,21 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
-import android.graphics.drawable.Drawable;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.IntArray;
import android.util.Log;
import android.util.SparseArray;
-import android.view.DisplayListCanvas;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.RenderNodeAnimator;
@@ -1131,8 +1129,8 @@ public class LockPatternView extends View {
drawCellDrawable(canvas, i, j, cellState.radius, drawLookup[i][j]);
} else {
if (isHardwareAccelerated() && cellState.hwAnimating) {
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
- displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
cellState.hwRadius, cellState.hwPaint);
} else {
drawCircle(canvas, (int) centerX, (int) centerY + translationY,
diff --git a/core/jni/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
index 4a30babafa49..b52f137da7d6 100644
--- a/core/jni/android_opengl_EGL15.cpp
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -456,27 +456,41 @@ exit:
static jobject
android_eglCreatePlatformPixmapSurface
(JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_pixmap_buf, jlongArray attrib_list_ref, jint offset) {
+ jniThrowException(_env, "java/lang/UnsupportedOperationException",
+ "eglCreatePlatformPixmapSurface");
+ return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
+}
+
+/* EGLBoolean eglWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags ) */
+static jboolean
+android_eglWaitSync
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint flags) {
+ EGLBoolean _returnValue = (EGLBoolean) 0;
+ EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+ EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+
+ _returnValue = eglWaitSync(
+ (EGLDisplay)dpy_native,
+ (EGLSync)sync_native,
+ (EGLint)flags
+ );
+ return (jboolean)_returnValue;
+}
+
+/* EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateImage
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject context, jint target, jlong buffer, jlongArray attrib_list_ref, jint offset) {
jint _exception = 0;
const char * _exceptionType = NULL;
const char * _exceptionMessage = NULL;
- jarray _array = (jarray) 0;
- jint _bufferOffset = (jint) 0;
- EGLSurface _returnValue = (EGLSurface) 0;
+ EGLImage _returnValue = (EGLImage) 0;
EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
- EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
- jint _native_pixmapRemaining;
- void *native_pixmap = (void *) 0;
+ EGLContext context_native = (EGLContext) fromEGLHandle(_env, eglcontextGetHandleID, context);
EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
- jint _attrib_listRemaining;
+ jint _remaining;
EGLAttrib *attrib_list = (EGLAttrib *) 0;
- if (!native_pixmap_buf) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "native_pixmap == null";
- goto exit;
- }
- native_pixmap = (void *)getPointer(_env, native_pixmap_buf, (jarray*)&_array, &_native_pixmapRemaining, &_bufferOffset);
if (!attrib_list_ref) {
_exception = 1;
_exceptionType = "java/lang/IllegalArgumentException";
@@ -489,19 +503,16 @@ android_eglCreatePlatformPixmapSurface
_exceptionMessage = "offset < 0";
goto exit;
}
- _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - offset;
+ _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
attrib_list_base = (EGLAttrib *)
_env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
attrib_list = attrib_list_base + offset;
- if (native_pixmap == NULL) {
- char * _native_pixmapBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
- native_pixmap = (void *) (_native_pixmapBase + _bufferOffset);
- }
- _returnValue = eglCreatePlatformPixmapSurface(
+ _returnValue = eglCreateImage(
(EGLDisplay)dpy_native,
- (EGLConfig)config_native,
- (void *)native_pixmap,
+ (EGLContext)context_native,
+ (EGLenum)target,
+ (EGLClientBuffer)buffer,
(EGLAttrib *)attrib_list
);
@@ -510,27 +521,23 @@ exit:
_env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
JNI_ABORT);
}
- if (_array) {
- releasePointer(_env, _array, native_pixmap, _exception ? JNI_FALSE : JNI_TRUE);
- }
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
}
- return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+ return toEGLHandle(_env, eglimageClass, eglimageConstructor, _returnValue);
}
-/* EGLBoolean eglWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags ) */
+/* EGLBoolean eglDestroyImage ( EGLDisplay dpy, EGLImage image ) */
static jboolean
-android_eglWaitSync
- (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint flags) {
+android_eglDestroyImage
+ (JNIEnv *_env, jobject _this, jobject dpy, jobject image) {
EGLBoolean _returnValue = (EGLBoolean) 0;
EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
- EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+ EGLImage image_native = (EGLImage) fromEGLHandle(_env, eglimageGetHandleID, image);
- _returnValue = eglWaitSync(
+ _returnValue = eglDestroyImage(
(EGLDisplay)dpy_native,
- (EGLSync)sync_native,
- (EGLint)flags
+ (EGLImage)image_native
);
return (jboolean)_returnValue;
}
@@ -547,6 +554,8 @@ static const JNINativeMethod methods[] = {
{"eglCreatePlatformWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformWindowSurface },
{"eglCreatePlatformPixmapSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformPixmapSurface },
{"eglWaitSync", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;I)Z", (void *) android_eglWaitSync },
+{"eglCreateImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLContext;IJ[JI)Landroid/opengl/EGLImage;", (void *) android_eglCreateImage },
+{"eglDestroyImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLImage;)Z", (void *) android_eglDestroyImage },
};
int register_android_opengl_jni_EGL15(JNIEnv *_env)
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 4fdd2bcd4f39..8998cd706dd8 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -183,7 +183,7 @@ static void android_view_DisplayListCanvas_drawCircleProps(jlong canvasPtr,
// JNI Glue
// ----------------------------------------------------------------------------
-const char* const kClassPathName = "android/view/DisplayListCanvas";
+const char* const kClassPathName = "android/graphics/RecordingCanvas";
static JNINativeMethod gMethods[] = {
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 63b004681df9..bb71a5d4accf 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -576,7 +576,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
// JNI Glue
// ----------------------------------------------------------------------------
-const char* const kClassPathName = "android/view/RenderNode";
+const char* const kClassPathName = "android/graphics/RenderNode";
static const JNINativeMethod gMethods[] = {
// ----------------------------------------------------------------------------
@@ -588,7 +588,7 @@ static const JNINativeMethod gMethods[] = {
{ "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize },
{ "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
{ "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
- { "nRequestPositionUpdates", "(JLandroid/view/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
+ { "nRequestPositionUpdates", "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
{ "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
@@ -677,7 +677,7 @@ static const JNINativeMethod gMethods[] = {
};
int register_android_view_RenderNode(JNIEnv* env) {
- jclass clazz = FindClassOrDie(env, "android/view/RenderNode$PositionUpdateListener");
+ jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
"positionChanged", "(JIIII)V");
gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9bedab53bb2c..32cf2e8bac86 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7894,6 +7894,9 @@
<!-- Wallpapers optimized and capable of drawing in ambient mode will return true. -->
<attr name="supportsAmbientMode" format="boolean" />
+ <!-- Uri that specifies a settings Slice for this wallpaper. -->
+ <attr name="settingsSliceUri" />
+
</declare-styleable>
<!-- Use <code>dream</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 31212a6ab28f..fd688a72b7ea 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2916,6 +2916,7 @@
<public name="isLightTheme" />
<public name="isSplitRequired" />
<public name="textLocale" />
+ <public name="settingsSliceUri" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
index 1097bc731de8..01382aae923e 100644
--- a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
+++ b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
@@ -17,14 +17,9 @@
package android.content.pm;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import android.content.Context;
import android.os.FileUtils;
-import android.os.Process;
import android.os.ServiceManager;
import android.os.UserManager;
import android.support.test.InstrumentationRegistry;
@@ -32,7 +27,6 @@ import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -86,12 +80,23 @@ public class KernelPackageMappingTests {
}
@Test
+ public void testSharedInstalledPrimary() throws Exception {
+ assertEquals("1001", getContent(getKernelPackageFile("shared:android.uid.phone", "appid")));
+ }
+
+ @Test
public void testInstalledAll() throws Exception {
assertEquals("", getContent(getKernelPackageFile("com.android.settings",
"excluded_userids")));
}
@Test
+ public void testSharedInstalledAll() throws Exception {
+ assertEquals("", getContent(getKernelPackageFile("shared:android.uid.phone",
+ "excluded_userids")));
+ }
+
+ @Test
public void testNotInstalledSecondary() throws Exception {
mSecondaryUser = getUserManager().createUser("Secondary", 0);
assertEquals(Integer.toString(mSecondaryUser.id),
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 44f8737da2c1..28e92dbe264a 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -146,6 +146,7 @@ applications that come with the platform
<permission name="android.permission.CLEAR_APP_CACHE"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
+ <permission name="android.permission.GET_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
</privapp-permissions>
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index ea0a109c3a04..3db240b54299 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -83,7 +83,7 @@ public abstract class BaseCanvas {
// ---------------------------------------------------------------------------
// Drawing methods
- // These are also implemented in DisplayListCanvas so that we can
+ // These are also implemented in RecordingCanvas so that we can
// selectively apply on them
// Everything below here is copy/pasted from Canvas.java
// The JNI registration is handled by android_view_Canvas.cpp
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 1cd756f9f73f..364fb04e57b1 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -31,8 +31,6 @@ import android.os.StrictMode;
import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import android.view.ThreadedRenderer;
import dalvik.annotation.optimization.CriticalNative;
@@ -1297,7 +1295,7 @@ public final class Bitmap implements Parcelable {
node.setLeftTopRightBottom(0, 0, width, height);
node.setClipToBounds(false);
node.setAllowForceDark(false);
- final DisplayListCanvas canvas = node.start(width, height);
+ final RecordingCanvas canvas = node.start(width, height);
if (source.getWidth() != width || source.getHeight() != height) {
canvas.scale(width / (float) source.getWidth(),
height / (float) source.getHeight());
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index f7acb11c8811..f6d801b3ba43 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -17,6 +17,7 @@
package android.graphics;
import android.annotation.UnsupportedAppUsage;
+
import java.io.InputStream;
import java.io.OutputStream;
@@ -216,7 +217,7 @@ public class Picture {
public PictureCanvas(Picture pict, long nativeCanvas) {
super(nativeCanvas);
mPicture = pict;
- // Disable bitmap density scaling. This matches DisplayListCanvas.
+ // Disable bitmap density scaling. This matches RecordingCanvas.
mDensity = 0;
}
diff --git a/core/java/android/view/DisplayListCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 667fab5537c9..7af006b4bdf0 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -14,47 +14,47 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
-import android.graphics.BaseRecordingCanvas;
-import android.graphics.Bitmap;
-import android.graphics.CanvasProperty;
-import android.graphics.Paint;
import android.util.Pools.SynchronizedPool;
+import android.view.TextureLayer;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
/**
* A Canvas implementation that records view system drawing operations for deferred rendering.
- * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
+ * This is intended for use with RenderNode. This class keeps a list of all the Paint and
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
- * the DisplayList is still holding a native reference to the memory.
+ * the RecordingCanvas is still holding a native reference to the memory.
*
* @hide
*/
-public final class DisplayListCanvas extends BaseRecordingCanvas {
+public final class RecordingCanvas extends BaseRecordingCanvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
public static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
- private static final SynchronizedPool<DisplayListCanvas> sPool =
+ private static final SynchronizedPool<RecordingCanvas> sPool =
new SynchronizedPool<>(POOL_LIMIT);
- RenderNode mNode;
+ /**
+ * TODO: Temporarily exposed for RenderNodeAnimator(Set)
+ * @hide */
+ public RenderNode mNode;
private int mWidth;
private int mHeight;
- static DisplayListCanvas obtain(@NonNull RenderNode node, int width, int height) {
+ static RecordingCanvas obtain(@NonNull RenderNode node, int width, int height) {
if (node == null) throw new IllegalArgumentException("node cannot be null");
- DisplayListCanvas canvas = sPool.acquire();
+ RecordingCanvas canvas = sPool.acquire();
if (canvas == null) {
- canvas = new DisplayListCanvas(node, width, height);
+ canvas = new RecordingCanvas(node, width, height);
} else {
nResetDisplayListCanvas(canvas.mNativeCanvasWrapper, node.mNativeRenderNode,
width, height);
@@ -83,7 +83,7 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
// Constructors
///////////////////////////////////////////////////////////////////////////
- private DisplayListCanvas(@NonNull RenderNode node, int width, int height) {
+ private RecordingCanvas(@NonNull RenderNode node, int width, int height) {
super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
mDensity = 0; // disable bitmap density scaling
}
@@ -95,7 +95,7 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
@Override
public void setDensity(int density) {
- // drop silently, since DisplayListCanvas doesn't perform density scaling
+ // drop silently, since RecordingCanvas doesn't perform density scaling
}
@Override
@@ -156,6 +156,8 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
* functionality used by webview for calling into their renderer from our display lists.
*
* @param drawGLFunction A native function pointer
+ *
+ * @hide
*/
@UnsupportedAppUsage
public void callDrawGLFunction2(long drawGLFunction) {
@@ -166,13 +168,15 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
* Records the functor specified with the drawGLFunction function pointer. This is
* functionality used by webview for calling into their renderer from our display lists.
*
- * @param drawGLFunction A native function pointer
+ * @param drawGLFunctor A native function pointer
* @param releasedCallback Called when the display list is destroyed, and thus
* the functor is no longer referenced by this canvas's display list.
*
* NOTE: The callback does *not* necessarily mean that there are no longer
* any references to the functor, just that the reference from this specific
* canvas's display list has been released.
+ *
+ * @hide
*/
@UnsupportedAppUsage
public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
@@ -201,8 +205,9 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
* Draws the specified layer onto this canvas.
*
* @param layer The layer to composite on this canvas
+ * @hide
*/
- void drawTextureLayer(TextureLayer layer) {
+ public void drawTextureLayer(TextureLayer layer) {
nDrawTextureLayer(mNativeCanvasWrapper, layer.getLayerHandle());
}
@@ -210,6 +215,16 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
// Drawing
///////////////////////////////////////////////////////////////////////////
+ /**
+ * Draws a circle
+ *
+ * @param cx
+ * @param cy
+ * @param radius
+ * @param paint
+ *
+ * @hide
+ */
@UnsupportedAppUsage
public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
@@ -217,6 +232,19 @@ public final class DisplayListCanvas extends BaseRecordingCanvas {
radius.getNativeContainer(), paint.getNativeContainer());
}
+ /**
+ * Draws a round rect
+ *
+ * @param left
+ * @param top
+ * @param right
+ * @param bottom
+ * @param rx
+ * @param ry
+ * @param paint
+ *
+ * @hide
+ */
public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
diff --git a/core/java/android/view/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 8ae912762fdb..60641d82cb65 100644
--- a/core/java/android/view/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
-import android.graphics.Matrix;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Rect;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.RenderNodeAnimator;
+import android.view.View;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -36,7 +35,7 @@ import java.lang.annotation.RetentionPolicy;
/**
* <p>A display list records a series of graphics related operations and can replay
* them later. Display lists are usually built by recording operations on a
- * {@link DisplayListCanvas}. Replaying the operations from a display list avoids
+ * {@link RecordingCanvas}. Replaying the operations from a display list avoids
* executing application code on every frame, and is thus much more efficient.</p>
*
* <p>Display lists are used internally for all views by default, and are not
@@ -53,7 +52,7 @@ import java.lang.annotation.RetentionPolicy;
* affected paragraph needs to be recorded again.</p>
*
* <h3>Hardware acceleration</h3>
- * <p>Display lists can only be replayed using a {@link DisplayListCanvas}. They are not
+ * <p>Display lists can only be replayed using a {@link RecordingCanvas}. They are not
* supported in software. Always make sure that the {@link android.graphics.Canvas}
* you are using to render a display list is hardware accelerated using
* {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
@@ -63,7 +62,7 @@ import java.lang.annotation.RetentionPolicy;
* ThreadedRenderer renderer = myView.getThreadedRenderer();
* if (renderer != null) {
* DisplayList displayList = renderer.createDisplayList();
- * DisplayListCanvas canvas = displayList.start(width, height);
+ * RecordingCanvas canvas = displayList.start(width, height);
* try {
* // Draw onto the canvas
* // For instance: canvas.drawBitmap(...);
@@ -77,7 +76,7 @@ import java.lang.annotation.RetentionPolicy;
* <pre class="prettyprint">
* protected void onDraw(Canvas canvas) {
* if (canvas.isHardwareAccelerated()) {
- * DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ * RecordingCanvas displayListCanvas = (RecordingCanvas) canvas;
* displayListCanvas.drawDisplayList(mDisplayList);
* }
* }
@@ -102,7 +101,7 @@ import java.lang.annotation.RetentionPolicy;
* <pre class="prettyprint">
* private void createDisplayList() {
* mDisplayList = DisplayList.create("MyDisplayList");
- * DisplayListCanvas canvas = mDisplayList.start(width, height);
+ * RecordingCanvas canvas = mDisplayList.start(width, height);
* try {
* for (Bitmap b : mBitmaps) {
* canvas.drawBitmap(b, 0.0f, 0.0f, null);
@@ -115,7 +114,7 @@ import java.lang.annotation.RetentionPolicy;
*
* protected void onDraw(Canvas canvas) {
* if (canvas.isHardwareAccelerated()) {
- * DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ * RecordingCanvas displayListCanvas = (RecordingCanvas) canvas;
* displayListCanvas.drawDisplayList(mDisplayList);
* }
* }
@@ -143,10 +142,10 @@ public class RenderNode {
RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024);
}
- /** Not for general use; use only if you are ThreadedRenderer or DisplayListCanvas.
+ /** Not for general use; use only if you are ThreadedRenderer or RecordingCanvas.
* @hide
*/
- final long mNativeRenderNode;
+ public final long mNativeRenderNode;
private final AnimationHost mAnimationHost;
private RenderNode(String name, AnimationHost animationHost) {
@@ -195,7 +194,7 @@ public class RenderNode {
*
* @hide
*/
- interface PositionUpdateListener {
+ public interface PositionUpdateListener {
/**
* Called by native by a Rendering Worker thread to update window position
@@ -228,7 +227,7 @@ public class RenderNode {
* stored in this display list.
*
* Calling this method will mark the render node invalid until
- * {@link #end(DisplayListCanvas)} is called.
+ * {@link #end(RecordingCanvas)} is called.
* Only valid render nodes can be replayed.
*
* @param width The width of the recording viewport
@@ -236,19 +235,19 @@ public class RenderNode {
*
* @return A canvas to record drawing operations.
*
- * @see #end(DisplayListCanvas)
+ * @see #end(RecordingCanvas)
* @see #isValid()
*/
@UnsupportedAppUsage
- public DisplayListCanvas start(int width, int height) {
- return DisplayListCanvas.obtain(this, width, height);
+ public RecordingCanvas start(int width, int height) {
+ return RecordingCanvas.obtain(this, width, height);
}
/**
* Same as {@link #start(int, int)} but with the RenderNode's width & height
*/
- public DisplayListCanvas start() {
- return DisplayListCanvas.obtain(this,
+ public RecordingCanvas start() {
+ return RecordingCanvas.obtain(this,
nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
}
@@ -261,7 +260,7 @@ public class RenderNode {
* @see #isValid()
*/
@UnsupportedAppUsage
- public void end(DisplayListCanvas canvas) {
+ public void end(RecordingCanvas canvas) {
long displayList = canvas.finishRecording();
nSetDisplayList(mNativeRenderNode, displayList);
canvas.recycle();
@@ -292,14 +291,32 @@ public class RenderNode {
// Matrix manipulation
///////////////////////////////////////////////////////////////////////////
+ /**
+ * Whether or not the RenderNode has an identity transform. This is a faster
+ * way to do the otherwise equivalent {@link #getMatrix(Matrix)} {@link Matrix#isIdentity()}
+ * as it doesn't require copying the Matrix first, thus minimizing overhead.
+ *
+ * @return true if the RenderNode has an identity transform, false otherwise
+ */
public boolean hasIdentityMatrix() {
return nHasIdentityMatrix(mNativeRenderNode);
}
+ /**
+ * Gets the current transform matrix
+ *
+ * @param outMatrix The matrix to store the transform of the RenderNode
+ */
public void getMatrix(@NonNull Matrix outMatrix) {
nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
}
+ /**
+ * Gets the current transform inverted. This is a faster way to do the otherwise
+ * equivalent {@link #getMatrix(Matrix)} followed by {@link Matrix#invert(Matrix)}
+ *
+ * @param outMatrix The matrix to store the inverse transform of the RenderNode
+ */
public void getInverseMatrix(@NonNull Matrix outMatrix) {
nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
}
@@ -308,14 +325,25 @@ public class RenderNode {
// RenderProperty Setters
///////////////////////////////////////////////////////////////////////////
+ /**
+ * TODO
+ */
public boolean setLayerType(int layerType) {
return nSetLayerType(mNativeRenderNode, layerType);
}
+ /**
+ * TODO
+ */
public boolean setLayerPaint(@Nullable Paint paint) {
return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0);
}
+ /**
+ * Sets the clip bounds of the RenderNode.
+ * @param rect the bounds to clip to. If null, the clip bounds are reset
+ * @return True if the clip bounds changed, false otherwise
+ */
public boolean setClipBounds(@Nullable Rect rect) {
if (rect == null) {
return nSetClipBoundsEmpty(mNativeRenderNode);
@@ -371,8 +399,10 @@ public class RenderNode {
case Outline.MODE_EMPTY:
return nSetOutlineEmpty(mNativeRenderNode);
case Outline.MODE_ROUND_RECT:
- return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
- outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
+ return nSetOutlineRoundRect(mNativeRenderNode,
+ outline.mRect.left, outline.mRect.top,
+ outline.mRect.right, outline.mRect.bottom,
+ outline.mRadius, outline.mAlpha);
case Outline.MODE_CONVEX_PATH:
return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
outline.mAlpha);
@@ -381,6 +411,9 @@ public class RenderNode {
throw new IllegalArgumentException("Unrecognized outline?");
}
+ /**
+ * @return True if this RenderNode has a shadow, false otherwise
+ */
public boolean hasShadow() {
return nHasShadow(mNativeRenderNode);
}
@@ -414,6 +447,11 @@ public class RenderNode {
return nSetClipToOutline(mNativeRenderNode, clipToOutline);
}
+ /**
+ * See {@link #setClipToOutline(boolean)}
+ *
+ * @return True if this RenderNode clips to its outline, false otherwise
+ */
public boolean getClipToOutline() {
return nGetClipToOutline(mNativeRenderNode);
}
@@ -518,10 +556,21 @@ public class RenderNode {
return nHasOverlappingRendering(mNativeRenderNode);
}
+ /**
+ * Sets the base elevation of this RenderNode in pixels
+ *
+ * @param lift the elevation in pixels
+ * @return true if the elevation changed, false if it was the same
+ */
public boolean setElevation(float lift) {
return nSetElevation(mNativeRenderNode, lift);
}
+ /**
+ * See {@link #setElevation(float)}
+ *
+ * @return The RenderNode's current elevation
+ */
public float getElevation() {
return nGetElevation(mNativeRenderNode);
}
@@ -906,9 +955,12 @@ public class RenderNode {
* bit of a kludge.
*
* @hide */
- interface AnimationHost {
+ public interface AnimationHost {
+ /** checkstyle */
void registerAnimatingRenderNode(RenderNode animator);
+ /** checkstyle */
void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator);
+ /** checkstyle */
boolean isAttached();
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 6c1372ff25b4..789e38c4e650 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -39,7 +39,9 @@ import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.os.Build;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -50,9 +52,7 @@ import android.util.PathParser;
import android.util.Property;
import android.util.TimeUtils;
import android.view.Choreographer;
-import android.view.DisplayListCanvas;
import android.view.NativeVectorDrawableAnimator;
-import android.view.RenderNode;
import android.view.RenderNodeAnimatorSetHelper;
import android.view.View;
@@ -1542,11 +1542,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
}
/**
- * Holds a weak reference to the target that was last seen (through the DisplayListCanvas
+ * Holds a weak reference to the target that was last seen (through the RecordingCanvas
* in the last draw call), so that when animator set needs to start, we can add the animator
* to the last seen RenderNode target and start right away.
*/
- protected void recordLastSeenTarget(DisplayListCanvas canvas) {
+ protected void recordLastSeenTarget(RecordingCanvas canvas) {
final RenderNode node = RenderNodeAnimatorSetHelper.getTarget(canvas);
mLastSeenTarget = new WeakReference<RenderNode>(node);
// Add the animator to the list of animators on every draw
@@ -1742,7 +1742,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
@Override
public void onDraw(Canvas canvas) {
if (canvas.isHardwareAccelerated()) {
- recordLastSeenTarget((DisplayListCanvas) canvas);
+ recordLastSeenTarget((RecordingCanvas) canvas);
}
}
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index 626bcee9454b..c1f8798faaeb 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -16,15 +16,8 @@
package android.graphics.drawable;
-import android.animation.Animator;
-import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
-import android.view.DisplayListCanvas;
-import android.view.RenderNodeAnimator;
-
-import java.util.ArrayList;
/**
* Abstract class that handles size & positioning common to the ripple & focus states.
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index a8dc34af292b..cce9ba31929f 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -23,10 +23,10 @@ import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.util.FloatProperty;
import android.util.MathUtils;
-import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
@@ -132,7 +132,7 @@ class RippleForeground extends RippleComponent {
}
}
- private void startPending(DisplayListCanvas c) {
+ private void startPending(RecordingCanvas c) {
if (!mPendingHwAnimators.isEmpty()) {
for (int i = 0; i < mPendingHwAnimators.size(); i++) {
RenderNodeAnimator animator = mPendingHwAnimators.get(i);
@@ -164,7 +164,7 @@ class RippleForeground extends RippleComponent {
}
}
- private void drawHardware(DisplayListCanvas c, Paint p) {
+ private void drawHardware(RecordingCanvas c, Paint p) {
startPending(c);
pruneHwFinished();
if (mPropPaint != null) {
@@ -332,11 +332,11 @@ class RippleForeground extends RippleComponent {
* @param p the paint used to draw the ripple
*/
public void draw(Canvas c, Paint p) {
- final boolean hasDisplayListCanvas = !mForceSoftware && c instanceof DisplayListCanvas;
+ final boolean hasDisplayListCanvas = !mForceSoftware && c instanceof RecordingCanvas;
pruneSwFinished();
if (hasDisplayListCanvas) {
- final DisplayListCanvas hw = (DisplayListCanvas) c;
+ final RecordingCanvas hw = (RecordingCanvas) c;
drawHardware(hw, p);
} else {
drawSoftware(c, p);
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 503951d1adc6..f0053a48ae3d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -231,6 +231,9 @@ cc_defaults {
"protos/graphicsstats.proto",
],
+ // Allow implicit fallthroughs in HardwareBitmapUploader.cpp until they are fixed.
+ cflags: ["-Wno-implicit-fallthrough"],
+
proto: {
export_proto_headers: true,
},
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 3ca0f8139c02..13d2dae8e281 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -71,15 +71,12 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
paint.setAlpha(layer->getAlpha());
paint.setBlendMode(layer->getMode());
paint.setColorFilter(layer->getColorSpaceWithFilter());
- if (layer->getForceFilter()) {
- paint.setFilterQuality(kLow_SkFilterQuality);
- }
-
const bool nonIdentityMatrix = !matrix.isIdentity();
if (nonIdentityMatrix) {
canvas->save();
canvas->concat(matrix);
}
+ const SkMatrix& totalMatrix = canvas->getTotalMatrix();
if (dstRect || srcRect) {
SkMatrix matrixInv;
if (!matrix.invert(&matrixInv)) {
@@ -99,9 +96,28 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
}
matrixInv.mapRect(&skiaDestRect);
+ // If (matrix is identity or an integer translation) and (src/dst buffers size match),
+ // then use nearest neighbor, otherwise use bilerp sampling.
+ // Integer translation is defined as when src rect and dst rect align fractionally.
+ // Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
+ // only for SrcOver blending and without color filter (readback uses Src blending).
+ bool isIntegerTranslate = totalMatrix.isTranslate()
+ && SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX])
+ == SkScalarFraction(skiaSrcRect.fLeft)
+ && SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY])
+ == SkScalarFraction(skiaSrcRect.fTop);
+ if (layer->getForceFilter() || !isIntegerTranslate) {
+ paint.setFilterQuality(kLow_SkFilterQuality);
+ }
canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, &paint,
SkCanvas::kFast_SrcRectConstraint);
} else {
+ bool isIntegerTranslate = totalMatrix.isTranslate()
+ && SkScalarIsInt(totalMatrix[SkMatrix::kMTransX])
+ && SkScalarIsInt(totalMatrix[SkMatrix::kMTransY]);
+ if (layer->getForceFilter() || !isIntegerTranslate) {
+ paint.setFilterQuality(kLow_SkFilterQuality);
+ }
canvas->drawImage(layerImage.get(), 0, 0, &paint);
}
// restore the original matrix
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index e3c97ce686d9..524dfb0fe4ef 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -288,7 +288,7 @@ void parseOptions(int argc, char* argv[]) {
case '?':
fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
- // fall-through
+ [[fallthrough]];
default:
error = true;
break;
diff --git a/opengl/java/android/opengl/EGL15.java b/opengl/java/android/opengl/EGL15.java
index 9aae6ad0f080..f855fe2591e1 100644
--- a/opengl/java/android/opengl/EGL15.java
+++ b/opengl/java/android/opengl/EGL15.java
@@ -146,4 +146,22 @@ public class EGL15 {
int flags
);
+ // C function EGLImage eglCreateImage ( EGLDisplay dpy, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list )
+
+ public static native EGLImage eglCreateImage(
+ EGLDisplay dpy,
+ EGLContext context,
+ int target,
+ long buffer,
+ long[] attrib_list,
+ int offset
+ );
+
+ // C function EGLBoolean eglDestroyImage ( EGLDisplay dpy, EGLImage image )
+
+ public static native boolean eglDestroyImage(
+ EGLDisplay dpy,
+ EGLImage image
+ );
+
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index b58ea00997ef..f4922088bb05 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -14,6 +14,7 @@
package com.android.systemui.plugins;
+import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Intent;
@@ -36,7 +37,17 @@ public interface ActivityStarter {
void postStartActivityDismissingKeyguard(PendingIntent intent);
void postQSRunnableDismissingKeyguard(Runnable runnable);
+ void dismissKeyguardThenExecute(OnDismissAction action, @Nullable Runnable cancel,
+ boolean afterKeyguardGone);
+
interface Callback {
void onActivityStarted(int resultCode);
}
+
+ interface OnDismissAction {
+ /**
+ * @return {@code true} if the dismiss should be deferred
+ */
+ boolean onDismiss();
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
index 19e8673fba89..114d69e35e39 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
@@ -27,6 +27,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Background task resource loader
*/
+@Deprecated
class BackgroundTaskLoader implements Runnable {
static String TAG = "BackgroundTaskLoader";
static boolean DEBUG = false;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java
index 898d64a1ea1a..7e0f8fe2e033 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java
@@ -27,6 +27,7 @@ import java.util.List;
/**
* A list of filtered tasks.
*/
+@Deprecated
class FilteredTaskList {
private final ArrayList<Task> mTasks = new ArrayList<>();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
index 852463ffc188..f02bc5ab15e1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
/**
* Loader class that loads full-resolution thumbnails when appropriate.
*/
+@Deprecated
public class HighResThumbnailLoader implements
TaskCallbacks, BackgroundTaskLoader.OnIdleChangedListener {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
index f69e91145dfc..8b3ae42ef479 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
@@ -45,6 +45,7 @@ import java.util.List;
* 3) executePlan() will actually load and fill in the icons and thumbnails according to the load
* options specified, such that we can transition into the Recents activity seamlessly
*/
+@Deprecated
public class RecentsTaskLoadPlan {
/** The set of conditions to preload tasks. */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
index 996c837ba121..b50aa76e1d0d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
@@ -42,6 +42,7 @@ import java.util.Map;
/**
* Recents task loader
*/
+@Deprecated
public class RecentsTaskLoader {
private static final String TAG = "RecentsTaskLoader";
private static final boolean DEBUG = false;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index b51004bf6d56..368e50362cd6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.recents.model;
+import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.content.ComponentName;
import android.content.Intent;
@@ -31,13 +32,14 @@ import java.util.ArrayList;
import java.util.Objects;
/**
- * A task represents the top most task in the system's task stack.
+ * A task in the recent tasks list.
*/
public class Task {
public static final String TAG = "Task";
/* Task callbacks */
+ @Deprecated
public interface TaskCallbacks {
/* Notifies when a task has been bound */
void onTaskDataLoaded(Task task, ThumbnailData thumbnailData);
@@ -65,6 +67,21 @@ public class Task {
private int mHashCode;
+ public TaskKey(ActivityManager.RecentTaskInfo t) {
+ ComponentName sourceComponent = t.origActivity != null
+ // Activity alias if there is one
+ ? t.origActivity
+ // The real activity if there is no alias (or the target if there is one)
+ : t.realActivity;
+ this.id = t.taskId;
+ this.windowingMode = t.configuration.windowConfiguration.getWindowingMode();
+ this.baseIntent = t.baseIntent;
+ this.sourceComponent = sourceComponent;
+ this.userId = t.userId;
+ this.lastActiveTime = t.lastActiveTime;
+ updateHashCode();
+ }
+
public TaskKey(int id, int windowingMode, Intent intent,
ComponentName sourceComponent, int userId, long lastActiveTime) {
this.id = id;
@@ -125,7 +142,8 @@ public class Task {
/**
* The temporary sort index in the stack, used when ordering the stack.
*/
- public int temporarySortIndexInStack;
+ @Deprecated
+ int temporarySortIndexInStack;
/**
* The icon is the task description icon (if provided), which falls back to the activity icon,
@@ -134,6 +152,7 @@ public class Task {
public Drawable icon;
public ThumbnailData thumbnail;
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public String title;
@ViewDebug.ExportedProperty(category="recents")
public String titleDescription;
@@ -142,6 +161,7 @@ public class Task {
@ViewDebug.ExportedProperty(category="recents")
public int colorBackground;
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public boolean useLightOnPrimaryColor;
/**
@@ -153,10 +173,13 @@ public class Task {
* The state isLaunchTarget will be set for the correct task upon launching Recents.
*/
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public boolean isLaunchTarget;
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public boolean isStackTask;
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public boolean isSystemApp;
@ViewDebug.ExportedProperty(category="recents")
public boolean isDockable;
@@ -165,6 +188,7 @@ public class Task {
* Resize mode. See {@link ActivityInfo#resizeMode}.
*/
@ViewDebug.ExportedProperty(category="recents")
+ @Deprecated
public int resizeMode;
@ViewDebug.ExportedProperty(category="recents")
@@ -173,12 +197,31 @@ public class Task {
@ViewDebug.ExportedProperty(category="recents")
public boolean isLocked;
+ @Deprecated
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
public Task() {
// Do nothing
}
+ public Task(TaskKey key) {
+ this.key = key;
+ this.taskDescription = new TaskDescription();
+ }
+
+ public Task(TaskKey key, int colorPrimary, int colorBackground,
+ boolean isDockable, boolean isLocked, TaskDescription taskDescription,
+ ComponentName topActivity) {
+ this.key = key;
+ this.colorPrimary = colorPrimary;
+ this.colorBackground = colorBackground;
+ this.taskDescription = taskDescription;
+ this.isDockable = isDockable;
+ this.isLocked = isLocked;
+ this.topActivity = topActivity;
+ }
+
+ @Deprecated
public Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title,
String titleDescription, int colorPrimary, int colorBackground, boolean isLaunchTarget,
boolean isStackTask, boolean isSystemApp, boolean isDockable,
@@ -206,6 +249,7 @@ public class Task {
/**
* Copies the metadata from another task, but retains the current callbacks.
*/
+ @Deprecated
public void copyFrom(Task o) {
this.key = o.key;
this.icon = o.icon;
@@ -228,6 +272,7 @@ public class Task {
/**
* Add a callback.
*/
+ @Deprecated
public void addCallback(TaskCallbacks cb) {
if (!mCallbacks.contains(cb)) {
mCallbacks.add(cb);
@@ -237,11 +282,13 @@ public class Task {
/**
* Remove a callback.
*/
+ @Deprecated
public void removeCallback(TaskCallbacks cb) {
mCallbacks.remove(cb);
}
/** Updates the task's windowing mode. */
+ @Deprecated
public void setWindowingMode(int windowingMode) {
key.setWindowingMode(windowingMode);
int callbackCount = mCallbacks.size();
@@ -251,6 +298,7 @@ public class Task {
}
/** Notifies the callback listeners that this task has been loaded */
+ @Deprecated
public void notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon) {
this.icon = applicationIcon;
this.thumbnail = thumbnailData;
@@ -261,6 +309,7 @@ public class Task {
}
/** Notifies the callback listeners that this task has been unloaded */
+ @Deprecated
public void notifyTaskDataUnloaded(Drawable defaultApplicationIcon) {
icon = defaultApplicationIcon;
thumbnail = null;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java
index 5f3dcd16e074..d378189b1675 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java
@@ -21,6 +21,7 @@ import android.util.SparseArray;
/**
* An interface for a task filter to query whether a particular task should show in a stack.
*/
+@Deprecated
public interface TaskFilter {
/** Returns whether the filter accepts the specified task */
boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
index 23582d4bc21d..342cb75b2c14 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java
@@ -34,7 +34,7 @@ public abstract class TaskKeyCache<V> {
* Gets a specific entry in the cache with the specified key, regardless of whether the cached
* value is valid or not.
*/
- final synchronized V get(TaskKey key) {
+ public final synchronized V get(TaskKey key) {
return getCacheEntry(key.id);
}
@@ -42,7 +42,7 @@ public abstract class TaskKeyCache<V> {
* Returns the value only if the key is valid (has not been updated since the last time it was
* in the cache)
*/
- final synchronized V getAndInvalidateIfModified(TaskKey key) {
+ public final synchronized V getAndInvalidateIfModified(TaskKey key) {
TaskKey lastKey = mKeys.get(key.id);
if (lastKey != null) {
if ((lastKey.windowingMode != key.windowingMode) ||
@@ -59,7 +59,7 @@ public abstract class TaskKeyCache<V> {
}
/** Puts an entry in the cache for a specific key. */
- final synchronized void put(TaskKey key, V value) {
+ public final synchronized void put(TaskKey key, V value) {
if (key == null || value == null) {
Log.e(TAG, "Unexpected null key or value: " + key + ", " + value);
return;
@@ -70,14 +70,14 @@ public abstract class TaskKeyCache<V> {
/** Removes a cache entry for a specific key. */
- final synchronized void remove(TaskKey key) {
+ public final synchronized void remove(TaskKey key) {
// Remove the key after the cache value because we need it to make the callback
removeCacheEntry(key.id);
mKeys.remove(key.id);
}
/** Removes all the entries in the cache. */
- final synchronized void evictAll() {
+ public final synchronized void evictAll() {
evictAllCache();
mKeys.clear();
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java
index fbb6acebc8e0..6b9b9f55e49e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
/**
* A Task load queue
*/
+@Deprecated
class TaskResourceLoadQueue {
private final ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<>();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
index c731ac9b8886..fd92bca7fcda 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
@@ -33,6 +33,7 @@ import java.util.List;
/**
* The task stack contains a list of multiple tasks.
*/
+@Deprecated
public class TaskStack {
private static final String TAG = "TaskStack";
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java
index 2de7f74ba477..26f6b596e023 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java
@@ -34,6 +34,7 @@ import java.util.List;
* The generic set of animation properties to animate a {@link View}. The animation can have
* different interpolators, start delays and durations for each of the different properties.
*/
+@Deprecated
public class AnimationProps {
private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
index 45728c403ac4..30bea32dedff 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
@@ -27,6 +27,7 @@ import com.android.systemui.shared.recents.utilities.Utilities;
/**
* An outline provider that has a clip and outline that can be animated.
*/
+@Deprecated
public class AnimateableViewBounds extends ViewOutlineProvider {
private static final float MIN_ALPHA = 0.1f;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java
new file mode 100644
index 000000000000..c42e7e3fd216
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java
@@ -0,0 +1,32 @@
+/*
+ * 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.shared.system;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+
+public class KeyguardManagerCompat {
+ private final KeyguardManager mKeyguardManager;
+
+ public KeyguardManagerCompat(Context context) {
+ mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+ }
+
+ public boolean isDeviceLocked(int userId) {
+ return mKeyguardManager.isDeviceLocked(userId);
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java
new file mode 100644
index 000000000000..a5299038d3a9
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java
@@ -0,0 +1,45 @@
+/*
+ * 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.shared.system;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+
+public class RecentTaskInfoCompat {
+
+ private ActivityManager.RecentTaskInfo mInfo;
+
+ public RecentTaskInfoCompat(ActivityManager.RecentTaskInfo info) {
+ mInfo = info;
+ }
+
+ public int getUserId() {
+ return mInfo.userId;
+ }
+
+ public boolean supportsSplitScreenMultiWindow() {
+ return mInfo.supportsSplitScreenMultiWindow;
+ }
+
+ public ComponentName getTopActivity() {
+ return mInfo.topActivity;
+ }
+
+ public ActivityManager.TaskDescription getTaskDescription() {
+ return mInfo.taskDescription;
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskDescriptionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskDescriptionCompat.java
new file mode 100644
index 000000000000..eaf8d9b57398
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskDescriptionCompat.java
@@ -0,0 +1,40 @@
+/*
+ * 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.shared.system;
+
+import android.app.ActivityManager;
+
+public class TaskDescriptionCompat {
+
+ private ActivityManager.TaskDescription mTaskDescription;
+
+ public TaskDescriptionCompat(ActivityManager.TaskDescription td) {
+ mTaskDescription = td;
+ }
+
+ public int getPrimaryColor() {
+ return mTaskDescription != null
+ ? mTaskDescription.getPrimaryColor()
+ : 0;
+ }
+
+ public int getBackgroundColor() {
+ return mTaskDescription != null
+ ? mTaskDescription.getBackgroundColor()
+ : 0;
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowCallbacksCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowCallbacksCompat.java
index b2b140e4b0a9..de2a3e44841e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowCallbacksCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowCallbacksCompat.java
@@ -17,7 +17,7 @@ package com.android.systemui.shared.system;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.view.DisplayListCanvas;
+import android.graphics.RecordingCanvas;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowCallbacks;
@@ -55,7 +55,7 @@ public class WindowCallbacksCompat {
}
@Override
- public void onPostDraw(DisplayListCanvas canvas) {
+ public void onPostDraw(RecordingCanvas canvas) {
WindowCallbacksCompat.this.onPostDraw(canvas);
}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 265a961cd985..34df15f17869 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -29,13 +29,13 @@ import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import java.io.File;
@@ -50,13 +50,6 @@ import java.io.File;
*/
public class KeyguardHostView extends FrameLayout implements SecurityCallback {
- public interface OnDismissAction {
- /**
- * @return true if the dismiss should be deferred
- */
- boolean onDismiss();
- }
-
private AudioManager mAudioManager;
private TelephonyManager mTelephonyManager = null;
protected ViewMediatorCallback mViewMediatorCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index e58538db9cea..e1b8dc839bde 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -29,46 +29,69 @@ public class ActivityStarterDelegate implements ActivityStarter {
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.startPendingIntentDismissingKeyguard(intent);
}
@Override
public void startActivity(Intent intent, boolean dismissShade) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.startActivity(intent, dismissShade);
}
@Override
public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.startActivity(intent, onlyProvisioned, dismissShade);
}
@Override
public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.startActivity(intent, dismissShade, callback);
}
@Override
public void postStartActivityDismissingKeyguard(Intent intent, int delay) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.postStartActivityDismissingKeyguard(intent, delay);
}
@Override
public void postStartActivityDismissingKeyguard(PendingIntent intent) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.postStartActivityDismissingKeyguard(intent);
}
@Override
public void postQSRunnableDismissingKeyguard(Runnable runnable) {
- if (mActualStarter == null) return;
+ if (mActualStarter == null) {
+ return;
+ }
mActualStarter.postQSRunnableDismissingKeyguard(runnable);
}
+ @Override
+ public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancel,
+ boolean afterKeyguardGone) {
+ if (mActualStarter == null) {
+ return;
+ }
+ mActualStarter.dismissKeyguardThenExecute(action, cancel, afterKeyguardGone);
+ }
+
public void setActivityStarterImpl(ActivityStarter starter) {
mActualStarter = starter;
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 2c821b25f0a5..494880e96ff7 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -48,16 +48,22 @@ import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.AppOpsListener;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
@@ -343,6 +349,14 @@ public class Dependency extends SystemUI {
mProviders.put(LockscreenGestureLogger.class, () -> new LockscreenGestureLogger());
+ mProviders.put(KeyguardEnvironment.class, () -> new KeyguardEnvironmentImpl());
+ mProviders.put(ShadeController.class, () ->
+ SysUiServiceProvider.getComponent(mContext, StatusBar.class));
+ mProviders.put(NotificationRemoteInputManager.Callback.class,
+ () -> new StatusBarRemoteInputCallback(mContext));
+
+ mProviders.put(InitController.class, InitController::new);
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 77f4bf529f21..d8eb96504e79 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -30,7 +30,7 @@ import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.DisplayListCanvas;
+import android.graphics.RecordingCanvas;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -381,7 +381,7 @@ public class ImageWallpaper extends WallpaperService {
try {
Bitmap wallpaper = mWallpaperManager.getBitmap(true /* hardware */);
if (wallpaper != null
- && wallpaper.getByteCount() > DisplayListCanvas.MAX_BITMAP_SIZE) {
+ && wallpaper.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) {
throw new RuntimeException("Wallpaper is too large to draw!");
}
return wallpaper;
diff --git a/packages/SystemUI/src/com/android/systemui/InitController.java b/packages/SystemUI/src/com/android/systemui/InitController.java
new file mode 100644
index 000000000000..52ba66a93524
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/InitController.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+
+/**
+ * Created by {@link Dependency} on SystemUI startup. Add tasks which need to be executed only
+ * after all other dependencies have been created.
+ */
+public class InitController {
+
+ private final ArrayList<Runnable> mTasks = new ArrayList<>();
+
+ /**
+ * Add a task to be executed after {@link Dependency#start()}
+ * @param runnable the task to be executed
+ */
+ public void addPostInitTask(Runnable runnable) {
+ mTasks.add(runnable);
+ }
+
+ /**
+ * Run post-init tasks and remove them from the tasks list
+ */
+ public void executePostInitTasks() {
+ while (!mTasks.isEmpty()) {
+ mTasks.remove(0).run();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 78053b28c4c3..92aa652131ba 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -194,6 +194,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
mServices[i].onBootCompleted();
}
}
+ Dependency.get(InitController.class).executePostInitTasks();
log.traceEnd();
Dependency.get(PluginManager.class).addPluginListener(
new PluginListener<OverlayPlugin>() {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 258b6f61d4c0..c4bf27b5104a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -32,6 +32,7 @@ import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -133,7 +134,7 @@ public class SystemUIFactory {
Context context) {
providers.put(StatusBarStateController.class, StatusBarStateController::new);
providers.put(NotificationLockscreenUserManager.class,
- () -> new NotificationLockscreenUserManager(context));
+ () -> new NotificationLockscreenUserManagerImpl(context));
providers.put(VisualStabilityManager.class, VisualStabilityManager::new);
providers.put(NotificationGroupManager.class, NotificationGroupManager::new);
providers.put(NotificationMediaManager.class, () -> new NotificationMediaManager(context));
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 38a90cfd96a5..53cdee549536 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -202,7 +202,8 @@ public class AssistManager implements ConfigurationChangedReceiver {
// Close Recent Apps if needed
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL);
+ CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+ false /* force */);
boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 5739c997d8bf..96af08b6bf6b 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -44,7 +44,7 @@ public class CarNotificationEntryManager extends NotificationEntryManager {
// Because space is usually constrained in the auto use-case, there should not be a
// pinned notification when the shade has been expanded. Ensure this by not pinning any
// notification if the shade is already opened.
- if (!mPresenter.isPresenterFullyCollapsed()) {
+ if (!getPresenter().isPresenterFullyCollapsed()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java
new file mode 100644
index 000000000000..f34d6b3e03e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationMediaManager.java
@@ -0,0 +1,30 @@
+/*
+ * 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.car;
+
+import android.content.Context;
+
+import com.android.systemui.statusbar.NotificationMediaManager;
+
+public class CarNotificationMediaManager extends NotificationMediaManager {
+ public CarNotificationMediaManager(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
+ // Do nothing, we don't want to display media art in the lock screen for a car.
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index a015a18cd9a8..e4b2e07dc81e 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -22,6 +22,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dependency.DependencyProvider;
import com.android.systemui.SystemUIFactory;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.car.CarFacetButtonController;
import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
@@ -46,5 +47,7 @@ public class CarSystemUIFactory extends SystemUIFactory {
() -> new CarNotificationEntryManager(context));
providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context));
providers.put(HvacController.class, () -> new HvacController(context));
+ providers.put(NotificationMediaManager.class,
+ () -> new CarNotificationMediaManager(context));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index bb059809be2b..1e61a77a76cf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -47,6 +47,12 @@ public interface DozeHost {
void onIgnoreTouchWhilePulsing(boolean ignore);
+ /**
+ * If the device was waken up by a passive interrupt that will show the lock screen without
+ * expanding the notification panel/shade.
+ */
+ void setPassiveInterrupt(boolean lightInterrupt);
+
interface Callback {
/**
* Called when a high priority notification is added.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index cb91d7815be5..d69b1bfa64c3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -142,6 +142,7 @@ public class DozeTriggers implements DozeMachine.Part {
mDozeHost.onDoubleTap(screenX, screenY);
mMachine.wakeUp();
} else if (isPickup || isWakeLockScreen) {
+ mDozeHost.setPassiveInterrupt(true);
mMachine.wakeUp();
} else {
mDozeHost.extendPulse();
@@ -210,6 +211,7 @@ public class DozeTriggers implements DozeMachine.Part {
case INITIALIZED:
mBroadcastReceiver.register(mContext);
mDozeHost.addCallback(mHostCallback);
+ mDozeHost.setPassiveInterrupt(false);
checkTriggersAtInit();
break;
case DOZE:
@@ -219,6 +221,7 @@ public class DozeTriggers implements DozeMachine.Part {
mDozeSensors.reregisterAllSensors();
}
mDozeSensors.setListening(true);
+ mDozeHost.setPassiveInterrupt(false);
break;
case DOZE_AOD_PAUSED:
case DOZE_AOD_PAUSING:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
index f217596bd4a9..5bb5b2da32b4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.views;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.graphics.Point;
@@ -25,14 +24,11 @@ import android.util.SparseArray;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.TaskStack;
public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate {
private static final String TAG = "TaskViewAccessibilityDelegate";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5c0b3289c61a..daaefb9b2559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
+
+import android.app.StatusBarManager;
import android.content.ComponentName;
import android.graphics.Rect;
import android.hardware.biometrics.IBiometricPromptReceiver;
@@ -24,7 +27,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.RemoteException;
+
import androidx.annotation.VisibleForTesting;
import android.util.Pair;
@@ -117,7 +120,7 @@ public class CommandQueue extends IStatusBar.Stub {
default void removeIcon(String slot) { }
default void disable(int state1, int state2, boolean animate) { }
default void animateExpandNotificationsPanel() { }
- default void animateCollapsePanels(int flags) { }
+ default void animateCollapsePanels(int flags, boolean force) { }
default void togglePanel() { }
default void animateExpandSettingsPanel(String obj) { }
default void setSystemUiVisibility(int vis, int fullscreenStackVis,
@@ -169,7 +172,13 @@ public class CommandQueue extends IStatusBar.Stub {
}
@VisibleForTesting
- protected CommandQueue() {
+ public CommandQueue() {
+ }
+
+ public boolean panelsEnabled() {
+ return (mDisable1 & StatusBarManager.DISABLE_EXPAND) == 0
+ && (mDisable2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
+ && !ONLY_CORE_APPS;
}
public void addCallbacks(Callbacks callbacks) {
@@ -234,10 +243,10 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- public void animateCollapsePanels(int flags) {
+ public void animateCollapsePanels(int flags, boolean force) {
synchronized (mLock) {
mHandler.removeMessages(MSG_COLLAPSE_PANELS);
- mHandler.obtainMessage(MSG_COLLAPSE_PANELS, flags, 0).sendToTarget();
+ mHandler.obtainMessage(MSG_COLLAPSE_PANELS, flags, force ? 1 : 0).sendToTarget();
}
}
@@ -592,7 +601,7 @@ public class CommandQueue extends IStatusBar.Stub {
break;
case MSG_COLLAPSE_PANELS:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).animateCollapsePanels(msg.arg1);
+ mCallbacks.get(i).animateCollapsePanels(msg.arg1, msg.arg2 != 0);
}
break;
case MSG_TOGGLE_PANEL:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 30d9ef7bd7a3..8526afd34514 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -131,7 +131,7 @@ public class DragDownHelper implements Gefingerpoken {
if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild,
(int) (y - mInitialTouchY))) {
if (mStartingChild == null) {
- mDragDownCallback.setEmptyDragAmount(0f);
+ cancelExpansion();
} else {
mCallback.setUserLockedChild(mStartingChild, false);
mStartingChild = null;
@@ -206,11 +206,8 @@ public class DragDownHelper implements Gefingerpoken {
ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
- }
+ anim.addUpdateListener(animation -> {
+ mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
});
anim.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 18151d0e794a..1f576342d5cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -29,9 +29,9 @@ import android.graphics.CanvasProperty;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
+import android.graphics.RecordingCanvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewAnimationUtils;
@@ -192,8 +192,8 @@ public class KeyguardAffordanceView extends ImageView {
// Our hardware drawing proparties can be null if the finishing started but we have
// never drawn before. In that case we are not doing a render thread animation
// anyway, so we need to use the normal drawing.
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
- displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
mHwCirclePaint);
} else {
updateCircleColor();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index cfa09bc93adb..f3a46ce5778a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -29,6 +29,7 @@ import android.util.Log;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
/**
@@ -41,11 +42,14 @@ public class NotificationListener extends NotificationListenerWithPlugins {
// Dependencies:
private final NotificationRemoteInputManager mRemoteInputManager =
Dependency.get(NotificationRemoteInputManager.class);
+ private final NotificationEntryManager mEntryManager =
+ Dependency.get(NotificationEntryManager.class);
+ private final NotificationGroupManager mGroupManager =
+ Dependency.get(NotificationGroupManager.class);
private final Context mContext;
protected NotificationPresenter mPresenter;
- protected NotificationEntryManager mEntryManager;
public NotificationListener(Context context) {
mContext = context;
@@ -61,7 +65,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
return;
}
final RankingMap currentRanking = getCurrentRanking();
- mPresenter.getHandler().post(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
for (StatusBarNotification sbn : notifications) {
mEntryManager.addNotification(sbn, currentRanking);
}
@@ -73,7 +77,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
- mPresenter.getHandler().post(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
processForRemoteInput(sbn.getNotification(), mContext);
String key = sbn.getKey();
boolean isUpdate =
@@ -83,7 +87,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
// anyway. This is true also when the summary is canceled,
// because children are automatically canceled by NoMan in that case.
if (!ENABLE_CHILD_NOTIFICATIONS
- && mPresenter.getGroupManager().isChildInGroupWithSummary(sbn)) {
+ && mGroupManager.isChildInGroupWithSummary(sbn)) {
if (DEBUG) {
Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
}
@@ -112,7 +116,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
final String key = sbn.getKey();
- mPresenter.getHandler().post(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
mEntryManager.removeNotification(key, rankingMap);
});
}
@@ -123,16 +127,14 @@ public class NotificationListener extends NotificationListenerWithPlugins {
if (DEBUG) Log.d(TAG, "onRankingUpdate");
if (rankingMap != null) {
RankingMap r = onPluginRankingUpdate(rankingMap);
- mPresenter.getHandler().post(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
mEntryManager.updateNotificationRanking(r);
});
}
}
- public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager) {
+ public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
- mEntryManager = entryManager;
try {
registerAsSystemService(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 89a842e11c68..bc662e3d8855 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -1,516 +1,61 @@
/*
* 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
+ * 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
+ * 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 android.app.ActivityManager;
-import android.app.KeyguardManager;
-import android.app.Notification;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
import android.service.notification.StatusBarNotification;
-import android.util.Log;
import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
-import com.android.systemui.OverviewProxyService;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
-/**
- * Handles keeping track of the current user, profiles, and various things related to hiding
- * contents, redacting notifications, and the lockscreen.
- */
-public class NotificationLockscreenUserManager implements Dumpable, StateListener {
- private static final String TAG = "LockscreenUserManager";
- private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
- public static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
- public static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
+public interface NotificationLockscreenUserManager {
+ String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+ String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
= "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
- private final DevicePolicyManager mDevicePolicyManager;
- private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
- private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
- private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
- private final DeviceProvisionedController mDeviceProvisionedController =
- Dependency.get(DeviceProvisionedController.class);
- private final UserManager mUserManager;
- private final IStatusBarService mBarService;
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardManager mKeyguardManager;
- private StatusBarKeyguardViewManager mKeyguardViewManager;
-
- private boolean mShowLockscreenNotifications;
- private boolean mAllowLockscreenRemoteInput;
- private int mState = StatusBarState.SHADE;
-
- protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-
- if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
- isCurrentProfile(getSendingUserId())) {
- mUsersAllowingPrivateNotifications.clear();
- updateLockscreenNotificationSetting();
- mEntryManager.updateNotifications();
- } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
- if (userId != mCurrentUserId && isCurrentProfile(userId)) {
- updatePublicMode();
- mPresenter.onWorkChallengeChanged();
- mEntryManager.updateNotifications();
- }
- }
- }
- };
-
- protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- updateCurrentProfilesCache();
- Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
-
- updateLockscreenNotificationSetting();
- updatePublicMode();
- mPresenter.onUserSwitched(mCurrentUserId);
- mEntryManager.getNotificationData().filterAndSort();
- } else if (Intent.ACTION_USER_ADDED.equals(action)) {
- updateCurrentProfilesCache();
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- // Start the overview connection to the launcher service
- Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
- } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
- final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
- final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
- if (intentSender != null) {
- try {
- mContext.startIntentSender(intentSender, null, 0, 0, 0);
- } catch (IntentSender.SendIntentException e) {
- /* ignore */
- }
- }
- if (notificationKey != null) {
- final int count =
- mEntryManager.getNotificationData().getActiveNotifications().size();
- final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
- final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
- rank, count, true);
- try {
- mBarService.onNotificationClick(notificationKey, nv);
- } catch (RemoteException e) {
- /* ignore */
- }
- }
- }
- }
- };
-
- protected final Context mContext;
- protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
-
- protected int mCurrentUserId = 0;
- protected NotificationPresenter mPresenter;
- protected NotificationEntryManager mEntryManager;
- protected ContentObserver mLockscreenSettingsObserver;
- protected ContentObserver mSettingsObserver;
-
- public NotificationLockscreenUserManager(Context context) {
- mContext = context;
- mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mCurrentUserId = ActivityManager.getCurrentUser();
- mBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- mLockPatternUtils = new LockPatternUtils(mContext);
- mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- Dependency.get(StatusBarStateController.class).addListener(this);
- }
-
- public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager) {
- mPresenter = presenter;
- mEntryManager = entryManager;
-
- mLockscreenSettingsObserver = new ContentObserver(mPresenter.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
- // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
- mUsersAllowingPrivateNotifications.clear();
- mUsersAllowingNotifications.clear();
- // ... and refresh all the notifications
- updateLockscreenNotificationSetting();
- mEntryManager.updateNotifications();
- }
- };
-
- mSettingsObserver = new ContentObserver(mPresenter.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- updateLockscreenNotificationSetting();
- if (mDeviceProvisionedController.isDeviceProvisioned()) {
- mEntryManager.updateNotifications();
- }
- }
- };
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
- mLockscreenSettingsObserver,
- UserHandle.USER_ALL);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
- true,
- mLockscreenSettingsObserver,
- UserHandle.USER_ALL);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
- mSettingsObserver);
-
- if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
- false,
- mSettingsObserver,
- UserHandle.USER_ALL);
- }
-
- IntentFilter allUsersFilter = new IntentFilter();
- allUsersFilter.addAction(
- DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
- mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
- null, null);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(Intent.ACTION_USER_ADDED);
- filter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiver(mBaseBroadcastReceiver, filter);
-
- IntentFilter internalFilter = new IntentFilter();
- internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
- mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
-
- updateCurrentProfilesCache();
-
- mSettingsObserver.onChange(false); // set up
- }
-
- public boolean shouldShowLockscreenNotifications() {
- return mShowLockscreenNotifications;
- }
-
- public boolean shouldAllowLockscreenRemoteInput() {
- return mAllowLockscreenRemoteInput;
- }
-
- public boolean isCurrentProfile(int userId) {
- synchronized (mCurrentProfiles) {
- return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
- }
- }
-
- public void setKeyguardViewManager(StatusBarKeyguardViewManager sbkvm) {
- mKeyguardViewManager = sbkvm;
- }
-
- @Override
- public void onStateChanged(int newState) {
- mState = newState;
- updatePublicMode();
- }
-
- public void updatePublicMode() {
- //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
- // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
- // asking if the keyguard is showing. We still need to check it though because showing the
- // camera on the keyguard has a state of SHADE but the keyguard is still showing.
- boolean showingKeyguard = mState != StatusBarState.SHADE
- || mKeyguardViewManager.isShowing();
- boolean devicePublic = showingKeyguard && mKeyguardViewManager.isSecure(getCurrentUserId());
-
- SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
- for (int i = currentProfiles.size() - 1; i >= 0; i--) {
- final int userId = currentProfiles.valueAt(i).id;
- boolean isProfilePublic = devicePublic;
- if (!devicePublic && userId != mCurrentUserId) {
- // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
- // due to a race condition where this code could be called before
- // TrustManagerService updates its internal records, resulting in an incorrect
- // state being cached in mLockscreenPublicMode. (b/35951989)
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
- && mKeyguardViewManager.isSecure(userId)) {
- isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
- }
- }
- setLockscreenPublicMode(isProfilePublic, userId);
- }
- }
+ boolean shouldAllowLockscreenRemoteInput();
/**
- * Returns true if notifications are temporarily disabled for this user for security reasons,
- * regardless of the normal settings for that user.
+ * @param userId user Id
+ * @return true if we re on a secure lock screen
*/
- private boolean shouldTemporarilyHideNotifications(int userId) {
- if (userId == UserHandle.USER_ALL) {
- userId = mCurrentUserId;
- }
- return KeyguardUpdateMonitor.getInstance(mContext).isUserInLockdown(userId);
- }
+ boolean isLockscreenPublicMode(int userId);
- /**
- * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
- * If so, notifications should be hidden.
- */
- public boolean shouldHideNotifications(int userId) {
- return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
- || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
- || shouldTemporarilyHideNotifications(userId);
- }
-
- /**
- * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
- * package-specific override.
- */
- public boolean shouldHideNotifications(String key) {
- if (mEntryManager == null) {
- Log.wtf(TAG, "mEntryManager was null!", new Throwable());
- return true;
- }
- return isLockscreenPublicMode(mCurrentUserId)
- && mEntryManager.getNotificationData().getVisibilityOverride(key) ==
- Notification.VISIBILITY_SECRET;
- }
-
- public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
- if (mEntryManager == null) {
- Log.wtf(TAG, "mEntryManager was null!", new Throwable());
- return false;
- }
- return mShowLockscreenNotifications
- && !mEntryManager.getNotificationData().isAmbient(sbn.getKey());
- }
+ void setUpWithPresenter(NotificationPresenter presenter);
- private void setShowLockscreenNotifications(boolean show) {
- mShowLockscreenNotifications = show;
- }
+ int getCurrentUserId();
- private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
- mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
- }
+ boolean isCurrentProfile(int userId);
- protected void updateLockscreenNotificationSetting() {
- final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
- 1,
- mCurrentUserId) != 0;
- final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
- null /* admin */, mCurrentUserId);
- final boolean allowedByDpm = (dpmFlags
- & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+ void destroy();
- setShowLockscreenNotifications(show && allowedByDpm);
+ SparseArray<UserInfo> getCurrentProfiles();
- if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
- final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
- 0,
- mCurrentUserId) != 0;
- final boolean remoteInputDpm =
- (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
+ void setLockscreenPublicMode(boolean isProfilePublic, int userId);
- setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
- } else {
- setLockscreenAllowRemoteInput(false);
- }
- }
-
- /**
- * Has the given user chosen to allow their private (full) notifications to be shown even
- * when the lockscreen is in "public" (secure & locked) mode?
- */
- public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
- if (userHandle == UserHandle.USER_ALL) {
- return true;
- }
-
- if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
- final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
- final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
- DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
- final boolean allowed = allowedByUser && allowedByDpm;
- mUsersAllowingPrivateNotifications.append(userHandle, allowed);
- return allowed;
- }
-
- return mUsersAllowingPrivateNotifications.get(userHandle);
- }
-
- private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
- if (userHandle == UserHandle.USER_ALL) {
- return true;
- }
- final int dpmFlags =
- mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle);
- return (dpmFlags & feature) == 0;
- }
-
- /**
- * Save the current "public" (locked and secure) state of the lockscreen.
- */
- public void setLockscreenPublicMode(boolean publicMode, int userId) {
- mLockscreenPublicMode.put(userId, publicMode);
- }
+ boolean shouldShowLockscreenNotifications();
- public boolean isLockscreenPublicMode(int userId) {
- if (userId == UserHandle.USER_ALL) {
- return mLockscreenPublicMode.get(mCurrentUserId, false);
- }
- return mLockscreenPublicMode.get(userId, false);
- }
+ boolean shouldHideNotifications(int userId);
+ boolean shouldHideNotifications(String key);
+ boolean shouldShowOnKeyguard(StatusBarNotification sbn);
- /**
- * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
- * "public" (secure & locked) mode?
- */
- private boolean userAllowsNotificationsInPublic(int userHandle) {
- if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
- return true;
- }
-
- if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
- final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
- final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
- DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
- final boolean allowed = allowedByUser && allowedByDpm;
- mUsersAllowingNotifications.append(userHandle, allowed);
- return allowed;
- }
-
- return mUsersAllowingNotifications.get(userHandle);
- }
-
- /** @return true if the entry needs redaction when on the lockscreen. */
- public boolean needsRedaction(NotificationData.Entry ent) {
- int userId = ent.notification.getUserId();
-
- boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
- boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
- boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
-
- boolean notificationRequestsRedaction =
- ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
- boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
-
- return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
- }
-
- private boolean packageHasVisibilityOverride(String key) {
- if (mEntryManager == null) {
- Log.wtf(TAG, "mEntryManager was null!", new Throwable());
- return true;
- }
- return mEntryManager.getNotificationData().getVisibilityOverride(key) ==
- Notification.VISIBILITY_PRIVATE;
- }
-
- private void updateCurrentProfilesCache() {
- synchronized (mCurrentProfiles) {
- mCurrentProfiles.clear();
- if (mUserManager != null) {
- for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
- mCurrentProfiles.put(user.id, user);
- }
- }
- }
- }
-
- public boolean isAnyProfilePublicMode() {
- for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
- if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the current user id. This can change if the user is switched.
- */
- public int getCurrentUserId() {
- return mCurrentUserId;
- }
+ boolean isAnyProfilePublicMode();
- public SparseArray<UserInfo> getCurrentProfiles() {
- return mCurrentProfiles;
- }
+ void updatePublicMode();
- public void destroy() {
- mContext.unregisterReceiver(mBaseBroadcastReceiver);
- mContext.unregisterReceiver(mAllUsersReceiver);
- }
+ boolean needsRedaction(Entry entry);
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NotificationLockscreenUserManager state:");
- pw.print(" mCurrentUserId=");
- pw.println(mCurrentUserId);
- pw.print(" mShowLockscreenNotifications=");
- pw.println(mShowLockscreenNotifications);
- pw.print(" mAllowLockscreenRemoteInput=");
- pw.println(mAllowLockscreenRemoteInput);
- pw.print(" mCurrentProfiles=");
- for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
- final int userId = mCurrentProfiles.valueAt(i).id;
- pw.print("" + userId + " ");
- }
- pw.println();
- }
+ boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
new file mode 100644
index 000000000000..178c5c516e7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -0,0 +1,551 @@
+/*
+ * 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 android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
+
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.OverviewProxyService;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Handles keeping track of the current user, profiles, and various things related to hiding
+ * contents, redacting notifications, and the lockscreen.
+ */
+public class NotificationLockscreenUserManagerImpl implements
+ Dumpable, NotificationLockscreenUserManager, StateListener {
+ private static final String TAG = "LockscreenUserManager";
+ private static final boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
+
+ private final DeviceProvisionedController mDeviceProvisionedController =
+ Dependency.get(DeviceProvisionedController.class);
+ private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+
+ // Lazy
+ private NotificationEntryManager mEntryManager;
+
+ private final DevicePolicyManager mDevicePolicyManager;
+ private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
+ private final UserManager mUserManager;
+ private final IStatusBarService mBarService;
+
+ private boolean mShowLockscreenNotifications;
+ private boolean mAllowLockscreenRemoteInput;
+ private LockPatternUtils mLockPatternUtils;
+ protected KeyguardManager mKeyguardManager;
+ private int mState = StatusBarState.SHADE;
+
+ protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+
+ if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
+ isCurrentProfile(getSendingUserId())) {
+ mUsersAllowingPrivateNotifications.clear();
+ updateLockscreenNotificationSetting();
+ getEntryManager().updateNotifications();
+ }
+ }
+ };
+
+ protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ updateCurrentProfilesCache();
+ Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
+
+ updateLockscreenNotificationSetting();
+ updatePublicMode();
+ mPresenter.onUserSwitched(mCurrentUserId);
+ getEntryManager().getNotificationData().filterAndSort();
+ } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+ updateCurrentProfilesCache();
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ // Start the overview connection to the launcher service
+ Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
+ } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
+ final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
+ final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
+ if (intentSender != null) {
+ try {
+ mContext.startIntentSender(intentSender, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ /* ignore */
+ }
+ }
+ if (notificationKey != null) {
+ final int count =
+ getEntryManager().getNotificationData().getActiveNotifications().size();
+ final int rank = getEntryManager().getNotificationData().getRank(notificationKey);
+ final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
+ rank, count, true);
+ try {
+ mBarService.onNotificationClick(notificationKey, nv);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ }
+ }
+ }
+ };
+
+ protected final Context mContext;
+ protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
+
+ protected int mCurrentUserId = 0;
+ protected NotificationPresenter mPresenter;
+ protected ContentObserver mLockscreenSettingsObserver;
+ protected ContentObserver mSettingsObserver;
+
+ private NotificationEntryManager getEntryManager() {
+ if (mEntryManager == null) {
+ mEntryManager = Dependency.get(NotificationEntryManager.class);
+ }
+ return mEntryManager;
+ }
+
+ public NotificationLockscreenUserManagerImpl(Context context) {
+ mContext = context;
+ mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mCurrentUserId = ActivityManager.getCurrentUser();
+ mBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ Dependency.get(StatusBarStateController.class).addListener(this);
+ mLockPatternUtils = new LockPatternUtils(context);
+ mKeyguardManager = context.getSystemService(KeyguardManager.class);
+ }
+
+ public void setUpWithPresenter(NotificationPresenter presenter) {
+ mPresenter = presenter;
+
+ mLockscreenSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
+ @Override
+ public void onChange(boolean selfChange) {
+ // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+ // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
+ mUsersAllowingPrivateNotifications.clear();
+ mUsersAllowingNotifications.clear();
+ // ... and refresh all the notifications
+ updateLockscreenNotificationSetting();
+ getEntryManager().updateNotifications();
+ }
+ };
+
+ mSettingsObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateLockscreenNotificationSetting();
+ if (mDeviceProvisionedController.isDeviceProvisioned()) {
+ getEntryManager().updateNotifications();
+ }
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
+ mLockscreenSettingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+ true,
+ mLockscreenSettingsObserver,
+ UserHandle.USER_ALL);
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
+ mSettingsObserver);
+
+ if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
+ false,
+ mSettingsObserver,
+ UserHandle.USER_ALL);
+ }
+
+ mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL,
+ new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ null, null);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_ADDED);
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ mContext.registerReceiver(mBaseBroadcastReceiver, filter);
+
+ IntentFilter internalFilter = new IntentFilter();
+ internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
+ mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
+
+ updateCurrentProfilesCache();
+
+ mSettingsObserver.onChange(false); // set up
+ }
+
+ public boolean shouldShowLockscreenNotifications() {
+ return mShowLockscreenNotifications;
+ }
+
+ public boolean shouldAllowLockscreenRemoteInput() {
+ return mAllowLockscreenRemoteInput;
+ }
+
+ public boolean isCurrentProfile(int userId) {
+ synchronized (mCurrentProfiles) {
+ return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
+ }
+ }
+
+ /**
+ * Returns true if notifications are temporarily disabled for this user for security reasons,
+ * regardless of the normal settings for that user.
+ */
+ private boolean shouldTemporarilyHideNotifications(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ userId = mCurrentUserId;
+ }
+ return KeyguardUpdateMonitor.getInstance(mContext).isUserInLockdown(userId);
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
+ * If so, notifications should be hidden.
+ */
+ public boolean shouldHideNotifications(int userId) {
+ return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
+ || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
+ || shouldTemporarilyHideNotifications(userId);
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
+ * package-specific override.
+ */
+ public boolean shouldHideNotifications(String key) {
+ if (getEntryManager() == null) {
+ Log.wtf(TAG, "mEntryManager was null!", new Throwable());
+ return true;
+ }
+ return isLockscreenPublicMode(mCurrentUserId)
+ && getEntryManager().getNotificationData().getVisibilityOverride(key) ==
+ Notification.VISIBILITY_SECRET;
+ }
+
+ public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+ if (getEntryManager() == null) {
+ Log.wtf(TAG, "mEntryManager was null!", new Throwable());
+ return false;
+ }
+ return mShowLockscreenNotifications
+ && !getEntryManager().getNotificationData().isAmbient(sbn.getKey());
+ }
+
+ private void setShowLockscreenNotifications(boolean show) {
+ mShowLockscreenNotifications = show;
+ }
+
+ private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
+ mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
+ }
+
+ protected void updateLockscreenNotificationSetting() {
+ final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ 1,
+ mCurrentUserId) != 0;
+ final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
+ null /* admin */, mCurrentUserId);
+ final boolean allowedByDpm = (dpmFlags
+ & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+
+ setShowLockscreenNotifications(show && allowedByDpm);
+
+ if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+ final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
+ 0,
+ mCurrentUserId) != 0;
+ final boolean remoteInputDpm =
+ (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
+
+ setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
+ } else {
+ setLockscreenAllowRemoteInput(false);
+ }
+ }
+
+ /**
+ * Has the given user chosen to allow their private (full) notifications to be shown even
+ * when the lockscreen is in "public" (secure & locked) mode?
+ */
+ public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
+ if (userHandle == UserHandle.USER_ALL) {
+ return true;
+ }
+
+ if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+ final boolean allowed = allowedByUser && allowedByDpm;
+ mUsersAllowingPrivateNotifications.append(userHandle, allowed);
+ return allowed;
+ }
+
+ return mUsersAllowingPrivateNotifications.get(userHandle);
+ }
+
+ private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
+ if (userHandle == UserHandle.USER_ALL) {
+ return true;
+ }
+ final int dpmFlags =
+ mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle);
+ return (dpmFlags & feature) == 0;
+ }
+
+ /**
+ * Save the current "public" (locked and secure) state of the lockscreen.
+ */
+ public void setLockscreenPublicMode(boolean publicMode, int userId) {
+ mLockscreenPublicMode.put(userId, publicMode);
+ }
+
+ public boolean isLockscreenPublicMode(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return mLockscreenPublicMode.get(mCurrentUserId, false);
+ }
+ return mLockscreenPublicMode.get(userId, false);
+ }
+
+ /**
+ * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+ * "public" (secure & locked) mode?
+ */
+ private boolean userAllowsNotificationsInPublic(int userHandle) {
+ if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
+ return true;
+ }
+
+ if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+ final boolean allowed = allowedByUser && allowedByDpm;
+ mUsersAllowingNotifications.append(userHandle, allowed);
+ return allowed;
+ }
+
+ return mUsersAllowingNotifications.get(userHandle);
+ }
+
+ /** @return true if the entry needs redaction when on the lockscreen. */
+ public boolean needsRedaction(NotificationData.Entry ent) {
+ int userId = ent.notification.getUserId();
+
+ boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
+ boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
+ boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
+
+ boolean notificationRequestsRedaction =
+ ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+ boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
+
+ return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
+ }
+
+ private boolean packageHasVisibilityOverride(String key) {
+ if (getEntryManager() == null) {
+ Log.wtf(TAG, "mEntryManager was null!", new Throwable());
+ return true;
+ }
+ return getEntryManager().getNotificationData().getVisibilityOverride(key) ==
+ Notification.VISIBILITY_PRIVATE;
+ }
+
+ private void updateCurrentProfilesCache() {
+ synchronized (mCurrentProfiles) {
+ mCurrentProfiles.clear();
+ if (mUserManager != null) {
+ for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
+ mCurrentProfiles.put(user.id, user);
+ }
+ }
+ }
+ }
+
+ public boolean isAnyProfilePublicMode() {
+ for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
+ if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the current user id. This can change if the user is switched.
+ */
+ public int getCurrentUserId() {
+ return mCurrentUserId;
+ }
+
+ public SparseArray<UserInfo> getCurrentProfiles() {
+ return mCurrentProfiles;
+ }
+
+ @Override
+ public void onStateChanged(int newState) {
+ mState = newState;
+ updatePublicMode();
+ }
+
+ public void updatePublicMode() {
+ //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
+ // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
+ // asking if the keyguard is showing. We still need to check it though because showing the
+ // camera on the keyguard has a state of SHADE but the keyguard is still showing.
+ final boolean showingKeyguard = mState != StatusBarState.SHADE
+ || mKeyguardMonitor.isShowing();
+ final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
+
+
+ // Look for public mode users. Users are considered public in either case of:
+ // - device keyguard is shown in secure mode;
+ // - profile is locked with a work challenge.
+ SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
+ for (int i = currentProfiles.size() - 1; i >= 0; i--) {
+ final int userId = currentProfiles.valueAt(i).id;
+ boolean isProfilePublic = devicePublic;
+ if (!devicePublic && userId != getCurrentUserId()) {
+ // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
+ // due to a race condition where this code could be called before
+ // TrustManagerService updates its internal records, resulting in an incorrect
+ // state being cached in mLockscreenPublicMode. (b/35951989)
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+ && isSecure(userId)) {
+ isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
+ }
+ }
+ setLockscreenPublicMode(isProfilePublic, userId);
+ }
+ }
+
+
+// public void updatePublicMode() {
+// //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
+// // false when it should be true. Therefore, if we are not on the SHADE, don't even bother
+// // asking if the keyguard is showing. We still need to check it though because showing the
+// // camera on the keyguard has a state of SHADE but the keyguard is still showing.
+// final boolean showingKeyguard = mState != StatusBarState.SHADE
+// || mKeyguardMonitor.isShowing();
+// final boolean devicePublic = showingKeyguard && isSecure(getCurrentUserId());
+//
+//
+// // Look for public mode users. Users are considered public in either case of:
+// // - device keyguard is shown in secure mode;
+// // - profile is locked with a work challenge.
+// SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
+// for (int i = currentProfiles.size() - 1; i >= 0; i--) {
+// final int userId = currentProfiles.valueAt(i).id;
+// boolean isProfilePublic = devicePublic;
+// if (!devicePublic && userId != getCurrentUserId()) {
+// // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
+// // due to a race condition where this code could be called before
+// // TrustManagerService updates its internal records, resulting in an incorrect
+// // state being cached in mLockscreenPublicMode. (b/35951989)
+// if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+// && isSecure(userId)) {
+// isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
+// }
+// }
+// setLockscreenPublicMode(isProfilePublic, userId);
+// }
+// }
+
+ private boolean isSecure(int userId) {
+ return mKeyguardMonitor.isSecure() || mLockPatternUtils.isSecure(userId);
+ }
+
+ public void destroy() {
+ mContext.unregisterReceiver(mBaseBroadcastReceiver);
+ mContext.unregisterReceiver(mAllUsersReceiver);
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NotificationLockscreenUserManager state:");
+ pw.print(" mCurrentUserId=");
+ pw.println(mCurrentUserId);
+ pw.print(" mShowLockscreenNotifications=");
+ pw.println(mShowLockscreenNotifications);
+ pw.print(" mAllowLockscreenRemoteInput=");
+ pw.println(mAllowLockscreenRemoteInput);
+ pw.print(" mCurrentProfiles=");
+ for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
+ final int userId = mCurrentProfiles.valueAt(i).id;
+ pw.print("" + userId + " ");
+ }
+ pw.println();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 2db99453e36c..67b21e1c8752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -15,19 +15,46 @@
*/
package com.android.systemui.statusbar;
+import static com.android.systemui.Dependency.MAIN_HANDLER;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK;
+import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
+import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
+
+import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
+import android.os.Handler;
+import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.Interpolators;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.ScrimState;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -42,15 +69,45 @@ public class NotificationMediaManager implements Dumpable {
private static final String TAG = "NotificationMediaManager";
public static final boolean DEBUG_MEDIA = false;
+ private final StatusBarStateController mStatusBarStateController
+ = Dependency.get(StatusBarStateController.class);
+ private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+
+ // Late binding
+ private NotificationEntryManager mEntryManager;
+
+ // Late binding, also @Nullable due to being in com.android.systemui.statusbar.phone package
+ @Nullable
+ private ShadeController mShadeController;
+ @Nullable
+ private StatusBarWindowController mStatusBarWindowController;
+
+ @Nullable
+ private BiometricUnlockController mBiometricUnlockController;
+ @Nullable
+ private ScrimController mScrimController;
+ @Nullable
+ private LockscreenWallpaper mLockscreenWallpaper;
+
+ protected final PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+ protected final PorterDuffXfermode mSrcOverXferMode =
+ new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
+
+ private final Handler mHandler = Dependency.get(MAIN_HANDLER);
+
private final Context mContext;
private final MediaSessionManager mMediaSessionManager;
protected NotificationPresenter mPresenter;
- protected NotificationEntryManager mEntryManager;
private MediaController mMediaController;
private String mMediaNotificationKey;
private MediaMetadata mMediaMetadata;
+ private BackDropView mBackdrop;
+ private ImageView mBackdropFront;
+ private ImageView mBackdropBack;
+
private final MediaController.Callback mMediaListener = new MediaController.Callback() {
@Override
public void onPlaybackStateChanged(PlaybackState state) {
@@ -77,6 +134,29 @@ public class NotificationMediaManager implements Dumpable {
}
};
+ @Nullable
+ private ShadeController getShadeController() {
+ if (mShadeController == null) {
+ mShadeController = Dependency.get(ShadeController.class);
+ }
+ return mShadeController;
+ }
+
+ @Nullable
+ private StatusBarWindowController getWindowController() {
+ if (mStatusBarWindowController == null) {
+ mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
+ }
+ return mStatusBarWindowController;
+ }
+
+ private NotificationEntryManager getEntryManager() {
+ if (mEntryManager == null) {
+ mEntryManager = Dependency.get(NotificationEntryManager.class);
+ }
+ return mEntryManager;
+ }
+
public NotificationMediaManager(Context context) {
mContext = context;
mMediaSessionManager
@@ -85,10 +165,8 @@ public class NotificationMediaManager implements Dumpable {
// in session state
}
- public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager) {
+ public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
- mEntryManager = entryManager;
}
public void onNotificationRemoved(String key) {
@@ -109,8 +187,9 @@ public class NotificationMediaManager implements Dumpable {
public void findAndUpdateMediaNotifications() {
boolean metaDataChanged = false;
- synchronized (mEntryManager.getNotificationData()) {
- ArrayList<NotificationData.Entry> activeNotifications = mEntryManager
+ NotificationEntryManager manager = getEntryManager();
+ synchronized (manager.getNotificationData()) {
+ ArrayList<NotificationData.Entry> activeNotifications = manager
.getNotificationData().getActiveNotifications();
final int N = activeNotifications.size();
@@ -199,7 +278,7 @@ public class NotificationMediaManager implements Dumpable {
}
if (metaDataChanged) {
- mEntryManager.updateNotifications();
+ getEntryManager().updateNotifications();
}
mPresenter.updateMediaMetaData(metaDataChanged, true);
}
@@ -272,4 +351,202 @@ public class NotificationMediaManager implements Dumpable {
}
mMediaController = null;
}
+
+ /**
+ * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
+ */
+ public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
+ Trace.beginSection("StatusBar#updateMediaMetaData");
+ if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) {
+ Trace.endSection();
+ return;
+ }
+
+ if (mBackdrop == null) {
+ Trace.endSection();
+ return; // called too early
+ }
+
+ boolean wakeAndUnlock = mBiometricUnlockController != null
+ && mBiometricUnlockController.isWakeAndUnlock();
+ if (mKeyguardMonitor.isLaunchTransitionFadingAway() || wakeAndUnlock) {
+ mBackdrop.setVisibility(View.INVISIBLE);
+ Trace.endSection();
+ return;
+ }
+
+ MediaMetadata mediaMetadata = getMediaMetadata();
+
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: updating album art for notification "
+ + getMediaNotificationKey()
+ + " metadata=" + mediaMetadata
+ + " metaDataChanged=" + metaDataChanged
+ + " state=" + mStatusBarStateController.getState());
+ }
+
+ Drawable artworkDrawable = null;
+ if (mediaMetadata != null) {
+ Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
+ if (artworkBitmap == null) {
+ artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+ // might still be null
+ }
+ if (artworkBitmap != null) {
+ artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap);
+ }
+ }
+ boolean allowWhenShade = false;
+ if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) {
+ Bitmap lockWallpaper =
+ mLockscreenWallpaper != null ? mLockscreenWallpaper.getBitmap() : null;
+ if (lockWallpaper != null) {
+ artworkDrawable = new LockscreenWallpaper.WallpaperDrawable(
+ mBackdropBack.getResources(), lockWallpaper);
+ // We're in the SHADE mode on the SIM screen - yet we still need to show
+ // the lockscreen wallpaper in that mode.
+ allowWhenShade = mStatusBarStateController.getState() == KEYGUARD;
+ }
+ }
+
+ boolean hideBecauseOccluded = getShadeController() != null
+ && getShadeController().isOccluded();
+
+ final boolean hasArtwork = artworkDrawable != null;
+ mColorExtractor.setHasBackdrop(hasArtwork);
+ if (mScrimController != null) {
+ mScrimController.setHasBackdrop(hasArtwork);
+ }
+
+ if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
+ && (mStatusBarStateController.getState() != StatusBarState.SHADE || allowWhenShade)
+ && mBiometricUnlockController != null && mBiometricUnlockController.getMode()
+ != BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ && !hideBecauseOccluded) {
+ // time to show some art!
+ if (mBackdrop.getVisibility() != View.VISIBLE) {
+ mBackdrop.setVisibility(View.VISIBLE);
+ if (allowEnterAnimation) {
+ mBackdrop.setAlpha(0);
+ mBackdrop.animate().alpha(1f);
+ } else {
+ mBackdrop.animate().cancel();
+ mBackdrop.setAlpha(1f);
+ }
+ if (getWindowController() != null) {
+ getWindowController().setBackdropShowing(true);
+ }
+ metaDataChanged = true;
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
+ }
+ }
+ if (metaDataChanged) {
+ if (mBackdropBack.getDrawable() != null) {
+ Drawable drawable =
+ mBackdropBack.getDrawable().getConstantState()
+ .newDrawable(mBackdropFront.getResources()).mutate();
+ mBackdropFront.setImageDrawable(drawable);
+ mBackdropFront.setAlpha(1f);
+ mBackdropFront.setVisibility(View.VISIBLE);
+ } else {
+ mBackdropFront.setVisibility(View.INVISIBLE);
+ }
+
+ if (DEBUG_MEDIA_FAKE_ARTWORK) {
+ final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF);
+ Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c));
+ mBackdropBack.setBackgroundColor(0xFFFFFFFF);
+ mBackdropBack.setImageDrawable(new ColorDrawable(c));
+ } else {
+ mBackdropBack.setImageDrawable(artworkDrawable);
+ }
+
+ if (mBackdropFront.getVisibility() == View.VISIBLE) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from "
+ + mBackdropFront.getDrawable()
+ + " to "
+ + mBackdropBack.getDrawable());
+ }
+ mBackdropFront.animate()
+ .setDuration(250)
+ .alpha(0f).withEndAction(mHideBackdropFront);
+ }
+ }
+ } else {
+ // need to hide the album art, either because we are unlocked, on AOD
+ // or because the metadata isn't there to support it
+ if (mBackdrop.getVisibility() != View.GONE) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
+ }
+ boolean cannotAnimateDoze = getShadeController() != null
+ && getShadeController().isDozing()
+ && !ScrimState.AOD.getAnimateChange();
+ if (mBiometricUnlockController != null && mBiometricUnlockController.getMode()
+ == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ || hideBecauseOccluded || cannotAnimateDoze) {
+
+ // We are unlocking directly - no animation!
+ mBackdrop.setVisibility(View.GONE);
+ mBackdropBack.setImageDrawable(null);
+ if (getWindowController() != null) {
+ getWindowController().setBackdropShowing(false);
+ }
+ } else {
+ if (getWindowController() != null) {
+ getWindowController().setBackdropShowing(false);
+ }
+ mBackdrop.animate()
+ .alpha(0)
+ .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
+ .setDuration(300)
+ .setStartDelay(0)
+ .withEndAction(() -> {
+ mBackdrop.setVisibility(View.GONE);
+ mBackdropFront.animate().cancel();
+ mBackdropBack.setImageDrawable(null);
+ mHandler.post(mHideBackdropFront);
+ });
+ if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ mBackdrop.animate()
+ // Make it disappear faster, as the focus should be on the activity
+ // behind.
+ .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
+ .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+ .setInterpolator(Interpolators.LINEAR)
+ .start();
+ }
+ }
+ }
+ }
+ Trace.endSection();
+ }
+
+ public void setup(BackDropView backdrop, ImageView backdropFront, ImageView backdropBack,
+ BiometricUnlockController biometricUnlockController, ScrimController scrimController,
+ LockscreenWallpaper lockscreenWallpaper) {
+ mBackdrop = backdrop;
+ mBackdropFront = backdropFront;
+ mBackdropBack = backdropBack;
+ mBiometricUnlockController = biometricUnlockController;
+ mScrimController = scrimController;
+ mLockscreenWallpaper = lockscreenWallpaper;
+ }
+
+ /**
+ * Hide the album artwork that is fading out and release its bitmap.
+ */
+ protected final Runnable mHideBackdropFront = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: removing fade layer");
+ }
+ mBackdropFront.setVisibility(View.INVISIBLE);
+ mBackdropFront.animate().cancel();
+ mBackdropFront.setImageDrawable(null);
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index c58eb80efd25..5c8f4cbf6078 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -19,6 +19,7 @@ import android.content.Intent;
import android.os.Handler;
import android.view.View;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -31,9 +32,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
* for affecting the state of the system (e.g. starting an intent, given that the presenter may
* want to perform some action before doing so).
*/
-public interface NotificationPresenter extends NotificationData.Environment,
- NotificationRemoteInputManager.Callback,
- ExpandableNotificationRow.OnExpandClickListener,
+public interface NotificationPresenter extends ExpandableNotificationRow.OnExpandClickListener,
ActivatableNotificationView.OnActivatedListener,
NotificationEntryManager.Callback {
/**
@@ -43,59 +42,23 @@ public interface NotificationPresenter extends NotificationData.Environment,
boolean isPresenterFullyCollapsed();
/**
- * Returns true if the presenter is locked. For example, if the keyguard is active.
- */
- boolean isPresenterLocked();
-
- /**
* Runs the given intent. The presenter may want to run some animations or close itself when
* this happens.
*/
void startNotificationGutsIntent(Intent intent, int appUid, ExpandableNotificationRow row);
/**
- * Returns the Handler for NotificationPresenter.
- */
- Handler getHandler();
-
- /**
* Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
*/
void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation);
/**
- * Called when the locked status of the device is changed for a work profile.
- */
- void onWorkChallengeChanged();
-
- /**
* Called when the current user changes.
* @param newUserId new user id
*/
void onUserSwitched(int newUserId);
/**
- * Gets the NotificationLockscreenUserManager for this Presenter.
- */
- NotificationLockscreenUserManager getNotificationLockscreenUserManager();
-
- /**
- * Wakes the device up if dozing.
- *
- * @param time the time when the request to wake up was issued
- * @param where which view caused this wake up request
- */
- void wakeUpIfDozing(long time, View where);
-
- /**
- * True if the device currently requires a PIN, pattern, or password to unlock.
- *
- * @param userId user id to query about
- * @return true iff the device is locked
- */
- boolean isDeviceLocked(int userId);
-
- /**
* @return true iff the device is in vr mode
*/
boolean isDeviceInVrMode();
@@ -114,7 +77,36 @@ public interface NotificationPresenter extends NotificationData.Environment,
int getMaxNotificationsWhileLocked(boolean recompute);
/**
- * Called when the row states are updated by NotificationViewHierarchyManager.
+ * True if the presenter
+ * @return
+ */
+ default boolean isPresenterLocked() { return false; }
+
+ /**
+ * Called when the row states are updated by {@link NotificationViewHierarchyManager}.
*/
void onUpdateRowStates();
+
+ /**
+ * @return true if the shade is collapsing.
+ */
+ boolean isCollapsing();
+
+ /**
+ * @return true if the shade is collapsing to show an activity over the lock screen
+ */
+ default public boolean isCollapsingToShowActivityOverLockscreen() {
+ return false;
+ }
+
+ /**
+ * Get the {@link ActivityLaunchAnimator} from the presenter so it can be queried by
+ * {@link com.android.systemui.statusbar.phone.StatusBar}
+ * @return the current animator
+ * @deprecated This is only here for now because StatusBar is still the ActivityLaunchAnimator
+ * callback but shouldn't be.
+ */
+ default public ActivityLaunchAnimator getActivityLaunchAnimator() {
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index ea7e03e686b5..f30377ead957 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
@@ -46,9 +47,11 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.InitController;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.RemoteInputView;
import java.io.FileDescriptor;
@@ -97,13 +100,18 @@ public class NotificationRemoteInputManager implements Dumpable {
Dependency.get(NotificationLockscreenUserManager.class);
protected final SmartReplyController mSmartReplyController =
Dependency.get(SmartReplyController.class);
+ private final NotificationEntryManager mEntryManager
+ = Dependency.get(NotificationEntryManager.class);
+
+ // Lazy
+ private ShadeController mShadeController;
protected final Context mContext;
private final UserManager mUserManager;
+ private final KeyguardManager mKeyguardManager;
protected RemoteInputController mRemoteInputController;
protected NotificationPresenter mPresenter;
- protected NotificationEntryManager mEntryManager;
protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
mNotificationLifetimeFinishedCallback;
protected IStatusBarService mBarService;
@@ -115,7 +123,7 @@ public class NotificationRemoteInputManager implements Dumpable {
@Override
public boolean onClickHandler(
final View view, final PendingIntent pendingIntent, final Intent fillInIntent) {
- mPresenter.wakeUpIfDozing(SystemClock.uptimeMillis(), view);
+ getShadeController().wakeUpIfDozing(SystemClock.uptimeMillis(), view);
if (handleRemoteInput(view, pendingIntent)) {
return true;
@@ -240,7 +248,7 @@ public class NotificationRemoteInputManager implements Dumpable {
return true;
}
if (mUserManager.getUserInfo(userId).isManagedProfile()
- && mPresenter.isDeviceLocked(userId)) {
+ && mKeyguardManager.isDeviceLocked(userId)) {
mCallback.onLockedWorkRemoteInput(userId, row, view);
return true;
}
@@ -291,20 +299,26 @@ public class NotificationRemoteInputManager implements Dumpable {
}
};
+ private ShadeController getShadeController() {
+ if (mShadeController == null) {
+ mShadeController = Dependency.get(ShadeController.class);
+ }
+ return mShadeController;
+ }
+
public NotificationRemoteInputManager(Context context) {
mContext = context;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
addLifetimeExtenders();
+ mKeyguardManager = context.getSystemService(KeyguardManager.class);
}
public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager,
Callback callback,
RemoteInputController.Delegate delegate) {
mPresenter = presenter;
- mEntryManager = entryManager;
mCallback = callback;
mRemoteInputController = new RemoteInputController(delegate);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@@ -318,7 +332,7 @@ public class NotificationRemoteInputManager implements Dumpable {
// view it is already canceled, so we'll need to cancel it on the apps behalf
// after sending - unless the app posts an update in the mean time, so wait a
// bit.
- mPresenter.getHandler().postDelayed(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).postDelayed(() -> {
if (mEntriesKeptForRemoteInputActive.remove(entry)) {
mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 7fa042655e53..cd3da123ed32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -34,6 +34,7 @@ import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -103,7 +104,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
@Override
- protected void onFinishInflate() {
+ @VisibleForTesting
+ public void onFinishInflate() {
super.onFinishInflate();
mShelfIcons = findViewById(R.id.content);
mShelfIcons.setClipChildren(false);
@@ -793,7 +795,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
private void setOpenedAmount(float openedAmount) {
mNoAnimationsInThisFrame = openedAmount == 1.0f && mOpenedAmount == 0.0f;
mOpenedAmount = openedAmount;
- if (!mAmbientState.isPanelFullWidth()) {
+ if (!mAmbientState.isPanelFullWidth() || mAmbientState.isDark()) {
// We don't do a transformation at all, lets just assume we are fully opened
openedAmount = 1.0f;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 5b3082b04d58..92765bbec5b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -24,6 +24,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -31,6 +32,7 @@ import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import java.util.ArrayList;
import java.util.HashMap;
@@ -57,6 +59,13 @@ public class NotificationViewHierarchyManager {
Dependency.get(NotificationGroupManager.class);
protected final VisualStabilityManager mVisualStabilityManager =
Dependency.get(VisualStabilityManager.class);
+ private final StatusBarStateController mStatusBarStateController =
+ Dependency.get(StatusBarStateController.class);
+ private final NotificationEntryManager mEntryManager =
+ Dependency.get(NotificationEntryManager.class);
+
+ // Lazy
+ private ShadeController mShadeController;
/**
* {@code true} if notifications not part of a group should by default be rendered in their
@@ -66,9 +75,15 @@ public class NotificationViewHierarchyManager {
private final boolean mAlwaysExpandNonGroupedNotification;
private NotificationPresenter mPresenter;
- private NotificationEntryManager mEntryManager;
private NotificationListContainer mListContainer;
+ private ShadeController getShadeController() {
+ if (mShadeController == null) {
+ mShadeController = Dependency.get(ShadeController.class);
+ }
+ return mShadeController;
+ }
+
public NotificationViewHierarchyManager(Context context) {
Resources res = context.getResources();
mAlwaysExpandNonGroupedNotification =
@@ -76,9 +91,8 @@ public class NotificationViewHierarchyManager {
}
public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager, NotificationListContainer listContainer) {
+ NotificationListContainer listContainer) {
mPresenter = presenter;
- mEntryManager = entryManager;
mListContainer = listContainer;
}
@@ -291,9 +305,9 @@ public class NotificationViewHierarchyManager {
final int N = mListContainer.getContainerChildCount();
int visibleNotifications = 0;
- boolean isLocked = mPresenter.isPresenterLocked();
+ boolean onKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
int maxNotifications = -1;
- if (isLocked) {
+ if (onKeyguard) {
maxNotifications = mPresenter.getMaxNotificationsWhileLocked(true /* recompute */);
}
mListContainer.setMaxDisplayedNotifications(maxNotifications);
@@ -311,9 +325,9 @@ public class NotificationViewHierarchyManager {
boolean isChildNotification =
mGroupManager.isChildInGroupWithSummary(entry.notification);
- row.setOnKeyguard(isLocked);
+ row.setOnKeyguard(onKeyguard);
- if (!isLocked) {
+ if (!onKeyguard) {
// If mAlwaysExpandNonGroupedNotification is false, then only expand the
// very first notification and if it's not a child of grouped notifications.
row.setSystemExpanded(mAlwaysExpandNonGroupedNotification
@@ -321,7 +335,7 @@ public class NotificationViewHierarchyManager {
&& !row.isLowPriority()));
}
- entry.row.setOnAmbient(mPresenter.isDozing());
+ entry.row.setOnAmbient(getShadeController().isDozing());
int userId = entry.notification.getUserId();
boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
entry.notification) && !entry.row.isRemoved();
@@ -340,7 +354,7 @@ public class NotificationViewHierarchyManager {
}
if (suppressedSummary
|| mLockscreenUserManager.shouldHideNotifications(userId)
- || (isLocked && !showOnKeyguard)) {
+ || (onKeyguard && !showOnKeyguard)) {
entry.row.setVisibility(View.GONE);
} else {
boolean wasGone = entry.row.getVisibility() == View.GONE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 78a5817c32b2..12c0fcbed204 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -44,6 +44,7 @@ public class StatusBarStateController {
private int mState;
private int mLastState;
private boolean mLeaveOpenOnKeyguardHide;
+ private boolean mKeyguardRequested;
// TODO: b/115739177 (remove this explicit ordering if we can)
@Retention(SOURCE)
@@ -173,6 +174,14 @@ public class StatusBarStateController {
}
}
+ public void setKeyguardRequested(boolean keyguardRequested) {
+ mKeyguardRequested = keyguardRequested;
+ }
+
+ public boolean isKeyguardRequested() {
+ return mKeyguardRequested;
+ }
+
public static String describe(int state) {
return StatusBarState.toShortString(state);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 24665eac76a7..879934146ac0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -525,12 +525,6 @@ public class CarStatusBar extends StatusBar implements
}
@Override
- public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
- // Do nothing, we don't want to display media art in the lock screen for a car.
- }
-
-
- @Override
public void animateExpandNotificationsPanel() {
// Because space is usually constrained in the auto use-case, there should not be a
// pinned notification when the shade has been expanded. Ensure this by removing all heads-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
index 8cae80635e69..9e99fbb3afc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
@@ -33,10 +33,11 @@ public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
// Dependencies:
private final ForegroundServiceController mFsc =
Dependency.get(ForegroundServiceController.class);
+ private final NotificationEntryManager mEntryManager =
+ Dependency.get(NotificationEntryManager.class);
private final Context mContext;
protected NotificationPresenter mPresenter;
- protected NotificationEntryManager mEntryManager;
protected final AppOpsManager mAppOps;
protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA,
@@ -48,10 +49,8 @@ public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
- public void setUpWithPresenter(NotificationPresenter presenter,
- NotificationEntryManager entryManager) {
+ public void setUpWithPresenter(NotificationPresenter presenter) {
mPresenter = presenter;
- mEntryManager = entryManager;
mAppOps.startWatchingActive(OPS, this);
}
@@ -62,7 +61,7 @@ public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
@Override
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
mFsc.onAppOpChanged(code, uid, packageName, active);
- mPresenter.getHandler().post(() -> {
+ Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index fbf12ed39561..3539fff8bb33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -51,21 +51,22 @@ import android.util.ArraySet;
import android.view.View;
import android.widget.ImageView;
-import androidx.annotation.Nullable;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.InitController;
import com.android.systemui.statusbar.InflationTask;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -74,16 +75,23 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
+import androidx.annotation.Nullable;
+
/**
* The list of currently displaying notifications.
*/
public class NotificationData {
- private final Environment mEnvironment;
- private HeadsUpManager mHeadsUpManager;
+ /**
+ * These dependencies are late init-ed
+ */
+ private KeyguardEnvironment mEnvironment;
+ private ShadeController mShadeController;
+ private NotificationMediaManager mMediaManager;
+ private ForegroundServiceController mFsc;
+ private NotificationLockscreenUserManager mUserManager;
- final ZenModeController mZen = Dependency.get(ZenModeController.class);
- final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class);
+ private HeadsUpManager mHeadsUpManager;
public static final class Entry {
private static final long LAUNCH_COOLDOWN = 2000;
@@ -375,7 +383,8 @@ public class NotificationData {
private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>();
private final ArrayList<Entry> mFilteredForUser = new ArrayList<>();
- private NotificationGroupManager mGroupManager;
+ private final NotificationGroupManager mGroupManager
+ = Dependency.get(NotificationGroupManager.class);
private RankingMap mRankingMap;
private final Ranking mTmpRanking = new Ranking();
@@ -407,7 +416,7 @@ public class NotificationData {
bRank = mRankingB.getRank();
}
- String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
+ String mediaNotification = getMediaManager().getMediaNotificationKey();
// IMPORTANCE_MIN media streams are allowed to drift to the bottom
final boolean aMedia = a.key.equals(mediaNotification)
@@ -442,13 +451,43 @@ public class NotificationData {
}
};
- public NotificationData(Environment environment) {
- mEnvironment = environment;
- mGroupManager = environment.getGroupManager();
+ private KeyguardEnvironment getEnvironment() {
+ if (mEnvironment == null) {
+ mEnvironment = Dependency.get(KeyguardEnvironment.class);
+ }
+ return mEnvironment;
+ }
+
+ private ShadeController getShadeController() {
+ if (mShadeController == null) {
+ mShadeController = Dependency.get(ShadeController.class);
+ }
+ return mShadeController;
+ }
+
+ private NotificationMediaManager getMediaManager() {
+ if (mMediaManager == null) {
+ mMediaManager = Dependency.get(NotificationMediaManager.class);
+ }
+ return mMediaManager;
+ }
+
+ private ForegroundServiceController getFsc() {
+ if (mFsc == null) {
+ mFsc = Dependency.get(ForegroundServiceController.class);
+ }
+ return mFsc;
+ }
+
+ private NotificationLockscreenUserManager getUserManager() {
+ if (mUserManager == null) {
+ mUserManager = Dependency.get(NotificationLockscreenUserManager.class);
+ }
+ return mUserManager;
}
/**
- * Returns the sorted list of active notifications (depending on {@link Environment}
+ * Returns the sorted list of active notifications (depending on {@link KeyguardEnvironment}
*
* <p>
* This call doesn't update the list of active notifications. Call {@link #filterAndSort()}
@@ -468,7 +507,7 @@ public class NotificationData {
for (int i = 0; i < N; i++) {
Entry entry = mEntries.valueAt(i);
final StatusBarNotification sbn = entry.notification;
- if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
+ if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
continue;
}
mFilteredForUser.add(entry);
@@ -719,27 +758,27 @@ public class NotificationData {
*/
public boolean shouldFilterOut(Entry entry) {
final StatusBarNotification sbn = entry.notification;
- if (!(mEnvironment.isDeviceProvisioned() ||
+ if (!(getEnvironment().isDeviceProvisioned() ||
showNotificationEvenIfUnprovisioned(sbn))) {
return true;
}
- if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
+ if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
return true;
}
- if (mEnvironment.isSecurelyLocked(sbn.getUserId()) &&
+ if (getUserManager().isLockscreenPublicMode(sbn.getUserId()) &&
(sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
- || mEnvironment.shouldHideNotifications(sbn.getUserId())
- || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
+ || getUserManager().shouldHideNotifications(sbn.getUserId())
+ || getUserManager().shouldHideNotifications(sbn.getKey()))) {
return true;
}
- if (mEnvironment.isDozing() && shouldSuppressAmbient(entry)) {
+ if (getShadeController().isDozing() && shouldSuppressAmbient(entry)) {
return true;
}
- if (!mEnvironment.isDozing() && shouldSuppressNotificationList(entry)) {
+ if (!getShadeController().isDozing() && shouldSuppressNotificationList(entry)) {
return true;
}
@@ -752,15 +791,16 @@ public class NotificationData {
return true;
}
- if (mFsc.isDungeonNotification(sbn) && !mFsc.isDungeonNeededForUser(sbn.getUserId())) {
+ if (getFsc().isDungeonNotification(sbn)
+ && !getFsc().isDungeonNeededForUser(sbn.getUserId())) {
// this is a foreground-service disclosure for a user that does not need to show one
return true;
}
- if (mFsc.isSystemAlertNotification(sbn)) {
+ if (getFsc().isSystemAlertNotification(sbn)) {
final String[] apps = sbn.getNotification().extras.getStringArray(
Notification.EXTRA_FOREGROUND_APPS);
if (apps != null && apps.length >= 1) {
- if (!mFsc.isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
+ if (!getFsc().isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
return true;
}
}
@@ -838,18 +878,8 @@ public class NotificationData {
/**
* Provides access to keyguard state and user settings dependent data.
*/
- public interface Environment {
- public boolean isSecurelyLocked(int userId);
- public boolean shouldHideNotifications(int userid);
- public boolean shouldHideNotifications(String key);
- public boolean isDeviceProvisioned();
- public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
- public String getCurrentMediaNotificationKey();
- public NotificationGroupManager getGroupManager();
-
- /**
- * @return true iff the device is dozing
- */
- boolean isDozing();
+ public interface KeyguardEnvironment {
+ boolean isDeviceProvisioned();
+ boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 28d339aaeab2..d136c4a24fbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -62,6 +62,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
@@ -74,13 +75,15 @@ import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.NotificationUpdateHandler;
+import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -110,33 +113,31 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
protected final HashMap<String, NotificationData.Entry> mPendingNotifications = new HashMap<>();
protected final NotificationClicker mNotificationClicker = new NotificationClicker();
- // Dependencies:
- protected final NotificationLockscreenUserManager mLockscreenUserManager =
- Dependency.get(NotificationLockscreenUserManager.class);
- protected final NotificationGroupManager mGroupManager =
+ private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
- protected final NotificationGutsManager mGutsManager =
+ private final NotificationGutsManager mGutsManager =
Dependency.get(NotificationGutsManager.class);
- protected final NotificationRemoteInputManager mRemoteInputManager =
- Dependency.get(NotificationRemoteInputManager.class);
- protected final NotificationMediaManager mMediaManager =
- Dependency.get(NotificationMediaManager.class);
- protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
- protected final DeviceProvisionedController mDeviceProvisionedController =
+ private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+ private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
- protected final VisualStabilityManager mVisualStabilityManager =
+ private final VisualStabilityManager mVisualStabilityManager =
Dependency.get(VisualStabilityManager.class);
- protected final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
- protected final ForegroundServiceController mForegroundServiceController =
+ private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final ForegroundServiceController mForegroundServiceController =
Dependency.get(ForegroundServiceController.class);
- protected final NotificationListener mNotificationListener =
- Dependency.get(NotificationListener.class);
- protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
+ private final AmbientPulseManager mAmbientPulseManager =
+ Dependency.get(AmbientPulseManager.class);
+
+ // Lazily retrieved dependencies
+ private NotificationRemoteInputManager mRemoteInputManager;
+ private NotificationMediaManager mMediaManager;
+ private NotificationListener mNotificationListener;
+ private ShadeController mShadeController;
protected IDreamManager mDreamManager;
protected IStatusBarService mBarService;
- protected NotificationPresenter mPresenter;
- protected Callback mCallback;
+ private NotificationPresenter mPresenter;
+ private Callback mCallback;
protected PowerManager mPowerManager;
protected NotificationListenerService.RankingMap mLatestRankingMap;
protected HeadsUpManager mHeadsUpManager;
@@ -149,7 +150,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
= new ArrayList<>();
private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
-
private final class NotificationClicker implements View.OnClickListener {
@Override
@@ -159,7 +159,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
return;
}
- mPresenter.wakeUpIfDozing(SystemClock.uptimeMillis(), v);
+ getShadeController().wakeUpIfDozing(SystemClock.uptimeMillis(), v);
final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
final StatusBarNotification sbn = row.getStatusBarNotification();
@@ -232,20 +232,55 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mMessagingUtil = new NotificationMessagingUtil(context);
+ mNotificationData = new NotificationData();
+ Dependency.get(InitController.class).addPostInitTask(this::onPostInit);
+ }
+
+ private void onPostInit() {
mGroupManager.setPendingEntries(mPendingNotifications);
}
+ /**
+ * Our dependencies can have cyclic references, so some need to be lazy
+ */
+ private NotificationRemoteInputManager getRemoteInputManager() {
+ if (mRemoteInputManager == null) {
+ mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
+ }
+ return mRemoteInputManager;
+ }
+
+ private NotificationMediaManager getMediaManager() {
+ if (mMediaManager == null) {
+ mMediaManager = Dependency.get(NotificationMediaManager.class);
+ }
+ return mMediaManager;
+ }
+
+ private NotificationListener getNotificationListener() {
+ if (mNotificationListener == null) {
+ mNotificationListener = Dependency.get(NotificationListener.class);
+ }
+ return mNotificationListener;
+ }
+
+ private ShadeController getShadeController() {
+ if (mShadeController == null) {
+ mShadeController = Dependency.get(ShadeController.class);
+ }
+ return mShadeController;
+ }
+
public void setUpWithPresenter(NotificationPresenter presenter,
NotificationListContainer listContainer, Callback callback,
HeadsUpManager headsUpManager) {
mPresenter = presenter;
mCallback = callback;
- mNotificationData = new NotificationData(presenter);
mHeadsUpManager = headsUpManager;
mNotificationData.setHeadsUpManager(mHeadsUpManager);
mListContainer = listContainer;
- mHeadsUpObserver = new ContentObserver(mPresenter.getHandler()) {
+ mHeadsUpObserver = new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
@Override
public void onChange(boolean selfChange) {
boolean wasUsing = mUseHeadsUp;
@@ -278,7 +313,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mNotificationLifetimeExtenders.add(mHeadsUpManager);
mNotificationLifetimeExtenders.add(mAmbientPulseManager);
mNotificationLifetimeExtenders.add(mGutsManager);
- mNotificationLifetimeExtenders.addAll(mRemoteInputManager.getLifetimeExtenders());
+ mNotificationLifetimeExtenders.addAll(getRemoteInputManager().getLifetimeExtenders());
for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
extender.setCallback(key -> removeNotification(key, mLatestRankingMap));
@@ -294,6 +329,14 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
return mNotificationData;
}
+ protected Context getContext() {
+ return mContext;
+ }
+
+ protected NotificationPresenter getPresenter() {
+ return mPresenter;
+ }
+
public ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
return mGutsManager::openGuts;
}
@@ -348,7 +391,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
row.setInflationCallback(this);
row.setLongPressListener(getNotificationLongClicker());
mListContainer.bindRow(row);
- mRemoteInputManager.bindRow(row);
+ getRemoteInputManager().bindRow(row);
// Get the app name.
// Note that Notification.Builder#bindHeaderAppName has similar logic
@@ -387,7 +430,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
true);
NotificationData.Entry entry = mNotificationData.get(n.getKey());
- mRemoteInputManager.onPerformRemoveNotification(n, entry);
+ getRemoteInputManager().onPerformRemoveNotification(n, entry);
final String pkg = n.getPackageName();
final String tag = n.getTag();
final int id = n.getId();
@@ -512,7 +555,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
// sending look longer than it takes.
// Also we should not defer the removal if reordering isn't allowed since otherwise
// some notifications can't disappear before the panel is closed.
- boolean ignoreEarliestRemovalTime = mRemoteInputManager.getController().isSpinning(key)
+ boolean ignoreEarliestRemovalTime = getRemoteInputManager().getController().isSpinning(key)
&& !FORCE_REMOTE_INPUT_HISTORY
|| !mVisualStabilityManager.isReorderingAllowed();
mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime);
@@ -547,7 +590,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
extender.setShouldManageLifetime(entry, false /* shouldManage */);
}
- mMediaManager.onNotificationRemoved(key);
+ getMediaManager().onNotificationRemoved(key);
mForegroundServiceController.removeNotification(entry.notification);
if (entry.row != null) {
@@ -602,8 +645,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
boolean isForeground = (row.getStatusBarNotification().getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) != 0;
boolean keepForReply =
- mRemoteInputManager.shouldKeepForRemoteInputHistory(childEntry)
- || mRemoteInputManager.shouldKeepForSmartReplyHistory(childEntry);
+ getRemoteInputManager().shouldKeepForRemoteInputHistory(childEntry)
+ || getRemoteInputManager().shouldKeepForSmartReplyHistory(childEntry);
if (isForeground || keepForReply) {
// the child is a foreground service notification which we can't remove or it's
// a child we're keeping around for reply!
@@ -633,7 +676,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
protected void updateNotification(NotificationData.Entry entry, PackageManager pmUser,
StatusBarNotification sbn, ExpandableNotificationRow row) {
- row.setNeedsRedaction(mLockscreenUserManager.needsRedaction(entry));
+ row.setNeedsRedaction(
+ Dependency.get(NotificationLockscreenUserManager.class).needsRedaction(entry));
boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
boolean isUpdate = mNotificationData.get(entry.key) != null;
boolean wasLowPriority = row.isLowPriority();
@@ -818,7 +862,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mNotificationData.getImportance(key));
boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
- if (mPresenter.isDozing()) {
+ if (getShadeController().isDozing()) {
updateAlertState(entry, shouldPulse(entry), alertAgain, mAmbientPulseManager);
} else {
updateAlertState(entry, shouldHeadsUp(entry), alertAgain, mHeadsUpManager);
@@ -833,7 +877,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
if (DEBUG) {
// Is this for you?
- boolean isForCurrentUser = mPresenter.isNotificationForCurrentProfiles(notification);
+ boolean isForCurrentUser = Dependency.get(KeyguardEnvironment.class)
+ .isNotificationForCurrentProfiles(notification);
Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
}
@@ -917,7 +962,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
public boolean shouldHeadsUp(NotificationData.Entry entry) {
StatusBarNotification sbn = entry.notification;
- if (mPresenter.isDozing()) {
+ if (getShadeController().isDozing()) {
if (DEBUG) {
Log.d(TAG, "No heads up: device is dozing: " + sbn.getKey());
}
@@ -998,7 +1043,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
protected boolean shouldPulse(NotificationData.Entry entry) {
StatusBarNotification sbn = entry.notification;
- if (!mPresenter.isDozing()) {
+ if (!getShadeController().isDozing()) {
if (DEBUG) {
Log.d(TAG, "No pulsing: not dozing: " + sbn.getKey());
}
@@ -1076,7 +1121,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
protected void setNotificationsShown(String[] keys) {
try {
- mNotificationListener.setNotificationsShown(keys);
+ getNotificationListener().setNotificationsShown(keys);
} catch (RuntimeException e) {
Log.d(TAG, "failed setNotificationsShown: ", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index e96e176cc503..b5fbde136c87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -56,8 +56,9 @@ public class NotificationLogger {
private final NotificationListenerService mNotificationListener =
Dependency.get(NotificationListener.class);
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ protected NotificationEntryManager mEntryManager
+ = Dependency.get(NotificationEntryManager.class);
- protected NotificationEntryManager mEntryManager;
protected Handler mHandler = new Handler();
protected IStatusBarService mBarService;
private long mLastVisibilityReportUptimeMs;
@@ -147,9 +148,7 @@ public class NotificationLogger {
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
}
- public void setUpWithEntryManager(NotificationEntryManager entryManager,
- NotificationListContainer listContainer) {
- mEntryManager = entryManager;
+ public void setUpWithContainer(NotificationListContainer listContainer) {
mListContainer = listContainer;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index f4ef0f865a76..24999525ab72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -41,15 +42,23 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -71,14 +80,20 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
// Dependencies:
private final NotificationLockscreenUserManager mLockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
+ private final StatusBarStateController mStatusBarStateController =
+ Dependency.get(StatusBarStateController.class);
+ private final DeviceProvisionedController mDeviceProvisionedController =
+ Dependency.get(DeviceProvisionedController.class);
+ private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
// which notification is currently being longpress-examined by the user
+ private final IStatusBarService mBarService;
private NotificationGuts mNotificationGutsExposed;
private NotificationMenuRowPlugin.MenuItem mGutsMenuItem;
- private NotificationPresenter mPresenter;
private NotificationSafeToRemoveCallback mNotificationLifetimeFinishedCallback;
+ private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
- private NotificationInfo.CheckSaveListener mCheckSaveListener;
+ private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@VisibleForTesting
protected String mKeyToRemoveOnGutsClosed;
@@ -89,16 +104,17 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ mBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
}
public void setUpWithPresenter(NotificationPresenter presenter,
NotificationListContainer listContainer,
- NotificationInfo.CheckSaveListener checkSaveListener,
- OnSettingsClickListener onSettingsClickListener) {
+ CheckSaveListener checkSave, OnSettingsClickListener onSettingsClick) {
mPresenter = presenter;
mListContainer = listContainer;
- mCheckSaveListener = checkSaveListener;
- mOnSettingsClickListener = onSettingsClickListener;
+ mCheckSaveListener = checkSave;
+ mOnSettingsClickListener = onSettingsClick;
}
public void onDensityOrFontScaleChanged(ExpandableNotificationRow row) {
@@ -264,7 +280,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_NOTE_INFO);
guts.resetFalsingCheck();
- mOnSettingsClickListener.onClick(sbn.getKey());
+ mOnSettingsClickListener.onSettingsClick(sbn.getKey());
startAppNotificationSettingsActivity(packageName, appUid, channel, row);
};
}
@@ -279,7 +295,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mCheckSaveListener,
onSettingsClick,
onAppSettingsClick,
- mPresenter.isDeviceProvisioned(),
+ mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
isForBlockingHelper,
row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
@@ -317,6 +333,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mNotificationGutsExposed = guts;
}
+ public ExpandableNotificationRow.LongPressListener getNotificationLongClicker() {
+ return this::openGuts;
+ }
+
/**
* Opens guts on the given ExpandableNotificationRow {@code view}. This handles opening guts for
* the normal half-swipe and long-press use cases via a circular reveal. When the blocking
@@ -385,7 +405,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
guts.setVisibility(View.VISIBLE);
final boolean needsFalsingProtection =
- (mPresenter.isPresenterLocked() &&
+ (mStatusBarStateController.getState() == StatusBarState.KEYGUARD &&
!mAccessibilityManager.isTouchExplorationEnabled());
guts.openControls(
@@ -442,6 +462,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
}
public interface OnSettingsClickListener {
- void onClick(String key);
+ public void onSettingsClick(String key);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 0bc54a33347c..c9cbb40317da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -44,7 +44,6 @@ import android.os.Bundle;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
-
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -88,33 +87,33 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEv
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
+import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.FakeShadowView;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.ShadeViewRefactor;
+import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
+import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationSnooze;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.FakeShadowView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.ShadeViewRefactor;
-import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent;
-import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
@@ -125,6 +124,7 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChan
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -435,6 +435,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private float mVerticalPanelTranslation;
private final NotificationLockscreenUserManager mLockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
+ protected final NotificationGutsManager mGutsManager =
+ Dependency.get(NotificationGutsManager.class);
private final Rect mTmpRect = new Rect();
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
@@ -454,6 +456,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
private NotificationPanelView mNotificationPanel;
+ private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private final NotificationGutsManager
mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
@@ -4740,7 +4743,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- private void setStatusBarState(int statusBarState) {
+ @VisibleForTesting
+ protected void setStatusBarState(int statusBarState) {
mStatusBarState = statusBarState;
mAmbientState.setStatusBarState(statusBarState);
}
@@ -4942,7 +4946,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return;
}
- mStatusBar.addPostCollapseAction(() -> {
+ mShadeController.addPostCollapseAction(() -> {
setDismissAllInProgress(false);
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
if (canChildBeDismissed(rowToRemove)) {
@@ -5042,6 +5046,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mNotificationPanel = notificationPanelView;
}
+ public void updateIconAreaViews() {
+ mIconAreaController.updateNotificationIcons();
+ }
+
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@@ -5654,19 +5662,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public boolean onDraggedDown(View startingChild, int dragLengthY) {
if (mStatusBarState == StatusBarState.KEYGUARD
- && hasActiveNotifications() && (!mStatusBar.isDozing()
- || mStatusBar.isPulsing())) {
+ && hasActiveNotifications()) {
mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_SHADE,
(int) (dragLengthY / mDisplayMetrics.density),
0 /* velocityDp - N/A */);
- // We have notifications, go to locked shade.
- mStatusBar.goToLockedShade(startingChild);
- if (startingChild instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
- row.onExpandedByGesture(true /* drag down is always an open */);
+ if (mNotificationPanel.onDraggedDown() || startingChild != null) {
+ // We have notifications, go to locked shade.
+ mShadeController.goToLockedShade(startingChild);
+ if (startingChild instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
+ row.onExpandedByGesture(true /* drag down is always an open */);
+ }
}
+
return true;
} else {
// abort gesture.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index c094669e67bf..8325bf8085bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -32,6 +32,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.NotificationMediaManager;
import java.io.PrintWriter;
@@ -95,6 +96,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
*/
private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
+ private final NotificationMediaManager mMediaManager =
+ Dependency.get(NotificationMediaManager.class);
private PowerManager mPowerManager;
private Handler mHandler = new Handler();
private PowerManager.WakeLock mWakeLock;
@@ -264,7 +267,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
- mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
+ mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
} else if (mMode == MODE_WAKE_AND_UNLOCK){
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index a781be69c93e..fa63831b5e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -64,11 +64,12 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private StatusBar mStatusBarComponent;
private DarkIconManager mDarkIconManager;
private View mOperatorNameFrame;
+ private CommandQueue mCommandQueue;
private SignalCallback mSignalCallback = new SignalCallback() {
@Override
public void setIsAirplaneMode(NetworkController.IconState icon) {
- mStatusBarComponent.recomputeDisableFlags(true /* animate */);
+ mCommandQueue.recomputeDisableFlags(true /* animate */);
}
};
@@ -78,6 +79,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mNetworkController = Dependency.get(NetworkController.class);
mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
+ mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class);
}
@Override
@@ -116,13 +118,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override
public void onResume() {
super.onResume();
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ mCommandQueue.addCallbacks(this);
}
@Override
public void onPause() {
super.onPause();
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
+ mCommandQueue.removeCallbacks(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 072343a8b101..32c930132977 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -787,6 +787,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mIndicationController = keyguardIndicationController;
}
+ public void showTransientIndication(int id) {
+ mIndicationController.showTransientIndication(id);
+ }
+
public void updateLeftAffordance() {
updateLeftAffordanceIcon();
updateLeftPreview();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 8ac867727e65..235629bbb509 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.phone;
-import static com.android.keyguard.KeyguardHostView.OnDismissAction;
+import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import android.content.Context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 33bc164d807c..836a55fde0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -108,11 +108,7 @@ public class KeyguardClockPositionAlgorithm {
* Dozing and receiving a notification (AOD notification.)
*/
private boolean mPulsing;
-
- /**
- * Distance in pixels between the top of the screen and the first view of the bouncer.
- */
- private int mBouncerTop;
+ private float mEmptyDragAmount;
/**
* Refreshes the dimension values.
@@ -131,9 +127,8 @@ public class KeyguardClockPositionAlgorithm {
}
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
- float panelExpansion, int parentHeight,
- int keyguardStatusHeight, float dark, boolean secure, boolean pulsing,
- int bouncerTop) {
+ float panelExpansion, int parentHeight, int keyguardStatusHeight, float dark,
+ boolean secure, boolean pulsing, float emptyDragAmount) {
mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
@@ -143,7 +138,7 @@ public class KeyguardClockPositionAlgorithm {
mDarkAmount = dark;
mCurrentlySecure = secure;
mPulsing = pulsing;
- mBouncerTop = bouncerTop;
+ mEmptyDragAmount = emptyDragAmount;
}
public void run(Result result) {
@@ -194,15 +189,14 @@ public class KeyguardClockPositionAlgorithm {
}
float clockYRegular = getExpandedClockPosition();
- boolean hasEnoughSpace = mMinTopMargin + mKeyguardStatusHeight < mBouncerTop;
- float clockYTarget = mCurrentlySecure && hasEnoughSpace ?
- mMinTopMargin : -mKeyguardStatusHeight;
+ float clockYBouncer = -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(mPanelExpansion);
- final float clockY = MathUtils.lerp(clockYTarget, clockYRegular, shadeExpansion);
+ float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
+ clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
- return (int) MathUtils.lerp(clockY, clockYDark, mDarkAmount);
+ return (int) (MathUtils.lerp(clockY, clockYDark, mDarkAmount) + mEmptyDragAmount);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
index 76ddca47d33e..6111178bbac9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
@@ -16,9 +16,7 @@
package com.android.systemui.statusbar.phone;
-import android.annotation.Nullable;
-
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
/** Executes actions that require the screen to be unlocked. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
index d67669289915..462201c6dac2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.phone;
import android.util.Log;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
/**
* Executes actions that require the screen to be unlocked. Delegates the actual handling to an
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
new file mode 100644
index 000000000000..b3423a84542e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.phone;
+
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
+import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
+
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+public class KeyguardEnvironmentImpl implements KeyguardEnvironment {
+
+ private static final String TAG = "KeyguardEnvironmentImpl";
+
+ private final NotificationLockscreenUserManager mLockscreenUserManager =
+ Dependency.get(NotificationLockscreenUserManager.class);
+ private final DeviceProvisionedController mDeviceProvisionedController =
+ Dependency.get(DeviceProvisionedController.class);
+ private final NotificationMediaManager mMediaManager =
+ Dependency.get(NotificationMediaManager.class);
+
+ public KeyguardEnvironmentImpl() {
+ }
+
+ @Override // NotificationData.KeyguardEnvironment
+ public boolean isDeviceProvisioned() {
+ return mDeviceProvisionedController.isDeviceProvisioned();
+ }
+
+ @Override // NotificationData.KeyguardEnvironment
+ public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
+ final int notificationUserId = n.getUserId();
+ if (DEBUG && MULTIUSER_DEBUG) {
+ Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", n,
+ mLockscreenUserManager.getCurrentUserId(), notificationUserId));
+ }
+ return mLockscreenUserManager.isCurrentProfile(notificationUserId);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 40ddf5b497ae..673cdb7c78ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -40,6 +40,8 @@ import android.app.WallpaperColors;
import android.util.Log;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.Dependency;
+import com.android.systemui.statusbar.NotificationMediaManager;
import libcore.io.IoUtils;
@@ -52,6 +54,9 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
private static final String TAG = "LockscreenWallpaper";
+ private final NotificationMediaManager mMediaManager =
+ Dependency.get(NotificationMediaManager.class);
+
private final StatusBar mBar;
private final WallpaperManager mWallpaperManager;
private final Handler mH;
@@ -193,7 +198,7 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
mCached = true;
mCache = result.bitmap;
mUpdateMonitor.setHasLockscreenWallpaper(result.bitmap != null);
- mBar.updateMediaMetaData(
+ mMediaManager.updateMediaMetaData(
true /* metaDataChanged */, true /* allowEnterAnimation */);
}
mLoader = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 80f35060b737..f105f6121709 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -95,6 +95,7 @@ import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.statusbar.policy.RotationLockController;
@@ -126,6 +127,9 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
+ private final DeviceProvisionedController mDeviceProvisionedController =
+ Dependency.get(DeviceProvisionedController.class);
+
protected NavigationBarView mNavigationBarView = null;
protected AssistManager mAssistManager;
@@ -725,7 +729,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
}
private boolean shouldDisableNavbarGestures() {
- return !mStatusBar.isDeviceProvisioned()
+ return !mDeviceProvisionedController.isDeviceProvisioned()
|| (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e92656ae0c02..a2bd00eae6c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -350,7 +350,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
@Override
public boolean onTouchEvent(MotionEvent event) {
shouldDeadZoneConsumeTouchEvents(event);
- if (mGestureHelper.onTouchEvent(event)) {
+ if (mGestureHelper != null && mGestureHelper.onTouchEvent(event)) {
return true;
}
return super.onTouchEvent(event);
@@ -680,7 +680,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
public void onNavigationButtonLongPress(View v) {
- mGestureHelper.onNavigationButtonLongPress(v);
+ if (mGestureHelper != null) {
+ mGestureHelper.onNavigationButtonLongPress(v);
+ }
}
public void onPanelExpandedChange(boolean expanded) {
@@ -807,7 +809,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
@Override
protected void onDraw(Canvas canvas) {
- mGestureHelper.onDraw(canvas);
+ if (mGestureHelper != null) {
+ mGestureHelper.onDraw(canvas);
+ }
mDeadZone.onDraw(canvas);
super.onDraw(canvas);
}
@@ -819,7 +823,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
updateButtonLocationOnScreen(getRecentsButton(), mRecentsButtonBounds);
updateButtonLocationOnScreen(getRotateSuggestionButton(), mRotationButtonBounds);
- mGestureHelper.onLayout(changed, left, top, right, bottom);
+ if (mGestureHelper != null) {
+ mGestureHelper.onLayout(changed, left, top, right, bottom);
+ }
mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
}
@@ -1117,7 +1123,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
pw.println(" }");
mContextualButtonGroup.dump(pw);
- mGestureHelper.dump(pw);
+ if (mGestureHelper != null) {
+ mGestureHelper.dump(pw);
+ }
mRecentsOnboarding.dump(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 75077029c16b..5ee08237e228 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
.ExpandAnimationParameters;
@@ -38,6 +39,7 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.PowerManager;
+import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
@@ -64,10 +66,12 @@ import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFragment;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
@@ -104,6 +108,11 @@ public class NotificationPanelView extends PanelView implements
private static final boolean DEBUG = false;
+ private static final boolean EXPAND_ON_WAKE_UP = SystemProperties.getBoolean(
+ "persist.sysui.expand_shade_on_wake_up", true);
+ private static final boolean WAKE_UP_TO_SHADE = SystemProperties.getBoolean(
+ "persist.sysui.go_to_shade_on_wake_up", true);
+
/**
* Fling expanding QS.
*/
@@ -280,6 +289,12 @@ public class NotificationPanelView extends PanelView implements
*/
private float mLinearDarkAmount;
+ /**
+ * State where the device isn't dozing anymore, but the lock screen isn't fully awake.
+ * The screen will be dimmed down with the shade collapsed.
+ */
+ private boolean mSemiAwake;
+
private float mDarkAmountTarget;
private boolean mPulsing;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
@@ -325,6 +340,11 @@ public class NotificationPanelView extends PanelView implements
Dependency.get(NotificationEntryManager.class);
private final StateListener mListener = this::setBarState;
+ private final CommandQueue mCommandQueue;
+ private final NotificationLockscreenUserManager mLockscreenUserManager =
+ Dependency.get(NotificationLockscreenUserManager.class);
+ private final ShadeController mShadeController =
+ Dependency.get(ShadeController.class);
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -335,6 +355,7 @@ public class NotificationPanelView extends PanelView implements
setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
mAlphaPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
setPanelAlpha(255, false /* animate */);
+ mCommandQueue = getComponent(context, CommandQueue.class);
}
private void setStatusBar(StatusBar bar) {
@@ -573,7 +594,7 @@ public class NotificationPanelView extends PanelView implements
mInterpolatedDarkAmount,
mStatusBar.isKeyguardCurrentlySecure(),
mPulsing,
- mBouncerTop);
+ mEmptyDragAmount);
mClockPositionAlgorithm.run(mClockPositionResult);
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
@@ -618,7 +639,7 @@ public class NotificationPanelView extends PanelView implements
if (suppressedSummary) {
continue;
}
- if (!mStatusBar.getNotificationLockscreenUserManager().shouldShowOnKeyguard(
+ if (!mLockscreenUserManager.shouldShowOnKeyguard(
row.getStatusBarNotification())) {
continue;
}
@@ -1235,6 +1256,12 @@ public class NotificationPanelView extends PanelView implements
if (keyguardShowing) {
updateDozingVisibilities(false /* animate */);
}
+
+ // Expand notification shade if the device was is semi-awake state
+ if (mBarState == StatusBarState.SHADE && isSemiAwake()) {
+ mNotificationStackScroller.setDark(false /* dark */, false /* animated */,
+ null /* touchLocation */);
+ }
resetVerticalPanelPosition();
updateQsState();
}
@@ -2335,13 +2362,7 @@ public class NotificationPanelView extends PanelView implements
}
public void setEmptyDragAmount(float amount) {
- float factor = 0.8f;
- if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
- factor = 0.4f;
- } else if (!mStatusBar.hasActiveNotifications()) {
- factor = 0.4f;
- }
- mEmptyDragAmount = amount * factor;
+ mEmptyDragAmount = amount * 0.2f;
positionClockAndNotifications();
}
@@ -2402,7 +2423,7 @@ public class NotificationPanelView extends PanelView implements
return true;
case StatusBarState.SHADE_LOCKED:
if (!mQsExpanded) {
- mStatusBar.goToKeyguard();
+ mShadeController.goToKeyguard();
}
return true;
case StatusBarState.SHADE:
@@ -2605,7 +2626,7 @@ public class NotificationPanelView extends PanelView implements
}
if (showIconsWhenExpanded != mShowIconsWhenExpanded) {
mShowIconsWhenExpanded = showIconsWhenExpanded;
- mStatusBar.recomputeDisableFlags(false);
+ mCommandQueue.recomputeDisableFlags(false);
}
}
@@ -2769,11 +2790,14 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setAnimationsEnabled(!disabled);
}
- public void setDozing(boolean dozing, boolean animate,
- PointF wakeUpTouchLocation) {
- mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
+ public void setDozing(boolean dozing, boolean animate, PointF wakeUpTouchLocation,
+ boolean passiveInterrupted) {
if (dozing == mDozing) return;
mDozing = dozing;
+ mSemiAwake = !EXPAND_ON_WAKE_UP && !mDozing && passiveInterrupted;
+ if (!mSemiAwake) {
+ mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
+ }
if (mBarState == StatusBarState.KEYGUARD
|| mBarState == StatusBarState.SHADE_LOCKED) {
@@ -2787,24 +2811,38 @@ public class NotificationPanelView extends PanelView implements
} else {
mDarkAnimator.cancel();
}
+ if (mSemiAwake) {
+ setDarkAmount(0, 0);
+ }
}
mDarkAmountTarget = darkAmount;
- if (animate) {
- if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
- mDarkInterpolator = dozing
- ? Interpolators.FAST_OUT_SLOW_IN
- : Interpolators.TOUCH_RESPONSE_REVERSE;
+ if (!mSemiAwake) {
+ if (animate) {
+ startDarkAnimation();
+ } else {
+ setDarkAmount(darkAmount, darkAmount);
}
- mNotificationStackScroller.notifyDarkAnimationStart(dozing);
- mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount);
- mDarkAnimator.setInterpolator(Interpolators.LINEAR);
- mDarkAnimator.setDuration(mNotificationStackScroller.getDarkAnimationDuration(dozing));
- mDarkAnimator.start();
- } else {
- setDarkAmount(darkAmount, darkAmount);
}
}
+ public boolean isSemiAwake() {
+ return mSemiAwake;
+ }
+
+ private void startDarkAnimation() {
+ if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
+ mDarkInterpolator = mDozing
+ ? Interpolators.FAST_OUT_SLOW_IN
+ : Interpolators.TOUCH_RESPONSE_REVERSE;
+ }
+ mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
+ mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozing ? 1 : 0);
+ mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+ mDarkAnimator.setDuration(
+ mNotificationStackScroller.getDarkAnimationDuration(mDozing));
+ mDarkAnimator.start();
+ }
+
private void setDarkAmount(float linearAmount, float amount) {
mInterpolatedDarkAmount = amount;
mLinearDarkAmount = linearAmount;
@@ -2875,7 +2913,7 @@ public class NotificationPanelView extends PanelView implements
if (hideIcons != mHideIconsDuringNotificationLaunch) {
mHideIconsDuringNotificationLaunch = hideIcons;
if (!hideIcons) {
- mStatusBar.recomputeDisableFlags(true /* animate */);
+ mCommandQueue.recomputeDisableFlags(true /* animate */);
}
}
}
@@ -2943,6 +2981,7 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.updateSpeedBumpIndex();
mNotificationStackScroller.updateFooter();
updateShowEmptyShadeView();
+ mNotificationStackScroller.updateIconAreaViews();
}
public void onUpdateRowStates() {
@@ -2989,4 +3028,26 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setScrimController(scrimController);
updateShowEmptyShadeView();
}
+
+ public void showTransientIndication(int id) {
+ mKeyguardBottomArea.showTransientIndication(id);
+ }
+
+ /**
+ * Whenever a user drags down on the empty area (pulling down the shade and clock) and lets go.
+ *
+ * @return {@code true} if dragging down should take the user to SHADE_LOCKED.
+ */
+ public boolean onDraggedDown() {
+ if (isSemiAwake()) {
+ mSemiAwake = false;
+ mNotificationStackScroller.setDark(false /* dark */, true /* animate */,
+ null /* touchLocation */);
+ startDarkAnimation();
+ mStatusBar.updateScrimController();
+
+ return WAKE_UP_TO_SHADE;
+ }
+ return true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 59863ecb1191..2129835945d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+import static com.android.systemui.SysUiServiceProvider.getComponent;
import android.annotation.Nullable;
import android.content.Context;
@@ -42,6 +43,7 @@ import android.widget.LinearLayout;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
@@ -52,6 +54,7 @@ public class PhoneStatusBarView extends PanelBar {
private static final boolean DEBUG = StatusBar.DEBUG;
private static final boolean DEBUG_GESTURES = false;
private static final int NO_VALUE = Integer.MIN_VALUE;
+ private final CommandQueue mCommandQueue;
StatusBar mBar;
@@ -82,6 +85,7 @@ public class PhoneStatusBarView extends PanelBar {
super(context, attrs);
mBarTransitions = new PhoneStatusBarTransitions(this);
+ mCommandQueue = getComponent(context, CommandQueue.class);
}
public BarTransitions getBarTransitions() {
@@ -166,7 +170,7 @@ public class PhoneStatusBarView extends PanelBar {
@Override
public boolean panelEnabled() {
- return mBar.panelsEnabled();
+ return mCommandQueue.panelsEnabled();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index e3a7b75554d3..1bed26dd3474 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -63,7 +63,7 @@ import java.util.function.Consumer;
public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener,
Dumpable {
- private static final String TAG = "ScrimController";
+ static final String TAG = "ScrimController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
@@ -96,6 +96,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
*/
public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.70f;
/**
+ * A scrim varies its opacity based on a busyness factor, for example
+ * how many notifications are currently visible.
+ */
+ public static final float GRADIENT_SCRIM_DARK_KEYGUARD = 0.80f;
+ /**
* The most common scrim, the one under the keyguard.
*/
protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA;
@@ -361,7 +366,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mExpansionFraction = fraction;
final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED
- || mState == ScrimState.KEYGUARD;
+ || mState == ScrimState.KEYGUARD || mState == ScrimState.DARK_KEYGUARD;
if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 085f7b6394ef..ade063d9718f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -49,6 +49,8 @@ public enum ScrimState {
// fade it out afterwards.
mBlankScreen = true;
}
+ } else if (previousState == ScrimState.KEYGUARD) {
+ mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
} else {
mAnimationDuration = ScrimController.ANIMATION_DURATION;
}
@@ -59,8 +61,24 @@ public enum ScrimState {
@Override
public float getBehindAlpha(float busynessFactor) {
return MathUtils.map(0 /* start */, 1 /* stop */,
- mScrimBehindAlphaKeyguard, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
- busynessFactor);
+ mScrimBehindAlphaKeyguard, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
+ busynessFactor);
+ }
+ },
+
+ /**
+ * On semi-awake lock screen.
+ */
+ DARK_KEYGUARD(7) {
+
+ @Override
+ public void prepare(ScrimState previousState) {
+ mBlankScreen = mDisplayRequiresBlanking && previousState != ScrimState.AOD;
+ mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+ mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_DARK_KEYGUARD;
+ mCurrentInFrontAlpha = 0;
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
}
},
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
new file mode 100644
index 000000000000..e546119968aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -0,0 +1,147 @@
+/*
+ * 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.phone;
+
+import android.view.View;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+
+/**
+ * {@link ShadeController} is an abstraction of the work that used to be hard-coded in
+ * {@link StatusBar}. The shade itself represents the concept of the status bar window state, and
+ * can be in multiple states: dozing, locked, showing the bouncer, occluded, etc. All/some of these
+ * are coordinated with {@link StatusBarKeyguardViewManager} via
+ * {@link com.android.systemui.keyguard.KeyguardViewMediator} and others.
+ */
+public interface ShadeController {
+
+ /**
+ * Shows the keyguard bouncer - the password challenge on the lock screen
+ *
+ * @param scrimmed true when the bouncer should show scrimmed, false when the user will be
+ * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
+ */
+ void showBouncer(boolean scrimmed);
+
+ /**
+ * Make our window larger and the panel expanded
+ */
+ void instantExpandNotificationsPanel();
+
+ /**
+ * If the notifications panel is not fully expanded, collapse it animated.
+ *
+ * @return Seems to always return false
+ */
+ boolean closeShadeIfOpen();
+
+ /**
+ * Add a runnable for NotificationPanelView to post when the panel is expanded.
+ *
+ * @param action the action to post
+ */
+ void postOnShadeExpanded(Runnable action);
+
+ /**
+ * Add a runnable to be executed after the shade collapses. Post-collapse runnables are
+ * aggregated and run serially.
+ *
+ * @param action the action to execute
+ */
+ void addPostCollapseAction(Runnable action);
+
+ /**
+ * Ask shade controller to set the state to {@link StatusBarState#KEYGUARD}, but only from
+ * {@link StatusBarState#SHADE_LOCKED}
+ */
+ void goToKeyguard();
+
+ /**
+ * When the keyguard is showing and covered by something (bouncer, keyguard activity, etc.) it
+ * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager}
+ *
+ * @return whether the keyguard is currently occluded
+ */
+ boolean isOccluded();
+
+ /**
+ * Notify the shade controller that the current user changed
+ *
+ * @param newUserId userId of the new user
+ */
+ void setLockscreenUser(int newUserId);
+
+ /**
+ * Dozing is when the screen is in AOD or asleep
+ *
+ * @return true if we are dozing
+ */
+ boolean isDozing();
+
+ /**
+ * Ask the display to wake up if currently dozing, else do nothing
+ *
+ * @param time when to wake up
+ * @param view the view requesting the wakeup
+ */
+ void wakeUpIfDozing(long time, View view);
+
+ /**
+ * If secure with redaction: Show bouncer, go to unlocked shade.
+ *
+ * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
+ *
+ * @param startingChild The view to expand after going to the shade.
+ */
+ void goToLockedShade(View startingChild);
+
+ /**
+ * Adds a {@param runnable} to be executed after Keyguard is gone.
+ */
+ void addAfterKeyguardGoneRunnable(Runnable runnable);
+
+ /**
+ * Close the shade if it was open
+ *
+ * @return true if the shade was open, else false
+ */
+ boolean collapsePanel();
+
+ /**
+ * If {@param animate}, does the same as {@link #collapsePanel()}. Otherwise, instantly collapse
+ * the panel. Post collapse runnables will be executed
+ *
+ * @param animate
+ */
+ void collapsePanel(boolean animate);
+
+ /**
+ * Callback to tell the shade controller that an activity launch animation was canceled
+ */
+ void onLaunchAnimationCancelled();
+
+ /**
+ * When notifications update, give the shade controller a chance to do thing in response to
+ * the new data set
+ */
+ void updateAreThereNotifications();
+
+ /**
+ * Callback to notify the shade controller that a {@link ActivatableNotificationView} has become
+ * inactive
+ */
+ void onActivationReset();
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index cc9adb86a6b4..f56e219b073a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -26,10 +26,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
-import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID;
-import static com.android.systemui.statusbar.NotificationLockscreenUserManager
- .NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
+import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
import static com.android.systemui.statusbar.NotificationMediaManager.DEBUG_MEDIA;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
@@ -54,7 +52,6 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
-import android.app.TaskStackBuilder;
import android.app.UiModeManager;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
@@ -65,31 +62,21 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IntentSender;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
-import android.media.MediaMetadata;
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -105,14 +92,10 @@ import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
@@ -122,7 +105,6 @@ import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -130,19 +112,15 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.widget.DateTimeView;
import android.widget.ImageView;
-import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.MessagingGroup;
import com.android.internal.widget.MessagingMessage;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
@@ -152,11 +130,11 @@ import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
+import com.android.systemui.InitController;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
@@ -185,38 +163,34 @@ import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
-import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.AmbientPulseManager;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.AppOpsListener;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationData.Entry;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.NotificationInfo;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.ScrimView;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.AppOpsListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
@@ -230,7 +204,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
@@ -253,9 +226,9 @@ import java.util.Map;
public class StatusBar extends SystemUI implements DemoMode,
ActivityStarter, OnUnlockMethodChangedListener,
OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
- ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter,
- StatusBarStateController.StateListener, AmbientPulseManager.OnAmbientChangedListener,
- ActivityLaunchAnimator.Callback {
+ ColorExtractor.OnColorsChangedListener, ConfigurationListener,
+ StatusBarStateController.StateListener, ShadeController,
+ ActivityLaunchAnimator.Callback, AmbientPulseManager.OnAmbientChangedListener {
public static final boolean MULTIUSER_DEBUG = false;
public static final boolean ENABLE_CHILD_NOTIFICATIONS
@@ -324,10 +297,10 @@ public class StatusBar extends SystemUI implements DemoMode,
/** If true, the system is in the half-boot-to-decryption-screen state.
* Prudently disable QS and notifications. */
- private static final boolean ONLY_CORE_APPS;
+ public static final boolean ONLY_CORE_APPS;
/** If true, the lockscreen will show a distinct wallpaper */
- private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
+ public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
static {
boolean onlyCoreApps;
@@ -376,7 +349,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
- private TextView mNotificationPanelDebugText;
// settings
private QSPanel mQSPanel;
@@ -385,15 +357,12 @@ public class StatusBar extends SystemUI implements DemoMode,
// RemoteInputView to be activated after unlock
private View mPendingRemoteInputView;
- private View mPendingWorkRemoteInputView;
private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler =
Dependency.get(RemoteInputQuickSettingsDisabler.class);
private View mReportRejectedTouch;
- private int mMaxAllowedKeyguardNotifications;
-
private boolean mExpandedVisible;
private final int[] mAbsPos = new int[2];
@@ -460,7 +429,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private int mInteractingWindows;
private boolean mAutohideSuspended;
private int mStatusBarMode;
- private int mMaxKeyguardNotifications;
private ViewMediatorCallback mKeyguardViewMediatorCallback;
protected ScrimController mScrimController;
@@ -479,9 +447,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected BackDropView mBackdrop;
protected ImageView mBackdropFront, mBackdropBack;
- protected final PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
- protected final PorterDuffXfermode mSrcOverXferMode =
- new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
private NotificationMediaManager mMediaManager;
protected NotificationLockscreenUserManager mLockscreenUserManager;
@@ -524,7 +489,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mIsOccluded;
private boolean mWereIconsJustHidden;
private boolean mBouncerWasShowingWhenHidden;
- private boolean mIsCollapsingToShowActivityOverLockscreen;
// Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
// this animation is tied to the scrim for historic reasons.
@@ -557,13 +521,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private BatteryController mBatteryController;
protected boolean mPanelExpanded;
private UiModeManager mUiModeManager;
- private boolean mKeyguardRequested;
private boolean mIsKeyguard;
private LogMaker mStatusBarStateLog;
- private final LockscreenGestureLogger mLockscreenGestureLogger =
- Dependency.get(LockscreenGestureLogger.class);
protected NotificationIconAreaController mNotificationIconAreaController;
- private boolean mReinflateNotificationsOnUserSwitched;
@Nullable private View mAmbientIndicationContainer;
private SysuiColorExtractor mColorExtractor;
private ScreenLifecycle mScreenLifecycle;
@@ -598,10 +558,10 @@ public class StatusBar extends SystemUI implements DemoMode,
private NavigationBarFragment mNavigationBar;
private View mNavigationBarView;
- protected ActivityLaunchAnimator mActivityLaunchAnimator;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private boolean mVibrateOnOpening;
private VibratorHelper mVibratorHelper;
+ protected NotificationPresenter mPresenter;
@Override
public void start() {
@@ -626,11 +586,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mEntryManager = Dependency.get(NotificationEntryManager.class);
mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
mAppOpsListener = Dependency.get(AppOpsListener.class);
- mAppOpsListener.setUpWithPresenter(this, mEntryManager);
mZenController = Dependency.get(ZenModeController.class);
mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
-
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+
mColorExtractor.addOnColorsChangedListener(this);
mStatusBarStateController.addListener(this, StatusBarStateController.RANK_STATUS_BAR);
@@ -659,17 +619,12 @@ public class StatusBar extends SystemUI implements DemoMode,
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
-
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mRecents = getComponent(Recents.class);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mLockPatternUtils = new LockPatternUtils(mContext);
-
- mMediaManager.setUpWithPresenter(this, mEntryManager);
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);
@@ -696,7 +651,6 @@ public class StatusBar extends SystemUI implements DemoMode,
wallpaperChangedFilter, null /* broadcastPermission */, null /* scheduler */);
mWallpaperChangedReceiver.onReceive(mContext, null);
- mLockscreenUserManager.setUpWithPresenter(this, mEntryManager);
mCommandQueue.disable(switches[0], switches[6], false /* animate */);
setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
fullscreenStackBounds, dockedStackBounds);
@@ -711,7 +665,16 @@ public class StatusBar extends SystemUI implements DemoMode,
}
// Set up the initial notification state.
- mNotificationListener.setUpWithPresenter(this, mEntryManager);
+ mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
+ mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
+ mScrimController, this);
+ mAppOpsListener.setUpWithPresenter(mPresenter);
+ mNotificationListener.setUpWithPresenter(mPresenter);
+ mNotificationShelf.setOnActivatedListener(mPresenter);
+ mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
+
+ // set the initial view visibility
+ Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
if (DEBUG) {
Log.d(TAG, String.format(
@@ -724,24 +687,12 @@ public class StatusBar extends SystemUI implements DemoMode,
));
}
- setHeadsUpUser(mLockscreenUserManager.getCurrentUserId());
-
IntentFilter internalFilter = new IntentFilter();
internalFilter.addAction(BANNER_ACTION_CANCEL);
internalFilter.addAction(BANNER_ACTION_SETUP);
mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
null);
- IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
- Context.VR_SERVICE));
- if (vrManager != null) {
- try {
- vrManager.registerListener(mVrStateCallbacks);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register VR mode state listener: " + e);
- }
- }
-
IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
ServiceManager.getService(Context.WALLPAPER_SERVICE));
try {
@@ -788,24 +739,9 @@ public class StatusBar extends SystemUI implements DemoMode,
// into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
- NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
mZenController.addCallback(this);
- mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow,
- this,
- mNotificationPanel,
- notifListContainer);
- mGutsManager.setUpWithPresenter(this, notifListContainer, mCheckSaveListener,
- key -> {
- try {
- mBarService.onNotificationSettingsViewed(key);
- } catch (RemoteException e) {
- // if we're here we're dead
- }
- });
- mNotificationLogger.setUpWithEntryManager(mEntryManager, notifListContainer);
- mAboveShelfObserver = new AboveShelfObserver(mStackScroller);
- mAboveShelfObserver.setListener(mStatusBarWindow.findViewById(
- R.id.notification_container_parent));
+ NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
+ mNotificationLogger.setUpWithContainer(notifListContainer);
mNotificationIconAreaController = SystemUIFactory.getInstance()
.createNotificationIconAreaController(context, this);
@@ -850,7 +786,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
mHeadsUpAppearanceController.readFrom(oldController);
mStatusBarWindow.setStatusBarView(mStatusBarView);
- setAreThereNotifications();
+ updateAreThereNotifications();
checkBarModes();
}).getFragmentManager()
.beginTransaction()
@@ -872,13 +808,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mGroupManager.setHeadsUpManager(mHeadsUpManager);
putComponent(HeadsUpManager.class, mHeadsUpManager);
- mEntryManager.setUpWithPresenter(this, notifListContainer, this, mHeadsUpManager);
- mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, notifListContainer);
-
- if (MULTIUSER_DEBUG) {
- mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
- mNotificationPanelDebugText.setVisibility(View.VISIBLE);
- }
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
@@ -890,14 +819,16 @@ public class StatusBar extends SystemUI implements DemoMode,
// no window manager? good luck with that
}
- mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
- mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front);
- mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back);
-
if (ENABLE_LOCKSCREEN_WALLPAPER) {
mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
}
+ mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
+ mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front);
+ mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back);
+ mMediaManager.setup(mBackdrop, mBackdropFront, mBackdropBack, mBiometricUnlockController,
+ mScrimController, mLockscreenWallpaper);
+
mKeyguardIndicationController =
SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
@@ -908,9 +839,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mAmbientIndicationContainer = mStatusBarWindow.findViewById(
R.id.ambient_indication_container);
- // set the initial view visibility
- setAreThereNotifications();
-
// TODO: Find better place for this callback.
mBatteryController.addCallback(new BatteryStateChangeCallback() {
@Override
@@ -1053,6 +981,30 @@ public class StatusBar extends SystemUI implements DemoMode,
ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
}
+ @Override
+ public void addAfterKeyguardGoneRunnable(Runnable runnable) {
+ mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
+ }
+
+ @Override
+ public boolean isDozing() {
+ return mDozing && mNotificationPanel.isFullyDark();
+ }
+
+ @Override
+ public void wakeUpIfDozing(long time, View where) {
+ if (mDozing) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ pm.wakeUp(time, "com.android.systemui:NODOZE");
+ mWakeUpComingFromTouch = true;
+ where.getLocationInWindow(mTmpInt2);
+ mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
+ mTmpInt2[1] + where.getHeight() / 2);
+ mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+ mFalsingManager.onScreenOnFromTouch();
+ }
+ }
+
protected void createNavigationBar() {
mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
mNavigationBar = (NavigationBarFragment) fragment;
@@ -1084,7 +1036,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationShelf =
(NotificationShelf) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_shelf, mStackScroller, false);
- mNotificationShelf.setOnActivatedListener(this);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -1092,13 +1043,6 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onDensityOrFontScaleChanged() {
MessagingMessage.dropCache();
MessagingGroup.dropCache();
- // start old BaseStatusBar.onDensityOrFontScaleChanged().
- if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
- mEntryManager.updateNotificationsOnDensityOrFontScaleChanged();
- } else {
- mReinflateNotificationsOnUserSwitched = true;
- }
- // end old BaseStatusBar.onDensityOrFontScaleChanged().
// TODO: Remove this.
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.onDensityOrFontScaleChanged();
@@ -1169,8 +1113,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController, this, UnlockMethodCache.getInstance(mContext));
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController);
- //TODO: Can we put the keyguard view manager in Dependency?
- mLockscreenUserManager.setKeyguardViewManager(mStatusBarKeyguardViewManager);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -1234,73 +1176,13 @@ public class StatusBar extends SystemUI implements DemoMode,
return true;
}
- @Override
- public void onPerformRemoveNotification(StatusBarNotification n) {
- if (mNotificationPanel.hasPulsingNotifications() &&
- !mAmbientPulseManager.hasNotifications()) {
- // We were showing a pulse for a notification, but no notifications are pulsing anymore.
- // Finish the pulse.
- mDozeScrimController.pulseOutNow();
- }
- }
-
- @Override
- public void updateNotificationViews() {
- // The function updateRowStates depends on both of these being non-null, so check them here.
- // We may be called before they are set from DeviceProvisionedController's callback.
- if (mScrimController == null) return;
-
- // Do not modify the notifications during collapse.
- if (isCollapsing()) {
- addPostCollapseAction(this::updateNotificationViews);
- return;
- }
-
- mViewHierarchyManager.updateNotificationViews();
-
- mNotificationPanel.updateNotificationViews();
-
- updateQsExpansionEnabled();
-
- // Let's also update the icons
- mNotificationIconAreaController.updateNotificationIcons();
- }
-
- @Override
- public void onNotificationAdded(Entry shadeEntry) {
- // Recalculate the position of the sliding windows and the titles.
- setAreThereNotifications();
- }
-
- @Override
- public void onNotificationUpdated(StatusBarNotification notification) {
- setAreThereNotifications();
- }
-
- @Override
- public void onNotificationRemoved(String key, StatusBarNotification old) {
- if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
-
- if (old != null) {
- if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
- && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
- if (mState == StatusBarState.SHADE) {
- animateCollapsePanels();
- } else if (mState == StatusBarState.SHADE_LOCKED && !isCollapsing()) {
- goToKeyguard();
- }
- }
- }
- setAreThereNotifications();
- }
-
/**
* Disable QS if device not provisioned.
* If the user switcher is simple then disable QS during setup because
* the user intends to use the lock screen user switcher, QS in not needed.
*/
private void updateQsExpansionEnabled() {
- mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned()
+ mNotificationPanel.setQsExpansionEnabled(mDeviceProvisionedController.isDeviceProvisioned()
&& (mUserSetup || mUserSwitcherController == null
|| !mUserSwitcherController.isSimpleUserSwitcher())
&& ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0)
@@ -1337,12 +1219,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mEntryManager.updateNotifications();
}
- protected void setAreThereNotifications() {
-
+ public void updateAreThereNotifications() {
if (SPEW) {
final boolean clearable = hasActiveNotifications() &&
mNotificationPanel.hasActiveClearableNotifications();
- Log.d(TAG, "setAreThereNotifications: N=" +
+ Log.d(TAG, "updateAreThereNotifications: N=" +
mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" +
hasActiveNotifications() + " clearable=" + clearable);
}
@@ -1368,192 +1249,9 @@ public class StatusBar extends SystemUI implements DemoMode,
.start();
}
}
-
mMediaManager.findAndUpdateMediaNotifications();
}
-
- /**
- * Hide the album artwork that is fading out and release its bitmap.
- */
- protected final Runnable mHideBackdropFront = new Runnable() {
- @Override
- public void run() {
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: removing fade layer");
- }
- mBackdropFront.setVisibility(View.INVISIBLE);
- mBackdropFront.animate().cancel();
- mBackdropFront.setImageDrawable(null);
- }
- };
-
- // TODO: Move this to NotificationMediaManager.
- /**
- * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
- */
- @Override
- public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
- Trace.beginSection("StatusBar#updateMediaMetaData");
- if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) {
- Trace.endSection();
- return;
- }
-
- if (mBackdrop == null) {
- Trace.endSection();
- return; // called too early
- }
-
- boolean wakeAndUnlock = mBiometricUnlockController != null
- && mBiometricUnlockController.isWakeAndUnlock();
- if (mLaunchTransitionFadingAway || wakeAndUnlock) {
- mBackdrop.setVisibility(View.INVISIBLE);
- Trace.endSection();
- return;
- }
-
- MediaMetadata mediaMetadata = mMediaManager.getMediaMetadata();
-
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: updating album art for notification "
- + mMediaManager.getMediaNotificationKey()
- + " metadata=" + mediaMetadata
- + " metaDataChanged=" + metaDataChanged
- + " state=" + mState);
- }
-
- Drawable artworkDrawable = null;
- if (mediaMetadata != null) {
- Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
- if (artworkBitmap == null) {
- artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
- // might still be null
- }
- if (artworkBitmap != null) {
- artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap);
- }
- }
- boolean allowWhenShade = false;
- if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) {
- Bitmap lockWallpaper = mLockscreenWallpaper.getBitmap();
- if (lockWallpaper != null) {
- artworkDrawable = new LockscreenWallpaper.WallpaperDrawable(
- mBackdropBack.getResources(), lockWallpaper);
- // We're in the SHADE mode on the SIM screen - yet we still need to show
- // the lockscreen wallpaper in that mode.
- allowWhenShade = mStatusBarKeyguardViewManager != null
- && mStatusBarKeyguardViewManager.isShowing();
- }
- }
-
- boolean hideBecauseOccluded = mStatusBarKeyguardViewManager != null
- && mStatusBarKeyguardViewManager.isOccluded();
-
- final boolean hasArtwork = artworkDrawable != null;
- mColorExtractor.setHasBackdrop(hasArtwork);
- if (mScrimController != null) {
- mScrimController.setHasBackdrop(hasArtwork);
- }
-
- if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
- && (mState != StatusBarState.SHADE || allowWhenShade)
- && mBiometricUnlockController.getMode()
- != BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
- && !hideBecauseOccluded) {
- // time to show some art!
- if (mBackdrop.getVisibility() != View.VISIBLE) {
- mBackdrop.setVisibility(View.VISIBLE);
- if (allowEnterAnimation) {
- mBackdrop.setAlpha(0);
- mBackdrop.animate().alpha(1f);
- } else {
- mBackdrop.animate().cancel();
- mBackdrop.setAlpha(1f);
- }
- mStatusBarWindowController.setBackdropShowing(true);
- metaDataChanged = true;
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
- }
- }
- if (metaDataChanged) {
- if (mBackdropBack.getDrawable() != null) {
- Drawable drawable =
- mBackdropBack.getDrawable().getConstantState()
- .newDrawable(mBackdropFront.getResources()).mutate();
- mBackdropFront.setImageDrawable(drawable);
- mBackdropFront.setAlpha(1f);
- mBackdropFront.setVisibility(View.VISIBLE);
- } else {
- mBackdropFront.setVisibility(View.INVISIBLE);
- }
-
- if (DEBUG_MEDIA_FAKE_ARTWORK) {
- final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF);
- Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c));
- mBackdropBack.setBackgroundColor(0xFFFFFFFF);
- mBackdropBack.setImageDrawable(new ColorDrawable(c));
- } else {
- mBackdropBack.setImageDrawable(artworkDrawable);
- }
-
- if (mBackdropFront.getVisibility() == View.VISIBLE) {
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from "
- + mBackdropFront.getDrawable()
- + " to "
- + mBackdropBack.getDrawable());
- }
- mBackdropFront.animate()
- .setDuration(250)
- .alpha(0f).withEndAction(mHideBackdropFront);
- }
- }
- } else {
- // need to hide the album art, either because we are unlocked, on AOD
- // or because the metadata isn't there to support it
- if (mBackdrop.getVisibility() != View.GONE) {
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
- }
- boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange();
- if (mBiometricUnlockController.getMode()
- == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
- || hideBecauseOccluded || cannotAnimateDoze) {
-
- // We are unlocking directly - no animation!
- mBackdrop.setVisibility(View.GONE);
- mBackdropBack.setImageDrawable(null);
- mStatusBarWindowController.setBackdropShowing(false);
- } else {
- mStatusBarWindowController.setBackdropShowing(false);
- mBackdrop.animate()
- .alpha(0)
- .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
- .setDuration(300)
- .setStartDelay(0)
- .withEndAction(() -> {
- mBackdrop.setVisibility(View.GONE);
- mBackdropFront.animate().cancel();
- mBackdropBack.setImageDrawable(null);
- mHandler.post(mHideBackdropFront);
- });
- if (mKeyguardMonitor.isKeyguardFadingAway()) {
- mBackdrop.animate()
- // Make it disappear faster, as the focus should be on the activity
- // behind.
- .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
- .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
- .setInterpolator(Interpolators.LINEAR)
- .start();
- }
- }
- }
- }
- Trace.endSection();
- }
-
private void updateReportRejectedTouchVisibility() {
if (mReportRejectedTouch == null) {
return;
@@ -1646,15 +1344,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- /**
- * Reapplies the disable flags as last requested by StatusBarManager.
- *
- * This needs to be called if state used by adjustDisableFlags changes.
- */
- public void recomputeDisableFlags(boolean animate) {
- mCommandQueue.recomputeDisableFlags(animate);
- }
-
protected H createHandler() {
return new StatusBar.H();
}
@@ -1695,53 +1384,6 @@ public class StatusBar extends SystemUI implements DemoMode,
return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
}
- @Override
- public boolean isDozing() {
- return mDozing && mNotificationPanel.isFullyDark();
- }
-
- @Override
- public boolean canHeadsUp(Entry entry, StatusBarNotification sbn) {
- if (isDozing()) {
- return false;
- }
-
- if (mIsOccluded) {
- boolean devicePublic = mLockscreenUserManager.
- isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
- boolean userPublic = devicePublic
- || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
- boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
- if (userPublic && needsRedaction) {
- return false;
- }
- }
-
- if (!panelsEnabled()) {
- if (DEBUG) {
- Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
- }
- return false;
- }
-
- if (sbn.getNotification().fullScreenIntent != null) {
- if (mAccessibilityManager.isTouchExplorationEnabled()) {
- if (DEBUG) Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
- return false;
- } else {
- // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
- return !mStatusBarKeyguardViewManager.isShowing()
- || mStatusBarKeyguardViewManager.isOccluded();
- }
- }
- return true;
- }
-
- @Override // NotificationData.Environment
- public String getCurrentMediaNotificationKey() {
- return mMediaManager.getMediaNotificationKey();
- }
-
/**
* To be called when there's a state change in StatusBarKeyguardViewManager.
*/
@@ -1815,12 +1457,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- protected void setHeadsUpUser(int newUserId) {
- if (mHeadsUpManager != null) {
- mHeadsUpManager.setUser(newUserId);
- }
- }
-
public boolean isKeyguardCurrentlySecure() {
return !mUnlockMethodCache.canSkipBouncer();
}
@@ -1868,6 +1504,11 @@ public class StatusBar extends SystemUI implements DemoMode,
return mAmbientIndicationContainer;
}
+ @Override
+ public boolean isOccluded() {
+ return mIsOccluded;
+ }
+
public void setOccluded(boolean occluded) {
mIsOccluded = occluded;
mScrimController.setKeyguardOccluded(occluded);
@@ -1901,10 +1542,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mWereIconsJustHidden = true;
mHandler.postDelayed(() -> {
mWereIconsJustHidden = false;
- recomputeDisableFlags(true);
+ mCommandQueue.recomputeDisableFlags(true);
}, 500);
} else {
- recomputeDisableFlags(animate);
+ mCommandQueue.recomputeDisableFlags(animate);
}
}
if (shouldHideIconsForBouncer) {
@@ -1912,20 +1553,21 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
+ public boolean isHeadsUpShouldBeVisible() {
+ return mHeadsUpAppearanceController.shouldBeVisible();
+ }
+
+ //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
@Override
public void onLaunchAnimationCancelled() {
- if (!isCollapsing()) {
+ if (!mPresenter.isCollapsing()) {
onClosingFinished();
}
}
- public boolean isHeadsUpShouldBeVisible() {
- return mHeadsUpAppearanceController.shouldBeVisible();
- }
-
@Override
public void onExpandAnimationFinished(boolean launchIsFullScreen) {
- if (!isCollapsing()) {
+ if (!mPresenter.isCollapsing()) {
onClosingFinished();
}
if (launchIsFullScreen) {
@@ -1935,8 +1577,9 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onExpandAnimationTimedOut() {
- if (isPresenterFullyCollapsed() && !isCollapsing()
- && !mActivityLaunchAnimator.isLaunchForActivity()) {
+ ActivityLaunchAnimator animator = mPresenter.getActivityLaunchAnimator();
+ if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
+ && animator != null && !animator.isLaunchForActivity()) {
onClosingFinished();
} else {
collapsePanel(true /* animate */);
@@ -1948,6 +1591,14 @@ public class StatusBar extends SystemUI implements DemoMode,
return mState == StatusBarState.SHADE;
}
+ public boolean isDeviceInVrMode() {
+ return mPresenter.isDeviceInVrMode();
+ }
+
+ public NotificationPresenter getPresenter() {
+ return mPresenter;
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -2005,7 +1656,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void handleSystemKey(int key) {
if (SPEW) Log.d(TAG, "handleNavigationKey: " + key);
- if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
+ if (!mCommandQueue.panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
|| mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) {
return;
}
@@ -2047,15 +1698,9 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- boolean panelsEnabled() {
- return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0
- && (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0
- && !ONLY_CORE_APPS;
- }
-
void makeExpandedVisible(boolean force) {
if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
- if (!force && (mExpandedVisible || !panelsEnabled())) {
+ if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) {
return;
}
@@ -2066,7 +1711,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarWindowController.setPanelVisible(true);
visibilityChanged(true);
- recomputeDisableFlags(!force /* animate */);
+ mCommandQueue.recomputeDisableFlags(!force /* animate */);
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
}
@@ -2099,12 +1744,12 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- @Override
public void animateCollapsePanels(int flags) {
animateCollapsePanels(flags, false /* force */, false /* delayed */,
1.0f /* speedUpFactor */);
}
+ @Override
public void animateCollapsePanels(int flags, boolean force) {
animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);
}
@@ -2155,7 +1800,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void dispatchNotificationsPanelTouchEvent(MotionEvent ev) {
- if (!panelsEnabled()) {
+ if (!mCommandQueue.panelsEnabled()) {
return;
}
mNotificationPanel.dispatchTouchEvent(ev);
@@ -2173,7 +1818,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void animateExpandNotificationsPanel() {
if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
- if (!panelsEnabled()) {
+ if (!mCommandQueue.panelsEnabled()) {
return ;
}
@@ -2185,7 +1830,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void animateExpandSettingsPanel(@Nullable String subPanel) {
if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
- if (!panelsEnabled()) {
+ if (!mCommandQueue.panelsEnabled()) {
return;
}
@@ -2233,12 +1878,13 @@ public class StatusBar extends SystemUI implements DemoMode,
runPostCollapseRunnables();
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
- if (!mIsCollapsingToShowActivityOverLockscreen) {
+ if (!mPresenter.isCollapsingToShowActivityOverLockscreen()) {
showBouncerIfKeyguard();
} else if (DEBUG) {
Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
}
- recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */);
+ mCommandQueue.recomputeDisableFlags(
+ mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */);
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -2330,7 +1976,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// update low profile
if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
- setAreThereNotifications();
+ updateAreThereNotifications();
}
// ready to unhide
@@ -2703,9 +2349,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
- mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
- mNotificationPanel.createRemoteInputDelegate());
- mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
}
@@ -2750,7 +2393,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
final Callback callback, int flags) {
- if (onlyProvisioned && !isDeviceProvisioned()) return;
+ if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, mLockscreenUserManager.getCurrentUserId());
@@ -2888,7 +2531,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
} else if (ACTION_FAKE_ARTWORK.equals(action)) {
if (DEBUG_MEDIA_FAKE_ARTWORK) {
- updateMediaMetaData(true, true);
+ mPresenter.updateMediaMetaData(true, true);
}
}
}
@@ -2917,7 +2560,8 @@ public class StatusBar extends SystemUI implements DemoMode,
dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
}
- private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
+ @Override
+ public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
&& mUnlockMethodCache.canSkipBouncer()
@@ -2951,38 +2595,10 @@ public class StatusBar extends SystemUI implements DemoMode,
}
@Override
- public void onUserSwitched(int newUserId) {
- // Begin old BaseStatusBar.userSwitched
- setHeadsUpUser(newUserId);
- // End old BaseStatusBar.userSwitched
- if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
- animateCollapsePanels();
- if (mReinflateNotificationsOnUserSwitched) {
- mEntryManager.updateNotificationsOnDensityOrFontScaleChanged();
- mReinflateNotificationsOnUserSwitched = false;
- }
- updateNotificationViews();
- mMediaManager.clearCurrentMediaNotification();
- setLockscreenUser(newUserId);
- mWallpaperChangedReceiver.onReceive(mContext, null);
- }
-
- @Override
- public NotificationLockscreenUserManager getNotificationLockscreenUserManager() {
- return mLockscreenUserManager;
- }
-
- @Override
- public void onBindRow(Entry entry, PackageManager pmUser,
- StatusBarNotification sbn, ExpandableNotificationRow row) {
- row.setAboveShelfChangedListener(mAboveShelfObserver);
- row.setSecureStateProvider(this::isKeyguardCurrentlySecure);
- }
-
- protected void setLockscreenUser(int newUserId) {
+ public void setLockscreenUser(int newUserId) {
mLockscreenWallpaper.setCurrentUser(newUserId);
mScrimController.setCurrentUser(newUserId);
- updateMediaMetaData(true, false);
+ mWallpaperChangedReceiver.onReceive(mContext, null);
}
/**
@@ -3020,8 +2636,6 @@ public class StatusBar extends SystemUI implements DemoMode,
if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
}
- mMaxAllowedKeyguardNotifications = res.getInteger(
- R.integer.keyguard_max_notification_count);
if (DEBUG) Log.v(TAG, "defineSlots");
}
@@ -3058,12 +2672,12 @@ public class StatusBar extends SystemUI implements DemoMode,
if (visibleToUser) {
boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
boolean clearNotificationEffects =
- !isPresenterFullyCollapsed() &&
+ !mPresenter.isPresenterFullyCollapsed() &&
(mState == StatusBarState.SHADE
|| mState == StatusBarState.SHADE_LOCKED);
int notificationLoad = mEntryManager.getNotificationData().getActiveNotifications()
.size();
- if (pinnedHeadsUp && isPresenterFullyCollapsed()) {
+ if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
notificationLoad = 1;
}
final int finalNotificationLoad = notificationLoad;
@@ -3298,13 +2912,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- @Override
- public boolean isPresenterFullyCollapsed() {
- return mNotificationPanel.isFullyCollapsed();
- }
-
public void showKeyguard() {
- mKeyguardRequested = true;
+ mStatusBarStateController.setKeyguardRequested(true);
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
mPendingRemoteInputView = null;
updateIsKeyguard();
@@ -3312,11 +2921,12 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public boolean hideKeyguard() {
- mKeyguardRequested = false;
+ mStatusBarStateController.setKeyguardRequested(false);
return updateIsKeyguard();
}
/**
+ * stop(tag)
* @return True if StatusBar state is FULLSCREEN_USER_SWITCHER.
*/
public boolean isFullScreenUserSwitcherState() {
@@ -3333,7 +2943,8 @@ public class StatusBar extends SystemUI implements DemoMode,
// turned off fully.
boolean keyguardForDozing = mDozingRequested &&
(!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
- boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking;
+ boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
+ || keyguardForDozing) && !wakeAndUnlocking;
if (keyguardForDozing) {
updatePanelExpansionForKeyguard();
}
@@ -3385,13 +2996,7 @@ public class StatusBar extends SystemUI implements DemoMode,
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mLaunchTransitionFadingAway = false;
- updateMediaMetaData(true /* metaDataChanged */, true);
- }
-
- public boolean isCollapsing() {
- return mNotificationPanel.isCollapsing()
- || mActivityLaunchAnimator.isAnimationPending()
- || mActivityLaunchAnimator.isAnimationRunning();
+ mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
}
public void addPostCollapseAction(Runnable r) {
@@ -3415,12 +3020,13 @@ public class StatusBar extends SystemUI implements DemoMode,
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
mLaunchTransitionEndRunnable = endRunnable;
Runnable hideRunnable = () -> {
+ mKeyguardMonitor.setLaunchTransitionFadingAway(true);
mLaunchTransitionFadingAway = true;
if (beforeFading != null) {
beforeFading.run();
}
updateScrimController();
- updateMediaMetaData(false, true);
+ mPresenter.updateMediaMetaData(false, true);
mNotificationPanel.setAlpha(1);
mNotificationPanel.animate()
.alpha(0)
@@ -3505,9 +3111,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mLockscreenUserManager.updatePublicMode();
mEntryManager.updateNotifications();
}
- View viewToClick = null;
if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
- if (!mKeyguardRequested) {
+ if (!mStatusBarStateController.isKeyguardRequested()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
}
long delay = mKeyguardMonitor.calculateGoingToFullShadeDelay();
@@ -3516,10 +3121,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mDraggedDownRow.setUserLocked(false);
mDraggedDownRow = null;
}
- if (!mKeyguardRequested) {
- viewToClick = mPendingRemoteInputView;
- mPendingRemoteInputView = null;
- }
// Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device.
@@ -3530,10 +3131,6 @@ public class StatusBar extends SystemUI implements DemoMode,
instantCollapseNotificationPanel();
}
- if (viewToClick != null && viewToClick.isAttachedToWindow()) {
- viewToClick.callOnClick();
- }
-
// Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
// visibilities so next time we open the panel we know the correct height already.
if (mQSPanel != null) {
@@ -3575,7 +3172,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mCommandQueue.appTransitionStarting(startTime + fadeoutDuration
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
- recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
+ mCommandQueue.recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
mCommandQueue.appTransitionStarting(
startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
@@ -3617,7 +3214,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mDozeScrimController.setDozing(mDozing);
mKeyguardIndicationController.setDozing(mDozing);
- mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation);
+ mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation,
+ mDozeServiceHost.wasPassivelyInterrupted());
mNotificationLogger.setDozing(mDozing);
mGroupManager.setDozing(mDozing);
updateQsExpansionEnabled();
@@ -3696,42 +3294,52 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- protected void showBouncer(boolean scrimmed) {
+ @Override
+ public void showBouncer(boolean scrimmed) {
mStatusBarKeyguardViewManager.showBouncer(scrimmed);
}
- private void instantExpandNotificationsPanel() {
+ @Override
+ public void instantExpandNotificationsPanel() {
// Make our window larger and the panel expanded.
makeExpandedVisible(true);
mNotificationPanel.expand(false /* animate */);
- recomputeDisableFlags(false /* animate */);
+ mCommandQueue.recomputeDisableFlags(false /* animate */);
}
- private void instantCollapseNotificationPanel() {
- mNotificationPanel.instantCollapse();
- runPostCollapseRunnables();
+ @Override
+ public boolean closeShadeIfOpen() {
+ if (!mNotificationPanel.isFullyCollapsed()) {
+ mCommandQueue.animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
+ visibilityChanged(false);
+ mAssistManager.hideAssist();
+ }
+ return false;
}
@Override
- public void onActivated(ActivatableNotificationView view) {
- onActivated((View) view);
- mNotificationPanel.setActivatedChild(view);
+ public void postOnShadeExpanded(Runnable executable) {
+ mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (getStatusBarWindow().getHeight() != getStatusBarHeight()) {
+ mNotificationPanel.getViewTreeObserver()
+ .removeOnGlobalLayoutListener(this);
+ mNotificationPanel.post(executable);
+ }
+ }
+ });
}
- public void onActivated(View view) {
- mLockscreenGestureLogger.write(
- MetricsEvent.ACTION_LS_NOTE,
- 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
- mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again);
- ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
- if (previousView != null) {
- previousView.makeInactive(true /* animate */);
- }
+ private void instantCollapseNotificationPanel() {
+ mNotificationPanel.instantCollapse();
+ runPostCollapseRunnables();
}
@Override
public void onStatePreChange(int oldState, int newState) {
-
// If we're visible and switched to SHADE_LOCKED (the user dragged
// down on the lockscreen), clear notification LED, vibration,
// ringing.
@@ -3779,7 +3387,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateDozingState();
checkBarModes();
updateScrimController();
- updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+ mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mUnlockMethodCache.isMethodSecure(),
mStatusBarKeyguardViewManager.isOccluded());
@@ -3796,6 +3404,7 @@ public class StatusBar extends SystemUI implements DemoMode,
&& DozeParameters.getInstance(mContext).shouldControlScreenOff();
mNotificationPanel.resetViews(dozingAnimated);
+ updateQsExpansionEnabled();
mKeyguardViewMediator.setAodShowing(mDozing);
//TODO: make these folks listeners of StatusBarStateController.onDozingChanged
@@ -3827,15 +3436,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController.setIsDozing(dozing);
}
- @Override
- public void onActivationReset(ActivatableNotificationView view) {
- if (view == mNotificationPanel.getActivatedChild()) {
- mNotificationPanel.setActivatedChild(null);
- onActivationReset((View)view);
- }
- }
-
- public void onActivationReset(View view) {
+ public void onActivationReset() {
mKeyguardIndicationController.hideTransientIndication();
}
@@ -3845,7 +3446,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onClosingFinished() {
runPostCollapseRunnables();
- if (!isPresenterFullyCollapsed()) {
+ if (!mPresenter.isPresenterFullyCollapsed()) {
// if we set it not to be focusable when collapsing, we have to undo it when we aborted
// the closing
mStatusBarWindowController.setStatusBarFocusable(true);
@@ -3885,22 +3486,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- @Override
- public int getMaxNotificationsWhileLocked(boolean recompute) {
- if (recompute) {
- mMaxKeyguardNotifications = Math.max(1,
- mNotificationPanel.computeMaxKeyguardNotifications(
- mMaxAllowedKeyguardNotifications));
- return mMaxKeyguardNotifications;
- }
- return mMaxKeyguardNotifications;
- }
-
- @Override
- public void onUpdateRowStates() {
- mNotificationPanel.onUpdateRowStates();
- }
-
// TODO: Figure out way to remove these.
public NavigationBarView getNavigationBarView() {
return (mNavigationBar != null ? (NavigationBarView) mNavigationBar.getView() : null);
@@ -3957,184 +3542,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
- mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
- dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */);
- }
-
- @Override
- public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
- mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
- showBouncer(true /* scrimmed */);
- mPendingRemoteInputView = clicked;
- }
-
- @Override
- public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row,
- View clickedView) {
- if (isKeyguardShowing()) {
- onLockedRemoteInput(row, clickedView);
- } else {
- row.setUserExpanded(true);
- row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
- }
- }
-
- @Override
- public boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent) {
- // Skip remote input as doing so will expand the notification shade.
- return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
- }
-
- @Override
- public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent,
- Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) {
- final boolean isActivity = pendingIntent.isActivity();
- if (isActivity) {
- final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
- mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
- dismissKeyguardThenExecute(() -> {
- try {
- ActivityManager.getService().resumeAppSwitches();
- } catch (RemoteException e) {
- }
-
- boolean handled = defaultHandler.handleClick();
-
- // close the shade if it was open
- if (handled && !mNotificationPanel.isFullyCollapsed()) {
- animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
- visibilityChanged(false);
- mAssistManager.hideAssist();
-
- // Wait for activity start.
- return true;
- } else {
- return false;
- }
-
- }, afterKeyguardGone);
- return true;
- } else {
- return defaultHandler.handleClick();
- }
- }
-
- protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
- String notificationKey) {
- // Clear pending remote view, as we do not want to trigger pending remote input view when
- // it's called by other code
- mPendingWorkRemoteInputView = null;
- // Begin old BaseStatusBar.startWorkChallengeIfNecessary.
- final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
- null, userId);
- if (newIntent == null) {
- return false;
- }
- final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
- callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
- callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
- callBackIntent.setPackage(mContext.getPackageName());
-
- PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
- mContext,
- 0,
- callBackIntent,
- PendingIntent.FLAG_CANCEL_CURRENT |
- PendingIntent.FLAG_ONE_SHOT |
- PendingIntent.FLAG_IMMUTABLE);
- newIntent.putExtra(
- Intent.EXTRA_INTENT,
- callBackPendingIntent.getIntentSender());
- try {
- ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent,
- null /*options*/);
- } catch (RemoteException ex) {
- // ignore
- }
- return true;
- // End old BaseStatusBar.startWorkChallengeIfNecessary.
- }
-
- @Override
- public void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
- View clicked) {
- // Collapse notification and show work challenge
- animateCollapsePanels();
- startWorkChallengeIfNecessary(userId, null, null);
- // Add pending remote input view after starting work challenge, as starting work challenge
- // will clear all previous pending review view
- mPendingWorkRemoteInputView = clicked;
- }
-
- @Override
- public void onWorkChallengeChanged() {
- if (mPendingWorkRemoteInputView != null
- && !mLockscreenUserManager.isAnyProfilePublicMode()) {
- // Expand notification panel and the notification row, then click on remote input view
- final Runnable clickPendingViewRunnable = () -> {
- final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView;
- if (pendingWorkRemoteInputView == null) {
- return;
- }
-
- // Climb up the hierarchy until we get to the container for this row.
- ViewParent p = pendingWorkRemoteInputView.getParent();
- while (!(p instanceof ExpandableNotificationRow)) {
- if (p == null) {
- return;
- }
- p = p.getParent();
- }
-
- final ExpandableNotificationRow row = (ExpandableNotificationRow) p;
- ViewParent viewParent = row.getParent();
- if (viewParent instanceof NotificationStackScrollLayout) {
- final NotificationStackScrollLayout scrollLayout =
- (NotificationStackScrollLayout) viewParent;
- row.makeActionsVisibile();
- row.post(() -> {
- final Runnable finishScrollingCallback = () -> {
- mPendingWorkRemoteInputView.callOnClick();
- mPendingWorkRemoteInputView = null;
- scrollLayout.setFinishScrollingCallback(null);
- };
- if (scrollLayout.scrollTo(row)) {
- // It scrolls! So call it when it's finished.
- scrollLayout.setFinishScrollingCallback(finishScrollingCallback);
- } else {
- // It does not scroll, so call it now!
- finishScrollingCallback.run();
- }
- });
- }
- };
- mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- if (mNotificationPanel.mStatusBar.getStatusBarWindow()
- .getHeight() != mNotificationPanel.mStatusBar
- .getStatusBarHeight()) {
- mNotificationPanel.getViewTreeObserver()
- .removeOnGlobalLayoutListener(this);
- mNotificationPanel.post(clickPendingViewRunnable);
- }
- }
- });
- instantExpandNotificationsPanel();
- }
- }
-
- @Override
- public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
- mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
- if (mState == StatusBarState.KEYGUARD && nowExpanded) {
- goToLockedShade(clickedEntry.row);
- }
- }
-
/**
* Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
*/
@@ -4148,7 +3555,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mBouncerShowing = bouncerShowing;
if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
updateHideIconsForBouncer(true /* animate */);
- recomputeDisableFlags(true /* animate */);
+ mCommandQueue.recomputeDisableFlags(true /* animate */);
updateScrimController();
}
@@ -4203,7 +3610,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mAmbientPulseManager.releaseAllImmediately();
mVisualStabilityManager.setScreenOn(true);
mNotificationPanel.setTouchAndAnimationDisabled(false);
- mDozeServiceHost.stopDozing();
updateVisibleToUser();
updateIsKeyguard();
updateScrimController();
@@ -4273,25 +3679,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
@Override
- public void wakeUpIfDozing(long time, View where) {
- if (mDozing) {
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- pm.wakeUp(time, "com.android.systemui:NODOZE");
- mWakeUpComingFromTouch = true;
- where.getLocationInWindow(mTmpInt2);
- mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
- mTmpInt2[1] + where.getHeight() / 2);
- mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
- mFalsingManager.onScreenOnFromTouch();
- }
- }
-
- @Override
- public boolean isDeviceLocked(int userId) {
- return mKeyguardManager.isDeviceLocked(userId);
- }
-
- @Override
public void appTransitionCancelled() {
getComponent(Divider.class).onAppTransitionFinished();
}
@@ -4401,6 +3788,9 @@ public class StatusBar extends SystemUI implements DemoMode,
// FLAG_DISMISS_KEYGUARD_ACTIVITY.
ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
+ if (mNotificationPanel.isSemiAwake()) {
+ state = ScrimState.DARK_KEYGUARD;
+ }
mScrimController.transitionTo(state);
} else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn
|| launchingAffordanceWithPreview) {
@@ -4412,7 +3802,8 @@ public class StatusBar extends SystemUI implements DemoMode,
} else if (mDozing) {
mScrimController.transitionTo(ScrimState.AOD);
} else if (mIsKeyguard && !wakeAndUnlocking) {
- mScrimController.transitionTo(ScrimState.KEYGUARD);
+ mScrimController.transitionTo(mNotificationPanel.isSemiAwake()
+ ? ScrimState.DARK_KEYGUARD : ScrimState.KEYGUARD);
} else {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
}
@@ -4432,6 +3823,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mAnimateWakeup;
private boolean mAnimateScreenOff;
private boolean mIgnoreTouchWhilePulsing;
+ private boolean mPassivelyInterrupted;
@Override
public String toString() {
@@ -4515,6 +3907,11 @@ public class StatusBar extends SystemUI implements DemoMode,
}
@Override
+ public void setPassiveInterrupt(boolean passiveInterrupt) {
+ mPassivelyInterrupted = passiveInterrupt;
+ }
+
+ @Override
public void onIgnoreTouchWhilePulsing(boolean ignore) {
if (ignore != mIgnoreTouchWhilePulsing) {
DozeLog.tracePulseTouchDisabledByProx(mContext, ignore);
@@ -4633,6 +4030,10 @@ public class StatusBar extends SystemUI implements DemoMode,
public boolean shouldAnimateScreenOff() {
return mAnimateScreenOff;
}
+
+ public boolean wasPassivelyInterrupted() {
+ return mPassivelyInterrupted;
+ }
}
public boolean shouldIgnoreTouch() {
@@ -4655,8 +4056,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
- private AboveShelfObserver mAboveShelfObserver;
-
// handling reordering
protected VisualStabilityManager mVisualStabilityManager;
@@ -4674,7 +4073,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
protected KeyguardManager mKeyguardManager;
- private LockPatternUtils mLockPatternUtils;
private DeviceProvisionedController mDeviceProvisionedController
= Dependency.get(DeviceProvisionedController.class);
@@ -4693,28 +4091,10 @@ public class StatusBar extends SystemUI implements DemoMode,
protected AssistManager mAssistManager;
- protected boolean mVrMode;
-
public boolean isDeviceInteractive() {
return mDeviceInteractive;
}
- @Override // NotificationData.Environment
- public boolean isDeviceProvisioned() {
- return mDeviceProvisionedController.isDeviceProvisioned();
- }
-
- private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
- @Override
- public void onVrStateChanged(boolean enabled) {
- mVrMode = enabled;
- }
- };
-
- public boolean isDeviceInVrMode() {
- return mVrMode;
- }
-
private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -4740,182 +4120,13 @@ public class StatusBar extends SystemUI implements DemoMode,
};
@Override
- public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
- RemoteInputController controller = mRemoteInputManager.getController();
- if (controller.isRemoteInputActive(row.getEntry())
- && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
- // We have an active remote input typed and the user clicked on the notification.
- // this was probably unintentional, so we're closing the edit text instead.
- controller.closeRemoteInputs();
- return;
- }
- Notification notification = sbn.getNotification();
- final PendingIntent intent = notification.contentIntent != null
- ? notification.contentIntent
- : notification.fullScreenIntent;
- final String notificationKey = sbn.getKey();
-
- boolean isActivityIntent = intent.isActivity();
- final boolean afterKeyguardGone = isActivityIntent
- && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
- mLockscreenUserManager.getCurrentUserId());
- final boolean wasOccluded = mIsOccluded;
- boolean showOverLockscreen = mStatusBarKeyguardViewManager.isShowing()
- && PreviewInflater.wouldShowOverLockscreen(mContext,
- intent.getIntent(),
- mLockscreenUserManager.getCurrentUserId());
- OnDismissAction postKeyguardAction = () -> {
- // TODO: Some of this code may be able to move to NotificationEntryManager.
- if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(notificationKey)) {
- // Release the HUN notification to the shade.
-
- if (isPresenterFullyCollapsed()) {
- HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
- }
- //
- // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
- // become canceled shortly by NoMan, but we can't assume that.
- mHeadsUpManager.removeNotification(sbn.getKey(),
- true /* releaseImmediately */);
- }
- StatusBarNotification parentToCancel = null;
- if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
- StatusBarNotification summarySbn =
- mGroupManager.getLogicalGroupSummary(sbn).getStatusBarNotification();
- if (shouldAutoCancel(summarySbn)) {
- parentToCancel = summarySbn;
- }
- }
- final StatusBarNotification parentToCancelFinal = parentToCancel;
- final Runnable runnable = () -> {
- try {
- // The intent we are sending is for the application, which
- // won't have permission to immediately start an activity after
- // the user switches to home. We know it is safe to do at this
- // point, so make sure new activity switches are now allowed.
- ActivityManager.getService().resumeAppSwitches();
- } catch (RemoteException e) {
- }
- int launchResult = ActivityManager.START_CANCELED;
- if (intent != null) {
- // If we are launching a work activity and require to launch
- // separate work challenge, we defer the activity action and cancel
- // notification until work challenge is unlocked.
- if (isActivityIntent) {
- final int userId = intent.getCreatorUserHandle().getIdentifier();
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
- && mKeyguardManager.isDeviceLocked(userId)) {
- // TODO(b/28935539): should allow certain activities to
- // bypass work challenge
- if (startWorkChallengeIfNecessary(userId, intent.getIntentSender(),
- notificationKey)) {
- // Show work challenge, do not run PendingIntent and
- // remove notification
- collapseOnMainThread();
- return;
- }
- }
- }
- Intent fillInIntent = null;
- Entry entry = row.getEntry();
- CharSequence remoteInputText = null;
- if (!TextUtils.isEmpty(entry.remoteInputText)) {
- remoteInputText = entry.remoteInputText;
- }
- if (!TextUtils.isEmpty(remoteInputText)
- && !controller.isSpinning(entry.key)) {
- fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
- remoteInputText.toString());
- }
- RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
- row, wasOccluded);
- try {
- if (adapter != null) {
- ActivityTaskManager.getService()
- .registerRemoteAnimationForNextActivityStart(
- intent.getCreatorPackage(), adapter);
- }
- launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
- null, null, getActivityOptions(adapter));
- mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
- } catch (RemoteException | PendingIntent.CanceledException e) {
- // the stack trace isn't very helpful here.
- // Just log the exception message.
- Log.w(TAG, "Sending contentIntent failed: " + e);
-
- // TODO: Dismiss Keyguard.
- }
- if (isActivityIntent) {
- mAssistManager.hideAssist();
- }
- }
- if (shouldCollapse()) {
- collapseOnMainThread();
- }
-
- final int count =
- mEntryManager.getNotificationData().getActiveNotifications().size();
- final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
- final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
- rank, count, true);
- try {
- mBarService.onNotificationClick(notificationKey, nv);
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
- if (parentToCancelFinal != null) {
- removeNotification(parentToCancelFinal);
- }
- if (shouldAutoCancel(sbn)
- || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
- notificationKey)) {
- // Automatically remove all notifications that we may have kept around longer
- removeNotification(sbn);
- }
-
- mIsCollapsingToShowActivityOverLockscreen = false;
- };
-
- if (showOverLockscreen) {
- addPostCollapseAction(runnable);
- collapsePanel(true /* animate */);
- } else if (mStatusBarKeyguardViewManager.isShowing()
- && mStatusBarKeyguardViewManager.isOccluded()) {
- mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
- collapsePanel(true /* animate */);
- } else {
- new Thread(runnable).start();
- }
-
- return !mNotificationPanel.isFullyCollapsed();
- };
- if (showOverLockscreen) {
- mIsCollapsingToShowActivityOverLockscreen = true;
- postKeyguardAction.onDismiss();
- } else {
- dismissKeyguardThenExecute(postKeyguardAction, afterKeyguardGone);
- }
- }
-
- private void collapseOnMainThread() {
- if (Looper.getMainLooper().isCurrentThread()) {
- collapsePanel();
- } else {
- Dependency.get(Dependency.MAIN_HANDLER).post(this::collapsePanel);
- }
- }
-
- private boolean shouldCollapse() {
- return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending();
- }
-
public void collapsePanel(boolean animate) {
if (animate) {
boolean willCollapse = collapsePanel();
if (!willCollapse) {
runPostCollapseRunnables();
}
- } else if (!isPresenterFullyCollapsed()) {
+ } else if (!mPresenter.isPresenterFullyCollapsed()) {
instantCollapseNotificationPanel();
visibilityChanged(false);
} else {
@@ -4923,7 +4134,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- private boolean collapsePanel() {
+ @Override
+ public boolean collapsePanel() {
if (!mNotificationPanel.isFullyCollapsed()) {
// close the shade if it was open
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
@@ -4936,59 +4148,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- private void removeNotification(StatusBarNotification notification) {
- // We have to post it to the UI thread for synchronization
- mHandler.post(() -> {
- Runnable removeRunnable =
- () -> mEntryManager.performRemoveNotification(notification);
- if (isCollapsing()) {
- // To avoid lags we're only performing the remove
- // after the shade was collapsed
- addPostCollapseAction(removeRunnable);
- } else {
- removeRunnable.run();
- }
- });
- }
-
protected NotificationListener mNotificationListener;
- @Override // NotificationData.Environment
- public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
- final int notificationUserId = n.getUserId();
- if (DEBUG && MULTIUSER_DEBUG) {
- Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", n,
- mLockscreenUserManager.getCurrentUserId(), notificationUserId));
- }
- return mLockscreenUserManager.isCurrentProfile(notificationUserId);
- }
-
- @Override
- public NotificationGroupManager getGroupManager() {
- return mGroupManager;
- }
-
- @Override
- public void startNotificationGutsIntent(final Intent intent, final int appUid,
- ExpandableNotificationRow row) {
- dismissKeyguardThenExecute(() -> {
- AsyncTask.execute(() -> {
- int launchResult = TaskStackBuilder.create(mContext)
- .addNextIntentWithParentStack(intent)
- .startActivities(getActivityOptions(
- mActivityLaunchAnimator.getLaunchAnimation(row, mIsOccluded)),
- new UserHandle(UserHandle.getUserId(appUid)));
- mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
- if (shouldCollapse()) {
- // Putting it back on the main thread, since we're touching views
- mStatusBarWindow.post(() -> animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
- }
- });
- return true;
- }, false /* afterKeyguardGone */);
- }
-
public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
if (snoozeOption.getSnoozeCriterion() != null) {
mNotificationListener.snoozeNotification(sbn.getKey(),
@@ -5049,7 +4210,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// Immediately update the icon hidden state, since that should only apply if we're
// staying fullscreen.
mWereIconsJustHidden = false;
- recomputeDisableFlags(true);
+ mCommandQueue.recomputeDisableFlags(true);
}
updateHideIconsForBouncer(true /* animate */);
}
@@ -5062,24 +4223,6 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyboardShortcuts.dismiss();
}
- @Override // NotificationData.Environment
- public boolean shouldHideNotifications(int userId) {
- return mLockscreenUserManager.shouldHideNotifications(userId);
- }
-
- @Override // NotificationDate.Environment
- public boolean shouldHideNotifications(String key) {
- return mLockscreenUserManager.shouldHideNotifications(key);
- }
-
- /**
- * Returns true if we're on a secure lockscreen.
- */
- @Override // NotificationData.Environment
- public boolean isSecurelyLocked(int userId) {
- return mLockscreenUserManager.isLockscreenPublicMode(userId);
- }
-
/**
* Called when the notification panel layouts
*/
@@ -5091,8 +4234,8 @@ public class StatusBar extends SystemUI implements DemoMode,
if (mState == StatusBarState.KEYGUARD) {
// Since the number of notifications is determined based on the height of the view, we
// need to update them.
- int maxBefore = getMaxNotificationsWhileLocked(false /* recompute */);
- int maxNotifications = getMaxNotificationsWhileLocked(true /* recompute */);
+ int maxBefore = mPresenter.getMaxNotificationsWhileLocked(false /* recompute */);
+ int maxNotifications = mPresenter.getMaxNotificationsWhileLocked(true /* recompute */);
if (maxBefore != maxNotifications) {
mViewHierarchyManager.updateRowStates();
}
@@ -5100,7 +4243,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
- if (!isDeviceProvisioned()) return;
+ if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
final boolean afterKeyguardGone = intent.isActivity()
&& PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
@@ -5134,18 +4277,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}, afterKeyguardGone);
}
- private boolean shouldAutoCancel(StatusBarNotification sbn) {
- int flags = sbn.getNotification().flags;
- if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
- return false;
- }
- if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
- return false;
- }
- return true;
- }
-
- protected Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
+ public static Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
ActivityOptions options;
if (animationAdapter != null) {
options = ActivityOptions.makeRemoteAnimation(animationAdapter);
@@ -5262,28 +4394,4 @@ public class StatusBar extends SystemUI implements DemoMode,
public NotificationGutsManager getGutsManager() {
return mGutsManager;
}
-
- @Override
- public boolean isPresenterLocked() {
- return mState == StatusBarState.KEYGUARD;
- }
-
- @Override
- public Handler getHandler() {
- return mHandler;
- }
-
- private final NotificationInfo.CheckSaveListener mCheckSaveListener =
- (Runnable saveImportance, StatusBarNotification sbn) -> {
- // If the user has security enabled, show challenge if the setting is changed.
- if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
- && mKeyguardManager.isKeyguardLocked()) {
- onLockedNotificationImportanceChange(() -> {
- saveImportance.run();
- return true;
- });
- } else {
- saveImportance.run();
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index ac3608bc622a..c5603016fc56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.phone;
-import static com.android.keyguard.KeyguardHostView.OnDismissAction;
+import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
@@ -43,6 +43,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
@@ -124,6 +125,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
private DismissWithActionRequest mPendingWakeupAction;
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final NotificationMediaManager mMediaManager =
+ Dependency.get(NotificationMediaManager.class);
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@@ -381,7 +384,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
boolean isOccluding = !mOccluded && occluded;
mOccluded = occluded;
if (mShowing) {
- mStatusBar.updateMediaMetaData(false, animate && !occluded);
+ mMediaManager.updateMediaMetaData(false, animate && !occluded);
}
mStatusBarWindowController.setKeyguardOccluded(occluded);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
new file mode 100644
index 000000000000..635ffc75182f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -0,0 +1,672 @@
+/*
+ * 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.phone;
+
+import static com.android.systemui.Dependency.MAIN_HANDLER;
+import static com.android.systemui.SysUiServiceProvider.getComponent;
+import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
+import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
+import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
+import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
+
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.view.RemoteAnimationAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
+import com.android.systemui.R;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.AboveShelfObserver;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.HeadsUpUtil;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.PreviewInflater;
+
+public class StatusBarNotificationPresenter implements NotificationPresenter {
+
+ private final LockscreenGestureLogger mLockscreenGestureLogger =
+ Dependency.get(LockscreenGestureLogger.class);
+
+ private static final String TAG = "StatusBarNotificationPresenter";
+
+ private final ShadeController mShadeController = Dependency.get(ShadeController.class);
+ private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+ private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
+ private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final NotificationViewHierarchyManager mViewHierarchyManager =
+ Dependency.get(NotificationViewHierarchyManager.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager =
+ Dependency.get(NotificationLockscreenUserManager.class);
+ private final StatusBarStateController mStatusBarStateController =
+ Dependency.get(StatusBarStateController.class);
+ private final NotificationEntryManager mEntryManager =
+ Dependency.get(NotificationEntryManager.class);
+ private final NotificationMediaManager mMediaManager =
+ Dependency.get(NotificationMediaManager.class);
+ private final NotificationRemoteInputManager mRemoteInputManager =
+ Dependency.get(NotificationRemoteInputManager.class);
+ private final NotificationGroupManager mGroupManager =
+ Dependency.get(NotificationGroupManager.class);
+ private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback =
+ (StatusBarRemoteInputCallback) Dependency.get(Callback.class);
+ protected AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
+
+ private final NotificationPanelView mNotificationPanel;
+ private final HeadsUpManagerPhone mHeadsUpManager;
+ private final AboveShelfObserver mAboveShelfObserver;
+ private final DozeScrimController mDozeScrimController;
+ private final ScrimController mScrimController;
+ private final Context mContext;
+ private final CommandQueue mCommandQueue;
+
+ private final AccessibilityManager mAccessibilityManager;
+ private final LockPatternUtils mLockPatternUtils;
+ private final KeyguardManager mKeyguardManager;
+ private final ActivityLaunchAnimator mActivityLaunchAnimator;
+ private final int mMaxAllowedKeyguardNotifications;
+ private final IStatusBarService mBarService;
+ private boolean mReinflateNotificationsOnUserSwitched;
+ private final UnlockMethodCache mUnlockMethodCache;
+ private TextView mNotificationPanelDebugText;
+
+ protected boolean mVrMode;
+ private int mMaxKeyguardNotifications;
+ private boolean mIsCollapsingToShowActivityOverLockscreen;
+
+ public StatusBarNotificationPresenter(Context context, NotificationPanelView panel,
+ HeadsUpManagerPhone headsUp, StatusBarWindowView statusBarWindow,
+ ViewGroup stackScroller, DozeScrimController dozeScrimController,
+ ScrimController scrimController,
+ ActivityLaunchAnimator.Callback launchAnimatorCallback) {
+ mContext = context;
+ mNotificationPanel = panel;
+ mHeadsUpManager = headsUp;
+ mCommandQueue = getComponent(context, CommandQueue.class);
+ mAboveShelfObserver = new AboveShelfObserver(stackScroller);
+ mAboveShelfObserver.setListener(statusBarWindow.findViewById(
+ R.id.notification_container_parent));
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+ mDozeScrimController = dozeScrimController;
+ mScrimController = scrimController;
+ mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
+ mLockPatternUtils = new LockPatternUtils(context);
+ mKeyguardManager = context.getSystemService(KeyguardManager.class);
+ mMaxAllowedKeyguardNotifications = context.getResources().getInteger(
+ R.integer.keyguard_max_notification_count);
+ mBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mActivityLaunchAnimator = new ActivityLaunchAnimator(statusBarWindow,
+ launchAnimatorCallback,
+ mNotificationPanel,
+ (NotificationListContainer) stackScroller);
+
+ if (MULTIUSER_DEBUG) {
+ mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
+ mNotificationPanelDebugText.setVisibility(View.VISIBLE);
+ }
+
+ IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
+ Context.VR_SERVICE));
+ if (vrManager != null) {
+ try {
+ vrManager.registerListener(mVrStateCallbacks);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+ }
+ }
+ mRemoteInputManager.setUpWithPresenter(this,
+ Dependency.get(NotificationRemoteInputManager.Callback.class),
+ mNotificationPanel.createRemoteInputDelegate());
+ mRemoteInputManager.getController().addCallback(
+ Dependency.get(StatusBarWindowController.class));
+
+ NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
+ Dependency.get(InitController.class).addPostInitTask(() -> {
+ mViewHierarchyManager.setUpWithPresenter(this, notifListContainer);
+ mEntryManager.setUpWithPresenter(this, notifListContainer, this, mHeadsUpManager);
+ mLockscreenUserManager.setUpWithPresenter(this);
+ mMediaManager.setUpWithPresenter(this);
+ Dependency.get(NotificationGutsManager.class).setUpWithPresenter(this,
+ notifListContainer, mCheckSaveListener, mOnSettingsClickListener);
+
+ onUserSwitched(mLockscreenUserManager.getCurrentUserId());
+ });
+ }
+
+ public void onDensityOrFontScaleChanged() {
+ if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
+ mEntryManager.updateNotificationsOnDensityOrFontScaleChanged();
+ } else {
+ mReinflateNotificationsOnUserSwitched = true;
+ }
+ }
+
+ @Override
+ public ActivityLaunchAnimator getActivityLaunchAnimator() {
+ return mActivityLaunchAnimator;
+ }
+
+ @Override
+ public boolean isCollapsing() {
+ return mNotificationPanel.isCollapsing()
+ || mActivityLaunchAnimator.isAnimationPending()
+ || mActivityLaunchAnimator.isAnimationRunning();
+ }
+
+ @Override
+ public boolean isCollapsingToShowActivityOverLockscreen() {
+ return mIsCollapsingToShowActivityOverLockscreen;
+ }
+
+ @Override
+ public void onPerformRemoveNotification(StatusBarNotification n) {
+ if (mNotificationPanel.hasPulsingNotifications() &&
+ !mAmbientPulseManager.hasNotifications()) {
+ // We were showing a pulse for a notification, but no notifications are pulsing anymore.
+ // Finish the pulse.
+ mDozeScrimController.pulseOutNow();
+ }
+ }
+
+ @Override
+ public void updateNotificationViews() {
+ // The function updateRowStates depends on both of these being non-null, so check them here.
+ // We may be called before they are set from DeviceProvisionedController's callback.
+ if (mScrimController == null) return;
+
+ // Do not modify the notifications during collapse.
+ if (isCollapsing()) {
+ mShadeController.addPostCollapseAction(this::updateNotificationViews);
+ return;
+ }
+
+ mViewHierarchyManager.updateNotificationViews();
+
+ mNotificationPanel.updateNotificationViews();
+ }
+
+ @Override
+ public void onNotificationAdded(Entry shadeEntry) {
+ // Recalculate the position of the sliding windows and the titles.
+ mShadeController.updateAreThereNotifications();
+ }
+
+ @Override
+ public void onNotificationUpdated(StatusBarNotification notification) {
+ mShadeController.updateAreThereNotifications();
+ }
+
+ @Override
+ public void onNotificationRemoved(String key, StatusBarNotification old) {
+ if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
+
+ if (old != null) {
+ if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
+ && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
+ if (mStatusBarStateController.getState() == StatusBarState.SHADE) {
+ mCommandQueue.animateCollapsePanels();
+ } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
+ && !isCollapsing()) {
+ mShadeController.goToKeyguard();
+ }
+ }
+ }
+ mShadeController.updateAreThereNotifications();
+ }
+
+ public boolean hasActiveNotifications() {
+ return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+ }
+
+ @Override
+ public boolean canHeadsUp(Entry entry, StatusBarNotification sbn) {
+ if (!mShadeController.isDozing()) {
+ return false;
+ }
+
+ if (mShadeController.isOccluded()) {
+ boolean devicePublic = mLockscreenUserManager.
+ isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
+ boolean userPublic = devicePublic
+ || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
+ boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
+ if (userPublic && needsRedaction) {
+ return false;
+ }
+ }
+
+ if (!mCommandQueue.panelsEnabled()) {
+ if (DEBUG) {
+ Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
+ }
+ return false;
+ }
+
+ if (sbn.getNotification().fullScreenIntent != null) {
+ if (mAccessibilityManager.isTouchExplorationEnabled()) {
+ if (DEBUG) Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
+ return false;
+ } else {
+ // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
+ return !mKeyguardMonitor.isShowing()
+ || mShadeController.isOccluded();
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+ // Begin old BaseStatusBar.userSwitched
+ mHeadsUpManager.setUser(newUserId);
+ // End old BaseStatusBar.userSwitched
+ if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
+ mCommandQueue.animateCollapsePanels();
+ if (mReinflateNotificationsOnUserSwitched) {
+ mEntryManager.updateNotificationsOnDensityOrFontScaleChanged();
+ mReinflateNotificationsOnUserSwitched = false;
+ }
+ updateNotificationViews();
+ mMediaManager.clearCurrentMediaNotification();
+ mShadeController.setLockscreenUser(newUserId);
+ updateMediaMetaData(true, false);
+ }
+
+ @Override
+ public void onBindRow(Entry entry, PackageManager pmUser,
+ StatusBarNotification sbn, ExpandableNotificationRow row) {
+ row.setAboveShelfChangedListener(mAboveShelfObserver);
+ row.setSecureStateProvider(mUnlockMethodCache::canSkipBouncer);
+ }
+
+ @Override
+ public boolean isPresenterFullyCollapsed() {
+ return mNotificationPanel.isFullyCollapsed();
+ }
+
+ @Override
+ public void onActivated(ActivatableNotificationView view) {
+ onActivated();
+ if (view != null) mNotificationPanel.setActivatedChild(view);
+ }
+
+ public void onActivated() {
+ mLockscreenGestureLogger.write(
+ MetricsEvent.ACTION_LS_NOTE,
+ 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+ mNotificationPanel.showTransientIndication(R.string.notification_tap_again);
+ ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
+ if (previousView != null) {
+ previousView.makeInactive(true /* animate */);
+ }
+ }
+
+ @Override
+ public void onActivationReset(ActivatableNotificationView view) {
+ if (view == mNotificationPanel.getActivatedChild()) {
+ mNotificationPanel.setActivatedChild(null);
+ mShadeController.onActivationReset();
+ }
+ }
+
+ @Override
+ public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
+ mMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation);
+ }
+
+ @Override
+ public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
+ RemoteInputController controller = mRemoteInputManager.getController();
+ if (controller.isRemoteInputActive(row.getEntry())
+ && !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
+ // We have an active remote input typed and the user clicked on the notification.
+ // this was probably unintentional, so we're closing the edit text instead.
+ controller.closeRemoteInputs();
+ return;
+ }
+ Notification notification = sbn.getNotification();
+ final PendingIntent intent = notification.contentIntent != null
+ ? notification.contentIntent
+ : notification.fullScreenIntent;
+ final String notificationKey = sbn.getKey();
+
+ boolean isActivityIntent = intent.isActivity();
+ final boolean afterKeyguardGone = isActivityIntent
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+ mLockscreenUserManager.getCurrentUserId());
+ final boolean wasOccluded = mShadeController.isOccluded();
+ boolean showOverLockscreen = mKeyguardMonitor.isShowing()
+ && PreviewInflater.wouldShowOverLockscreen(mContext,
+ intent.getIntent(),
+ mLockscreenUserManager.getCurrentUserId());
+ OnDismissAction postKeyguardAction = () -> {
+ // TODO: Some of this code may be able to move to NotificationEntryManager.
+ if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(notificationKey)) {
+ // Release the HUN notification to the shade.
+
+ if (isPresenterFullyCollapsed()) {
+ HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
+ }
+ //
+ // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
+ // become canceled shortly by NoMan, but we can't assume that.
+ mHeadsUpManager.removeNotification(sbn.getKey(),
+ true /* releaseImmediately */);
+ }
+ StatusBarNotification parentToCancel = null;
+ if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
+ StatusBarNotification summarySbn =
+ mGroupManager.getLogicalGroupSummary(sbn).getStatusBarNotification();
+ if (shouldAutoCancel(summarySbn)) {
+ parentToCancel = summarySbn;
+ }
+ }
+ final StatusBarNotification parentToCancelFinal = parentToCancel;
+ final Runnable runnable = () -> {
+ try {
+ // The intent we are sending is for the application, which
+ // won't have permission to immediately start an activity after
+ // the user switches to home. We know it is safe to do at this
+ // point, so make sure new activity switches are now allowed.
+ ActivityManager.getService().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+ int launchResult = ActivityManager.START_CANCELED;
+ if (intent != null) {
+ // If we are launching a work activity and require to launch
+ // separate work challenge, we defer the activity action and cancel
+ // notification until work challenge is unlocked.
+ if (isActivityIntent) {
+ final int userId = intent.getCreatorUserHandle().getIdentifier();
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+ && mKeyguardManager.isDeviceLocked(userId)) {
+ // TODO(b/28935539): should allow certain activities to
+ // bypass work challenge
+ if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
+ intent.getIntentSender(), notificationKey)) {
+ // Show work challenge, do not run PendingIntent and
+ // remove notification
+ collapseOnMainThread();
+ return;
+ }
+ }
+ }
+ Intent fillInIntent = null;
+ Entry entry = row.getEntry();
+ CharSequence remoteInputText = null;
+ if (!TextUtils.isEmpty(entry.remoteInputText)) {
+ remoteInputText = entry.remoteInputText;
+ }
+ if (!TextUtils.isEmpty(remoteInputText)
+ && !controller.isSpinning(entry.key)) {
+ fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
+ remoteInputText.toString());
+ }
+ RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(
+ row, wasOccluded);
+ try {
+ if (adapter != null) {
+ ActivityTaskManager.getService()
+ .registerRemoteAnimationForNextActivityStart(
+ intent.getCreatorPackage(), adapter);
+ }
+ launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
+ null, null, getActivityOptions(adapter));
+ mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
+ } catch (RemoteException | PendingIntent.CanceledException e) {
+ // the stack trace isn't very helpful here.
+ // Just log the exception message.
+ Log.w(TAG, "Sending contentIntent failed: " + e);
+
+ // TODO: Dismiss Keyguard.
+ }
+ if (isActivityIntent) {
+ mAssistManager.hideAssist();
+ }
+ }
+ if (shouldCollapse()) {
+ collapseOnMainThread();
+ }
+
+ final int count =
+ mEntryManager.getNotificationData().getActiveNotifications().size();
+ final int rank = mEntryManager.getNotificationData().getRank(notificationKey);
+ final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
+ rank, count, true);
+ try {
+ mBarService.onNotificationClick(notificationKey, nv);
+ } catch (RemoteException ex) {
+ // system process is dead if we're here.
+ }
+ if (parentToCancelFinal != null) {
+ removeNotification(parentToCancelFinal);
+ }
+ if (shouldAutoCancel(sbn)
+ || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
+ notificationKey)) {
+ // Automatically remove all notifications that we may have kept around longer
+ removeNotification(sbn);
+ }
+ mIsCollapsingToShowActivityOverLockscreen = false;
+ };
+
+ if (showOverLockscreen) {
+ mShadeController.addPostCollapseAction(runnable);
+ mShadeController.collapsePanel(true /* animate */);
+ } else if (mKeyguardMonitor.isShowing()
+ && mShadeController.isOccluded()) {
+ mShadeController.addAfterKeyguardGoneRunnable(runnable);
+ mShadeController.collapsePanel();
+ } else {
+ new Thread(runnable).start();
+ }
+
+ return !mNotificationPanel.isFullyCollapsed();
+ };
+ if (showOverLockscreen) {
+ mIsCollapsingToShowActivityOverLockscreen = true;
+ postKeyguardAction.onDismiss();
+ } else {
+ mActivityStarter.dismissKeyguardThenExecute(
+ postKeyguardAction, null /* cancel */, afterKeyguardGone);
+ }
+ }
+
+ private void removeNotification(StatusBarNotification notification) {
+ // We have to post it to the UI thread for synchronization
+ Dependency.get(MAIN_HANDLER).post(() -> {
+ Runnable removeRunnable =
+ () -> mEntryManager.performRemoveNotification(notification);
+ if (isCollapsing()) {
+ // To avoid lags we're only performing the remove
+ // after the shade was collapsed
+ mShadeController.addPostCollapseAction(removeRunnable);
+ } else {
+ removeRunnable.run();
+ }
+ });
+ }
+
+ @Override
+ public void startNotificationGutsIntent(final Intent intent, final int appUid,
+ ExpandableNotificationRow row) {
+ mActivityStarter.dismissKeyguardThenExecute(() -> {
+ AsyncTask.execute(() -> {
+ int launchResult = TaskStackBuilder.create(mContext)
+ .addNextIntentWithParentStack(intent)
+ .startActivities(getActivityOptions(
+ mActivityLaunchAnimator.getLaunchAnimation(
+ row, mShadeController.isOccluded())),
+ new UserHandle(UserHandle.getUserId(appUid)));
+ mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */);
+ if (shouldCollapse()) {
+ // Putting it back on the main thread, since we're touching views
+ Dependency.get(MAIN_HANDLER).post(() -> mCommandQueue.animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
+ }
+ });
+ return true;
+ }, null, false /* afterKeyguardGone */);
+ }
+
+ @Override
+ public int getMaxNotificationsWhileLocked(boolean recompute) {
+ if (recompute) {
+ mMaxKeyguardNotifications = Math.max(1,
+ mNotificationPanel.computeMaxKeyguardNotifications(
+ mMaxAllowedKeyguardNotifications));
+ return mMaxKeyguardNotifications;
+ }
+ return mMaxKeyguardNotifications;
+ }
+
+ @Override
+ public void onUpdateRowStates() {
+ mNotificationPanel.onUpdateRowStates();
+ }
+
+ @Override
+ public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
+ mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
+ if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD && nowExpanded) {
+ mShadeController.goToLockedShade(clickedEntry.row);
+ }
+ }
+
+ @Override
+ public boolean isDeviceInVrMode() {
+ return mVrMode;
+ }
+
+ @Override
+ public boolean isPresenterLocked() {
+ return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+ }
+
+ private void collapseOnMainThread() {
+ if (Looper.getMainLooper().isCurrentThread()) {
+ mShadeController.collapsePanel();
+ } else {
+ Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel);
+ }
+ }
+
+ private boolean shouldCollapse() {
+ return mStatusBarStateController.getState() != StatusBarState.SHADE
+ || !mActivityLaunchAnimator.isAnimationPending();
+ }
+
+ private void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
+ mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
+ mActivityStarter.dismissKeyguardThenExecute(dismissAction, null,
+ true /* afterKeyguardGone */);
+ }
+
+ private static boolean shouldAutoCancel(StatusBarNotification sbn) {
+ int flags = sbn.getNotification().flags;
+ if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
+ return false;
+ }
+ if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+ @Override
+ public void onVrStateChanged(boolean enabled) {
+ mVrMode = enabled;
+ }
+ };
+
+ private final CheckSaveListener mCheckSaveListener = new CheckSaveListener() {
+ @Override
+ public void checkSave(Runnable saveImportance, StatusBarNotification sbn) {
+ int state = mStatusBarStateController.getState();
+ // If the user has security enabled, show challenge if the setting is changed.
+ if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
+ && mKeyguardManager.isKeyguardLocked()) {
+ onLockedNotificationImportanceChange(() -> {
+ saveImportance.run();
+ return true;
+ });
+ } else {
+ saveImportance.run();
+ }
+ }
+ };
+
+ private final OnSettingsClickListener mOnSettingsClickListener = new OnSettingsClickListener() {
+ @Override
+ public void onSettingsClick(String key) {
+ try {
+ mBarService.onNotificationSettingsViewed(key);
+ } catch (RemoteException e) {
+ // if we're here we're dead
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
new file mode 100644
index 000000000000..06f9658a0902
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -0,0 +1,252 @@
+/*
+ * 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.phone;
+
+import static android.content.Intent.ACTION_DEVICE_LOCKED_CHANGED;
+
+import static com.android.systemui.SysUiServiceProvider.getComponent;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager
+ .NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
+
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
+import android.app.PendingIntent;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewTreeObserver;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.PreviewInflater;
+
+public class StatusBarRemoteInputCallback implements Callback, Callbacks {
+
+ private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ private final StatusBarStateController mStatusBarStateController
+ = Dependency.get(StatusBarStateController.class);
+ private final NotificationLockscreenUserManager mLockscreenUserManager
+ = Dependency.get(NotificationLockscreenUserManager.class);
+ private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+ private final Context mContext;
+ private View mPendingWorkRemoteInputView;
+ private final StatusBarStateController.StateListener mStateListener = this::setStatusBarState;
+ private View mPendingRemoteInputView;
+ private final ShadeController mShadeController = Dependency.get(ShadeController.class);
+ private KeyguardManager mKeyguardManager;
+ private final CommandQueue mCommandQueue;
+ private int mDisabled2;
+ protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
+
+ public StatusBarRemoteInputCallback(Context context) {
+ mContext = context;
+ mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
+ new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
+ mStatusBarStateController.addListener(mStateListener);
+ mKeyguardManager = context.getSystemService(KeyguardManager.class);
+ mCommandQueue = getComponent(context, CommandQueue.class);
+ mCommandQueue.addCallbacks(this);
+ }
+
+ private void setStatusBarState(int state) {
+ if (state == StatusBarState.SHADE && mStatusBarStateController.leaveOpenOnKeyguardHide()) {
+ if (!mStatusBarStateController.isKeyguardRequested()) {
+ if (mPendingRemoteInputView != null
+ && mPendingRemoteInputView.isAttachedToWindow()) {
+ mPendingRemoteInputView.post(mPendingRemoteInputView::callOnClick);
+ }
+ mPendingRemoteInputView = null;
+ }
+ }
+ }
+
+ @Override
+ public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
+ mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
+ mShadeController.showBouncer(true /* scrimmed */);
+ mPendingRemoteInputView = clicked;
+ }
+
+ protected void onWorkChallengeChanged() {
+ if (mPendingWorkRemoteInputView != null
+ && !mLockscreenUserManager.isAnyProfilePublicMode()) {
+ // Expand notification panel and the notification row, then click on remote input view
+ final Runnable clickPendingViewRunnable = () -> {
+ final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView;
+ if (pendingWorkRemoteInputView == null) {
+ return;
+ }
+
+ // Climb up the hierarchy until we get to the container for this row.
+ ViewParent p = pendingWorkRemoteInputView.getParent();
+ while (!(p instanceof ExpandableNotificationRow)) {
+ if (p == null) {
+ return;
+ }
+ p = p.getParent();
+ }
+
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) p;
+ ViewParent viewParent = row.getParent();
+ if (viewParent instanceof NotificationStackScrollLayout) {
+ final NotificationStackScrollLayout scrollLayout =
+ (NotificationStackScrollLayout) viewParent;
+ row.makeActionsVisibile();
+ row.post(() -> {
+ final Runnable finishScrollingCallback = () -> {
+ mPendingWorkRemoteInputView.callOnClick();
+ mPendingWorkRemoteInputView = null;
+ scrollLayout.setFinishScrollingCallback(null);
+ };
+ if (scrollLayout.scrollTo(row)) {
+ // It scrolls! So call it when it's finished.
+ scrollLayout.setFinishScrollingCallback(finishScrollingCallback);
+ } else {
+ // It does not scroll, so call it now!
+ finishScrollingCallback.run();
+ }
+ });
+ }
+ };
+ mShadeController.postOnShadeExpanded(clickPendingViewRunnable);
+ mShadeController.instantExpandNotificationsPanel();
+ }
+ }
+
+ @Override
+ public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row,
+ View clickedView) {
+ if (mKeyguardMonitor.isShowing()) {
+ onLockedRemoteInput(row, clickedView);
+ } else {
+ row.setUserExpanded(true);
+ row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
+ }
+ }
+
+ @Override
+ public void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
+ View clicked) {
+ // Collapse notification and show work challenge
+ mCommandQueue.animateCollapsePanels();
+ startWorkChallengeIfNecessary(userId, null, null);
+ // Add pending remote input view after starting work challenge, as starting work challenge
+ // will clear all previous pending review view
+ mPendingWorkRemoteInputView = clicked;
+ }
+
+ protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
+ String notificationKey) {
+ // Clear pending remote view, as we do not want to trigger pending remote input view when
+ // it's called by other code
+ mPendingWorkRemoteInputView = null;
+ // Begin old BaseStatusBar.startWorkChallengeIfNecessary.
+ final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+ null, userId);
+ if (newIntent == null) {
+ return false;
+ }
+ final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
+ callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
+ callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
+ callBackIntent.setPackage(mContext.getPackageName());
+
+ PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
+ mContext,
+ 0,
+ callBackIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT |
+ PendingIntent.FLAG_ONE_SHOT |
+ PendingIntent.FLAG_IMMUTABLE);
+ newIntent.putExtra(
+ Intent.EXTRA_INTENT,
+ callBackPendingIntent.getIntentSender());
+ try {
+ ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent,
+ null /*options*/);
+ } catch (RemoteException ex) {
+ // ignore
+ }
+ return true;
+ // End old BaseStatusBar.startWorkChallengeIfNecessary.
+ }
+
+ @Override
+ public boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent) {
+ // Skip remote input as doing so will expand the notification shade.
+ return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
+ }
+
+ @Override
+ public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent,
+ Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) {
+ final boolean isActivity = pendingIntent.isActivity();
+ if (isActivity) {
+ final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
+ mActivityStarter.dismissKeyguardThenExecute(() -> {
+ try {
+ ActivityManager.getService().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+
+ boolean handled = defaultHandler.handleClick();
+
+ // close the shade if it was open and maybe wait for activity start.
+ return handled && mShadeController.closeShadeIfOpen();
+ }, null, afterKeyguardGone);
+ return true;
+ } else {
+ return defaultHandler.handleClick();
+ }
+ }
+
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ mDisabled2 = state2;
+ }
+
+ protected class ChallengeReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
+ if (userId != mLockscreenUserManager.getCurrentUserId()
+ && mLockscreenUserManager.isCurrentProfile(userId)) {
+ onWorkChallengeChanged();
+ }
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 8e32a0b44c28..59bd85eaabd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -27,8 +27,7 @@ import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.os.SystemProperties;
-import android.view.DisplayListCanvas;
+import android.graphics.RecordingCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewConfiguration;
@@ -122,7 +121,7 @@ public class KeyButtonRipple extends Drawable {
public void draw(Canvas canvas) {
mSupportHardware = canvas.isHardwareAccelerated();
if (mSupportHardware) {
- drawHardware((DisplayListCanvas) canvas);
+ drawHardware((RecordingCanvas) canvas);
} else {
drawSoftware(canvas);
}
@@ -147,7 +146,7 @@ public class KeyButtonRipple extends Drawable {
return getBounds().width() > getBounds().height();
}
- private void drawHardware(DisplayListCanvas c) {
+ private void drawHardware(RecordingCanvas c) {
if (mDrawingHardwareGlow) {
c.drawRoundRect(mLeftProp, mTopProp, mRightProp, mBottomProp, mRxProp, mRyProp,
mPaintProp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 7b42dd4c9817..aba23778f08c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -24,6 +24,7 @@ public interface KeyguardMonitor extends CallbackController<Callback> {
boolean isOccluded();
boolean isKeyguardFadingAway();
boolean isKeyguardGoingAway();
+ boolean isLaunchTransitionFadingAway();
long getKeyguardFadingAwayDuration();
long getKeyguardFadingAwayDelay();
long calculateGoingToFullShadeDelay();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 10cb09b75c16..5eb0fb76794d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -28,7 +28,7 @@ import java.util.ArrayList;
public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
implements KeyguardMonitor {
- private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+ private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final Context mContext;
private final CurrentUserTracker mUserTracker;
@@ -45,6 +45,7 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
private long mKeyguardFadingAwayDelay;
private long mKeyguardFadingAwayDuration;
private boolean mKeyguardGoingAway;
+ private boolean mLaunchTransitionFadingAway;
public KeyguardMonitorImpl(Context context) {
mContext = context;
@@ -123,7 +124,7 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
private void notifyKeyguardChanged() {
// Copy the list to allow removal during callback.
- new ArrayList<Callback>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
+ new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
}
public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
@@ -165,4 +166,13 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
mKeyguardGoingAway = keyguardGoingAway;
}
+
+ public void setLaunchTransitionFadingAway(boolean fadingAway) {
+ mLaunchTransitionFadingAway = fadingAway;
+ }
+
+ @Override
+ public boolean isLaunchTransitionFadingAway() {
+ return mLaunchTransitionFadingAway;
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index dd031623f356..aa4782fd864a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -28,7 +28,7 @@ import android.widget.Button;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ContrastColorUtil;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java
index 3f85c9d169c7..a69fd5619e99 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java
@@ -23,6 +23,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import org.junit.Assert;
import org.junit.Before;
@@ -44,7 +45,7 @@ public class KeyguardHostViewTest extends SysuiTestCase {
@Test
public void testHasDismissActions() {
Assert.assertFalse("Action not set yet", mKeyguardHostView.hasDismissActions());
- mKeyguardHostView.setOnDismissAction(mock(KeyguardHostView.OnDismissAction.class),
+ mKeyguardHostView.setOnDismissAction(mock(OnDismissAction.class),
null /* cancelAction */);
Assert.assertTrue("Action should exist", mKeyguardHostView.hasDismissActions());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index a35ca46833e7..a58bc8548bd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -58,7 +58,6 @@ public abstract class SysuiTestCase {
@Before
public void SysuiSetup() throws Exception {
- mContext.setTheme(R.style.Theme_SystemUI);
SystemUIFactory.createFromConfig(mContext);
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
index 9d3124e9ecc6..e811270a4450 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestableContext.java
@@ -25,10 +25,12 @@ public class SysuiTestableContext extends TestableContext implements SysUiServic
public SysuiTestableContext(Context base) {
super(base);
+ setTheme(R.style.Theme_SystemUI);
}
public SysuiTestableContext(Context base, LeakCheck check) {
super(base, check);
+ setTheme(R.style.Theme_SystemUI);
}
public ArrayMap<Class<?>, Object> getComponents() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
index 5c83d99b646a..0c8d137569f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
@@ -25,6 +25,9 @@ public class TestableDependency extends Dependency {
private final ArraySet<Object> mInstantiatedObjects = new ArraySet<>();
public TestableDependency(Context context) {
+ if (context instanceof SysuiTestableContext) {
+ mComponents = ((SysuiTestableContext) context).getComponents();
+ }
mContext = context;
if (SystemUIFactory.getInstance() == null) {
SystemUIFactory.createFromConfig(context);
@@ -43,6 +46,9 @@ public class TestableDependency extends Dependency {
}
public <T> void injectTestDependency(Class<T> key, T obj) {
+ if (mInstantiatedObjects.contains(key)) {
+ throw new IllegalStateException(key + " was already initialized");
+ }
mObjs.put(key, obj);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
index 2398fd3c4712..6abd407afd91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
@@ -115,6 +115,11 @@ class DozeHostFake implements DozeHost {
}
@Override
+ public void setPassiveInterrupt(boolean lightInterrupt) {
+
+ }
+
+ @Override
public void setDozeScreenBrightness(int value) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index a02ef98f834d..8ae3cd8d6acd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -84,7 +84,7 @@ public class CommandQueueTest extends SysuiTestCase {
public void testCollapsePanels() {
mCommandQueue.animateCollapsePanels();
waitForIdleSync();
- verify(mCallbacks).animateCollapsePanels(eq(0));
+ verify(mCallbacks).animateCollapsePanels(eq(0), eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index da59450af4df..fe0a7c78def1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar;
import static org.junit.Assert.assertFalse;
-import static org.mockito.Mockito.when;
import android.os.Handler;
import android.os.Looper;
@@ -26,13 +25,15 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.NotificationInfo;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -49,25 +50,27 @@ import org.mockito.MockitoAnnotations;
*/
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class NonPhoneDependencyTest extends SysuiTestCase {
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationListContainer mListContainer;
@Mock private NotificationEntryManager.Callback mEntryManagerCallback;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private RemoteInputController.Delegate mDelegate;
- @Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
- @Mock private NotificationGutsManager.OnSettingsClickListener mOnClickListener;
@Mock private NotificationRemoteInputManager.Callback mRemoteInputManagerCallback;
+ @Mock private CheckSaveListener mCheckSaveListener;
+ @Mock private OnSettingsClickListener mOnSettingsClickListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ new Handler(TestableLooper.get(this).getLooper()));
}
@Test
public void testNotificationManagementCodeHasNoDependencyOnStatusBarWindowManager() {
+ mDependency.injectMockDependency(ShadeController.class);
NotificationEntryManager entryManager = Dependency.get(NotificationEntryManager.class);
NotificationGutsManager gutsManager = Dependency.get(NotificationGutsManager.class);
NotificationListener notificationListener = Dependency.get(NotificationListener.class);
@@ -79,24 +82,20 @@ public class NonPhoneDependencyTest extends SysuiTestCase {
Dependency.get(NotificationLockscreenUserManager.class);
NotificationViewHierarchyManager viewHierarchyManager =
Dependency.get(NotificationViewHierarchyManager.class);
- NotificationGroupManager groupManager = Dependency.get(NotificationGroupManager.class);
-
- when(mPresenter.getNotificationLockscreenUserManager()).thenReturn(lockscreenUserManager);
- when(mPresenter.getGroupManager()).thenReturn(groupManager);
-
+ Dependency.get(InitController.class).executePostInitTasks();
entryManager.setUpWithPresenter(mPresenter, mListContainer, mEntryManagerCallback,
mHeadsUpManager);
- groupManager.setHeadsUpManager(mHeadsUpManager);
- gutsManager.setUpWithPresenter(mPresenter, mListContainer, mCheckSaveListener,
- mOnClickListener);
- notificationLogger.setUpWithEntryManager(entryManager, mListContainer);
- mediaManager.setUpWithPresenter(mPresenter, entryManager);
- remoteInputManager.setUpWithPresenter(mPresenter, entryManager, mRemoteInputManagerCallback,
+ gutsManager.setUpWithPresenter(mPresenter, mListContainer,
+ mCheckSaveListener, mOnSettingsClickListener);
+ notificationLogger.setUpWithContainer(mListContainer);
+ mediaManager.setUpWithPresenter(mPresenter);
+ remoteInputManager.setUpWithPresenter(mPresenter, mRemoteInputManagerCallback,
mDelegate);
- lockscreenUserManager.setUpWithPresenter(mPresenter, entryManager);
- viewHierarchyManager.setUpWithPresenter(mPresenter, entryManager, mListContainer);
- notificationListener.setUpWithPresenter(mPresenter, entryManager);
+ lockscreenUserManager.setUpWithPresenter(mPresenter);
+ viewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
+ notificationListener.setUpWithPresenter(mPresenter);
+ TestableLooper.get(this).processAllMessages();
assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowController.class));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index 7b0c0a077332..63ececbe2994 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -32,6 +32,7 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -44,7 +45,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class NotificationListenerTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = 0;
@@ -66,15 +67,16 @@ public class NotificationListenerTest extends SysuiTestCase {
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(NotificationRemoteInputManager.class,
mRemoteInputManager);
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ new Handler(TestableLooper.get(this).getLooper()));
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mListener = new NotificationListener(mContext);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
- mListener.setUpWithPresenter(mPresenter, mEntryManager);
+ mListener.setUpWithPresenter(mPresenter);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 515c10980ff6..f168a490acf4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -40,7 +40,7 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.util.Log;
+import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -83,12 +83,12 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
when(mUserManager.getProfiles(mCurrentUserId)).thenReturn(Lists.newArrayList(
new UserInfo(mCurrentUserId, "", 0), new UserInfo(mCurrentUserId + 1, "", 0)));
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ Handler.createAsync(Looper.myLooper()));
mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
- mLockscreenUserManager.setUpWithPresenter(mPresenter, mEntryManager);
- mLockscreenUserManager.setKeyguardViewManager(mKeyguardViewManager);
+ mLockscreenUserManager.setUpWithPresenter(mPresenter);
}
@Test
@@ -137,15 +137,6 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
}
@Test
- public void testActionDeviceLockedChangedWithDifferentUserIdCallsOnWorkChallengeChanged() {
- Intent intent = new Intent()
- .setAction(ACTION_DEVICE_LOCKED_CHANGED)
- .putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId + 1);
- mLockscreenUserManager.getAllUsersReceiverForTest().onReceive(mContext, intent);
- verify(mPresenter, times(1)).onWorkChallengeChanged();
- }
-
- @Test
public void testActionUserSwitchedCallsOnUserSwitched() {
Intent intent = new Intent()
.setAction(ACTION_USER_SWITCHED)
@@ -161,15 +152,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUserId));
}
- private class TestNotificationLockscreenUserManager extends NotificationLockscreenUserManager {
+ private class TestNotificationLockscreenUserManager extends NotificationLockscreenUserManagerImpl {
public TestNotificationLockscreenUserManager(Context context) {
super(context);
}
- public BroadcastReceiver getAllUsersReceiverForTest() {
- return mAllUsersReceiver;
- }
-
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
return mBaseBroadcastReceiver;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 8a59e968d16e..d409e2b254df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -20,6 +20,7 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
@@ -70,8 +71,8 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mLockscreenUserManager);
mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
-
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ Handler.createAsync(Looper.myLooper()));
mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID,
@@ -79,7 +80,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
mEntry = new NotificationData.Entry(mSbn);
mEntry.row = mRow;
- mRemoteInputManager.setUpWithPresenterForTest(mPresenter, mEntryManager, mCallback,
+ mRemoteInputManager.setUpWithPresenterForTest(mPresenter, mCallback,
mDelegate, mController);
for (NotificationLifetimeExtender extender : mRemoteInputManager.getLifetimeExtenders()) {
extender.setCallback(
@@ -201,11 +202,10 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
}
public void setUpWithPresenterForTest(NotificationPresenter presenter,
- NotificationEntryManager entryManager,
Callback callback,
RemoteInputController.Delegate delegate,
RemoteInputController controller) {
- super.setUpWithPresenter(presenter, entryManager, callback, delegate);
+ super.setUpWithPresenter(presenter, callback, delegate);
mRemoteInputController = controller;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 6b4ccc4a80b5..602e613388fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -32,6 +32,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import com.android.systemui.Dependency;
+import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.NotificationData;
@@ -42,6 +44,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.google.android.collect.Lists;
@@ -67,6 +70,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGroupManager mGroupManager;
@Mock private VisualStabilityManager mVisualStabilityManager;
+ @Mock private ShadeController mShadeController;
private NotificationViewHierarchyManager mViewHierarchyManager;
private NotificationTestHelper mHelper = new NotificationTestHelper(mContext);;
@@ -79,11 +83,13 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
mLockscreenUserManager);
mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
+ mDependency.injectTestDependency(ShadeController.class, mShadeController);
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext);
- mViewHierarchyManager.setUpWithPresenter(mPresenter, mEntryManager, mListContainer);
+ Dependency.get(InitController.class).executePostInitTasks();
+ mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}
private NotificationData.Entry createEntry() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 17daaacded87..1d977d8c5dad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -80,8 +80,7 @@ public class SmartReplyControllerTest extends SysuiTestCase {
mSmartReplyController);
mRemoteInputManager = new NotificationRemoteInputManager(mContext);
- mRemoteInputManager.setUpWithPresenter(mPresenter, mNotificationEntryManager, mCallback,
- mDelegate);
+ mRemoteInputManager.setUpWithPresenter(mPresenter, mCallback, mDelegate);
mNotification = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
index 78be783da17b..b405a5cd91bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.os.Handler;
@@ -27,6 +26,7 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -59,14 +59,15 @@ public class AppOpsListenerTest extends SysuiTestCase {
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ Handler.createAsync(Looper.myLooper()));
mListener = new AppOpsListener(mContext);
}
@Test
public void testOnlyListenForFewOps() {
- mListener.setUpWithPresenter(mPresenter, mEntryManager);
+ mListener.setUpWithPresenter(mPresenter);
verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsListener.OPS, mListener);
}
@@ -79,7 +80,7 @@ public class AppOpsListenerTest extends SysuiTestCase {
@Test
public void testInformEntryMgrOnAppOpsChange() {
- mListener.setUpWithPresenter(mPresenter, mEntryManager);
+ mListener.setUpWithPresenter(mPresenter);
mListener.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
TestableLooper.get(this).processAllMessages();
@@ -89,7 +90,7 @@ public class AppOpsListenerTest extends SysuiTestCase {
@Test
public void testInformFscOnAppOpsChange() {
- mListener.setUpWithPresenter(mPresenter, mEntryManager);
+ mListener.setUpWithPresenter(mPresenter);
mListener.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
TestableLooper.get(this).processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index de5a8a0a6d2d..459dc5d43c2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -55,13 +55,16 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet;
+import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -87,7 +90,7 @@ public class NotificationDataTest extends SysuiTestCase {
@Mock
ForegroundServiceController mFsc;
@Mock
- NotificationData.Environment mEnvironment;
+ NotificationData.KeyguardEnvironment mEnvironment;
private final IPackageManager mMockPackageManager = mock(IPackageManager.class);
private NotificationData mNotificationData;
@@ -108,10 +111,14 @@ public class NotificationDataTest extends SysuiTestCase {
.thenReturn(PackageManager.PERMISSION_GRANTED);
mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
- when(mEnvironment.getGroupManager()).thenReturn(new NotificationGroupManager());
+ mDependency.injectTestDependency(NotificationGroupManager.class,
+ new NotificationGroupManager());
+ mDependency.injectMockDependency(ShadeController.class);
+ mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
- mNotificationData = new TestableNotificationData(mEnvironment);
+ mNotificationData = new TestableNotificationData();
+ Dependency.get(InitController.class).executePostInitTasks();
mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
mRow = new NotificationTestHelper(getContext()).createRow();
}
@@ -298,11 +305,11 @@ public class NotificationDataTest extends SysuiTestCase {
mRow.getEntry().notification)).thenReturn(false);
when(mEnvironment.isNotificationForCurrentProfiles(
row2.getEntry().notification)).thenReturn(true);
- ArrayList<NotificationData.Entry> reuslt =
+ ArrayList<NotificationData.Entry> result =
mNotificationData.getNotificationsForCurrentUser();
- assertEquals(reuslt.size(), 1);
- junit.framework.Assert.assertEquals(reuslt.get(0), row2.getEntry());
+ assertEquals(result.size(), 1);
+ junit.framework.Assert.assertEquals(result.get(0), row2.getEntry());
}
@Test
@@ -416,8 +423,8 @@ public class NotificationDataTest extends SysuiTestCase {
}
private class TestableNotificationData extends NotificationData {
- public TestableNotificationData(Environment environment) {
- super(environment);
+ public TestableNotificationData() {
+ super();
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index f01ae7a23533..fb4ecd1383c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -54,7 +54,9 @@ import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
@@ -66,12 +68,14 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -97,6 +101,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
private static final int TEST_UID = 0;
@Mock private NotificationPresenter mPresenter;
+ @Mock private KeyguardEnvironment mEnvironment;
@Mock private ExpandableNotificationRow mRow;
@Mock private NotificationListContainer mListContainer;
@Mock private NotificationEntryManager.Callback mCallback;
@@ -190,6 +195,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mDependency.injectMockDependency(ShadeController.class);
mDependency.injectTestDependency(ForegroundServiceController.class,
mForegroundServiceController);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
@@ -204,12 +210,12 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController);
+ mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment);
mCountDownLatch = new CountDownLatch(1);
- when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper()));
- when(mPresenter.getNotificationLockscreenUserManager()).thenReturn(mLockscreenUserManager);
- when(mPresenter.getGroupManager()).thenReturn(mGroupManager);
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+ Handler.createAsync(Looper.myLooper()));
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
when(mListContainer.getViewParentForNotification(any())).thenReturn(
new FrameLayout(mContext));
@@ -224,6 +230,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntry.expandedIcon = mock(StatusBarIconView.class);
mEntryManager = new TestableNotificationEntryManager(mContext, mBarService);
+ Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mCallback, mHeadsUpManager);
setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
@@ -421,8 +428,9 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationRanking() {
- when(mPresenter.isDeviceProvisioned()).thenReturn(true);
- when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
+ when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mEntry.row = mRow;
mEntry.setInflationTask(mAsyncInflationTask);
@@ -437,8 +445,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationRanking_noChange() {
- when(mPresenter.isDeviceProvisioned()).thenReturn(true);
- when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mEntry.row = mRow;
mEntryManager.getNotificationData().add(mEntry);
@@ -451,8 +459,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationRanking_rowNotInflatedYet() {
- when(mPresenter.isDeviceProvisioned()).thenReturn(true);
- when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mEntry.row = null;
mEntryManager.getNotificationData().add(mEntry);
@@ -466,8 +474,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationRanking_pendingNotification() {
- when(mPresenter.isDeviceProvisioned()).thenReturn(true);
- when(mPresenter.isNotificationForCurrentProfiles(any())).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mEntry.row = null;
mEntryManager.mPendingNotifications.put(mEntry.key, mEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index ca62c3b5ee6f..1c7a8e8185a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -92,7 +92,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
mEntry.row = mRow;
mLogger = new TestableNotificationLogger(mBarService);
- mLogger.setUpWithEntryManager(mEntryManager, mListContainer);
+ mLogger.setUpWithContainer(mListContainer);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 8edbf176215a..ee35449e05da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -61,7 +61,9 @@ import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import org.junit.Before;
import org.junit.Rule;
@@ -93,11 +95,14 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationStackScrollLayout mStackScroller;
@Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
- @Mock private NotificationGutsManager.OnSettingsClickListener mOnSettingsClickListener;
+ @Mock private OnSettingsClickListener mOnSettingsClickListener;
+ @Mock private DeviceProvisionedController mDeviceProvisionedController;
@Before
public void setUp() {
mTestableLooper = TestableLooper.get(this);
+ mDependency.injectTestDependency(DeviceProvisionedController.class,
+ mDeviceProvisionedController);
mHandler = Handler.createAsync(mTestableLooper.getLooper());
mHelper = new NotificationTestHelper(mContext);
@@ -330,7 +335,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- when(mPresenter.isDeviceProvisioned()).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index f8b24363da8f..d2fe82fd93c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -17,6 +17,8 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -40,30 +42,31 @@ import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
+import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
+import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.EmptyShadeView;
-import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationData.Entry;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
-import java.util.ArrayList;
-
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -74,6 +77,8 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
+
/**
* Tests for {@link NotificationStackScrollLayout}.
*/
@@ -108,6 +113,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mDependency.injectTestDependency(StatusBarStateController.class, mBarState);
mDependency.injectTestDependency(NotificationRemoteInputManager.class,
mRemoteInputManager);
+ mDependency.injectMockDependency(ShadeController.class);
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
IPowerManager powerManagerService = mock(IPowerManager.class);
@@ -116,11 +122,13 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mEntryManager = new TestableNotificationEntryManager(mDreamManager, mPowerManager,
mContext);
+ mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+ Dependency.get(InitController.class).executePostInitTasks();
mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, null, mHeadsUpManager,
mNotificationData);
- mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
- NotificationShelf notificationShelf = spy(new NotificationShelf(getContext(), null));
+
+ NotificationShelf notificationShelf = mock(NotificationShelf.class);
mStackScroller = spy(new NotificationStackScrollLayout(getContext()));
mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
@@ -147,7 +155,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
when(mBarState.getState()).thenReturn(StatusBarState.SHADE);
mStackScroller.setDimmed(true /* dimmed */, false /* animate */);
mStackScroller.setDimmed(true /* dimmed */, true /* animate */);
- Assert.assertFalse(mStackScroller.isDimmed());
+ assertFalse(mStackScroller.isDimmed());
}
@Test
@@ -246,7 +254,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
assertEquals(0, mNotificationData.getActiveNotifications().size());
mStackScroller.updateFooter();
- verify(mStackScroller).updateFooterView(false, false);
+ verify(mStackScroller, atLeastOnce()).updateFooterView(false, false);
}
@Test
@@ -287,7 +295,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
setBarStateForTest(StatusBarState.SHADE);
ArrayList<Entry> entries = new ArrayList<>();
entries.add(mock(Entry.class));
- when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+ when(mEntryManager.getNotificationData().getActiveNotifications()).thenReturn(entries);
+ assertTrue(mEntryManager.getNotificationData().getActiveNotifications().size() != 0);
mStackScroller.updateFooter();
verify(mStackScroller).updateFooterView(true, false);
@@ -348,9 +357,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
private void setBarStateForTest(int state) {
- ArgumentCaptor<StatusBarStateController.StateListener> captor =
- ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
- verify(mBarState, atLeastOnce()).addListener(captor.capture());
- captor.getValue().onStateChanged(state);
+ // Can't inject this through the listener or we end up on the actual implementation
+ // rather than the mock because the spy just coppied the anonymous inner /shruggie.
+ mStackScroller.setStatusBarState(state);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 020682b6b4e8..7f8668fa064c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -45,6 +45,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import org.junit.Assert;
import org.junit.Before;
@@ -238,7 +239,7 @@ public class KeyguardBouncerTest extends SysuiTestCase {
@Test
public void testShowOnDismissAction_showsBouncer() {
- final KeyguardHostView.OnDismissAction dismissAction = () -> false;
+ final OnDismissAction dismissAction = () -> false;
final Runnable cancelAction = () -> {};
mBouncer.showWithDismissAction(dismissAction, cancelAction);
verify(mKeyguardHostView).setOnDismissAction(dismissAction, cancelAction);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index be4560b5b845..93dedfbe9656 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -31,10 +31,10 @@ import android.testing.TestableLooper;
import android.view.ViewGroup;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import org.junit.Before;
import org.junit.Test;
@@ -78,7 +78,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Test
public void dismissWithAction_AfterKeyguardGoneSetToFalse() {
- KeyguardHostView.OnDismissAction action = () -> false;
+ OnDismissAction action = () -> false;
Runnable cancelAction = () -> {};
mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
false /* afterKeyguardGone */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
new file mode 100644
index 000000000000..24baa7d770f1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.phone;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+
+import android.app.Notification;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.metrics.LogMaker;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.support.test.metricshelper.MetricsAsserts;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.logging.testing.FakeMetricsLogger;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class StatusBarNotificationPresenterTest extends SysuiTestCase {
+
+
+ private StatusBarNotificationPresenter mStatusBar;
+ private CommandQueue mCommandQueue;
+ private FakeMetricsLogger mMetricsLogger;
+ private ShadeController mShadeController = mock(ShadeController.class);
+
+ @Before
+ public void setup() {
+ mMetricsLogger = new FakeMetricsLogger();
+ mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
+ mCommandQueue = new CommandQueue();
+ mContext.putComponent(CommandQueue.class, mCommandQueue);
+ mDependency.injectTestDependency(ShadeController.class, mShadeController);
+
+ mStatusBar = new StatusBarNotificationPresenter(mContext,
+ mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
+ mock(StatusBarWindowView.class), mock(NotificationListContainerViewGroup.class),
+ mock(DozeScrimController.class), mock(ScrimController.class),
+ mock(ActivityLaunchAnimator.Callback.class));
+ }
+
+ @Test
+ public void testHeadsUp_disabledStatusBar() {
+ Notification n = new Notification.Builder(getContext(), "a").build();
+ StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+ UserHandle.of(0), null, 0);
+ NotificationData.Entry entry = new NotificationData.Entry(sbn);
+ mCommandQueue.disable(StatusBarManager.DISABLE_EXPAND, 0, false /* animate */);
+ TestableLooper.get(this).processAllMessages();
+
+ assertFalse("The panel shouldn't allow heads up while disabled",
+ mStatusBar.canHeadsUp(entry, sbn));
+ }
+
+ @Test
+ public void testHeadsUp_disabledNotificationShade() {
+ Notification n = new Notification.Builder(getContext(), "a").build();
+ StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+ UserHandle.of(0), null, 0);
+ NotificationData.Entry entry = new NotificationData.Entry(sbn);
+ mCommandQueue.disable(0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false /* animate */);
+ TestableLooper.get(this).processAllMessages();
+
+ assertFalse("The panel shouldn't allow heads up while notitifcation shade disabled",
+ mStatusBar.canHeadsUp(entry, sbn));
+ }
+
+ @Test
+ public void onActivatedMetrics() {
+ ActivatableNotificationView view = mock(ActivatableNotificationView.class);
+ mStatusBar.onActivated(view);
+
+ MetricsAsserts.assertHasLog("missing lockscreen note tap log",
+ mMetricsLogger.getLogs(),
+ new LogMaker(MetricsEvent.ACTION_LS_NOTE)
+ .setType(MetricsEvent.TYPE_ACTION));
+ }
+
+ // We need this because mockito doesn't know how to construct a mock that extends ViewGroup
+ // and implements NotificationListContainer without it because of classloader issues.
+ private abstract static class NotificationListContainerViewGroup extends ViewGroup
+ implements NotificationListContainer {
+
+ public NotificationListContainerViewGroup(Context context) {
+ super(context);
+ }
+ }
+}
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
new file mode 100644
index 000000000000..f28757f516da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.phone;
+
+import static android.content.Intent.ACTION_DEVICE_LOCKED_CHANGED;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
+ @Mock private NotificationPresenter mPresenter;
+ @Mock private UserManager mUserManager;
+
+ // Dependency mocks:
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private DeviceProvisionedController mDeviceProvisionedController;
+ @Mock private ShadeController mShadeController;
+ @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
+
+ private int mCurrentUserId = 0;
+ private StatusBarRemoteInputCallback mRemoteInputCallback;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
+ mDependency.injectTestDependency(DeviceProvisionedController.class,
+ mDeviceProvisionedController);
+ mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
+ mNotificationLockscreenUserManager);
+ mDependency.putComponent(CommandQueue.class, mock(CommandQueue.class));
+
+ mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext));
+ mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
+ }
+
+ @Test
+ public void testActionDeviceLockedChangedWithDifferentUserIdCallsOnWorkChallengeChanged() {
+ when(mNotificationLockscreenUserManager.getCurrentUserId()).thenReturn(mCurrentUserId);
+ when(mNotificationLockscreenUserManager.isCurrentProfile(anyInt())).thenReturn(true);
+ Intent intent = new Intent()
+ .setAction(ACTION_DEVICE_LOCKED_CHANGED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId + 1);
+ mRemoteInputCallback.mChallengeReceiver.onReceive(mContext, intent);
+ verify(mRemoteInputCallback, times(1)).onWorkChallengeChanged();
+ }
+
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index da93327061a8..939245f7cc7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -18,9 +18,7 @@ package com.android.systemui.statusbar.phone;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.fail;
@@ -64,42 +62,41 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.AppOpsListener;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationData.Entry;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.AppOpsListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationData.Entry;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import org.junit.Before;
import org.junit.Test;
@@ -137,18 +134,21 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
@Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private DeviceProvisionedController mDeviceProvisionedController;
+ @Mock private NotificationPresenter mNotificationPresenter;
+ @Mock private NotificationEntryManager.Callback mCallback;
private TestableStatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
private PowerManager mPowerManager;
private TestableNotificationEntryManager mEntryManager;
private NotificationLogger mNotificationLogger;
+ private CommandQueue mCommandQueue;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mDependency.injectMockDependency(AssistManager.class);
- mDependency.injectMockDependency(DeviceProvisionedController.class);
mDependency.injectMockDependency(NotificationGutsManager.class);
mDependency.injectMockDependency(NotificationMediaManager.class);
mDependency.injectMockDependency(ForegroundServiceController.class);
@@ -159,6 +159,8 @@ public class StatusBarTest extends SysuiTestCase {
mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
+ mDependency.injectTestDependency(DeviceProvisionedController.class,
+ mDeviceProvisionedController);
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -172,9 +174,9 @@ public class StatusBarTest extends SysuiTestCase {
mPowerManager = new PowerManager(mContext, powerManagerService,
Handler.createAsync(Looper.myLooper()));
- CommandQueue commandQueue = mock(CommandQueue.class);
- when(commandQueue.asBinder()).thenReturn(new Binder());
- mContext.putComponent(CommandQueue.class, commandQueue);
+ mCommandQueue = mock(CommandQueue.class);
+ when(mCommandQueue.asBinder()).thenReturn(new Binder());
+ mContext.putComponent(CommandQueue.class, mCommandQueue);
mContext.setTheme(R.style.Theme_SystemUI_Light);
@@ -202,17 +204,19 @@ public class StatusBarTest extends SysuiTestCase {
mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
mEntryManager, mScrimController, mBiometricUnlockController,
- mock(ActivityLaunchAnimator.class), mKeyguardViewMediator,
- mRemoteInputManager, mock(NotificationGroupManager.class),
+ mKeyguardViewMediator, mRemoteInputManager, mock(NotificationGroupManager.class),
mock(FalsingManager.class), mock(StatusBarWindowController.class),
mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
mock(NotificationShelf.class), mLockscreenUserManager,
- mock(CommandQueue.class));
+ mCommandQueue,
+ mNotificationPresenter);
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
- mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
- mNotificationData);
- mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller);
+ mStatusBar.putComponent(StatusBar.class, mStatusBar);
+ Dependency.get(InitController.class).executePostInitTasks();
+ mEntryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
+ mCallback, mHeadsUpManager, mNotificationData);
+ mNotificationLogger.setUpWithContainer(mStackScroller);
TestableLooper.get(this).setMessageHandler(m -> {
if (m.getCallback() == mStatusBar.mNotificationLogger.getVisibilityReporter()) {
@@ -347,17 +351,6 @@ public class StatusBarTest extends SysuiTestCase {
}
@Test
- public void onActivatedMetrics() {
- ActivatableNotificationView view = mock(ActivatableNotificationView.class);
- mStatusBar.onActivated(view);
-
- MetricsAsserts.assertHasLog("missing lockscreen note tap log",
- mMetricsLogger.getLogs(),
- new LogMaker(MetricsEvent.ACTION_LS_NOTE)
- .setType(MetricsEvent.TYPE_ACTION));
- }
-
- @Test
public void testShouldHeadsUp_nonSuppressedGroupSummary() throws Exception {
when(mPowerManager.isScreenOn()).thenReturn(true);
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
@@ -365,6 +358,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+ when(mCallback.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a")
.setGroup("a")
@@ -386,6 +380,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+ when(mCallback.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a")
.setGroup("a")
@@ -406,6 +401,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+ when(mCallback.canHeadsUp(any(), any())).thenReturn(true);
when(mNotificationData.shouldSuppressPeek(any())).thenReturn(true);
@@ -424,6 +420,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+ when(mCallback.canHeadsUp(any(), any())).thenReturn(true);
when(mNotificationData.shouldSuppressPeek(any())).thenReturn(false);
@@ -436,30 +433,6 @@ public class StatusBarTest extends SysuiTestCase {
}
@Test
- public void testHeadsUp_disabledStatusBar() {
- Notification n = new Notification.Builder(getContext(), "a").build();
- StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
- UserHandle.of(0), null, 0);
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- mStatusBar.disable(StatusBarManager.DISABLE_EXPAND, 0, false /* animate */);
-
- assertFalse("The panel shouldn't allow heads up while disabled",
- mStatusBar.canHeadsUp(entry, sbn));
- }
-
- @Test
- public void testHeadsUp_disabledNotificationShade() {
- Notification n = new Notification.Builder(getContext(), "a").build();
- StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
- UserHandle.of(0), null, 0);
- NotificationData.Entry entry = new NotificationData.Entry(sbn);
- mStatusBar.disable(0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false /* animate */);
-
- assertFalse("The panel shouldn't allow heads up while notification shade disabled",
- mStatusBar.canHeadsUp(entry, sbn));
- }
-
- @Test
public void testLogHidden() {
try {
mStatusBar.handleVisibleToUserChanged(false);
@@ -473,10 +446,11 @@ public class StatusBarTest extends SysuiTestCase {
@Test
public void testPanelOpenForHeadsUp() {
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
when(mNotificationList.size()).thenReturn(5);
- when(mNotificationPanelView.isFullyCollapsed()).thenReturn(true);
+ when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(true);
mStatusBar.setBarStateForTest(StatusBarState.SHADE);
try {
@@ -495,7 +469,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
when(mNotificationList.size()).thenReturn(5);
- when(mNotificationPanelView.isFullyCollapsed()).thenReturn(false);
+ when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(false);
mStatusBar.setBarStateForTest(StatusBarState.SHADE);
try {
@@ -514,7 +488,7 @@ public class StatusBarTest extends SysuiTestCase {
when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
when(mNotificationList.size()).thenReturn(5);
- when(mNotificationPanelView.isFullyCollapsed()).thenReturn(false);
+ when(mNotificationPresenter.isPresenterFullyCollapsed()).thenReturn(false);
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
try {
@@ -532,8 +506,9 @@ public class StatusBarTest extends SysuiTestCase {
public void testDisableExpandStatusBar() {
mStatusBar.setBarStateForTest(StatusBarState.SHADE);
mStatusBar.setUserSetupForTest(true);
- when(mStatusBar.isDeviceProvisioned()).thenReturn(true);
+ when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ when(mCommandQueue.panelsEnabled()).thenReturn(false);
mStatusBar.disable(StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
verify(mNotificationPanelView).setQsExpansionEnabled(false);
@@ -542,6 +517,7 @@ public class StatusBarTest extends SysuiTestCase {
mStatusBar.animateExpandSettingsPanel(null);
verify(mNotificationPanelView, never()).expand(anyBoolean());
+ when(mCommandQueue.panelsEnabled()).thenReturn(true);
mStatusBar.disable(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_NONE, false);
verify(mNotificationPanelView).setQsExpansionEnabled(true);
mStatusBar.animateExpandNotificationsPanel();
@@ -627,7 +603,7 @@ public class StatusBarTest extends SysuiTestCase {
NotificationViewHierarchyManager viewHierarchyManager,
TestableNotificationEntryManager entryManager, ScrimController scrimController,
BiometricUnlockController biometricUnlockController,
- ActivityLaunchAnimator launchAnimator, KeyguardViewMediator keyguardViewMediator,
+ KeyguardViewMediator keyguardViewMediator,
NotificationRemoteInputManager notificationRemoteInputManager,
NotificationGroupManager notificationGroupManager,
FalsingManager falsingManager,
@@ -636,7 +612,8 @@ public class StatusBarTest extends SysuiTestCase {
DozeScrimController dozeScrimController,
NotificationShelf notificationShelf,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ NotificationPresenter notificationPresenter) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -653,7 +630,6 @@ public class StatusBarTest extends SysuiTestCase {
mEntryManager = entryManager;
mScrimController = scrimController;
mBiometricUnlockController = biometricUnlockController;
- mActivityLaunchAnimator = launchAnimator;
mKeyguardViewMediator = keyguardViewMediator;
mRemoteInputManager = notificationRemoteInputManager;
mGroupManager = notificationGroupManager;
@@ -664,6 +640,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationShelf = notificationShelf;
mLockscreenUserManager = notificationLockscreenUserManager;
mCommandQueue = commandQueue;
+ mPresenter = notificationPresenter;
}
private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 01e63070e07d..4534ebee52be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -41,7 +41,7 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationData;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 51b86c26dff2..95c7a4d09f92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -62,6 +62,11 @@ public class FakeKeyguardMonitor implements KeyguardMonitor {
}
@Override
+ public boolean isLaunchTransitionFadingAway() {
+ return false;
+ }
+
+ @Override
public long getKeyguardFadingAwayDuration() {
return 0;
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index d86de5dfd799..da1fee374520 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6564,6 +6564,11 @@ message MetricsEvent {
// OS: Q
MOBILE_ROAMING_DIALOG = 1583;
+ // OPEN: Settings > Display > Lock screen display > On lock screen
+ // CATEGORY: SETTINGS
+ // OS: Q
+ LOCK_SCREEN_NOTIFICATION_CONTENT = 1584;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index b938f3be4926..17bf5705d489 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -32,6 +32,8 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
import android.view.MagnificationSpec;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
@@ -40,6 +42,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.wm.WindowManagerInternal;
@@ -55,7 +58,7 @@ import java.util.Locale;
* magnification region. If a value is out of bounds, it will be adjusted to guarantee these
* constraints.
*/
-public class MagnificationController implements Handler.Callback {
+public class MagnificationController {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "MagnificationController";
@@ -64,90 +67,553 @@ public class MagnificationController implements Handler.Callback {
private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
- private static final int INVALID_ID = -1;
-
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
- // Messages
- private static final int MSG_SEND_SPEC_TO_ANIMATION = 1;
- private static final int MSG_SCREEN_TURNED_OFF = 2;
- private static final int MSG_ON_MAGNIFIED_BOUNDS_CHANGED = 3;
- private static final int MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED = 4;
- private static final int MSG_ON_USER_CONTEXT_CHANGED = 5;
-
private final Object mLock;
+ private final AccessibilityManagerService mAms;
+
+ private final SettingsBridge mSettingsBridge;
+
+ private final ScreenStateObserver mScreenStateObserver;
+
+ private int mUserId;
+
+ private final long mMainThreadId;
+
+ private Handler mHandler;
+
+ private final WindowManagerInternal mWindowManager;
+
+ private final DisplayMagnification mDisplay;
+
/**
- * The current magnification spec. If an animation is running, this
- * reflects the end state.
+ * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
+ * magnification information per display.
*/
- private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
+ private final class DisplayMagnification implements
+ WindowManagerInternal.MagnificationCallbacks {
+ /**
+ * The current magnification spec. If an animation is running, this
+ * reflects the end state.
+ */
+ private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
- private final Region mMagnificationRegion = Region.obtain();
- private final Rect mMagnificationBounds = new Rect();
+ private final Region mMagnificationRegion = Region.obtain();
+ private final Rect mMagnificationBounds = new Rect();
- private final Rect mTempRect = new Rect();
- private final Rect mTempRect1 = new Rect();
+ private final Rect mTempRect = new Rect();
+ private final Rect mTempRect1 = new Rect();
- private final AccessibilityManagerService mAms;
+ private final SpecAnimationBridge mSpecAnimationBridge;
- private final SettingsBridge mSettingsBridge;
+ // Flag indicating that we are registered with window manager.
+ private boolean mRegistered;
+ private boolean mUnregisterPending;
- private final ScreenStateObserver mScreenStateObserver;
+ private final int mDisplayId;
+
+ private static final int INVALID_ID = -1;
+ private int mIdOfLastServiceToMagnify = INVALID_ID;
- private final SpecAnimationBridge mSpecAnimationBridge;
- private final WindowManagerInternal.MagnificationCallbacks mWMCallbacks =
- new WindowManagerInternal.MagnificationCallbacks () {
- @Override
- public void onMagnificationRegionChanged(Region region) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = Region.obtain(region);
- mHandler.obtainMessage(MSG_ON_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
+ DisplayMagnification(int displayId, SpecAnimationBridge specAnimation) {
+ mDisplayId = displayId;
+ mSpecAnimationBridge = specAnimation;
+ }
+
+ void register() {
+ synchronized (mLock) {
+ if (!mRegistered) {
+ mWindowManager.setMagnificationCallbacks(this);
+ mSpecAnimationBridge.setEnabled(true);
+ // Obtain initial state.
+ mWindowManager.getMagnificationRegion(mMagnificationRegion);
+ mMagnificationRegion.getBounds(mMagnificationBounds);
+ mRegistered = true;
}
+ }
+ }
- @Override
- public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
- final SomeArgs args = SomeArgs.obtain();
- args.argi1 = left;
- args.argi2 = top;
- args.argi3 = right;
- args.argi4 = bottom;
- mHandler.obtainMessage(MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED, args)
- .sendToTarget();
+ void unregister() {
+ synchronized (mLock) {
+ if (!isMagnifying()) {
+ unregisterInternalLocked();
+ } else {
+ mUnregisterPending = true;
+ reset(true);
}
+ }
+ }
+
+ boolean isRegisteredLocked() {
+ return mRegistered;
+ }
+
+
+ float getScale() {
+ return mCurrentMagnificationSpec.scale;
+ }
+
+ float getOffsetX() {
+ return mCurrentMagnificationSpec.offsetX;
+ }
+
+ float getCenterX() {
+ synchronized (mLock) {
+ return (mMagnificationBounds.width() / 2.0f
+ + mMagnificationBounds.left - getOffsetX()) / getScale();
+ }
+ }
+
+ float getCenterY() {
+ synchronized (mLock) {
+ return (mMagnificationBounds.height() / 2.0f
+ + mMagnificationBounds.top - getOffsetY()) / getScale();
+ }
+ }
- @Override
- public void onRotationChanged(int rotation) {
- // Treat as context change and reset
- mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
+ /**
+ * Returns the scale currently used by the window manager. If an
+ * animation is in progress, this reflects the current state of the
+ * animation.
+ *
+ * @return the scale currently used by the window manager
+ */
+ float getSentScale() {
+ return mSpecAnimationBridge.mSentMagnificationSpec.scale;
+ }
+
+ /**
+ * Returns the X offset currently used by the window manager. If an
+ * animation is in progress, this reflects the current state of the
+ * animation.
+ *
+ * @return the X offset currently used by the window manager
+ */
+ float getSentOffsetX() {
+ return mSpecAnimationBridge.mSentMagnificationSpec.offsetX;
+ }
+
+ /**
+ * Returns the Y offset currently used by the window manager. If an
+ * animation is in progress, this reflects the current state of the
+ * animation.
+ *
+ * @return the Y offset currently used by the window manager
+ */
+ float getSentOffsetY() {
+ return mSpecAnimationBridge.mSentMagnificationSpec.offsetY;
+ }
+
+ boolean resetIfNeeded(boolean animate) {
+ synchronized (mLock) {
+ if (isMagnifying()) {
+ reset(animate);
+ return true;
}
+ return false;
+ }
+ }
+
+ float getOffsetY() {
+ return mCurrentMagnificationSpec.offsetY;
+ }
+
+ boolean isMagnifying() {
+ return mCurrentMagnificationSpec.scale > 1.0f;
+ }
+
+ void unregisterInternalLocked() {
+ if (mRegistered) {
+ mSpecAnimationBridge.setEnabled(false);
+ mWindowManager.setMagnificationCallbacks(null);
+ mMagnificationRegion.setEmpty();
+
+ mRegistered = false;
+ }
+ mUnregisterPending = false;
+ }
+
+
+ @Override
+ public void onMagnificationRegionChanged(Region magnificationRegion) {
+ final Message m = PooledLambda.obtainMessage(
+ DisplayMagnification.this::updateMagnificationRegion,
+ Region.obtain(magnificationRegion));
+ mHandler.sendMessage(m);
+ }
+
+ @Override
+ public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
+ final Message m = PooledLambda.obtainMessage(
+ DisplayMagnification.this::requestRectangleOnScreen, left, top, right, bottom);
+ mHandler.sendMessage(m);
+ }
+
+ @Override
+ public void onRotationChanged(int rotation) {
+ // Treat as context change and reset
+ final Message m = PooledLambda.obtainMessage(DisplayMagnification.this::resetIfNeeded,
+ true);
+ mHandler.sendMessage(m);
+ }
- @Override
- public void onUserContextChanged() {
- mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
+ @Override
+ public void onUserContextChanged() {
+ final Message m = PooledLambda.obtainMessage(DisplayMagnification.this::resetIfNeeded,
+ true);
+ mHandler.sendMessage(m);
+ }
+
+ /**
+ * Update our copy of the current magnification region
+ *
+ * @param magnified the magnified region
+ */
+ void updateMagnificationRegion(Region magnified) {
+ synchronized (mLock) {
+ if (!mRegistered) {
+ // Don't update if we've unregistered
+ return;
}
- };
+ if (!mMagnificationRegion.equals(magnified)) {
+ mMagnificationRegion.set(magnified);
+ mMagnificationRegion.getBounds(mMagnificationBounds);
+ // It's possible that our magnification spec is invalid with the new bounds.
+ // Adjust the current spec's offsets if necessary.
+ if (updateCurrentSpecWithOffsetsLocked(
+ mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
+ sendSpecToAnimation(mCurrentMagnificationSpec, false);
+ }
+ onMagnificationChangedLocked();
+ }
+ magnified.recycle();
+ }
+ }
- private int mUserId;
+ void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG,
+ "sendSpecToAnimation(spec = " + spec + ", animate = " + animate + ")");
+ }
+ if (Thread.currentThread().getId() == mMainThreadId) {
+ mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
+ } else {
+ final Message m = PooledLambda.obtainMessage(
+ this.mSpecAnimationBridge::updateSentSpecMainThread, spec, animate);
+ mHandler.sendMessage(m);
+ }
+ }
- private final long mMainThreadId;
+ /**
+ * Get the ID of the last service that changed the magnification spec.
+ *
+ * @return The id
+ */
+ int getIdOfLastServiceToMagnify() {
+ return mIdOfLastServiceToMagnify;
+ }
- private Handler mHandler;
+ void onMagnificationChangedLocked() {
+ mAms.notifyMagnificationChanged(mMagnificationRegion,
+ getScale(), getCenterX(), getCenterY());
+ if (mUnregisterPending && !isMagnifying()) {
+ unregisterInternalLocked();
+ }
+ }
- private int mIdOfLastServiceToMagnify = INVALID_ID;
+ boolean magnificationRegionContains(float x, float y) {
+ synchronized (mLock) {
+ return mMagnificationRegion.contains((int) x, (int) y);
- private final WindowManagerInternal mWindowManager;
+ }
+ }
+
+ void getMagnificationBounds(@NonNull Rect outBounds) {
+ synchronized (mLock) {
+ outBounds.set(mMagnificationBounds);
+ }
+ }
+
+ void getMagnificationRegion(@NonNull Region outRegion) {
+ synchronized (mLock) {
+ outRegion.set(mMagnificationRegion);
+ }
+ }
+
+ void requestRectangleOnScreen(int left, int top, int right, int bottom) {
+ synchronized (mLock) {
+ final Rect magnifiedFrame = mTempRect;
+ getMagnificationBounds(magnifiedFrame);
+ if (!magnifiedFrame.intersects(left, top, right, bottom)) {
+ return;
+ }
+
+ final Rect magnifFrameInScreenCoords = mTempRect1;
+ getMagnifiedFrameInContentCoordsLocked(magnifFrameInScreenCoords);
+
+ final float scrollX;
+ final float scrollY;
+ if (right - left > magnifFrameInScreenCoords.width()) {
+ final int direction = TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault());
+ if (direction == View.LAYOUT_DIRECTION_LTR) {
+ scrollX = left - magnifFrameInScreenCoords.left;
+ } else {
+ scrollX = right - magnifFrameInScreenCoords.right;
+ }
+ } else if (left < magnifFrameInScreenCoords.left) {
+ scrollX = left - magnifFrameInScreenCoords.left;
+ } else if (right > magnifFrameInScreenCoords.right) {
+ scrollX = right - magnifFrameInScreenCoords.right;
+ } else {
+ scrollX = 0;
+ }
+
+ if (bottom - top > magnifFrameInScreenCoords.height()) {
+ scrollY = top - magnifFrameInScreenCoords.top;
+ } else if (top < magnifFrameInScreenCoords.top) {
+ scrollY = top - magnifFrameInScreenCoords.top;
+ } else if (bottom > magnifFrameInScreenCoords.bottom) {
+ scrollY = bottom - magnifFrameInScreenCoords.bottom;
+ } else {
+ scrollY = 0;
+ }
+
+ final float scale = getScale();
+ offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_ID);
+ }
+ }
+
+ void getMagnifiedFrameInContentCoordsLocked(Rect outFrame) {
+ final float scale = getSentScale();
+ final float offsetX = getSentOffsetX();
+ final float offsetY = getSentOffsetY();
+ getMagnificationBounds(outFrame);
+ outFrame.offset((int) -offsetX, (int) -offsetY);
+ outFrame.scale(1.0f / scale);
+ }
+
+ /**
+ * Resets magnification if last magnifying service is disabled.
+ *
+ * @param connectionId the connection ID be disabled.
+ * @return {@code true} on success, {@code false} on failure
+ */
+ boolean resetIfNeeded(int connectionId) {
+ if (mIdOfLastServiceToMagnify == connectionId) {
+ return resetIfNeeded(true /*animate*/);
+ }
+ return false;
+ }
+
+ void setForceShowMagnifiableBounds(boolean show) {
+ if (mRegistered) {
+ mWindowManager.setForceShowMagnifiableBounds(show);
+ }
+ }
+
+ boolean reset(boolean animate) {
+ synchronized (mLock) {
+ if (!mRegistered) {
+ return false;
+ }
+ final MagnificationSpec spec = mCurrentMagnificationSpec;
+ final boolean changed = !spec.isNop();
+ if (changed) {
+ spec.clear();
+ onMagnificationChangedLocked();
+ }
+ mIdOfLastServiceToMagnify = INVALID_ID;
+ sendSpecToAnimation(spec, animate);
+ return changed;
+ }
+ }
+
+
+ boolean setScale(float scale, float pivotX, float pivotY,
+ boolean animate, int id) {
+
+ synchronized (mLock) {
+ if (!mRegistered) {
+ return false;
+ }
+ // Constrain scale immediately for use in the pivot calculations.
+ scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+
+ final Rect viewport = mTempRect;
+ mMagnificationRegion.getBounds(viewport);
+ final MagnificationSpec spec = mCurrentMagnificationSpec;
+ final float oldScale = spec.scale;
+ final float oldCenterX
+ = (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
+ final float oldCenterY
+ = (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
+ final float normPivotX = (pivotX - spec.offsetX) / oldScale;
+ final float normPivotY = (pivotY - spec.offsetY) / oldScale;
+ final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
+ final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
+ final float centerX = normPivotX + offsetX;
+ final float centerY = normPivotY + offsetY;
+ mIdOfLastServiceToMagnify = id;
+
+ return setScaleAndCenter(scale, centerX, centerY, animate, id);
+ }
+ }
- // Flag indicating that we are registered with window manager.
- @VisibleForTesting boolean mRegistered;
+ boolean setScaleAndCenter(float scale, float centerX, float centerY,
+ boolean animate, int id) {
- private boolean mUnregisterPending;
+ synchronized (mLock) {
+ if (!mRegistered) {
+ return false;
+ }
+ if (DEBUG) {
+ Slog.i(LOG_TAG,
+ "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
+ + ", centerY = " + centerY + ", animate = " + animate
+ + ", id = " + id
+ + ")");
+ }
+ final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
+ sendSpecToAnimation(mCurrentMagnificationSpec, animate);
+ if (isMagnifying() && (id != INVALID_ID)) {
+ mIdOfLastServiceToMagnify = id;
+ }
+ return changed;
+ }
+ }
+
+ /**
+ * Updates the current magnification spec.
+ *
+ * @param scale the magnification scale
+ * @param centerX the unscaled, screen-relative X coordinate of the center
+ * of the viewport, or {@link Float#NaN} to leave unchanged
+ * @param centerY the unscaled, screen-relative Y coordinate of the center
+ * of the viewport, or {@link Float#NaN} to leave unchanged
+ * @return {@code true} if the magnification spec changed or {@code false}
+ * otherwise
+ */
+ boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
+ // Handle defaults.
+ if (Float.isNaN(centerX)) {
+ centerX = getCenterX();
+ }
+ if (Float.isNaN(centerY)) {
+ centerY = getCenterY();
+ }
+ if (Float.isNaN(scale)) {
+ scale = getScale();
+ }
+
+ // Compute changes.
+ boolean changed = false;
+
+ final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
+ if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
+ mCurrentMagnificationSpec.scale = normScale;
+ changed = true;
+ }
+
+ final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f
+ + mMagnificationBounds.left - centerX * normScale;
+ final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f
+ + mMagnificationBounds.top - centerY * normScale;
+ changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
+
+ if (changed) {
+ onMagnificationChangedLocked();
+ }
+
+ return changed;
+ }
+
+ void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
+ synchronized (mLock) {
+ if (!mRegistered) {
+ return;
+ }
+
+ final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
+ final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
+ if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
+ onMagnificationChangedLocked();
+ }
+ if (id != INVALID_ID) {
+ mIdOfLastServiceToMagnify = id;
+ }
+ sendSpecToAnimation(mCurrentMagnificationSpec, false);
+ }
+ }
+
+ boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG,
+ "updateCurrentSpecWithOffsetsLocked(nonNormOffsetX = " + nonNormOffsetX
+ + ", nonNormOffsetY = " + nonNormOffsetY + ")");
+ }
+ boolean changed = false;
+ final float offsetX = MathUtils.constrain(
+ nonNormOffsetX, getMinOffsetXLocked(), getMaxOffsetXLocked());
+ if (Float.compare(mCurrentMagnificationSpec.offsetX, offsetX) != 0) {
+ mCurrentMagnificationSpec.offsetX = offsetX;
+ changed = true;
+ }
+ final float offsetY = MathUtils.constrain(
+ nonNormOffsetY, getMinOffsetYLocked(), getMaxOffsetYLocked());
+ if (Float.compare(mCurrentMagnificationSpec.offsetY, offsetY) != 0) {
+ mCurrentMagnificationSpec.offsetY = offsetY;
+ changed = true;
+ }
+ return changed;
+ }
+
+ float getMinOffsetXLocked() {
+ final float viewportWidth = mMagnificationBounds.width();
+ final float viewportLeft = mMagnificationBounds.left;
+ return (viewportLeft + viewportWidth) -
+ (viewportLeft + viewportWidth) * mCurrentMagnificationSpec.scale;
+ }
+
+ float getMaxOffsetXLocked() {
+ return mMagnificationBounds.left -
+ mMagnificationBounds.left * mCurrentMagnificationSpec.scale;
+ }
+
+ float getMinOffsetYLocked() {
+ final float viewportHeight = mMagnificationBounds.height();
+ final float viewportTop = mMagnificationBounds.top;
+ return (viewportTop + viewportHeight) -
+ (viewportTop + viewportHeight) * mCurrentMagnificationSpec.scale;
+ }
+
+ float getMaxOffsetYLocked() {
+ return mMagnificationBounds.top -
+ mMagnificationBounds.top * mCurrentMagnificationSpec.scale;
+ }
+
+ @Override
+ public String toString() {
+ return "DisplayMagnification{" +
+ "mCurrentMagnificationSpec=" + mCurrentMagnificationSpec +
+ ", mMagnificationRegion=" + mMagnificationRegion +
+ ", mMagnificationBounds=" + mMagnificationBounds +
+ ", mDisplayId=" + mDisplayId +
+ ", mUserId=" + mUserId +
+ ", mIdOfLastServiceToMagnify=" + mIdOfLastServiceToMagnify +
+ ", mRegistered=" + mRegistered +
+ ", mUnregisterPending=" + mUnregisterPending +
+ '}';
+ }
+
+ }
public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
this(context, ams, lock, null, LocalServices.getService(WindowManagerInternal.class),
new ValueAnimator(), new SettingsBridge(context.getContentResolver()));
- mHandler = new Handler(context.getMainLooper(), this);
+ mHandler = new Handler(context.getMainLooper());
}
public MagnificationController(
@@ -164,9 +630,10 @@ public class MagnificationController implements Handler.Callback {
mAms = ams;
mScreenStateObserver = new ScreenStateObserver(context, this);
mLock = lock;
- mSpecAnimationBridge = new SpecAnimationBridge(
- context, mLock, mWindowManager, valueAnimator);
mSettingsBridge = settingsBridge;
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ mDisplay = new DisplayMagnification(Display.DEFAULT_DISPLAY,
+ new SpecAnimationBridge(context, mLock, mWindowManager, valueAnimator));
}
/**
@@ -178,16 +645,9 @@ public class MagnificationController implements Handler.Callback {
*/
public void register() {
synchronized (mLock) {
- if (!mRegistered) {
- mScreenStateObserver.register();
- mWindowManager.setMagnificationCallbacks(mWMCallbacks);
- mSpecAnimationBridge.setEnabled(true);
- // Obtain initial state.
- mWindowManager.getMagnificationRegion(mMagnificationRegion);
- mMagnificationRegion.getBounds(mMagnificationBounds);
- mRegistered = true;
- }
+ mScreenStateObserver.register();
}
+ mDisplay.register();
}
/**
@@ -196,33 +656,18 @@ public class MagnificationController implements Handler.Callback {
*/
public void unregister() {
synchronized (mLock) {
- if (!isMagnifying()) {
- unregisterInternalLocked();
- } else {
- mUnregisterPending = true;
- resetLocked(true);
- }
+ mScreenStateObserver.unregister();
}
+ mDisplay.unregister();
}
-
+
/**
* Check if we are registered. Note that we may be planning to unregister at any moment.
*
* @return {@code true} if the controller is registered. {@code false} otherwise.
*/
public boolean isRegisteredLocked() {
- return mRegistered;
- }
-
- private void unregisterInternalLocked() {
- if (mRegistered) {
- mSpecAnimationBridge.setEnabled(false);
- mScreenStateObserver.unregister();
- mWindowManager.setMagnificationCallbacks(null);
- mMagnificationRegion.setEmpty();
- mRegistered = false;
- }
- mUnregisterPending = false;
+ return mDisplay.isRegisteredLocked();
}
/**
@@ -230,32 +675,7 @@ public class MagnificationController implements Handler.Callback {
* is > 1, {@code false} otherwise
*/
public boolean isMagnifying() {
- return mCurrentMagnificationSpec.scale > 1.0f;
- }
-
- /**
- * Update our copy of the current magnification region
- *
- * @param magnified the magnified region
- */
- private void onMagnificationRegionChanged(Region magnified) {
- synchronized (mLock) {
- if (!mRegistered) {
- // Don't update if we've unregistered
- return;
- }
- if (!mMagnificationRegion.equals(magnified)) {
- mMagnificationRegion.set(magnified);
- mMagnificationRegion.getBounds(mMagnificationBounds);
- // It's possible that our magnification spec is invalid with the new bounds.
- // Adjust the current spec's offsets if necessary.
- if (updateCurrentSpecWithOffsetsLocked(
- mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
- sendSpecToAnimation(mCurrentMagnificationSpec, false);
- }
- onMagnificationChangedLocked();
- }
- }
+ return mDisplay.isMagnifying();
}
/**
@@ -268,9 +688,8 @@ public class MagnificationController implements Handler.Callback {
* magnified region, or {@code false} otherwise
*/
public boolean magnificationRegionContains(float x, float y) {
- synchronized (mLock) {
- return mMagnificationRegion.contains((int) x, (int) y);
- }
+ return mDisplay.magnificationRegionContains(x, y);
+
}
/**
@@ -282,9 +701,7 @@ public class MagnificationController implements Handler.Callback {
* region
*/
public void getMagnificationBounds(@NonNull Rect outBounds) {
- synchronized (mLock) {
- outBounds.set(mMagnificationBounds);
- }
+ mDisplay.getMagnificationBounds(outBounds);
}
/**
@@ -295,9 +712,7 @@ public class MagnificationController implements Handler.Callback {
* @param outRegion the region to populate
*/
public void getMagnificationRegion(@NonNull Region outRegion) {
- synchronized (mLock) {
- outRegion.set(mMagnificationRegion);
- }
+ mDisplay.getMagnificationRegion(outRegion);
}
/**
@@ -307,7 +722,7 @@ public class MagnificationController implements Handler.Callback {
* @return the scale
*/
public float getScale() {
- return mCurrentMagnificationSpec.scale;
+ return mDisplay.getScale();
}
/**
@@ -317,7 +732,7 @@ public class MagnificationController implements Handler.Callback {
* @return the X offset
*/
public float getOffsetX() {
- return mCurrentMagnificationSpec.offsetX;
+ return mDisplay.getOffsetX();
}
@@ -328,10 +743,7 @@ public class MagnificationController implements Handler.Callback {
* @return the X coordinate
*/
public float getCenterX() {
- synchronized (mLock) {
- return (mMagnificationBounds.width() / 2.0f
- + mMagnificationBounds.left - getOffsetX()) / getScale();
- }
+ return mDisplay.getCenterX();
}
/**
@@ -341,7 +753,7 @@ public class MagnificationController implements Handler.Callback {
* @return the Y offset
*/
public float getOffsetY() {
- return mCurrentMagnificationSpec.offsetY;
+ return mDisplay.getOffsetY();
}
/**
@@ -351,43 +763,7 @@ public class MagnificationController implements Handler.Callback {
* @return the Y coordinate
*/
public float getCenterY() {
- synchronized (mLock) {
- return (mMagnificationBounds.height() / 2.0f
- + mMagnificationBounds.top - getOffsetY()) / getScale();
- }
- }
-
- /**
- * Returns the scale currently used by the window manager. If an
- * animation is in progress, this reflects the current state of the
- * animation.
- *
- * @return the scale currently used by the window manager
- */
- private float getSentScale() {
- return mSpecAnimationBridge.mSentMagnificationSpec.scale;
- }
-
- /**
- * Returns the X offset currently used by the window manager. If an
- * animation is in progress, this reflects the current state of the
- * animation.
- *
- * @return the X offset currently used by the window manager
- */
- private float getSentOffsetX() {
- return mSpecAnimationBridge.mSentMagnificationSpec.offsetX;
- }
-
- /**
- * Returns the Y offset currently used by the window manager. If an
- * animation is in progress, this reflects the current state of the
- * animation.
- *
- * @return the Y offset currently used by the window manager
- */
- private float getSentOffsetY() {
- return mSpecAnimationBridge.mSentMagnificationSpec.offsetY;
+ return mDisplay.getCenterY();
}
/**
@@ -400,24 +776,9 @@ public class MagnificationController implements Handler.Callback {
* the spec did not change
*/
public boolean reset(boolean animate) {
- synchronized (mLock) {
- return resetLocked(animate);
- }
- }
- private boolean resetLocked(boolean animate) {
- if (!mRegistered) {
- return false;
- }
- final MagnificationSpec spec = mCurrentMagnificationSpec;
- final boolean changed = !spec.isNop();
- if (changed) {
- spec.clear();
- onMagnificationChangedLocked();
- }
- mIdOfLastServiceToMagnify = INVALID_ID;
- sendSpecToAnimation(spec, animate);
- return changed;
+ return mDisplay.reset(animate);
+
}
/**
@@ -435,30 +796,8 @@ public class MagnificationController implements Handler.Callback {
* the spec did not change
*/
public boolean setScale(float scale, float pivotX, float pivotY, boolean animate, int id) {
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- // Constrain scale immediately for use in the pivot calculations.
- scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
-
- final Rect viewport = mTempRect;
- mMagnificationRegion.getBounds(viewport);
- final MagnificationSpec spec = mCurrentMagnificationSpec;
- final float oldScale = spec.scale;
- final float oldCenterX
- = (viewport.width() / 2.0f - spec.offsetX + viewport.left) / oldScale;
- final float oldCenterY
- = (viewport.height() / 2.0f - spec.offsetY + viewport.top) / oldScale;
- final float normPivotX = (pivotX - spec.offsetX) / oldScale;
- final float normPivotY = (pivotY - spec.offsetY) / oldScale;
- final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
- final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
- final float centerX = normPivotX + offsetX;
- final float centerY = normPivotY + offsetY;
- mIdOfLastServiceToMagnify = id;
- return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
- }
+ return mDisplay.
+ setScale(scale, pivotX, pivotY, animate, id);
}
/**
@@ -471,17 +810,13 @@ public class MagnificationController implements Handler.Callback {
* center
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
- * @param id the ID of the service requesting the change
+ * @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
- * the spec did not change
+ * the spec did not change
*/
public boolean setCenter(float centerX, float centerY, boolean animate, int id) {
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- return setScaleAndCenterLocked(Float.NaN, centerX, centerY, animate, id);
- }
+ return mDisplay.
+ setScaleAndCenter(Float.NaN, centerX, centerY, animate, id);
}
/**
@@ -502,28 +837,8 @@ public class MagnificationController implements Handler.Callback {
*/
public boolean setScaleAndCenter(
float scale, float centerX, float centerY, boolean animate, int id) {
- synchronized (mLock) {
- if (!mRegistered) {
- return false;
- }
- return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
- }
- }
-
- private boolean setScaleAndCenterLocked(float scale, float centerX, float centerY,
- boolean animate, int id) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
- + ", centerY = " + centerY + ", animate = " + animate + ", id = " + id
- + ")");
- }
- final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
- sendSpecToAnimation(mCurrentMagnificationSpec, animate);
- if (isMagnifying() && (id != INVALID_ID)) {
- mIdOfLastServiceToMagnify = id;
- }
- return changed;
+ return mDisplay.
+ setScaleAndCenter(scale, centerX, centerY, animate, id);
}
/**
@@ -531,27 +846,14 @@ public class MagnificationController implements Handler.Callback {
* opposite direction as the offsets passed in here.
*
* @param offsetX the amount in pixels to offset the region in the X direction, in current
- * screen pixels.
+ * screen pixels.
* @param offsetY the amount in pixels to offset the region in the Y direction, in current
- * screen pixels.
- * @param id the ID of the service requesting the change
+ * screen pixels.
+ * @param id the ID of the service requesting the change
*/
public void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
- synchronized (mLock) {
- if (!mRegistered) {
- return;
- }
-
- final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
- final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
- if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
- onMagnificationChangedLocked();
- }
- if (id != INVALID_ID) {
- mIdOfLastServiceToMagnify = id;
- }
- sendSpecToAnimation(mCurrentMagnificationSpec, false);
- }
+ mDisplay.offsetMagnifiedRegion(offsetX, offsetY,
+ id);
}
/**
@@ -560,28 +862,26 @@ public class MagnificationController implements Handler.Callback {
* @return The id
*/
public int getIdOfLastServiceToMagnify() {
- return mIdOfLastServiceToMagnify;
- }
-
- private void onMagnificationChangedLocked() {
- mAms.notifyMagnificationChanged(mMagnificationRegion,
- getScale(), getCenterX(), getCenterY());
- if (mUnregisterPending && !isMagnifying()) {
- unregisterInternalLocked();
- }
+ return mDisplay.getIdOfLastServiceToMagnify();
}
/**
* Persists the current magnification scale to the current user's settings.
*/
public void persistScale() {
- final float scale = mCurrentMagnificationSpec.scale;
+ persistScale(Display.DEFAULT_DISPLAY);
+ }
+ /**
+ * Persists the current magnification scale to the current user's settings.
+ */
+ public void persistScale(int displayId) {
+ final float scale = mDisplay.getScale();
final int userId = mUserId;
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
- mSettingsBridge.putMagnificationScale(scale, userId);
+ mSettingsBridge.putMagnificationScale(scale, displayId, userId);
return null;
}
}.execute();
@@ -595,98 +895,7 @@ public class MagnificationController implements Handler.Callback {
* scale if none is available
*/
public float getPersistedScale() {
- return mSettingsBridge.getMagnificationScale(mUserId);
- }
-
- /**
- * Updates the current magnification spec.
- *
- * @param scale the magnification scale
- * @param centerX the unscaled, screen-relative X coordinate of the center
- * of the viewport, or {@link Float#NaN} to leave unchanged
- * @param centerY the unscaled, screen-relative Y coordinate of the center
- * of the viewport, or {@link Float#NaN} to leave unchanged
- * @return {@code true} if the magnification spec changed or {@code false}
- * otherwise
- */
- private boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
- // Handle defaults.
- if (Float.isNaN(centerX)) {
- centerX = getCenterX();
- }
- if (Float.isNaN(centerY)) {
- centerY = getCenterY();
- }
- if (Float.isNaN(scale)) {
- scale = getScale();
- }
-
- // Compute changes.
- boolean changed = false;
-
- final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
- if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
- mCurrentMagnificationSpec.scale = normScale;
- changed = true;
- }
-
- final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f
- + mMagnificationBounds.left - centerX * normScale;
- final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f
- + mMagnificationBounds.top - centerY * normScale;
- changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
-
- if (changed) {
- onMagnificationChangedLocked();
- }
-
- return changed;
- }
-
- private boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "updateCurrentSpecWithOffsetsLocked(nonNormOffsetX = " + nonNormOffsetX
- + ", nonNormOffsetY = " + nonNormOffsetY + ")");
- }
- boolean changed = false;
- final float offsetX = MathUtils.constrain(
- nonNormOffsetX, getMinOffsetXLocked(), getMaxOffsetXLocked());
- if (Float.compare(mCurrentMagnificationSpec.offsetX, offsetX) != 0) {
- mCurrentMagnificationSpec.offsetX = offsetX;
- changed = true;
- }
- final float offsetY = MathUtils.constrain(
- nonNormOffsetY, getMinOffsetYLocked(), getMaxOffsetYLocked());
- if (Float.compare(mCurrentMagnificationSpec.offsetY, offsetY) != 0) {
- mCurrentMagnificationSpec.offsetY = offsetY;
- changed = true;
- }
- return changed;
- }
-
- private float getMinOffsetXLocked() {
- final float viewportWidth = mMagnificationBounds.width();
- final float viewportLeft = mMagnificationBounds.left;
- return (viewportLeft + viewportWidth) -
- (viewportLeft + viewportWidth) * mCurrentMagnificationSpec.scale;
- }
-
- private float getMaxOffsetXLocked() {
- return mMagnificationBounds.left -
- mMagnificationBounds.left * mCurrentMagnificationSpec.scale;
- }
-
- private float getMinOffsetYLocked() {
- final float viewportHeight = mMagnificationBounds.height();
- final float viewportTop = mMagnificationBounds.top;
- return (viewportTop + viewportHeight) -
- (viewportTop + viewportHeight) * mCurrentMagnificationSpec.scale;
- }
-
- private float getMaxOffsetYLocked() {
- return mMagnificationBounds.top -
- mMagnificationBounds.top * mCurrentMagnificationSpec.scale;
+ return mSettingsBridge.getMagnificationScale(Display.DEFAULT_DISPLAY, mUserId);
}
/**
@@ -706,20 +915,14 @@ public class MagnificationController implements Handler.Callback {
}
}
- /**
+ /**
* Resets magnification if magnification and auto-update are both enabled.
*
* @param animate whether the animate the transition
* @return whether was {@link #isMagnifying magnifying}
*/
- boolean resetIfNeeded(boolean animate) {
- synchronized (mLock) {
- if (isMagnifying()) {
- reset(animate);
- return true;
- }
- return false;
- }
+ public boolean resetIfNeeded(boolean animate) {
+ return mDisplay.resetIfNeeded(animate);
}
/**
@@ -728,132 +931,23 @@ public class MagnificationController implements Handler.Callback {
* @param connectionId the connection ID be disabled.
* @return {@code true} on success, {@code false} on failure
*/
- boolean resetIfNeeded(int connectionId) {
- if (mIdOfLastServiceToMagnify == connectionId) {
- return resetIfNeeded(true /*animate*/);
- }
- return false;
+ public boolean resetIfNeeded(int connectionId) {
+ return mDisplay.resetIfNeeded(connectionId);
}
void setForceShowMagnifiableBounds(boolean show) {
- if (mRegistered) {
- mWindowManager.setForceShowMagnifiableBounds(show);
- }
- }
-
- private void getMagnifiedFrameInContentCoordsLocked(Rect outFrame) {
- final float scale = getSentScale();
- final float offsetX = getSentOffsetX();
- final float offsetY = getSentOffsetY();
- getMagnificationBounds(outFrame);
- outFrame.offset((int) -offsetX, (int) -offsetY);
- outFrame.scale(1.0f / scale);
- }
-
- private void requestRectangleOnScreen(int left, int top, int right, int bottom) {
- synchronized (mLock) {
- final Rect magnifiedFrame = mTempRect;
- getMagnificationBounds(magnifiedFrame);
- if (!magnifiedFrame.intersects(left, top, right, bottom)) {
- return;
- }
-
- final Rect magnifFrameInScreenCoords = mTempRect1;
- getMagnifiedFrameInContentCoordsLocked(magnifFrameInScreenCoords);
-
- final float scrollX;
- final float scrollY;
- if (right - left > magnifFrameInScreenCoords.width()) {
- final int direction = TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault());
- if (direction == View.LAYOUT_DIRECTION_LTR) {
- scrollX = left - magnifFrameInScreenCoords.left;
- } else {
- scrollX = right - magnifFrameInScreenCoords.right;
- }
- } else if (left < magnifFrameInScreenCoords.left) {
- scrollX = left - magnifFrameInScreenCoords.left;
- } else if (right > magnifFrameInScreenCoords.right) {
- scrollX = right - magnifFrameInScreenCoords.right;
- } else {
- scrollX = 0;
- }
-
- if (bottom - top > magnifFrameInScreenCoords.height()) {
- scrollY = top - magnifFrameInScreenCoords.top;
- } else if (top < magnifFrameInScreenCoords.top) {
- scrollY = top - magnifFrameInScreenCoords.top;
- } else if (bottom > magnifFrameInScreenCoords.bottom) {
- scrollY = bottom - magnifFrameInScreenCoords.bottom;
- } else {
- scrollY = 0;
- }
-
- final float scale = getScale();
- offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_ID);
- }
- }
-
- private void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "sendSpecToAnimation(spec = " + spec + ", animate = " + animate + ")");
- }
- if (Thread.currentThread().getId() == mMainThreadId) {
- mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
- } else {
- mHandler.obtainMessage(MSG_SEND_SPEC_TO_ANIMATION,
- animate ? 1 : 0, 0, spec).sendToTarget();
- }
+ mDisplay.setForceShowMagnifiableBounds(show);
}
private void onScreenTurnedOff() {
- mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
- }
-
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SEND_SPEC_TO_ANIMATION:
- final boolean animate = msg.arg1 == 1;
- final MagnificationSpec spec = (MagnificationSpec) msg.obj;
- mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
- break;
- case MSG_SCREEN_TURNED_OFF:
- resetIfNeeded(false);
- break;
- case MSG_ON_MAGNIFIED_BOUNDS_CHANGED: {
- final SomeArgs args = (SomeArgs) msg.obj;
- final Region magnifiedBounds = (Region) args.arg1;
- onMagnificationRegionChanged(magnifiedBounds);
- magnifiedBounds.recycle();
- args.recycle();
- } break;
- case MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
- final SomeArgs args = (SomeArgs) msg.obj;
- final int left = args.argi1;
- final int top = args.argi2;
- final int right = args.argi3;
- final int bottom = args.argi4;
- requestRectangleOnScreen(left, top, right, bottom);
- args.recycle();
- } break;
- case MSG_ON_USER_CONTEXT_CHANGED:
- resetIfNeeded(true);
- break;
- }
- return true;
+ final Message m = PooledLambda.obtainMessage(
+ mDisplay::resetIfNeeded, false);
+ mHandler.sendMessage(m);
}
@Override
public String toString() {
- return "MagnificationController{" +
- "mCurrentMagnificationSpec=" + mCurrentMagnificationSpec +
- ", mMagnificationRegion=" + mMagnificationRegion +
- ", mMagnificationBounds=" + mMagnificationBounds +
- ", mUserId=" + mUserId +
- ", mIdOfLastServiceToMagnify=" + mIdOfLastServiceToMagnify +
- ", mRegistered=" + mRegistered +
- ", mUnregisterPending=" + mUnregisterPending +
- '}';
+ return mDisplay.toString();
}
/**
@@ -974,6 +1068,7 @@ public class MagnificationController implements Handler.Callback {
private static class ScreenStateObserver extends BroadcastReceiver {
private final Context mContext;
private final MagnificationController mController;
+ private boolean mRegistered = false;
public ScreenStateObserver(Context context, MagnificationController controller) {
mContext = context;
@@ -981,11 +1076,17 @@ public class MagnificationController implements Handler.Callback {
}
public void register() {
- mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+ if (!mRegistered) {
+ mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+ mRegistered = true;
+ }
}
public void unregister() {
- mContext.unregisterReceiver(this);
+ if (mRegistered) {
+ mContext.unregisterReceiver(this);
+ mRegistered = false;
+ }
}
@Override
@@ -1002,14 +1103,17 @@ public class MagnificationController implements Handler.Callback {
mContentResolver = contentResolver;
}
- public void putMagnificationScale(float value, int userId) {
+ public void putMagnificationScale(float value, int displayId, int userId) {
Settings.Secure.putFloatForUser(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE + (
+ Display.DEFAULT_DISPLAY == displayId ? "" : displayId),
+ value, userId);
}
- public float getMagnificationScale(int userId) {
+ public float getMagnificationScale(int displayId, int userId) {
return Settings.Secure.getFloatForUser(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE
+ + (Display.DEFAULT_DISPLAY == displayId ? "" : displayId),
DEFAULT_MAGNIFICATION_SCALE, userId);
}
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 0b30ff5cc398..af9d4c8c69b6 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -54,6 +54,7 @@ import android.os.IMaintenanceActivityListener;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -116,6 +117,11 @@ import java.util.Arrays;
STATE_ACTIVE [label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon"]
STATE_INACTIVE [label="STATE_INACTIVE\nScreen off AND Not charging"]
+ STATE_QUICK_DOZE_DELAY [
+ label="STATE_QUICK_DOZE_DELAY\n"
+ + "Screen off AND Not charging\n"
+ + "Location, motion detection, and significant motion monitoring turned off"
+ ]
STATE_IDLE_PENDING [
label="STATE_IDLE_PENDING\nSignificant motion monitoring turned on"
]
@@ -125,26 +131,40 @@ import java.util.Arrays;
]
STATE_IDLE [
label="STATE_IDLE\nLocation and motion detection turned off\n"
- + "Significant motion monitoring still on"
+ + "Significant motion monitoring state unchanged"
]
STATE_IDLE_MAINTENANCE [label="STATE_IDLE_MAINTENANCE\n"]
- STATE_ACTIVE -> STATE_INACTIVE [label="becomeInactiveIfAppropriateLocked()"]
+ STATE_ACTIVE -> STATE_INACTIVE [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze not enabled"
+ ]
+ STATE_ACTIVE -> STATE_QUICK_DOZE_DELAY [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
+ ]
STATE_INACTIVE -> STATE_ACTIVE [
label="handleMotionDetectedLocked(), becomeActiveLocked()"
]
STATE_INACTIVE -> STATE_IDLE_PENDING [label="stepIdleStateLocked()"]
+ STATE_INACTIVE -> STATE_QUICK_DOZE_DELAY [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
+ ]
STATE_IDLE_PENDING -> STATE_ACTIVE [
label="handleMotionDetectedLocked(), becomeActiveLocked()"
]
STATE_IDLE_PENDING -> STATE_SENSING [label="stepIdleStateLocked()"]
+ STATE_IDLE_PENDING -> STATE_QUICK_DOZE_DELAY [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
+ ]
STATE_SENSING -> STATE_ACTIVE [
label="handleMotionDetectedLocked(), becomeActiveLocked()"
]
STATE_SENSING -> STATE_LOCATING [label="stepIdleStateLocked()"]
+ STATE_SENSING -> STATE_QUICK_DOZE_DELAY [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
+ ]
STATE_SENSING -> STATE_IDLE [
label="stepIdleStateLocked()\n"
+ "No Location Manager OR (no Network provider AND no GPS provider)"
@@ -153,8 +173,16 @@ import java.util.Arrays;
STATE_LOCATING -> STATE_ACTIVE [
label="handleMotionDetectedLocked(), becomeActiveLocked()"
]
+ STATE_LOCATING -> STATE_QUICK_DOZE_DELAY [
+ label="becomeInactiveIfAppropriateLocked() AND Quick Doze enabled"
+ ]
STATE_LOCATING -> STATE_IDLE [label="stepIdleStateLocked()"]
+ STATE_QUICK_DOZE_DELAY -> STATE_ACTIVE [
+ label="handleMotionDetectedLocked(), becomeActiveLocked()"
+ ]
+ STATE_QUICK_DOZE_DELAY -> STATE_IDLE [label="stepIdleStateLocked()"]
+
STATE_IDLE -> STATE_ACTIVE [label="handleMotionDetectedLocked(), becomeActiveLocked()"]
STATE_IDLE -> STATE_IDLE_MAINTENANCE [label="stepIdleStateLocked()"]
@@ -252,6 +280,7 @@ public class DeviceIdleController extends SystemService
private final AppStateTracker mAppStateTracker;
private boolean mLightEnabled;
private boolean mDeepEnabled;
+ private boolean mQuickDozeActivated;
private boolean mForceIdle;
private boolean mNetworkConnected;
private boolean mScreenOn;
@@ -287,6 +316,12 @@ public class DeviceIdleController extends SystemService
/** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
@VisibleForTesting
static final int STATE_IDLE_MAINTENANCE = 6;
+ /**
+ * Device is inactive and should go straight into idle (foregoing motion and location
+ * monitoring), but allow some time for current work to complete first.
+ */
+ @VisibleForTesting
+ static final int STATE_QUICK_DOZE_DELAY = 7;
@VisibleForTesting
static String stateToString(int state) {
@@ -298,6 +333,7 @@ public class DeviceIdleController extends SystemService
case STATE_LOCATING: return "LOCATING";
case STATE_IDLE: return "IDLE";
case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
+ case STATE_QUICK_DOZE_DELAY: return "QUICK_DOZE_DELAY";
default: return Integer.toString(state);
}
}
@@ -688,6 +724,7 @@ public class DeviceIdleController extends SystemService
private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
+ private static final String KEY_QUICK_DOZE_DELAY_TIMEOUT = "quick_doze_delay_to";
private static final String KEY_IDLE_TIMEOUT = "idle_to";
private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
private static final String KEY_IDLE_FACTOR = "idle_factor";
@@ -864,6 +901,15 @@ public class DeviceIdleController extends SystemService
public float IDLE_PENDING_FACTOR;
/**
+ * This is amount of time we will wait from the point where we go into
+ * STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs
+ * and other current activity to finish.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_QUICK_DOZE_DELAY_TIMEOUT
+ */
+ public long QUICK_DOZE_DELAY_TIMEOUT;
+
+ /**
* This is the initial time that we want to sit in the idle state before waking up
* again to return to pending idle and allowing normal work to run.
* @see Settings.Global#DEVICE_IDLE_CONSTANTS
@@ -999,6 +1045,8 @@ public class DeviceIdleController extends SystemService
!COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
2f);
+ QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis(
+ KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L);
IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
!COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
@@ -1093,6 +1141,10 @@ public class DeviceIdleController extends SystemService
pw.print(" "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
pw.println(IDLE_PENDING_FACTOR);
+ pw.print(" "); pw.print(KEY_QUICK_DOZE_DELAY_TIMEOUT); pw.print("=");
+ TimeUtils.formatDuration(QUICK_DOZE_DELAY_TIMEOUT, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
pw.println();
@@ -1738,6 +1790,16 @@ public class DeviceIdleController extends SystemService
mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
+ mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
+ state -> {
+ synchronized (DeviceIdleController.this) {
+ updateQuickDozeFlagLocked(state.batterySaverEnabled);
+ }
+ });
+ updateQuickDozeFlagLocked(
+ mLocalPowerManager.getLowPowerState(
+ ServiceType.QUICK_DOZE).batterySaverEnabled);
+
mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
passWhiteListsToForceAppStandbyTrackerLocked();
@@ -2211,7 +2273,9 @@ public class DeviceIdleController extends SystemService
@VisibleForTesting
boolean isScreenOn() {
- return mScreenOn;
+ synchronized (this) {
+ return mScreenOn;
+ }
}
void updateInteractivityLocked() {
@@ -2235,7 +2299,9 @@ public class DeviceIdleController extends SystemService
@VisibleForTesting
boolean isCharging() {
- return mCharging;
+ synchronized (this) {
+ return mCharging;
+ }
}
void updateChargingLocked(boolean charging) {
@@ -2253,6 +2319,27 @@ public class DeviceIdleController extends SystemService
}
}
+ @VisibleForTesting
+ boolean isQuickDozeEnabled() {
+ synchronized (this) {
+ return mQuickDozeActivated;
+ }
+ }
+
+ /** Updates the quick doze flag and enters deep doze if appropriate. */
+ @VisibleForTesting
+ void updateQuickDozeFlagLocked(boolean enabled) {
+ if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
+ mQuickDozeActivated = enabled;
+ if (enabled) {
+ // If Quick Doze is enabled, see if we should go straight into it.
+ becomeInactiveIfAppropriateLocked();
+ }
+ // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
+ // probably not worth the overhead, so leave in deep doze if that's the case until the
+ // next natural time to come out of it.
+ }
+
void keyguardShowingLocked(boolean showing) {
if (DEBUG) Slog.i(TAG, "keyguardShowing=" + showing);
if (mScreenLocked != showing) {
@@ -2304,14 +2391,34 @@ public class DeviceIdleController extends SystemService
void becomeInactiveIfAppropriateLocked() {
if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
if ((!mScreenOn && !mCharging) || mForceIdle) {
- // Screen has turned off; we are now going to become inactive and start
- // waiting to see if we will ultimately go idle.
- if (mState == STATE_ACTIVE && mDeepEnabled) {
- mState = STATE_INACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
- resetIdleManagementLocked();
- scheduleAlarmLocked(mInactiveTimeout, false);
- EventLogTags.writeDeviceIdle(mState, "no activity");
+ // Become inactive and determine if we will ultimately go idle.
+ if (mDeepEnabled) {
+ if (mQuickDozeActivated) {
+ if (mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
+ || mState == STATE_IDLE_MAINTENANCE) {
+ // Already "idling". Don't want to restart the process.
+ // mLightState can't be LIGHT_STATE_ACTIVE if mState is any of these 3
+ // values, so returning here is safe.
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Moved from "
+ + stateToString(mState) + " to STATE_QUICK_DOZE_DELAY");
+ }
+ mState = STATE_QUICK_DOZE_DELAY;
+ // Make sure any motion sensing or locating is stopped.
+ resetIdleManagementLocked();
+ // Wait a small amount of time in case something (eg: background service from
+ // recently closed app) needs to finish running.
+ scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false);
+ EventLogTags.writeDeviceIdle(mState, "no activity");
+ } else if (mState == STATE_ACTIVE) {
+ mState = STATE_INACTIVE;
+ if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
+ resetIdleManagementLocked();
+ scheduleAlarmLocked(mInactiveTimeout, false);
+ EventLogTags.writeDeviceIdle(mState, "no activity");
+ }
}
if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
mLightState = LIGHT_STATE_INACTIVE;
@@ -2473,9 +2580,6 @@ public class DeviceIdleController extends SystemService
// for motion and sleep some more while doing so.
startMonitoringMotionLocked();
scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
- // Reset the upcoming idle delays.
- mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
- mNextIdleDelay = mConstants.IDLE_TIMEOUT;
mState = STATE_IDLE_PENDING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
EventLogTags.writeDeviceIdle(mState, reason);
@@ -2528,6 +2632,13 @@ public class DeviceIdleController extends SystemService
cancelLocatingLocked();
mAnyMotionDetector.stop();
+ // Intentional fallthrough -- time to go into IDLE state.
+ case STATE_QUICK_DOZE_DELAY:
+ // Reset the upcoming idle delays.
+ mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
+ mNextIdleDelay = mConstants.IDLE_TIMEOUT;
+
+ // Everything is in place to go into IDLE state.
case STATE_IDLE_MAINTENANCE:
scheduleAlarmLocked(mNextIdleDelay, true);
if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
@@ -2782,11 +2893,15 @@ public class DeviceIdleController extends SystemService
void scheduleAlarmLocked(long delay, boolean idleUntil) {
if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
- if (mMotionSensor == null) {
+ if (mMotionSensor == null && !(mState == STATE_QUICK_DOZE_DELAY || mState == STATE_IDLE
+ || mState == STATE_IDLE_MAINTENANCE)) {
// If there is no motion sensor on this device, then we won't schedule
// alarms, because we can't determine if the device is not moving. This effectively
// turns off normal execution of device idling, although it is still possible to
// manually poke it by pretending like the alarm is going off.
+ // STATE_QUICK_DOZE_DELAY skips the motion sensing so if the state is past the motion
+ // sensing stage (ie, is QUICK_DOZE_DELAY, IDLE, or IDLE_MAINTENANCE), then idling
+ // can continue until the user interacts with the device.
return;
}
mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
@@ -3215,6 +3330,7 @@ public class DeviceIdleController extends SystemService
case "light": pw.println(lightStateToString(mLightState)); break;
case "deep": pw.println(stateToString(mState)); break;
case "force": pw.println(mForceIdle); break;
+ case "quick": pw.println(mQuickDozeActivated); break;
case "screen": pw.println(mScreenOn); break;
case "charging": pw.println(mCharging); break;
case "network": pw.println(mNetworkConnected); break;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7c67596d92b4..858dcedd03cc 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3150,10 +3150,10 @@ class StorageManagerService extends IStorageManager.Stub
if (toSystem) {
// Everything else goes into sandbox.
- return device + "Android/sandbox/" + sandboxId.replace(':', '/') + "/" + devicePath;
+ return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
} else {
// Does path belong to this sandbox? If so, leave sandbox.
- final String sandboxPrefix = "Android/sandbox/" + sandboxId.replace(':', '/') + "/";
+ final String sandboxPrefix = "Android/sandbox/" + sandboxId + "/";
if (devicePath.startsWith(sandboxPrefix)) {
return device + devicePath.substring(sandboxPrefix.length());
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4070bca199e0..405a2d0ca478 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1138,7 +1138,7 @@ public final class ActiveServices {
for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) {
ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j);
if (active.mUid == uidRec.uid) {
- if (uidRec.curProcState <= ActivityManager.PROCESS_STATE_TOP) {
+ if (uidRec.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP) {
if (!active.mAppOnTop) {
active.mAppOnTop = true;
changed = true;
@@ -1257,7 +1257,7 @@ public final class ActiveServices {
active.mShownWhileScreenOn = mScreenOn;
if (r.app != null) {
active.mAppOnTop = active.mShownWhileTop =
- r.app.uidRecord.curProcState
+ r.app.uidRecord.getCurProcState()
<= ActivityManager.PROCESS_STATE_TOP;
}
active.mStartTime = active.mStartVisibleTime
diff --git a/services/core/java/com/android/server/am/ActiveUids.java b/services/core/java/com/android/server/am/ActiveUids.java
new file mode 100644
index 000000000000..4e1435e14679
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActiveUids.java
@@ -0,0 +1,74 @@
+/*
+ * 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.server.am;
+
+import android.util.SparseArray;
+
+/** Class for tracking active uids for running processes. */
+final class ActiveUids {
+
+ private ActivityManagerService mService;
+
+ private boolean mPostChangesToAtm;
+ private final SparseArray<UidRecord> mActiveUids = new SparseArray<>();
+
+ ActiveUids(ActivityManagerService service, boolean postChangesToAtm) {
+ mService = service;
+ mPostChangesToAtm = postChangesToAtm;
+ }
+
+ void put(int uid, UidRecord value) {
+ mActiveUids.put(uid, value);
+ if (mPostChangesToAtm) {
+ mService.mAtmInternal.onUidActive(uid, value.getCurProcState());
+ }
+ }
+
+ void remove(int uid) {
+ mActiveUids.remove(uid);
+ if (mPostChangesToAtm) {
+ mService.mAtmInternal.onUidInactive(uid);
+ }
+ }
+
+ void clear() {
+ mActiveUids.clear();
+ if (mPostChangesToAtm) {
+ mService.mAtmInternal.onActiveUidsCleared();
+ }
+ }
+
+ UidRecord get(int uid) {
+ return mActiveUids.get(uid);
+ }
+
+ int size() {
+ return mActiveUids.size();
+ }
+
+ UidRecord valueAt(int index) {
+ return mActiveUids.valueAt(index);
+ }
+
+ int keyAt(int index) {
+ return mActiveUids.keyAt(index);
+ }
+
+ int indexOfKey(int uid) {
+ return mActiveUids.indexOfKey(uid);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d56b523f07aa..7a0a742bfae7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,8 +22,11 @@ import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.REMOVE_TASKS;
+import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
+import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.AppOpsManager.OP_NONE;
@@ -461,10 +464,6 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int BROADCAST_FG_TIMEOUT = 10*1000;
static final int BROADCAST_BG_TIMEOUT = 60*1000;
- // Disable hidden API checks for the newly started instrumentation.
- // Must be kept in sync with Am.
- private static final int INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0;
-
public static final int MY_PID = myPid();
static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -745,16 +744,14 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
boolean mFullPssPending = false;
- /**
- * Track all uids that have actively running processes.
- */
- final SparseArray<UidRecord> mActiveUids = new SparseArray<>();
+ /** Track all uids that have actively running processes. */
+ final ActiveUids mActiveUids = new ActiveUids(this, true /* postChangesToAtm */);
/**
* This is for verifying the UID report flow.
*/
static final boolean VALIDATE_UID_STATES = true;
- final SparseArray<UidRecord> mValidateUids = new SparseArray<>();
+ final ActiveUids mValidateUids = new ActiveUids(this, false /* postChangesToAtm */);
/**
* Fingerprints (hashCode()) of stack traces that we've
@@ -981,7 +978,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>();
+ final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this);
/**
* Information about and control over application operations
@@ -2703,7 +2700,7 @@ public class ActivityManagerService extends IActivityManager.Stub
"getPackageProcessState");
}
- int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+ int procState = PROCESS_STATE_NONEXISTENT;
synchronized (this) {
for (int i=mProcessList.mLruProcesses.size()-1; i>=0; i--) {
final ProcessRecord proc = mProcessList.mLruProcesses.get(i);
@@ -2839,7 +2836,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} else {
UidRecord validateUid = mValidateUids.get(item.uid);
if (validateUid == null) {
- validateUid = new UidRecord(item.uid);
+ validateUid = new UidRecord(item.uid, mAtmInternal);
mValidateUids.put(item.uid, validateUid);
}
if ((item.change & UidRecord.CHANGE_IDLE) != 0) {
@@ -2847,7 +2844,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) {
validateUid.idle = false;
}
- validateUid.curProcState = validateUid.setProcState = item.processState;
+ validateUid.setCurProcState(validateUid.setProcState = item.processState);
validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
@@ -2923,8 +2920,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final boolean newAboveCut = item.processState <= reg.cutpoint;
doReport = lastAboveCut != newAboveCut;
} else {
- doReport = item.processState
- != ActivityManager.PROCESS_STATE_NONEXISTENT;
+ doReport = item.processState != PROCESS_STATE_NONEXISTENT;
}
}
if (doReport) {
@@ -5142,7 +5138,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (uidRec == null || uidRec.idle) {
return false;
}
- return uidRec.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+ return uidRec.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
}
@@ -5156,7 +5152,7 @@ public class ActivityManagerService extends IActivityManager.Stub
int getUidStateLocked(int uid) {
UidRecord uidRec = mActiveUids.get(uid);
- return uidRec == null ? ActivityManager.PROCESS_STATE_NONEXISTENT : uidRec.curProcState;
+ return uidRec == null ? PROCESS_STATE_NONEXISTENT : uidRec.getCurProcState();
}
// =========================================================
@@ -5210,8 +5206,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (mPidsSelfLocked) {
for (int i = 0; i < pids.length; i++) {
ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
- states[i] = (pr == null) ? ActivityManager.PROCESS_STATE_NONEXISTENT :
- pr.getCurProcState();
+ states[i] = (pr == null) ? PROCESS_STATE_NONEXISTENT : pr.getCurProcState();
if (scores != null) {
scores[i] = (pr == null) ? ProcessList.INVALID_ADJ : pr.curAdj;
}
@@ -7136,13 +7131,13 @@ public class ActivityManagerService extends IActivityManager.Stub
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
String abiOverride) {
return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
- abiOverride);
+ false /* mountExtStorageFull */, abiOverride);
}
// TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
- boolean disableHiddenApiChecks, String abiOverride) {
+ boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -7175,7 +7170,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, "added application",
customProcess != null ? customProcess : app.processName, disableHiddenApiChecks,
- abiOverride);
+ mountExtStorageFull, abiOverride);
}
return app;
@@ -7619,7 +7614,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
UidRecord uidRec = mActiveUids.get(uid);
- return uidRec != null ? uidRec.curProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
+ return uidRec != null ? uidRec.getCurProcState() : PROCESS_STATE_NONEXISTENT;
}
}
@@ -9568,7 +9563,7 @@ public class ActivityManagerService extends IActivityManager.Stub
return -1;
}
- boolean dumpUids(PrintWriter pw, String dumpPackage, int dumpAppId, SparseArray<UidRecord> uids,
+ boolean dumpUids(PrintWriter pw, String dumpPackage, int dumpAppId, ActiveUids uids,
String header, boolean needSep) {
boolean printed = false;
for (int i=0; i<uids.size(); i++) {
@@ -14701,11 +14696,13 @@ public class ActivityManagerService extends IActivityManager.Stub
activeInstr.mResultClass = className;
boolean disableHiddenApiChecks = ai.usesNonSdkApi()
- || (flags & INSTRUMENTATION_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
+ || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
if (disableHiddenApiChecks) {
enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
"disable hidden API checks");
}
+ final boolean mountExtStorageFull = isCallerShell()
+ && (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0;
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
@@ -14718,7 +14715,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
- abiOverride);
+ mountExtStorageFull, abiOverride);
app.setActiveInstrumentation(activeInstr);
activeInstr.mFinished = false;
activeInstr.mRunningProcesses.add(app);
@@ -14731,6 +14728,11 @@ public class ActivityManagerService extends IActivityManager.Stub
return true;
}
+ private boolean isCallerShell() {
+ final int callingUid = Binder.getCallingUid();
+ return callingUid == SHELL_UID || callingUid == ROOT_UID;
+ }
+
/**
* Report errors that occur while attempting to start Instrumentation. Always writes the
* error to the logs, but if somebody is watching, send the report there too. This enables
@@ -16222,8 +16224,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mPendingPssProcesses.clear();
for (int i = mProcessList.getLruSizeLocked() - 1; i >= 0; i--) {
ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (app.thread == null
- || app.getCurProcState() == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ if (app.thread == null || app.getCurProcState() == PROCESS_STATE_NONEXISTENT) {
continue;
}
if (memLowered || (always && now >
@@ -16604,7 +16605,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
- if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
+ if (app.setProcState == PROCESS_STATE_NONEXISTENT
|| ProcessList.procStatesDifferForMem(app.getCurProcState(), app.setProcState)) {
if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
// Experimental code to more aggressively collect pss while
@@ -16793,8 +16794,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
pendingChange.change = change;
- pendingChange.processState = uidRec != null
- ? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
+ pendingChange.processState = uidRec != null ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT;
pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid);
pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
if (uidRec != null) {
@@ -17229,8 +17229,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final UidRecord uidRec = app.uidRecord;
if (uidRec != null) {
uidRec.ephemeral = app.info.isInstantApp();
- if (uidRec.curProcState > app.getCurProcState()) {
- uidRec.curProcState = app.getCurProcState();
+ if (uidRec.getCurProcState() > app.getCurProcState()) {
+ uidRec.setCurProcState(app.getCurProcState());
}
if (app.hasForegroundServices()) {
uidRec.foregroundServices = true;
@@ -17437,14 +17437,14 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
int uidChange = UidRecord.CHANGE_PROCSTATE;
- if (uidRec.curProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
- && (uidRec.setProcState != uidRec.curProcState
+ if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
+ && (uidRec.setProcState != uidRec.getCurProcState()
|| uidRec.setWhitelist != uidRec.curWhitelist)) {
- if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
- + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
+ if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
+ + ": proc state from " + uidRec.setProcState + " to "
+ + uidRec.getCurProcState() + ", whitelist from " + uidRec.setWhitelist
+ " to " + uidRec.curWhitelist);
- if (ActivityManager.isProcStateBackground(uidRec.curProcState)
+ if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
&& !uidRec.curWhitelist) {
// UID is now in the background (and not on the temp whitelist). Was it
// previously in the foreground (or on the temp whitelist)?
@@ -17477,17 +17477,16 @@ public class ActivityManagerService extends IActivityManager.Stub
}
final boolean wasCached = uidRec.setProcState
> ActivityManager.PROCESS_STATE_RECEIVER;
- final boolean isCached = uidRec.curProcState
+ final boolean isCached = uidRec.getCurProcState()
> ActivityManager.PROCESS_STATE_RECEIVER;
- if (wasCached != isCached ||
- uidRec.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ if (wasCached != isCached || uidRec.setProcState == PROCESS_STATE_NONEXISTENT) {
uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
}
- uidRec.setProcState = uidRec.curProcState;
+ uidRec.setProcState = uidRec.getCurProcState();
uidRec.setWhitelist = uidRec.curWhitelist;
uidRec.setIdle = uidRec.idle;
enqueueUidChangeLocked(uidRec, -1, uidChange);
- noteUidProcessState(uidRec.uid, uidRec.curProcState);
+ noteUidProcessState(uidRec.uid, uidRec.getCurProcState());
if (uidRec.foregroundServices) {
mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
@@ -17648,7 +17647,7 @@ public class ActivityManagerService extends IActivityManager.Stub
continue;
}
// If process state is not changed, then there's nothing to do.
- if (uidRec.setProcState == uidRec.curProcState) {
+ if (uidRec.setProcState == uidRec.getCurProcState()) {
continue;
}
final int blockState = getBlockStateForUid(uidRec);
@@ -17712,8 +17711,9 @@ public class ActivityManagerService extends IActivityManager.Stub
@VisibleForTesting
int getBlockStateForUid(UidRecord uidRec) {
// Denotes whether uid's process state is currently allowed network access.
- final boolean isAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.curProcState)
- || isProcStateAllowedWhileOnRestrictBackground(uidRec.curProcState);
+ final boolean isAllowed =
+ isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
+ || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
// Denotes whether uid's process state was previously allowed network access.
final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
|| isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 692b2d433dbc..96601a20471b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -17,14 +17,13 @@
package com.android.server.am;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityTaskManager.RESIZE_MODE_USER;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
@@ -2902,6 +2901,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" --receiver-permission <PERMISSION>: Require receiver to hold permission.");
pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
pw.println(" [--user <USER_ID> | current] [--no-hidden-api-checks]");
+ pw.println(" [--no-isolated-storage]");
pw.println(" [--no-window-animation] [--abi <ABI>] <COMPONENT>");
pw.println(" Start an Instrumentation. Typically this target <COMPONENT> is in the");
pw.println(" form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there");
@@ -2920,6 +2920,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" --user <USER_ID> | current: Specify user instrumentation runs in;");
pw.println(" current user if not specified.");
pw.println(" --no-hidden-api-checks: disable restrictions on use of hidden API.");
+ pw.println(" --no-isolated-storage: don't use isolated storage sandbox and ");
+ pw.println(" mount full external storage");
pw.println(" --no-window-animation: turn off window animations while running.");
pw.println(" --abi <ABI>: Launch the instrumented process with the selected ABI.");
pw.println(" This assumes that the process supports the selected ABI.");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 45a06524745a..fa227a27dced 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -883,23 +883,23 @@ class ActivityStarter {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart");
- final int callingUidProcState = mService.mAm.getUidStateLocked(callingUid);
+ final int callingUidProcState = mService.getUidStateLocked(callingUid);
final boolean callingUidHasAnyVisibleWindow =
mService.mWindowManager.isAnyWindowVisibleForUid(callingUid);
final int realCallingUidProcState = (callingUid == realCallingUid)
? callingUidProcState
- : mService.mAm.getUidStateLocked(realCallingUid);
+ : mService.getUidStateLocked(realCallingUid);
final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
? callingUidHasAnyVisibleWindow
: mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid);
final String targetPackage = r.packageName;
final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1;
- final int targetUidProcState = mService.mAm.getUidStateLocked(targetUid);
+ final int targetUidProcState = mService.getUidStateLocked(targetUid);
final boolean targetUidHasAnyVisibleWindow = (targetUid != -1)
? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid)
: false;
final String targetWhitelistTag = (targetUid != -1)
- ? mService.mAm.getPendingTempWhitelistTagForUidLocked(targetUid)
+ ? mService.getPendingTempWhitelistTagForUidLocked(targetUid)
: null;
mSupervisor.getActivityMetricsLogger().logActivityStart(intent, callerApp, r,
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index f79d9aa9ba67..02707fb9aff1 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -19,7 +19,6 @@ package com.android.server.am;
import static android.Manifest.permission.BIND_VOICE_INTERACTION;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
-import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -27,10 +26,11 @@ import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -71,6 +71,10 @@ import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
+import static com.android.server.am.ActivityManagerService.MY_PID;
+import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
+import static com.android.server.am.ActivityManagerService.dumpStackTraces;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CONTROLLER;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CURRENT_TRACKER;
@@ -81,12 +85,21 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HEA
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto
+ .PREVIOUS_PROC_VISIBLE_TIME_MS;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
+ .MODE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
+ .PACKAGE;
+import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_IMMERSIVE;
@@ -104,19 +117,8 @@ import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITC
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.MY_PID;
-import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
-import static com.android.server.am.ActivityManagerService.dumpStackTraces;
-import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
-import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
-import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
@@ -330,7 +332,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityThread mSystemThread;
H mH;
UiHandler mUiHandler;
- ActivityManagerService mAm;
ActivityManagerInternal mAmInternal;
UriGrantsManagerInternal mUgmInternal;
private PackageManagerInternal mPmInternal;
@@ -347,6 +348,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
WindowManagerService mWindowManager;
private UserManagerService mUserManager;
private AppOpsService mAppOpsService;
+ /** All active uids in the system. */
+ private final SparseArray<Integer> mActiveUids = new SparseArray<>();
+ private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
/** All processes we currently have running mapped by pid */
@@ -705,10 +709,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
// TODO: Will be converted to WM lock once transition is complete.
- void setActivityManagerService(ActivityManagerService am, Looper looper,
+ void setActivityManagerService(Object globalLock, Looper looper,
IntentFirewall intentFirewall, PendingIntentController intentController) {
- mAm = am;
- mGlobalLock = mAm;
+ mGlobalLock = globalLock;
mH = new H(looper);
mUiHandler = new UiHandler();
mIntentFirewall = intentFirewall;
@@ -4761,7 +4764,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
for (int i = mPidMap.size() - 1; i >= 0; i--) {
- WindowProcessController app = mPidMap.get(mPidMap.keyAt(i));
+ final int pid = mPidMap.keyAt(i);
+ final WindowProcessController app = mPidMap.get(pid);
if (DEBUG_CONFIGURATION) {
Slog.v(TAG_CONFIGURATION, "Update process config of "
+ app.mName + " to new config " + configCopy);
@@ -5455,6 +5459,18 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return null;
}
+ int getUidStateLocked(int uid) {
+ return mActiveUids.get(uid, PROCESS_STATE_NONEXISTENT);
+ }
+
+ /**
+ * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on
+ * the whitelist
+ */
+ String getPendingTempWhitelistTagForUidLocked(int uid) {
+ return mPendingTempWhitelist.get(uid);
+ }
+
void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
if (true || Build.IS_USER) {
return;
@@ -6015,7 +6031,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
* @param displayId The ID of the display showing the IME.
*/
@Override
- public void onImeWindowSetOnDisplay(int pid, int displayId) {
+ public void onImeWindowSetOnDisplay(final int pid, final int displayId) {
if (pid == MY_PID || pid < 0) {
if (DEBUG_CONFIGURATION) {
Slog.w(TAG,
@@ -6025,29 +6041,28 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
mH.post(() -> {
synchronized (mGlobalLock) {
- // Check if display is initialized in AM.
- if (!mStackSupervisor.isDisplayAdded(displayId)) {
- // Call come when display is not yet added or has already been removed.
+ final ActivityDisplay activityDisplay =
+ mStackSupervisor.getActivityDisplay(displayId);
+ if (activityDisplay == null) {
+ // Call might come when display is not yet added or has been removed.
if (DEBUG_CONFIGURATION) {
Slog.w(TAG, "Trying to update display configuration for non-existing "
- + "displayId=" + displayId);
+ + "displayId=" + displayId);
}
return;
}
- final WindowProcessController imeProcess = mPidMap.get(pid);
- if (imeProcess == null) {
+ final WindowProcessController process = mPidMap.get(pid);
+ if (process == null) {
if (DEBUG_CONFIGURATION) {
- Slog.w(TAG, "Trying to update display configuration for invalid pid: "
- + pid);
+ Slog.w(TAG, "Trying to update display configuration for invalid "
+ + "process, pid=" + pid);
}
return;
}
- // Fetch the current override configuration of the display and set it to the
- // process global configuration.
- imeProcess.onConfigurationChanged(
- mStackSupervisor.getDisplayOverrideConfiguration(displayId));
+ process.registerDisplayConfigurationListenerLocked(activityDisplay);
}
});
+
}
@Override
@@ -6630,5 +6645,49 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return mStackSupervisor.finishTopCrashedActivitiesLocked(crashedApp, reason);
}
}
+
+ @Override
+ public void onUidActive(int uid, int procState) {
+ synchronized (mGlobalLock) {
+ mActiveUids.put(uid, procState);
+ }
+ }
+
+ @Override
+ public void onUidInactive(int uid) {
+ synchronized (mGlobalLock) {
+ mActiveUids.remove(uid);
+ }
+ }
+
+ @Override
+ public void onActiveUidsCleared() {
+ synchronized (mGlobalLock) {
+ mActiveUids.clear();
+ }
+ }
+
+ @Override
+ public void onUidProcStateChanged(int uid, int procState) {
+ synchronized (mGlobalLock) {
+ if (mActiveUids.get(uid) != null) {
+ mActiveUids.put(uid, procState);
+ }
+ }
+ }
+
+ @Override
+ public void onUidAddedToPendingTempWhitelist(int uid, String tag) {
+ synchronized (mGlobalLock) {
+ mPendingTempWhitelist.put(uid, tag);
+ }
+ }
+
+ @Override
+ public void onUidRemovedFromPendingTempWhitelist(int uid) {
+ synchronized (mGlobalLock) {
+ mPendingTempWhitelist.remove(uid);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/am/PendingTempWhitelists.java b/services/core/java/com/android/server/am/PendingTempWhitelists.java
new file mode 100644
index 000000000000..b36e3c7b9e35
--- /dev/null
+++ b/services/core/java/com/android/server/am/PendingTempWhitelists.java
@@ -0,0 +1,59 @@
+/*
+ * 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.server.am;
+
+import android.util.SparseArray;
+
+/** Whitelists of uids to temporarily bypass Power Save mode. */
+final class PendingTempWhitelists {
+
+ private ActivityManagerService mService;
+
+ private final SparseArray<ActivityManagerService.PendingTempWhitelist> mPendingTempWhitelist =
+ new SparseArray<>();
+
+ PendingTempWhitelists(ActivityManagerService service) {
+ mService = service;
+ }
+
+ void put(int uid, ActivityManagerService.PendingTempWhitelist value) {
+ mPendingTempWhitelist.put(uid, value);
+ mService.mAtmInternal.onUidAddedToPendingTempWhitelist(uid, value.tag);
+ }
+
+ void removeAt(int index) {
+ final int uid = mPendingTempWhitelist.keyAt(index);
+ mPendingTempWhitelist.removeAt(index);
+ mService.mAtmInternal.onUidRemovedFromPendingTempWhitelist(uid);
+ }
+
+ ActivityManagerService.PendingTempWhitelist get(int uid) {
+ return mPendingTempWhitelist.get(uid);
+ }
+
+ int size() {
+ return mPendingTempWhitelist.size();
+ }
+
+ ActivityManagerService.PendingTempWhitelist valueAt(int index) {
+ return mPendingTempWhitelist.valueAt(index);
+ }
+
+ int indexOfKey(int key) {
+ return mPendingTempWhitelist.indexOfKey(key);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3f172cc11468..805b979b4bb7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -18,7 +18,6 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
-import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
import static android.os.Process.FIRST_ISOLATED_UID;
import static android.os.Process.LAST_ISOLATED_UID;
@@ -28,6 +27,7 @@ import static android.os.Process.getFreeMemory;
import static android.os.Process.getTotalMemory;
import static android.os.Process.killProcessQuiet;
import static android.os.Process.startWebView;
+import static android.os.storage.StorageManager.PROP_ISOLATED_STORAGE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
@@ -45,17 +45,6 @@ import static com.android.server.am.ActivityManagerService.TAG_PROCESSES;
import static com.android.server.am.ActivityManagerService.TAG_PSS;
import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
-import dalvik.system.VMRuntime;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppProtoEnums;
@@ -64,11 +53,14 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -77,6 +69,17 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.os.storage.StorageManagerInternal;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.LongSparseArray;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.StatsLog;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -91,21 +94,16 @@ import com.android.server.Watchdog;
import com.android.server.pm.dex.DexManager;
import com.android.server.wm.WindowManagerService;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.os.SystemProperties;
-import android.net.LocalSocketAddress;
-import android.net.LocalSocket;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.os.storage.StorageManagerInternal;
-import android.text.TextUtils;
-import android.util.EventLog;
-import android.util.LongSparseArray;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.StatsLog;
-import android.view.Display;
+import dalvik.system.VMRuntime;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* Activity manager code dealing with processes.
@@ -1182,7 +1180,8 @@ public final class ProcessList {
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, String hostingType,
- String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
+ String hostingNameStr, boolean disableHiddenApiChecks, boolean mountExtStorageFull,
+ String abiOverride) {
if (app.pendingStart) {
return true;
}
@@ -1224,10 +1223,15 @@ public final class ProcessList {
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DIRECT_BOOT_AUTO, app.userId);
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
- mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
- app.info.packageName);
+ if (SystemProperties.getBoolean(PROP_ISOLATED_STORAGE, false)
+ && mountExtStorageFull) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
+ } else {
+ StorageManagerInternal storageManagerInternal = LocalServices.getService(
+ StorageManagerInternal.class);
+ mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
+ app.info.packageName);
+ }
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1482,7 +1486,7 @@ public final class ProcessList {
final boolean startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr, String abiOverride) {
return startProcessLocked(app, hostingType, hostingNameStr,
- false /* disableHiddenApiChecks */, abiOverride);
+ false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride);
}
@GuardedBy("mService")
@@ -1911,7 +1915,7 @@ public final class ProcessList {
}
UidRecord uidRec = mService.mActiveUids.get(proc.uid);
if (uidRec == null) {
- uidRec = new UidRecord(proc.uid);
+ uidRec = new UidRecord(proc.uid, mService.mAtmInternal);
// This is the first appearance of the uid, report it now!
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Creating new process uid: " + uidRec);
@@ -1923,7 +1927,7 @@ public final class ProcessList {
uidRec.updateHasInternetPermission();
mService.mActiveUids.put(proc.uid, uidRec);
EventLogTags.writeAmUidRunning(uidRec.uid);
- mService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
+ mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState());
}
proc.uidRecord = uidRec;
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 3b859edd3cf9..6cb1097c7ddf 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -18,7 +18,6 @@ package com.android.server.am;
import android.Manifest;
import android.app.ActivityManager;
-import android.app.ActivityManagerProto;
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -27,14 +26,14 @@ import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.ActivityTaskManagerInternal;
/**
* Overall information about a uid that has actively running processes.
*/
public final class UidRecord {
final int uid;
- int curProcState;
+ private int mCurProcState;
int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
long lastBackgroundTime;
boolean ephemeral;
@@ -44,11 +43,12 @@ public final class UidRecord {
boolean idle;
boolean setIdle;
int numProcs;
+ final ActivityTaskManagerInternal mAtmInternal;
/**
- * Sequence number associated with the {@link #curProcState}. This is incremented using
+ * Sequence number associated with the {@link #mCurProcState}. This is incremented using
* {@link ActivityManagerService#mProcStateSeqCounter}
- * when {@link #curProcState} changes from background to foreground or vice versa.
+ * when {@link #mCurProcState} changes from background to foreground or vice versa.
*/
@GuardedBy("networkStateUpdate")
long curProcStateSeq;
@@ -117,14 +117,26 @@ public final class UidRecord {
ChangeItem pendingChange;
int lastReportedChange;
- public UidRecord(int _uid) {
+ public UidRecord(int _uid, ActivityTaskManagerInternal atmInternal) {
uid = _uid;
idle = true;
+ mAtmInternal = atmInternal;
reset();
}
+ public int getCurProcState() {
+ return mCurProcState;
+ }
+
+ public void setCurProcState(int curProcState) {
+ mCurProcState = curProcState;
+ if (mAtmInternal != null) {
+ mAtmInternal.onUidProcStateChanged(uid, curProcState);
+ }
+ }
+
public void reset() {
- curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+ setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
foregroundServices = false;
}
@@ -148,7 +160,7 @@ public final class UidRecord {
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(UidRecordProto.UID, uid);
- proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(curProcState));
+ proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(mCurProcState));
proto.write(UidRecordProto.EPHEMERAL, ephemeral);
proto.write(UidRecordProto.FG_SERVICES, foregroundServices);
proto.write(UidRecordProto.WHILELIST, curWhitelist);
@@ -178,7 +190,7 @@ public final class UidRecord {
sb.append(' ');
UserHandle.formatUid(sb, uid);
sb.append(' ');
- sb.append(ProcessList.makeProcStateString(curProcState));
+ sb.append(ProcessList.makeProcStateString(mCurProcState));
if (ephemeral) {
sb.append(" ephemeral");
}
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 1743ddeedd91..94f10022d10c 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -17,20 +17,22 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.view.Display.INVALID_DISPLAY;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.am.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityTaskManagerService
+ .INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.am.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -47,11 +49,12 @@ import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
-
import android.util.proto.ProtoOutputStream;
+
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.wm.ConfigurationContainer;
+import com.android.server.wm.ConfigurationContainerListener;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -67,7 +70,8 @@ import java.util.ArrayList;
* window manager so the window manager lock is held and appropriate permissions are checked before
* calls are allowed to proceed.
*/
-public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> {
+public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer>
+ implements ConfigurationContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM;
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
@@ -147,6 +151,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// Last configuration that was reported to the process.
private final Configuration mLastReportedConfiguration;
+ // Registered display id as a listener to override config change
+ private int mDisplayId;
WindowProcessController(ActivityTaskManagerService atm, ApplicationInfo info, String name,
int uid, int userId, Object owner, WindowProcessListener listener,
@@ -159,6 +165,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mListener = listener;
mAtm = atm;
mLastReportedConfiguration = new Configuration();
+ mDisplayId = INVALID_DISPLAY;
if (config != null) {
onConfigurationChanged(config);
}
@@ -704,6 +711,30 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mListener.appDied();
}
+ void registerDisplayConfigurationListenerLocked(ActivityDisplay activityDisplay) {
+ if (activityDisplay == null) {
+ return;
+ }
+ // A process can only register to one display to listener to the override configuration
+ // change. Unregister existing listener if it has one before register the new one.
+ unregisterDisplayConfigurationListenerLocked();
+ mDisplayId = activityDisplay.mDisplayId;
+ activityDisplay.registerConfigurationChangeListener(this);
+ }
+
+ private void unregisterDisplayConfigurationListenerLocked() {
+ if (mDisplayId == INVALID_DISPLAY) {
+ return;
+ }
+ final ActivityDisplay activityDisplay =
+ mAtm.mStackSupervisor.getActivityDisplay(mDisplayId);
+ if (activityDisplay != null) {
+ mAtm.mStackSupervisor.getActivityDisplay(
+ mDisplayId).unregisterConfigurationChangeListener(this);
+ }
+ mDisplayId = INVALID_DISPLAY;
+ }
+
@Override
public void onConfigurationChanged(Configuration newGlobalConfig) {
super.onConfigurationChanged(newGlobalConfig);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1180af87ae34..9399ebf5b413 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9539,7 +9539,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
- if (deleteSandboxData) {
+ if (deleteSandboxData && getStorageManagerInternal() != null) {
getStorageManagerInternal().destroySandboxForApp(pkg.packageName, realUserId);
}
} catch (PackageManagerException e) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6a7e65400fa7..e2818b70deb1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2634,6 +2634,10 @@ public final class Settings {
writeKernelMappingLPr(ps);
}
+ for (final SharedUserSetting sus : mSharedUsers.values()) {
+ knownSet.remove(sus.getSandboxName());
+ }
+
// Remove any unclaimed mappings
for (int i = 0; i < knownSet.size(); i++) {
final String name = knownSet.valueAt(i);
@@ -2644,30 +2648,42 @@ public final class Settings {
}
}
+ void writeKernelMappingLPr(SharedUserSetting sus) {
+ if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
+
+ writeKernelMappingLPr(sus.getSandboxName(), sus.userId, sus.getNotInstalledUserIds());
+ }
+
void writeKernelMappingLPr(PackageSetting ps) {
if (mKernelMappingFilename == null || ps == null || ps.name == null) return;
- KernelPackageState cur = mKernelMapping.get(ps.name);
+ writeKernelMappingLPr(ps.name, ps.appId, ps.getNotInstalledUserIds());
+ if (ps.sharedUser != null) {
+ writeKernelMappingLPr(ps.sharedUser);
+ }
+ }
+
+ void writeKernelMappingLPr(String name, int appId, int[] excludedUserIds) {
+ KernelPackageState cur = mKernelMapping.get(name);
final boolean firstTime = cur == null;
- int[] excludedUserIds = ps.getNotInstalledUserIds();
final boolean userIdsChanged = firstTime
|| !Arrays.equals(excludedUserIds, cur.excludedUserIds);
// Package directory
- final File dir = new File(mKernelMappingFilename, ps.name);
+ final File dir = new File(mKernelMappingFilename, name);
if (firstTime) {
dir.mkdir();
// Create a new mapping state
cur = new KernelPackageState();
- mKernelMapping.put(ps.name, cur);
+ mKernelMapping.put(name, cur);
}
// If mapping is incorrect or non-existent, write the appid file
- if (cur.appId != ps.appId) {
+ if (cur.appId != appId) {
final File appIdFile = new File(dir, "appid");
- writeIntToFile(appIdFile, ps.appId);
- if (DEBUG_KERNEL) Slog.d(TAG, "Mapping " + ps.name + " to " + ps.appId);
+ writeIntToFile(appIdFile, appId);
+ if (DEBUG_KERNEL) Slog.d(TAG, "Mapping " + name + " to " + appId);
}
if (userIdsChanged) {
@@ -2677,7 +2693,7 @@ public final class Settings {
excludedUserIds[i])) {
writeIntToFile(new File(dir, "excluded_userids"), excludedUserIds[i]);
if (DEBUG_KERNEL) Slog.d(TAG, "Writing " + excludedUserIds[i] + " to "
- + ps.name + "/excluded_userids");
+ + name + "/excluded_userids");
}
}
// Build the inclusion list -- the ids to remove from the exclusion list
@@ -2687,7 +2703,7 @@ public final class Settings {
writeIntToFile(new File(dir, "clear_userid"),
cur.excludedUserIds[i]);
if (DEBUG_KERNEL) Slog.d(TAG, "Writing " + cur.excludedUserIds[i] + " to "
- + ps.name + "/clear_userid");
+ + name + "/clear_userid");
}
}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 1a8b2af5a3a9..32826e51f0a4 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -23,6 +23,10 @@ import android.service.pm.PackageServiceDumpProto;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.util.ArrayUtils;
+
+import libcore.util.EmptyArray;
+
import java.util.ArrayList;
import java.util.List;
@@ -144,6 +148,28 @@ public final class SharedUserSetting extends SettingBase {
}
}
+ /** Returns userIds which doesn't have any packages with this sharedUserId */
+ public int[] getNotInstalledUserIds() {
+ int[] excludedUserIds = null;
+ for (PackageSetting ps : packages) {
+ final int[] userIds = ps.getNotInstalledUserIds();
+ if (excludedUserIds == null) {
+ excludedUserIds = userIds;
+ } else {
+ for (int userId : excludedUserIds) {
+ if (!ArrayUtils.contains(userIds, userId)) {
+ excludedUserIds = ArrayUtils.removeInt(excludedUserIds, userId);
+ }
+ }
+ }
+ }
+ return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
+ }
+
+ public String getSandboxName() {
+ return "shared:" + name;
+ }
+
/** Updates all fields in this shared user setting from another. */
public SharedUserSetting updateFrom(SharedUserSetting sharedUser) {
copyFrom(sharedUser);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index dae7b012b9b8..c5cee32f1596 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6864,37 +6864,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public int getUserRotationMode() {
- return Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
- WindowManagerPolicy.USER_ROTATION_FREE :
- WindowManagerPolicy.USER_ROTATION_LOCKED;
- }
-
- // User rotation: to be used when all else fails in assigning an orientation to the device
- @Override
- public void setUserRotationMode(int mode, int rot) {
- ContentResolver res = mContext.getContentResolver();
-
- // mUserRotationMode and mUserRotation will be assigned by the content observer
- if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
- Settings.System.putIntForUser(res,
- Settings.System.USER_ROTATION,
- rot,
- UserHandle.USER_CURRENT);
- Settings.System.putIntForUser(res,
- Settings.System.ACCELEROMETER_ROTATION,
- 0,
- UserHandle.USER_CURRENT);
- } else {
- Settings.System.putIntForUser(res,
- Settings.System.ACCELEROMETER_ROTATION,
- 1,
- UserHandle.USER_CURRENT);
- }
- }
-
- @Override
public void setSafeMode(boolean safeMode) {
mSafeMode = safeMode;
if (safeMode) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 2a8e523f04c2..db13cbccf993 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -82,7 +82,6 @@ import android.view.IApplicationToken;
import android.view.IWindowManager;
import android.view.InputEventReceiver;
import android.view.KeyEvent;
-import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicyConstants;
@@ -1483,26 +1482,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
public void keepScreenOnStoppedLw();
/**
- * Gets the current user rotation mode.
- *
- * @return The rotation mode.
- *
- * @see #USER_ROTATION_LOCKED
- * @see #USER_ROTATION_FREE
- */
- @UserRotationMode
- public int getUserRotationMode();
-
- /**
- * Inform the policy that the user has chosen a preferred orientation ("rotation lock").
- *
- * @param mode One of {@link #USER_ROTATION_LOCKED} or {@link #USER_ROTATION_FREE}.
- * @param rotation One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
- * {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
- */
- public void setUserRotationMode(@UserRotationMode int mode, @Surface.Rotation int rotation);
-
- /**
* Called when a new system UI visibility is being reported, allowing
* the policy to adjust what is actually reported.
* @param visibility The raw visibility reported by the status bar.
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index ed2b79e7380c..4f8e6b650e24 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -75,6 +75,8 @@ public class BatterySaverPolicy extends ContentObserver {
private static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check";
private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled";
private static final String KEY_AOD_DISABLED = "aod_disabled";
+ // Go into deep Doze as soon as the screen turns off.
+ private static final String KEY_QUICK_DOZE_ENABLED = "quick_doze_enabled";
private static final String KEY_SEND_TRON_LOG = "send_tron_log";
private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
@@ -228,6 +230,12 @@ public class BatterySaverPolicy extends ContentObserver {
private boolean mAodDisabled;
/**
+ * Whether Quick Doze is enabled or not.
+ */
+ @GuardedBy("mLock")
+ private boolean mQuickDozeEnabled;
+
+ /**
* Whether BatterySavingStats should send tron events.
*/
@GuardedBy("mLock")
@@ -392,6 +400,7 @@ public class BatterySaverPolicy extends ContentObserver {
mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true);
mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true);
+ mQuickDozeEnabled = parser.getBoolean(KEY_QUICK_DOZE_ENABLED, false);
mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, false);
// Get default value from Settings.Secure
@@ -434,6 +443,7 @@ public class BatterySaverPolicy extends ContentObserver {
if (mLaunchBoostDisabled) sb.append("l");
if (mOptionalSensorsDisabled) sb.append("S");
if (mAodDisabled) sb.append("o");
+ if (mQuickDozeEnabled) sb.append("q");
if (mSendTronLog) sb.append("t");
sb.append(mGpsMode);
@@ -502,6 +512,9 @@ public class BatterySaverPolicy extends ContentObserver {
case ServiceType.AOD:
return builder.setBatterySaverEnabled(mAodDisabled)
.build();
+ case ServiceType.QUICK_DOZE:
+ return builder.setBatterySaverEnabled(mQuickDozeEnabled)
+ .build();
default:
return builder.setBatterySaverEnabled(realMode)
.build();
@@ -562,6 +575,7 @@ public class BatterySaverPolicy extends ContentObserver {
pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck);
pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled);
pw.println(" " + KEY_AOD_DISABLED + "=" + mAodDisabled);
+ pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + mQuickDozeEnabled);
pw.println(" " + KEY_SEND_TRON_LOG + "=" + mSendTronLog);
pw.println();
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 93870e73ecab..c162afbf3e61 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -174,11 +174,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
private IWifiManager mWifiManager = null;
private TelephonyManager mTelephony = null;
- private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
- private final StatFs mStatFsSystem =
- new StatFs(Environment.getRootDirectory().getAbsolutePath());
- private final StatFs mStatFsTemp =
- new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@GuardedBy("sStatsdLock")
private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
@GuardedBy("sStatsdLock")
@@ -772,7 +767,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullBluetoothBytesTransfer(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = pullBluetoothData();
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
if (info.getUidTraffic() != null) {
for (UidTraffic traffic : info.getUidTraffic()) {
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
@@ -884,9 +879,12 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- if (mWifiManager == null) {
- mWifiManager =
- IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
+ synchronized (this) {
+ if (mWifiManager == null) {
+ mWifiManager =
+ IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ }
}
if (mWifiManager != null) {
try {
@@ -916,8 +914,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- if (mTelephony == null) {
- mTelephony = TelephonyManager.from(mContext);
+ synchronized (this) {
+ if (mTelephony == null) {
+ mTelephony = TelephonyManager.from(mContext);
+ }
}
if (mTelephony != null) {
SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -941,7 +941,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullBluetoothActivityInfo(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = pullBluetoothData();
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
e.writeLong(info.getTimeStamp());
e.writeInt(info.getBluetoothStackState());
@@ -952,7 +952,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pulledData.add(e);
}
- private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
+ private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
@@ -1323,30 +1323,35 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullProcessStats(int section, int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- try {
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
- List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
- long highWaterMark = mProcessStats.getCommittedStats(
- lastHighWaterMark, section, true, statsFiles);
- if (statsFiles.size() != 1) {
- return;
+ synchronized (this) {
+ try {
+ long lastHighWaterMark = readProcStatsHighWaterMark(section);
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ long highWaterMark = mProcessStats.getCommittedStats(
+ lastHighWaterMark, section, true, statsFiles);
+ if (statsFiles.size() != 1) {
+ return;
+ }
+ InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ statsFiles.get(0));
+ int[] len = new int[1];
+ byte[] stats = readFully(stream, len);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+ wallClockNanos);
+ e.writeStorage(Arrays.copyOf(stats, len[0]));
+ pulledData.add(e);
+ new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
+ + lastHighWaterMark).delete();
+ new File(
+ mBaseDir.getAbsolutePath() + "/" + section + "_"
+ + highWaterMark).createNewFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
}
- InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
- int[] len = new int[1];
- byte[] stats = readFully(stream, len);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeStorage(Arrays.copyOf(stats, len[0]));
- pulledData.add(e);
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark).delete();
- new File(
- mBaseDir.getAbsolutePath() + "/" + section + "_"
- + highWaterMark).createNewFile();
- } catch (IOException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 7f9ee8405dfc..443d6fe5de74 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -439,4 +439,12 @@ public abstract class ActivityTaskManagerInternal {
*/
public abstract int finishTopCrashedActivities(
WindowProcessController crashedApp, String reason);
+
+ public abstract void onUidActive(int uid, int procState);
+ public abstract void onUidInactive(int uid);
+ public abstract void onActiveUidsCleared();
+ public abstract void onUidProcStateChanged(int uid, int procState);
+
+ public abstract void onUidAddedToPendingTempWhitelist(int uid, String tag);
+ public abstract void onUidRemovedFromPendingTempWhitelist(int uid);
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index bd82553b804b..847cff9c6646 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -55,6 +55,7 @@ public class DisplayRotation {
private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayRotation" : TAG_WM;
private final WindowManagerService mService;
+ private final DisplayContent mDisplayContent;
private final DisplayPolicy mDisplayPolicy;
private final Context mContext;
private final Object mLock;
@@ -106,6 +107,7 @@ public class DisplayRotation {
DisplayRotation(WindowManagerService service, DisplayContent displayContent,
DisplayPolicy displayPolicy, Context context, Object lock) {
mService = service;
+ mDisplayContent = displayContent;
mDisplayPolicy = displayPolicy;
mContext = context;
mLock = lock;
@@ -225,6 +227,70 @@ public class DisplayRotation {
}
}
+ void restoreUserRotation(int userRotationMode, int userRotation) {
+ if (userRotationMode != WindowManagerPolicy.USER_ROTATION_FREE
+ && userRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
+ Slog.w(TAG, "Trying to restore an invalid user rotation mode " + userRotationMode
+ + " for " + mDisplayContent);
+ userRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
+ }
+ if (userRotation < Surface.ROTATION_0 || userRotation > Surface.ROTATION_270) {
+ Slog.w(TAG, "Trying to restore an invalid user rotation " + userRotation
+ + " for " + mDisplayContent);
+ userRotation = Surface.ROTATION_0;
+ }
+ mUserRotationMode = userRotationMode;
+ mUserRotation = userRotation;
+ }
+
+ private void setUserRotation(int userRotationMode, int userRotation) {
+ if (isDefaultDisplay) {
+ // We'll be notified via settings listener, so we don't need to update internal values.
+ final ContentResolver res = mContext.getContentResolver();
+ final int accelerometerRotation =
+ userRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED ? 0 : 1;
+ Settings.System.putIntForUser(res, Settings.System.ACCELEROMETER_ROTATION,
+ accelerometerRotation, UserHandle.USER_CURRENT);
+ Settings.System.putIntForUser(res, Settings.System.USER_ROTATION, userRotation,
+ UserHandle.USER_CURRENT);
+ return;
+ }
+
+ boolean changed = false;
+ if (mUserRotationMode != userRotationMode) {
+ mUserRotationMode = userRotationMode;
+ changed = true;
+ }
+ if (mUserRotation != userRotation) {
+ mUserRotation = userRotation;
+ changed = true;
+ }
+ mService.mDisplaySettings.setUserRotation(mDisplayContent, userRotationMode, userRotation);
+ if (changed) {
+ mService.updateRotation(true /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ mService.mDisplaySettings.writeSettingsLocked();
+ }
+ }
+
+ void freezeRotation(int rotation) {
+ rotation = (rotation == -1) ? mDisplayContent.getRotation() : rotation;
+ setUserRotation(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation);
+ }
+
+ void thawRotation() {
+ setUserRotation(WindowManagerPolicy.USER_ROTATION_FREE, mUserRotation);
+ }
+
+ boolean isRotationFrozen() {
+ if (!isDefaultDisplay) {
+ return mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED;
+ }
+
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
+ }
+
/** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
boolean isDefaultOrientationForced() {
return mForceDefaultOrientation;
@@ -381,9 +447,6 @@ public class DisplayRotation {
* @param orientation An orientation constant, such as
* {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
* @param lastRotation The most recently used rotation.
- * @param defaultDisplay Flag indicating whether the rotation is computed for the default
- * display. Currently for all non-default displays sensors, docking mode,
- * rotation lock and other factors are ignored.
* @return The surface rotation to use.
*/
int rotationForOrientation(int orientation, int lastRotation) {
@@ -418,8 +481,8 @@ public class DisplayRotation {
final int preferredRotation;
if (!isDefaultDisplay) {
// For secondary displays we ignore things like displays sensors, docking mode and
- // rotation lock, and always prefer a default rotation.
- preferredRotation = Surface.ROTATION_0;
+ // rotation lock, and always prefer user rotation.
+ preferredRotation = mUserRotation;
} else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
// Ignore sensor when lid switch is open and rotation is forced.
preferredRotation = mLidOpenRotation;
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index bbb690f6a34a..28dc008fda9b 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -20,20 +20,23 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.WindowConfiguration;
-import android.content.Context;
-import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Environment;
-import android.provider.Settings;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import com.android.server.policy.WindowManagerPolicy;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
@@ -43,10 +46,6 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
/**
* Current persistent settings about a display
*/
@@ -58,15 +57,25 @@ class DisplaySettings {
private final HashMap<String, Entry> mEntries = new HashMap<String, Entry>();
private static class Entry {
- private final String name;
- private int overscanLeft;
- private int overscanTop;
- private int overscanRight;
- private int overscanBottom;
- private int windowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ private final String mName;
+ private int mOverscanLeft;
+ private int mOverscanTop;
+ private int mOverscanRight;
+ private int mOverscanBottom;
+ private int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
+ private int mUserRotation = Surface.ROTATION_0;
private Entry(String _name) {
- name = _name;
+ mName = _name;
+ }
+
+ private boolean isEmpty() {
+ return mOverscanLeft == 0 && mOverscanTop == 0 && mOverscanRight == 0
+ && mOverscanBottom == 0
+ && mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
+ && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ && mUserRotation == Surface.ROTATION_0;
}
}
@@ -90,13 +99,30 @@ class DisplaySettings {
return entry;
}
+ private Entry getOrCreateEntry(String uniqueId, String name) {
+ Entry entry = getEntry(uniqueId, name);
+ if (entry == null) {
+ entry = new Entry(uniqueId);
+ mEntries.put(uniqueId, entry);
+ }
+ return entry;
+ }
+
+ private void removeEntryIfEmpty(String uniqueId, String name) {
+ final Entry entry = getEntry(uniqueId, name);
+ if (entry.isEmpty()) {
+ mEntries.remove(uniqueId);
+ mEntries.remove(name);
+ }
+ }
+
private void getOverscanLocked(String name, String uniqueId, Rect outRect) {
final Entry entry = getEntry(name, uniqueId);
if (entry != null) {
- outRect.left = entry.overscanLeft;
- outRect.top = entry.overscanTop;
- outRect.right = entry.overscanRight;
- outRect.bottom = entry.overscanBottom;
+ outRect.left = entry.mOverscanLeft;
+ outRect.top = entry.mOverscanTop;
+ outRect.right = entry.mOverscanRight;
+ outRect.bottom = entry.mOverscanBottom;
} else {
outRect.set(0, 0, 0, 0);
}
@@ -104,28 +130,22 @@ class DisplaySettings {
void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
int bottom) {
- if (left == 0 && top == 0 && right == 0 && bottom == 0) {
- // Right now all we are storing is overscan; if there is no overscan,
- // we have no need for the entry.
- mEntries.remove(uniqueId);
- // Legacy name might have been in used, so we need to clear it.
- mEntries.remove(name);
- return;
- }
Entry entry = mEntries.get(uniqueId);
- if (entry == null) {
- entry = new Entry(uniqueId);
- mEntries.put(uniqueId, entry);
+ if (left == 0 && top == 0 && right == 0 && bottom == 0 && entry == null) {
+ // All default value, no action needed.
+ return;
}
- entry.overscanLeft = left;
- entry.overscanTop = top;
- entry.overscanRight = right;
- entry.overscanBottom = bottom;
+ entry = getOrCreateEntry(uniqueId, name);
+ entry.mOverscanLeft = left;
+ entry.mOverscanTop = top;
+ entry.mOverscanRight = right;
+ entry.mOverscanBottom = bottom;
+ removeEntryIfEmpty(uniqueId, name);
}
private int getWindowingModeLocked(String name, String uniqueId, int displayId) {
final Entry entry = getEntry(name, uniqueId);
- int windowingMode = entry != null ? entry.windowingMode
+ int windowingMode = entry != null ? entry.mWindowingMode
: WindowConfiguration.WINDOWING_MODE_UNDEFINED;
// This display used to be in freeform, but we don't support freeform anymore, so fall
// back to fullscreen.
@@ -148,6 +168,36 @@ class DisplaySettings {
return windowingMode;
}
+ void setUserRotation(DisplayContent dc, int rotationMode, int rotation) {
+ final DisplayInfo displayInfo = dc.getDisplayInfo();
+
+ final String uniqueId = displayInfo.uniqueId;
+ final String name = displayInfo.name;
+ Entry entry = getEntry(displayInfo.name, uniqueId);
+ if (rotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ && rotation == Surface.ROTATION_0 && entry == null) {
+ // All default values. No action needed.
+ return;
+ }
+
+ entry = getOrCreateEntry(uniqueId, name);
+ entry.mUserRotationMode = rotationMode;
+ entry.mUserRotation = rotation;
+ removeEntryIfEmpty(uniqueId, name);
+ }
+
+ private void restoreUserRotation(DisplayContent dc) {
+ final DisplayInfo info = dc.getDisplayInfo();
+
+ final Entry entry = getEntry(info.name, info.uniqueId);
+ final int userRotationMode = entry != null ? entry.mUserRotationMode
+ : WindowManagerPolicy.USER_ROTATION_FREE;
+ final int userRotation = entry != null ? entry.mUserRotation
+ : Surface.ROTATION_0;
+
+ dc.getDisplayRotation().restoreUserRotation(userRotationMode, userRotation);
+ }
+
void applySettingsToDisplayLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
@@ -161,6 +211,8 @@ class DisplaySettings {
displayInfo.overscanTop = rect.top;
displayInfo.overscanRight = rect.right;
displayInfo.overscanBottom = rect.bottom;
+
+ restoreUserRotation(dc);
}
void readSettingsLocked() {
@@ -244,12 +296,16 @@ class DisplaySettings {
String name = parser.getAttributeValue(null, "name");
if (name != null) {
Entry entry = new Entry(name);
- entry.overscanLeft = getIntAttribute(parser, "overscanLeft");
- entry.overscanTop = getIntAttribute(parser, "overscanTop");
- entry.overscanRight = getIntAttribute(parser, "overscanRight");
- entry.overscanBottom = getIntAttribute(parser, "overscanBottom");
- entry.windowingMode = getIntAttribute(parser, "windowingMode",
+ entry.mOverscanLeft = getIntAttribute(parser, "overscanLeft");
+ entry.mOverscanTop = getIntAttribute(parser, "overscanTop");
+ entry.mOverscanRight = getIntAttribute(parser, "overscanRight");
+ entry.mOverscanBottom = getIntAttribute(parser, "overscanBottom");
+ entry.mWindowingMode = getIntAttribute(parser, "windowingMode",
WindowConfiguration.WINDOWING_MODE_UNDEFINED);
+ entry.mUserRotationMode = getIntAttribute(parser, "userRotationMode",
+ WindowManagerPolicy.USER_ROTATION_FREE);
+ entry.mUserRotation = getIntAttribute(parser, "userRotation",
+ Surface.ROTATION_0);
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -272,21 +328,28 @@ class DisplaySettings {
for (Entry entry : mEntries.values()) {
out.startTag(null, "display");
- out.attribute(null, "name", entry.name);
- if (entry.overscanLeft != 0) {
- out.attribute(null, "overscanLeft", Integer.toString(entry.overscanLeft));
+ out.attribute(null, "name", entry.mName);
+ if (entry.mOverscanLeft != 0) {
+ out.attribute(null, "overscanLeft", Integer.toString(entry.mOverscanLeft));
+ }
+ if (entry.mOverscanTop != 0) {
+ out.attribute(null, "overscanTop", Integer.toString(entry.mOverscanTop));
+ }
+ if (entry.mOverscanRight != 0) {
+ out.attribute(null, "overscanRight", Integer.toString(entry.mOverscanRight));
}
- if (entry.overscanTop != 0) {
- out.attribute(null, "overscanTop", Integer.toString(entry.overscanTop));
+ if (entry.mOverscanBottom != 0) {
+ out.attribute(null, "overscanBottom", Integer.toString(entry.mOverscanBottom));
}
- if (entry.overscanRight != 0) {
- out.attribute(null, "overscanRight", Integer.toString(entry.overscanRight));
+ if (entry.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ out.attribute(null, "windowingMode", Integer.toString(entry.mWindowingMode));
}
- if (entry.overscanBottom != 0) {
- out.attribute(null, "overscanBottom", Integer.toString(entry.overscanBottom));
+ if (entry.mUserRotationMode != WindowManagerPolicy.USER_ROTATION_FREE) {
+ out.attribute(null, "userRotationMode",
+ Integer.toString(entry.mUserRotationMode));
}
- if (entry.windowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- out.attribute(null, "windowingMode", Integer.toString(entry.windowingMode));
+ if (entry.mUserRotation != Surface.ROTATION_0) {
+ out.attribute(null, "userRotation", Integer.toString(entry.mUserRotation));
}
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b7507a42485c..ef63b9b70b3b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -29,13 +29,13 @@ import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
+import android.graphics.RenderNode;
import android.os.Environment;
import android.os.Handler;
import android.util.ArraySet;
import android.util.Slog;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
import android.view.SurfaceControl;
import android.view.ThreadedRenderer;
import android.view.WindowManager.LayoutParams;
@@ -371,7 +371,7 @@ class TaskSnapshotController {
final RenderNode node = RenderNode.create("TaskSnapshotController", null);
node.setLeftTopRightBottom(0, 0, width, height);
node.setClipToBounds(false);
- final DisplayListCanvas c = node.start(width, height);
+ final RecordingCanvas c = node.start(width, height);
c.drawColor(color);
decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 056e92e3b654..5642b1f91700 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3668,14 +3668,19 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
+ public void freezeRotation(int rotation) {
+ freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
+ }
+
/**
* Freeze rotation changes. (Enable "rotation lock".)
* Persists across reboots.
- * @param rotation The desired rotation to freeze to, or -1 to use the
- * current rotation.
+ * @param displayId The ID of the display to freeze.
+ * @param rotation The desired rotation to freeze to, or -1 to use the current rotation.
*/
@Override
- public void freezeRotation(int rotation) {
+ public void freezeDisplayRotation(int displayId, int rotation) {
// TODO(multi-display): Track which display is rotated.
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"freezeRotation()")) {
@@ -3686,14 +3691,16 @@ public class WindowManagerService extends IWindowManager.Stub
+ "rotation constant.");
}
- final int defaultDisplayRotation = getDefaultDisplayRotation();
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "freezeRotation: mRotation="
- + defaultDisplayRotation);
-
long origId = Binder.clearCallingIdentity();
try {
- mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
- rotation == -1 ? defaultDisplayRotation : rotation);
+ synchronized (mWindowMap) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to freeze rotation for a missing display.");
+ return;
+ }
+ display.getDisplayRotation().freezeRotation(rotation);
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3701,12 +3708,17 @@ public class WindowManagerService extends IWindowManager.Stub
updateRotationUnchecked(false, false);
}
+ @Override
+ public void thawRotation() {
+ thawDisplayRotation(Display.DEFAULT_DISPLAY);
+ }
+
/**
* Thaw rotation changes. (Disable "rotation lock".)
* Persists across reboots.
*/
@Override
- public void thawRotation() {
+ public void thawDisplayRotation(int displayId) {
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"thawRotation()")) {
throw new SecurityException("Requires SET_ORIENTATION permission");
@@ -3717,8 +3729,14 @@ public class WindowManagerService extends IWindowManager.Stub
long origId = Binder.clearCallingIdentity();
try {
- mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
- 777); // rot not used
+ synchronized (mWindowMap) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to thaw rotation for a missing display.");
+ return;
+ }
+ display.getDisplayRotation().thawRotation();
+ }
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3726,6 +3744,23 @@ public class WindowManagerService extends IWindowManager.Stub
updateRotationUnchecked(false, false);
}
+ @Override
+ public boolean isRotationFrozen() {
+ return isDisplayRotationFrozen(Display.DEFAULT_DISPLAY);
+ }
+
+ @Override
+ public boolean isDisplayRotationFrozen(int displayId) {
+ synchronized (mWindowMap) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to thaw rotation for a missing display.");
+ return false;
+ }
+ return display.getDisplayRotation().isRotationFrozen();
+ }
+ }
+
/**
* Recalculate the current rotation.
*
@@ -3795,11 +3830,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean isRotationFrozen() {
- return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
- }
-
- @Override
public int watchRotation(IRotationWatcher watcher, int displayId) {
final DisplayContent displayContent;
synchronized (mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 831418b4b2b4..bf2d0df2bec3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -26,6 +26,7 @@ import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.Surface;
import java.io.PrintWriter;
import java.util.regex.Matcher;
@@ -73,6 +74,8 @@ public class WindowManagerShellCommand extends ShellCommand {
// trace files can be written.
return mInternal.mWindowTracing.onShellCommand(this,
getNextArgRequired());
+ case "set-user-rotation":
+ return runSetDisplayUserRotation(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -262,6 +265,36 @@ public class WindowManagerShellCommand extends ShellCommand {
return Integer.parseInt(s);
}
+ private int runSetDisplayUserRotation(PrintWriter pw) {
+ final String lockMode = getNextArgRequired();
+
+ int displayId = Display.DEFAULT_DISPLAY;
+ String arg = getNextArg();
+ if ("-d".equals(arg)) {
+ displayId = Integer.parseInt(getNextArgRequired());
+ arg = getNextArg();
+ }
+
+ if ("free".equals(lockMode)) {
+ mInternal.thawDisplayRotation(displayId);
+ return 0;
+ }
+
+ if (!lockMode.equals("lock")) {
+ getErrPrintWriter().println("Error: lock mode needs to be either free or lock.");
+ return -1;
+ }
+
+ try {
+ final int rotation = arg != null ? Integer.parseInt(arg) : Surface.ROTATION_0;
+ mInternal.freezeDisplayRotation(displayId, rotation);
+ return 0;
+ } catch (IllegalArgumentException e) {
+ getErrPrintWriter().println("Error: " + e.getMessage());
+ return -1;
+ }
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -279,6 +312,8 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" Set display scaling mode.");
pw.println(" dismiss-keyguard");
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
+ pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
+ pw.println(" Set user rotation mode and user rotation.");
if (!IS_USER) {
pw.println(" tracing (start | stop)");
pw.println(" Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index eacbda198aba..f16008de0967 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2256,7 +2256,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private Configuration getProcessGlobalConfiguration() {
// For child windows we want to use the pid for the parent window in case the the child
// window was added from another process.
- final int pid = isChildWindow() ? getParentWindow().mSession.mPid : mSession.mPid;
+ final int pid = getParentWindow() != null ? getParentWindow().mSession.mPid : mSession.mPid;
mTempConfiguration.setTo(mService.mProcessConfigurations.get(
pid, mService.mRoot.getConfiguration()));
return mTempConfiguration;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 7a847f3284d2..ba1d83ee2a53 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -2680,9 +2680,7 @@ public class KeyValueBackupTaskTest {
return Files.createTempFile(mContext.getCacheDir().toPath(), "backup", ".tmp");
}
- private static IterableSubject<
- ? extends IterableSubject<?, Path, Iterable<Path>>, Path, Iterable<Path>>
- assertDirectory(Path directory) throws IOException {
+ private static IterableSubject assertDirectory(Path directory) throws IOException {
return assertThat(oneTimeIterable(Files.newDirectoryStream(directory).iterator()))
.named("directory " + directory);
}
diff --git a/services/tests/mockingservicestests/Android.mk b/services/tests/mockingservicestests/Android.mk
index b83a79fc232c..e6cbb5badb9e 100644
--- a/services/tests/mockingservicestests/Android.mk
+++ b/services/tests/mockingservicestests/Android.mk
@@ -23,7 +23,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
frameworks-base-testutils \
services.core \
services.net \
- androidx-test \
+ androidx.test.runner \
mockito-target-extended-minus-junit4 \
platform-test-annotations \
ShortcutManagerTestUtils \
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 8afd788256c1..04a84081bad8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -36,35 +36,36 @@ import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
import static com.android.server.DeviceIdleController.STATE_IDLE_PENDING;
import static com.android.server.DeviceIdleController.STATE_INACTIVE;
import static com.android.server.DeviceIdleController.STATE_LOCATING;
+import static com.android.server.DeviceIdleController.STATE_QUICK_DOZE_DELAY;
import static com.android.server.DeviceIdleController.STATE_SENSING;
import static com.android.server.DeviceIdleController.lightStateToString;
import static com.android.server.DeviceIdleController.stateToString;
import static org.junit.Assert.assertEquals;
-
-import android.net.NetworkInfo;
-
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
-import android.net.ConnectivityManager;
-import android.content.Intent;
import android.app.IActivityManager;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.hardware.SensorManager;
import android.location.LocationManager;
import android.location.LocationProvider;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
import android.os.SystemClock;
import androidx.test.runner.AndroidJUnit4;
@@ -105,6 +106,8 @@ public class DeviceIdleControllerTest {
private PowerManager mPowerManager;
@Mock
private PowerManager.WakeLock mWakeLock;
+ @Mock
+ private PowerManagerInternal mPowerManagerInternal;
class InjectorForTest extends DeviceIdleController.Injector {
ConnectivityService connectivityService;
@@ -204,12 +207,15 @@ public class DeviceIdleControllerTest {
.when(() -> LocalServices.getService(ActivityManagerInternal.class));
doReturn(mock(ActivityTaskManagerInternal.class))
.when(() -> LocalServices.getService(ActivityTaskManagerInternal.class));
- doReturn(mock(PowerManagerInternal.class))
+ doReturn(mPowerManagerInternal)
.when(() -> LocalServices.getService(PowerManagerInternal.class));
+ when(mPowerManagerInternal.getLowPowerState(anyInt())).thenReturn(
+ mock(PowerSaveState.class));
doReturn(mock(NetworkPolicyManagerInternal.class))
.when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class));
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
doNothing().when(mWakeLock).acquire();
+ doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
mAnyMotionDetector = new AnyMotionDetectorForTest();
mInjector = new InjectorForTest(getContext());
@@ -336,6 +342,28 @@ public class DeviceIdleControllerTest {
}
@Test
+ public void testUpdateQuickDozeFlagLocked() {
+ mDeviceIdleController.updateQuickDozeFlagLocked(false);
+ assertFalse(mDeviceIdleController.isQuickDozeEnabled());
+
+ // Make sure setting false when quick doze is already off doesn't change anything.
+ mDeviceIdleController.updateQuickDozeFlagLocked(false);
+ assertFalse(mDeviceIdleController.isQuickDozeEnabled());
+
+ // Test changing from quick doze off to quick doze on.
+ mDeviceIdleController.updateQuickDozeFlagLocked(true);
+ assertTrue(mDeviceIdleController.isQuickDozeEnabled());
+
+ // Make sure setting true when quick doze is already on doesn't change anything.
+ mDeviceIdleController.updateQuickDozeFlagLocked(true);
+ assertTrue(mDeviceIdleController.isQuickDozeEnabled());
+
+ // Test changing from quick doze on to quick doze off.
+ mDeviceIdleController.updateQuickDozeFlagLocked(false);
+ assertFalse(mDeviceIdleController.isQuickDozeEnabled());
+ }
+
+ @Test
public void testStateActiveToStateInactive_ConditionsNotMet() {
mDeviceIdleController.becomeActiveLocked("testing", 0);
verifyStateConditions(STATE_ACTIVE);
@@ -416,6 +444,46 @@ public class DeviceIdleControllerTest {
}
@Test
+ public void testTransitionFromAnyStateToStateQuickDozeDelay() {
+ enterDeepState(STATE_ACTIVE);
+ setQuickDozeEnabled(true);
+ setChargingOn(false);
+ setScreenOn(false);
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_INACTIVE);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_IDLE_PENDING);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_SENSING);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_LOCATING);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ // IDLE should stay as IDLE.
+ enterDeepState(STATE_IDLE);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_IDLE);
+
+ // IDLE_MAINTENANCE should stay as IDLE_MAINTENANCE.
+ enterDeepState(STATE_IDLE_MAINTENANCE);
+ setQuickDozeEnabled(true);
+ verifyStateConditions(STATE_IDLE_MAINTENANCE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+ }
+
+ @Test
public void testStepIdleStateLocked_InvalidStates() {
mDeviceIdleController.becomeActiveLocked("testing", 0);
mDeviceIdleController.stepIdleStateLocked("testing");
@@ -425,49 +493,77 @@ public class DeviceIdleControllerTest {
}
@Test
+ public void testStepIdleStateLocked_ValidStates_QuickDoze() {
+ setAlarmSoon(false);
+
+ // Quick doze should go directly into IDLE.
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE);
+
+ // Should just alternate between IDLE and IDLE_MAINTENANCE now.
+
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE_MAINTENANCE);
+
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE);
+
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_IDLE_MAINTENANCE);
+ }
+
+ @Test
public void testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon() {
enterDeepState(STATE_ACTIVE);
// Return that there's an alarm coming soon.
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_ACTIVE);
// Everything besides ACTIVE should end up as INACTIVE since the screen would be off.
enterDeepState(STATE_INACTIVE);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE_PENDING);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_SENSING);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_LOCATING);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_INACTIVE);
+
+ // With quick doze enabled, we should end up in QUICK_DOZE_DELAY instead of INACTIVE.
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(true);
+ setAlarmSoon(true);
+ mDeviceIdleController.stepIdleStateLocked("testing");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ // With quick doze disabled, we should end up in INACTIVE instead of QUICK_DOZE_DELAY.
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(false);
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE_MAINTENANCE);
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(true);
mDeviceIdleController.stepIdleStateLocked("testing");
verifyStateConditions(STATE_INACTIVE);
}
@@ -476,7 +572,7 @@ public class DeviceIdleControllerTest {
public void testStepIdleStateLocked_ValidStates_NoLocationManager() {
mInjector.locationManager = null;
// Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
- doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(false);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
@@ -508,7 +604,7 @@ public class DeviceIdleControllerTest {
@Test
public void testStepIdleStateLocked_ValidStates_WithLocationManager_NoProviders() {
// Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
- doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(false);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
@@ -543,7 +639,7 @@ public class DeviceIdleControllerTest {
mInjector.locationManager = mLocationManager;
doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString());
// Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
- doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(false);
// Set state to INACTIVE.
mDeviceIdleController.becomeActiveLocked("testing", 0);
setChargingOn(false);
@@ -729,6 +825,8 @@ public class DeviceIdleControllerTest {
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
}
+ ///////////////// EXIT conditions ///////////////////
+
@Test
public void testExitMaintenanceEarlyIfNeededLocked_deep_noActiveOps() {
mDeviceIdleController.setJobsActive(false);
@@ -766,6 +864,10 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.setActiveIdleOpsForTest(0);
mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
verifyStateConditions(STATE_IDLE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
}
@Test
@@ -803,6 +905,10 @@ public class DeviceIdleControllerTest {
enterDeepState(STATE_IDLE_MAINTENANCE);
mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
verifyStateConditions(STATE_IDLE_MAINTENANCE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
}
@Test
@@ -840,6 +946,10 @@ public class DeviceIdleControllerTest {
enterDeepState(STATE_IDLE_MAINTENANCE);
mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
verifyStateConditions(STATE_IDLE_MAINTENANCE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
}
@Test
@@ -877,6 +987,10 @@ public class DeviceIdleControllerTest {
enterDeepState(STATE_IDLE_MAINTENANCE);
mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
verifyStateConditions(STATE_IDLE_MAINTENANCE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.exitMaintenanceEarlyIfNeededLocked();
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
}
@Test
@@ -1030,39 +1144,100 @@ public class DeviceIdleControllerTest {
}
@Test
- public void testHandleMotionDetectedLocked_deep() {
+ public void testHandleMotionDetectedLocked_deep_quickDoze_off() {
enterDeepState(STATE_ACTIVE);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_ACTIVE);
// Anything that wasn't ACTIVE before motion detection should end up in the INACTIVE state.
enterDeepState(STATE_INACTIVE);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE_PENDING);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_SENSING);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_LOCATING);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE);
+ setQuickDozeEnabled(false);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
enterDeepState(STATE_IDLE_MAINTENANCE);
+ setQuickDozeEnabled(false);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_INACTIVE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(false);
+ // Disabling quick doze doesn't immediately change the state as coming out is harder than
+ // going in.
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
verifyStateConditions(STATE_INACTIVE);
}
@Test
+ public void testHandleMotionDetectedLocked_deep_quickDoze_on() {
+ enterDeepState(STATE_ACTIVE);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_ACTIVE);
+
+ // Anything that wasn't ACTIVE before motion detection should end up in the
+ // QUICK_DOZE_DELAY state since quick doze is enabled.
+
+ enterDeepState(STATE_INACTIVE);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_IDLE_PENDING);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_SENSING);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_LOCATING);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_IDLE);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_IDLE_MAINTENANCE);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(true);
+ mDeviceIdleController.handleMotionDetectedLocked(50, "test");
+ verifyStateConditions(STATE_QUICK_DOZE_DELAY);
+ }
+
+ @Test
public void testHandleMotionDetectedLocked_light() {
enterLightState(LIGHT_STATE_ACTIVE);
mDeviceIdleController.handleMotionDetectedLocked(50, "test");
@@ -1128,6 +1303,10 @@ public class DeviceIdleControllerTest {
enterDeepState(STATE_IDLE_MAINTENANCE);
mDeviceIdleController.becomeActiveLocked("test", 1000);
verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ mDeviceIdleController.becomeActiveLocked("test", 1000);
+ verifyStateConditions(STATE_ACTIVE);
}
@Test
@@ -1169,6 +1348,14 @@ public class DeviceIdleControllerTest {
setScreenOn(true);
mDeviceIdleController.becomeActiveLocked("testing", 0);
break;
+ case STATE_QUICK_DOZE_DELAY:
+ // Start off from ACTIVE in case we're already past the desired state.
+ enterDeepState(STATE_ACTIVE);
+ setQuickDozeEnabled(true);
+ setScreenOn(false);
+ setChargingOn(false);
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ break;
case STATE_LOCATING:
mInjector.locationManager = mLocationManager;
doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(
@@ -1180,8 +1367,11 @@ public class DeviceIdleControllerTest {
case STATE_IDLE_MAINTENANCE:
// Make sure the controller doesn't think there's a wake-from-idle alarm coming
// soon.
- doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
+ setAlarmSoon(false);
case STATE_INACTIVE:
+ // Start off from ACTIVE in case we're already past the desired state.
+ enterDeepState(STATE_ACTIVE);
+ setQuickDozeEnabled(false);
setScreenOn(false);
setChargingOn(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
@@ -1211,6 +1401,8 @@ public class DeviceIdleControllerTest {
case LIGHT_STATE_INACTIVE:
case LIGHT_STATE_IDLE:
case LIGHT_STATE_IDLE_MAINTENANCE:
+ // Start off from ACTIVE in case we're already past the desired state.
+ enterLightState(LIGHT_STATE_ACTIVE);
setScreenOn(false);
setChargingOn(false);
int count = 0;
@@ -1256,6 +1448,19 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.updateConnectivityState(null);
}
+ private void setQuickDozeEnabled(boolean on) {
+ mDeviceIdleController.updateQuickDozeFlagLocked(on);
+ }
+
+ private void setAlarmSoon(boolean isSoon) {
+ if (isSoon) {
+ doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
+ mAlarmManager).getNextWakeFromIdleTime();
+ } else {
+ doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
+ }
+ }
+
private void verifyStateConditions(int expectedState) {
int curState = mDeviceIdleController.getState();
assertEquals(
@@ -1292,7 +1497,9 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isScreenOn());
break;
case STATE_IDLE:
- assertTrue(mDeviceIdleController.mMotionListener.isActive());
+ assertTrue(mDeviceIdleController.mMotionListener.isActive()
+ // If quick doze is enabled, the motion listener should NOT be active.
+ || mDeviceIdleController.isQuickDozeEnabled());
assertFalse(mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
@@ -1300,7 +1507,16 @@ public class DeviceIdleControllerTest {
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
break;
case STATE_IDLE_MAINTENANCE:
- assertTrue(mDeviceIdleController.mMotionListener.isActive());
+ assertTrue(mDeviceIdleController.mMotionListener.isActive()
+ // If quick doze is enabled, the motion listener should NOT be active.
+ || mDeviceIdleController.isQuickDozeEnabled());
+ assertFalse(mAnyMotionDetector.isMonitoring);
+ assertFalse(mDeviceIdleController.isCharging());
+ assertFalse(mDeviceIdleController.isScreenOn());
+ break;
+ case STATE_QUICK_DOZE_DELAY:
+ // If quick doze is enabled, the motion listener should NOT be active.
+ assertFalse(mDeviceIdleController.mMotionListener.isActive());
assertFalse(mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 2957267d2e5b..878179bb251d 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -24,7 +24,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
services.net \
services.usage \
guava \
- androidx-test \
+ androidx.test.runner \
+ androidx.test.rules \
mockito-target-minus-junit4 \
platform-test-annotations \
ShortcutManagerTestUtils \
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index 43438b99edef..802253280614 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -124,7 +124,7 @@ public class StorageManagerServiceTest {
"/storage/emulated/0/Android/sandbox/com.grey/foo.jpg",
"/storage/emulated/0/foo.jpg", PKG_GREY);
assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared/colors/foo.jpg",
+ "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
"/storage/emulated/0/foo.jpg", PKG_RED);
}
@@ -134,7 +134,7 @@ public class StorageManagerServiceTest {
"/storage/0000-0000/Android/sandbox/com.grey/foo/bar.jpg",
"/storage/0000-0000/foo/bar.jpg", PKG_GREY);
assertTranslation(
- "/storage/0000-0000/Android/sandbox/shared/colors/foo/bar.jpg",
+ "/storage/0000-0000/Android/sandbox/shared:colors/foo/bar.jpg",
"/storage/0000-0000/foo/bar.jpg", PKG_RED);
}
@@ -147,7 +147,7 @@ public class StorageManagerServiceTest {
// Accessing other package paths goes into sandbox
assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared/colors/"
+ "/storage/emulated/0/Android/sandbox/shared:colors/"
+ "Android/data/com.grey/foo.jpg",
"/storage/emulated/0/Android/data/com.grey/foo.jpg", PKG_RED);
}
@@ -192,7 +192,7 @@ public class StorageManagerServiceTest {
// Sandboxes can't see paths in other sandboxes
try {
mService.translateSystemToApp(
- "/storage/emulated/0/Android/sandbox/shared/colors/foo.jpg",
+ "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
PKG_GREY, UserHandle.USER_SYSTEM);
fail();
} catch (SecurityException expected) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
index c88b87328809..feffeef3f044 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java
@@ -86,12 +86,8 @@ public class MagnificationControllerTest {
final AccessibilityManagerService mMockAms = mock(AccessibilityManagerService.class);
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
final MessageCapturingHandler mMessageCapturingHandler =
- new MessageCapturingHandler(new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- return mMagnificationController.handleMessage(msg);
- }
- });
+ new MessageCapturingHandler(null);
+
final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
MagnificationController.SettingsBridge mMockSettingsBridge;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
index 79e4d705db19..032074a7e398 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java
@@ -29,9 +29,11 @@ import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
import android.os.Message;
@@ -44,7 +46,9 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
+import com.android.server.wm.WindowManagerInternal;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -101,8 +105,15 @@ public class MagnificationGestureHandlerTest {
public static final float DEFAULT_Y = 299;
private Context mContext;
- private AccessibilityManagerService mAms;
- private MagnificationController mMagnificationController;
+ final AccessibilityManagerService mMockAms = mock(AccessibilityManagerService.class);
+ final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
+ final MessageCapturingHandler mMessageCapturingHandler =
+ new MessageCapturingHandler(null);
+ final ValueAnimator mMockValueAnimator = mock(ValueAnimator.class);
+ MagnificationController.SettingsBridge mMockSettingsBridge =
+ mock(MagnificationController.SettingsBridge.class);
+ MagnificationController mMagnificationController;
+
private OffsettableClock mClock;
private MagnificationGestureHandler mMgh;
private TestHandler mHandler;
@@ -112,9 +123,9 @@ public class MagnificationGestureHandlerTest {
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
- mAms = new AccessibilityManagerService(mContext);
- mMagnificationController = new MagnificationController(
- mContext, mAms, /* lock */ new Object()) {
+ mMagnificationController = new MagnificationController(mContext, mMockAms, new Object(),
+ mMessageCapturingHandler, mMockWindowManager, mMockValueAnimator,
+ mMockSettingsBridge) {
@Override
public boolean magnificationRegionContains(float x, float y) {
return true;
@@ -123,7 +134,7 @@ public class MagnificationGestureHandlerTest {
@Override
void setForceShowMagnifiableBounds(boolean show) {}
};
- mMagnificationController.mRegistered = true;
+ mMagnificationController.register();
mClock = new OffsettableClock.Stopped();
boolean detectTripleTap = true;
@@ -131,6 +142,11 @@ public class MagnificationGestureHandlerTest {
mMgh = newInstance(detectTripleTap, detectShortcutTrigger);
}
+ @After
+ public void tearDown() {
+ mMagnificationController.unregister();
+ }
+
@NonNull
private MagnificationGestureHandler newInstance(boolean detectTripleTap,
boolean detectShortcutTrigger) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index 9a7488e42326..8c27e256456f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -133,7 +133,7 @@ public class ActivityManagerInternalTest {
private UidRecord addActiveUidRecord(int uid, long curProcStateSeq,
long lastNetworkUpdatedProcStateSeq) {
- final UidRecord record = new UidRecord(uid);
+ final UidRecord record = new UidRecord(uid, null /* atmInternal */);
record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
record.curProcStateSeq = curProcStateSeq;
record.waitingForNetwork = true;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index f42f5b1fff2e..349c0a37a4c1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -255,7 +255,7 @@ public class ActivityManagerServiceTest {
}
private UidRecord addUidRecord(int uid) {
- final UidRecord uidRec = new UidRecord(uid);
+ final UidRecord uidRec = new UidRecord(uid, null /* atmInternal */);
uidRec.waitingForNetwork = true;
uidRec.hasInternetPermission = true;
mAms.mActiveUids.put(uid, uidRec);
@@ -274,7 +274,7 @@ public class ActivityManagerServiceTest {
thread.startAndWait("Unexpected state for " + uidRec);
uidRec.setProcState = prevState;
- uidRec.curProcState = curState;
+ uidRec.setCurProcState(curState);
mAms.incrementProcStateSeqAndNotifyAppsLocked();
assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
@@ -301,7 +301,7 @@ public class ActivityManagerServiceTest {
@Test
public void testBlockStateForUid() {
- final UidRecord uidRec = new UidRecord(TEST_UID);
+ final UidRecord uidRec = new UidRecord(TEST_UID, null /* atmInternal */);
int expectedBlockState;
final String errorTemplate = "Block state should be %s, prevState: %s, curState: %s";
@@ -309,47 +309,48 @@ public class ActivityManagerServiceTest {
return String.format(errorTemplate,
valueToString(ActivityManagerService.class, "NETWORK_STATE_", blockState),
valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState),
- valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.curProcState));
+ valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.getCurProcState())
+ );
};
// No change in uid state
uidRec.setProcState = PROCESS_STATE_RECEIVER;
- uidRec.curProcState = PROCESS_STATE_RECEIVER;
+ uidRec.setCurProcState(PROCESS_STATE_RECEIVER);
expectedBlockState = NETWORK_STATE_NO_CHANGE;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
// Foreground to foreground
uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
- uidRec.curProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ uidRec.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
expectedBlockState = NETWORK_STATE_NO_CHANGE;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
// Background to background
uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
- uidRec.curProcState = PROCESS_STATE_CACHED_EMPTY;
+ uidRec.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
expectedBlockState = NETWORK_STATE_NO_CHANGE;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
// Background to background
uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
- uidRec.curProcState = PROCESS_STATE_CACHED_ACTIVITY;
+ uidRec.setCurProcState(PROCESS_STATE_CACHED_ACTIVITY);
expectedBlockState = NETWORK_STATE_NO_CHANGE;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
// Background to foreground
uidRec.setProcState = PROCESS_STATE_SERVICE;
- uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+ uidRec.setCurProcState(PROCESS_STATE_FOREGROUND_SERVICE);
expectedBlockState = NETWORK_STATE_BLOCK;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
// Foreground to background
uidRec.setProcState = PROCESS_STATE_TOP;
- uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY;
+ uidRec.setCurProcState(PROCESS_STATE_LAST_ACTIVITY);
expectedBlockState = NETWORK_STATE_UNBLOCK;
assertEquals(errorMsg.apply(expectedBlockState),
expectedBlockState, mAms.getBlockStateForUid(uidRec));
@@ -593,10 +594,10 @@ public class ActivityManagerServiceTest {
assertNotNull("validateUidRecord should not be null since the change is neither "
+ "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord);
assertEquals("processState: " + item.processState + " curProcState: "
- + validateUidRecord.curProcState + " should have been equal",
- item.processState, validateUidRecord.curProcState);
+ + validateUidRecord.getCurProcState() + " should have been equal",
+ item.processState, validateUidRecord.getCurProcState());
assertEquals("processState: " + item.processState + " setProcState: "
- + validateUidRecord.curProcState + " should have been equal",
+ + validateUidRecord.getCurProcState() + " should have been equal",
item.processState, validateUidRecord.setProcState);
if (item.change == UidRecord.CHANGE_IDLE) {
assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE",
@@ -626,7 +627,7 @@ public class ActivityManagerServiceTest {
@Test
public void testEnqueueUidChangeLocked_procStateSeqUpdated() {
- final UidRecord uidRecord = new UidRecord(TEST_UID);
+ final UidRecord uidRecord = new UidRecord(TEST_UID, null /* atmInternal */);
uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
// Verify with no pending changes for TEST_UID.
@@ -672,7 +673,7 @@ public class ActivityManagerServiceTest {
@MediumTest
@Test
public void testEnqueueUidChangeLocked_dispatchUidsChanged() {
- final UidRecord uidRecord = new UidRecord(TEST_UID);
+ final UidRecord uidRecord = new UidRecord(TEST_UID, null /* atmInternal */);
final int expectedProcState = PROCESS_STATE_SERVICE;
uidRecord.setProcState = expectedProcState;
uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ1;
@@ -744,7 +745,7 @@ public class ActivityManagerServiceTest {
private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq,
long lastDispatchedProcStateSeq, long lastNetworkUpdatedProcStateSeq,
final long procStateSeqToWait, boolean expectWait) throws Exception {
- final UidRecord record = new UidRecord(Process.myUid());
+ final UidRecord record = new UidRecord(Process.myUid(), null /* atmInternal */);
record.curProcStateSeq = curProcStateSeq;
record.lastDispatchedProcStateSeq = lastDispatchedProcStateSeq;
record.lastNetworkUpdatedProcStateSeq = lastNetworkUpdatedProcStateSeq;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
index 65e4fa0f4aff..270d394ead34 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -109,7 +109,6 @@ public class ActivityStartInterceptorTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mService.mAm = mAm;
mService.mAmInternal = mAmInternal;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
diff --git a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
index bd4a356fcb5c..77f6a23c26b1 100644
--- a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
@@ -58,7 +58,8 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
+ "adjust_brightness_factor=0.7,"
+ "fullbackup_deferred=true,"
+ "keyvaluebackup_deferred=false,"
- + "gps_mode=0";
+ + "gps_mode=0,"
+ + "quick_doze_enabled=true";
private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
private class BatterySaverPolicyForTest extends BatterySaverPolicy {
@@ -102,48 +103,48 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
@SmallTest
public void testGetBatterySaverPolicy_PolicyNull_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.NULL);
+ testServiceDefaultValue_On(ServiceType.NULL);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.VIBRATION);
+ testServiceDefaultValue_On(ServiceType.VIBRATION);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyVibration_WithAccessibilityEnabled() {
mBatterySaverPolicy.setAccessibilityEnabledForTest(true);
- testServiceDefaultValue_unchanged(ServiceType.VIBRATION);
+ testServiceDefaultValue_Off(ServiceType.VIBRATION);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicySound_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.SOUND);
+ testServiceDefaultValue_On(ServiceType.SOUND);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyFullBackup_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.FULL_BACKUP);
+ testServiceDefaultValue_On(ServiceType.FULL_BACKUP);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyKeyValueBackup_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.KEYVALUE_BACKUP);
+ testServiceDefaultValue_On(ServiceType.KEYVALUE_BACKUP);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyAnimation_DefaultValueCorrect() {
- testServiceDefaultValue_unchanged(ServiceType.ANIMATION);
+ testServiceDefaultValue_Off(ServiceType.ANIMATION);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyBatteryStats_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.BATTERY_STATS);
+ testServiceDefaultValue_On(ServiceType.BATTERY_STATS);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyNetworkFirewall_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
+ testServiceDefaultValue_On(ServiceType.NETWORK_FIREWALL);
}
@SmallTest
@@ -160,12 +161,12 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
@SmallTest
public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
- testServiceDefaultValue_unchanged(ServiceType.SCREEN_BRIGHTNESS);
+ testServiceDefaultValue_Off(ServiceType.SCREEN_BRIGHTNESS);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
- testServiceDefaultValue(ServiceType.GPS);
+ testServiceDefaultValue_On(ServiceType.GPS);
PowerSaveState stateOn =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
@@ -173,6 +174,11 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
}
@SmallTest
+ public void testGetBatterySaverPolicy_PolicyQuickDoze_DefaultValueCorrect() {
+ testServiceDefaultValue_Off(ServiceType.QUICK_DOZE);
+ }
+
+ @SmallTest
public void testUpdateConstants_getCorrectData() {
mBatterySaverPolicy.updateConstantsLocked(BATTERY_SAVER_CONSTANTS, "");
@@ -214,6 +220,10 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
assertThat(gpsState.batterySaverEnabled).isTrue();
assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
+
+ final PowerSaveState quickDozeState = mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.QUICK_DOZE, BATTERY_SAVER_ON);
+ assertThat(quickDozeState.batterySaverEnabled).isTrue();
}
@SmallTest
@@ -223,7 +233,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
mBatterySaverPolicy.updateConstantsLocked(null, "");
}
- private void testServiceDefaultValue(@ServiceType int type) {
+ private void testServiceDefaultValue_On(@ServiceType int type) {
mBatterySaverPolicy.updateConstantsLocked("", "");
final PowerSaveState batterySaverStateOn =
mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
@@ -234,7 +244,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
}
- private void testServiceDefaultValue_unchanged(@ServiceType int type) {
+ private void testServiceDefaultValue_Off(@ServiceType int type) {
mBatterySaverPolicy.updateConstantsLocked("", "");
final PowerSaveState batterySaverStateOn =
mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
index 07eafa5c4be4..a028d5eeb02e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -18,23 +18,34 @@
package com.android.server.wm;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import android.app.WindowConfiguration;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.policy.WindowManagerPolicy;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
+/**
+ * Tests for the {@link DisplaySettings} class.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:com.android.server.wm.DisplaySettingsTests
+ */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -155,6 +166,71 @@ public class DisplaySettingsTests extends WindowTestsBase {
assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
}
+ @Test
+ public void testDefaultToFreeUserRotation() {
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, rotation.getUserRotationMode());
+ assertFalse(rotation.isRotationFrozen());
+ }
+
+ @Test
+ public void testDefaultTo0DegRotation() {
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(Surface.ROTATION_0, mSecondaryDisplay.getDisplayRotation().getUserRotation());
+ }
+
+ @Test
+ public void testPersistUserRotationModeInSameInstance() {
+ mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_90);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation.getUserRotationMode());
+ assertTrue(rotation.isRotationFrozen());
+ }
+
+ @Test
+ public void testPersistUserRotationInSameInstance() {
+ mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_90);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(Surface.ROTATION_90, mSecondaryDisplay.getDisplayRotation().getUserRotation());
+ }
+
+ @Test
+ public void testPersistUserRotationModeAcrossInstances() {
+ mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_270);
+ mTarget.writeSettingsLocked();
+
+ DisplaySettings target = new DisplaySettings(sWm, mTestFolder);
+ target.readSettingsLocked();
+
+ target.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation.getUserRotationMode());
+ assertTrue(rotation.isRotationFrozen());
+ }
+
+ @Test
+ public void testPersistUserRotationAcrossInstances() {
+ mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_270);
+
+ mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+ assertEquals(Surface.ROTATION_270,
+ mSecondaryDisplay.getDisplayRotation().getUserRotation());
+ }
+
private static void assertOverscan(DisplayContent display, int left, int top, int right,
int bottom) {
final DisplayInfo info = display.getDisplayInfo();
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 474e5b75e5d8..51595514624c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -432,17 +432,6 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
}
@Override
- public int getUserRotationMode() {
- return 0;
- }
-
- @Override
- public void setUserRotationMode(int mode,
- int rotation) {
-
- }
-
- @Override
public int adjustSystemUiVisibilityLw(int visibility) {
return 0;
}
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
index 7e7decfa8e3b..ab222b941e94 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
@@ -20,7 +20,7 @@ LOCAL_MODULE_TAGS := tests
LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_STATIC_JAVA_LIBRARIES := androidx-test ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.runner ub-uiautomator
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_SRC_FILES += ../../src/com/android/server/pm/SuspendPackagesTest.java
diff --git a/services/tests/wmtests/Android.mk b/services/tests/wmtests/Android.mk
index 0f8b18ab92cf..c095ae0dd2ff 100644
--- a/services/tests/wmtests/Android.mk
+++ b/services/tests/wmtests/Android.mk
@@ -14,7 +14,7 @@ LOCAL_SRC_FILES := \
$(call all-java-files-under, ../servicestests/utils)
LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx-test \
+ androidx.test.runner \
mockito-target-minus-junit4 \
platform-test-annotations \
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index 5bc8934279d6..571f623aea99 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -22,9 +22,9 @@ import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.graphics.RecordingCanvas;
import android.os.Bundle;
import android.os.Trace;
-import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.widget.LinearLayout;
@@ -88,8 +88,8 @@ public class CirclePropActivity extends Activity {
super.onDraw(canvas);
if (canvas.isHardwareAccelerated()) {
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
- displayListCanvas.drawCircle(mX, mY, mRadius, mPaint);
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawCircle(mX, mY, mRadius, mPaint);
}
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
index af8e10bc07ae..220016aa8ab7 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
@@ -16,25 +16,13 @@
package com.android.test.hwui;
-import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
-import static android.graphics.GraphicBuffer.USAGE_SW_READ_NEVER;
-import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_NEVER;
-import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_RARELY;
-
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.GraphicBuffer;
import android.graphics.Paint;
import android.graphics.Picture;
-import android.graphics.PixelFormat;
-import android.graphics.SurfaceTexture;
import android.os.Bundle;
-import android.view.DisplayListCanvas;
-import android.view.RenderNode;
-import android.view.Surface;
-import android.view.ThreadedRenderer;
import android.widget.ImageView;
public class DrawIntoHwBitmapActivity extends Activity {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
index 7713f5da36ed..e7d7f2b11801 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
@@ -21,12 +21,12 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.view.DisplayListCanvas;
import android.view.ThreadedRenderer;
-import android.view.RenderNode;
+import android.graphics.RenderNode;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsoluteLayout;
@@ -206,7 +206,7 @@ public class MultiProducerActivity extends Activity implements OnClickListener {
}
// Draw frame
- DisplayListCanvas canvas = nodeFrame.start(currentFrameBounds.width(),
+ RecordingCanvas canvas = nodeFrame.start(currentFrameBounds.width(),
currentFrameBounds.height());
mFrameContent.draw(canvas);
nodeFrame.end(canvas);
@@ -228,7 +228,7 @@ public class MultiProducerActivity extends Activity implements OnClickListener {
}
// Draw Backdrop
- DisplayListCanvas canvas = nodeBack.start(currentBackBounds.width(),
+ RecordingCanvas canvas = nodeBack.start(currentBackBounds.width(),
currentBackBounds.height());
mBackContent.draw(canvas);
nodeBack.end(canvas);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
index be5d7f98783d..4eb40722f6dd 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
@@ -8,9 +8,8 @@ import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
-import android.view.RenderNode;
+import android.graphics.RenderNode;
import android.view.View;
-import android.widget.LinearLayout;
public class ProjectionActivity extends Activity {
/**
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java
index 2ae960bd08db..9abd7ea5f361 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java
@@ -1,13 +1,7 @@
package com.android.test.hwui;
import android.app.Activity;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.RenderNode;
import android.view.View;
public class ProjectionClippingActivity extends Activity {
diff --git a/tests/Internal/res/xml/livewallpaper.xml b/tests/Internal/res/xml/livewallpaper.xml
index 6b5e84e8f9ad..36e7e4182c31 100644
--- a/tests/Internal/res/xml/livewallpaper.xml
+++ b/tests/Internal/res/xml/livewallpaper.xml
@@ -16,4 +16,5 @@
-->
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
- android:supportsAmbientMode="true"/> \ No newline at end of file
+ android:settingsSliceUri="content://com.android.internal.tests/slice"
+ android:supportsAmbientMode="true"/>
diff --git a/tests/Internal/src/android/app/WallpaperInfoTest.java b/tests/Internal/src/android/app/WallpaperInfoTest.java
index 98045ae98541..7f06f2cb7aeb 100644
--- a/tests/Internal/src/android/app/WallpaperInfoTest.java
+++ b/tests/Internal/src/android/app/WallpaperInfoTest.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
import android.os.Parcel;
import android.service.wallpaper.WallpaperService;
import android.support.test.InstrumentationRegistry;
@@ -64,5 +65,31 @@ public class WallpaperInfoTest {
fromParcel.supportsAmbientMode());
parcel.recycle();
}
+
+ @Test
+ public void testGetSettingsSliceUri() throws Exception {
+ Context context = InstrumentationRegistry.getTargetContext();
+
+ Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+ intent.setPackage("com.android.internal.tests");
+ PackageManager pm = context.getPackageManager();
+ List<ResolveInfo> result = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
+ assertEquals(1, result.size());
+ ResolveInfo info = result.get(0);
+ WallpaperInfo wallpaperInfo = new WallpaperInfo(context, info);
+
+ // This expected Uri must be the same as that in livewallpaper.xml
+ Uri expectedUri = Uri.parse("content://com.android.internal.tests/slice");
+ Uri settingsUri = wallpaperInfo.getSettingsSliceUri();
+ assertEquals("The loaded URI should equal to the string in livewallpaper.xml",
+ 0, expectedUri.compareTo(settingsUri));
+ Parcel parcel = Parcel.obtain();
+ wallpaperInfo.writeToParcel(parcel, 0 /* flags */);
+ parcel.setDataPosition(0);
+ WallpaperInfo fromParcel = WallpaperInfo.CREATOR.createFromParcel(parcel);
+ assertEquals("settingsSliceUri should be restorable from parcelable",
+ 0, expectedUri.compareTo(fromParcel.getSettingsSliceUri()));
+ parcel.recycle();
+ }
}
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
index 6500428253f6..18cdf96c7131 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
@@ -34,7 +34,7 @@ public class Cujs {
// Do an explicit GC in the system server process as part of the test
// case to reduce GC-related sources of noise.
// SIGUSR1 = 10 is the magic signal to trigger the GC.
- int pid = mDevice.getPidForProcess("system_server");
+ int pid = mDevice.getProcessPid("system_server");
mDevice.executeShellCommand("kill -10 " + pid);
// Invoke the Device Cujs instrumentation to run the cujs.
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java
index 03503cec5fec..26146ca0ea6c 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java
@@ -19,9 +19,6 @@ package com.android.tests.sysmem.host;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
-import java.util.InputMismatchException;
-import java.util.Scanner;
-
/**
* Wrapper around ITestDevice exposing useful device functions.
*/
@@ -58,29 +55,15 @@ class Device {
/**
* Returns the pid for the process with the given name.
*/
- public int getPidForProcess(String name) throws TestException {
- String psout = executeShellCommand("ps -A -o PID,CMD");
- Scanner sc = new Scanner(psout);
+ public int getProcessPid(String name) throws TestException {
try {
- // ps output is of the form:
- // PID CMD
- // 1 init
- // 2 kthreadd
- // ...
- // 9693 ps
- sc.nextLine();
- while (sc.hasNextLine()) {
- int pid = sc.nextInt();
- String cmd = sc.next();
-
- if (name.equals(cmd)) {
- return pid;
- }
+ String pid = mDevice.getProcessPid(name);
+ if (pid == null) {
+ throw new TestException("failed to get pid for " + name);
}
- } catch (InputMismatchException e) {
- throw new TestException("unexpected ps output format: " + psout, e);
+ return Integer.parseInt(pid);
+ } catch (DeviceNotAvailableException e) {
+ throw new TestException(e);
}
-
- throw new TestException("failed to get pid for process " + name);
}
}
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
index b408a81d8f93..b46e642b5e92 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
@@ -79,7 +79,7 @@ class Metrics {
// adb root access is required to get showmap
mDevice.enableAdbRoot();
- int pid = mDevice.getPidForProcess("system_server");
+ int pid = mDevice.getProcessPid("system_server");
// Read showmap for system server and add it as a test log
String showmap = mDevice.executeShellCommand("showmap " + pid);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 59ba8e7a6177..9adbe67c1553 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3754,6 +3754,13 @@ public class WifiManager {
mCallback.onProvisioningFailure(status);
});
}
+
+ @Override
+ public void onProvisioningComplete() {
+ mHandler.post(() -> {
+ mCallback.onProvisioningComplete();
+ });
+ }
}
/**
diff --git a/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl
index c2cb16ab847c..a6bdd5b6bfff 100644
--- a/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl
+++ b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl
@@ -32,5 +32,10 @@ oneway interface IProvisioningCallback
* Service to manager callback providing Provisioning status
*/
void onProvisioningStatus(int status);
+
+ /**
+ * Service to manager callback providing completion of Provisioning/Remediation flow
+ */
+ void onProvisioningComplete();
}
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index 6076175ce9d1..4b76526cbb59 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -108,6 +108,48 @@ public abstract class ProvisioningCallback {
public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15;
/**
+ * The reason code for provisioning failure when there is no PPS MO.
+ * MO.
+ */
+ public static final int OSU_FAILURE_NO_PPS_MO = 16;
+
+ /**
+ * The reason code for provisioning failure when there is no AAAServerTrustRoot node in a PPS
+ * MO.
+ */
+ public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17;
+
+ /**
+ * The reason code for provisioning failure when there is no TrustRoot node for remediation
+ * server in a PPS MO.
+ */
+ public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18;
+
+ /**
+ * The reason code for provisioning failure when there is no TrustRoot node for policy server in
+ * a PPS MO.
+ */
+ public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19;
+
+ /**
+ * The reason code for provisioning failure when failing to retrieve trust root certificates
+ * used for validating server certificate for AAA, Remediation and Policy server.
+ */
+ public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20;
+
+ /**
+ * The reason code for provisioning failure when there is no trust root certificate for AAA
+ * server.
+ */
+ public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21;
+
+ /**
+ * The reason code for provisioning failure when a {@link PasspointConfiguration} is failed to
+ * install.
+ */
+ public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22;
+
+ /**
* The status code for provisioning flow to indicate connecting to OSU AP
*/
public static final int OSU_STATUS_AP_CONNECTING = 1;
@@ -158,6 +200,12 @@ public abstract class ProvisioningCallback {
public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10;
/**
+ * The status code for provisioning flow to indicate starting a step retrieving trust root
+ * certs.
+ */
+ public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11;
+
+ /**
* Provisioning status for OSU failure
*
* @param status indicates error condition
@@ -170,5 +218,10 @@ public abstract class ProvisioningCallback {
* @param status indicates status of OSU flow
*/
public abstract void onProvisioningStatus(int status);
+
+ /**
+ * Provisioning complete when provisioning/remediation flow completes
+ */
+ public abstract void onProvisioningComplete();
}