From cdfcf6e4698566f5f9c002bee0a588c00634ee9b Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 8 Oct 2021 16:15:06 -0700 Subject: [PATCH 1/8] Apply the last recents animation transform on single-activity PIP tasks - When swiping up to enter PIP w/ auto-enter, SysUI applies a transform on the leash which is seamlessly applied to the task (to prevent jumps when the leash is removed). This was intended to be applied in both single and multiple activity PIP cases, but if that doesn't happen, then when the transform is later cleared, it will inadvertently reset the task's crop and matrix. Bug: 201127015 Test: atest PinnedStackTests Test: Open YT, enter PIP, turn screen off, turn screen back on Change-Id: I0d6d46c7c52f7a43058902b50a26131f626ae92d (cherry picked from commit 54d481dedac60bdc1af5e128c67c66b1d66c45af) --- .../core/java/com/android/server/wm/RootWindowContainer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index bd688a618c633..52da4b80a75d1 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2125,6 +2125,9 @@ class RootWindowContainer extends WindowContainer final Task rootTask; if (singleActivity) { rootTask = task; + + // Apply the last recents animation leash transform to the task entering PIP + rootTask.maybeApplyLastRecentsAnimationTransaction(); } else { // In the case of multiple activities, we will create a new task for it and then // move the PIP activity into the task. Note that we explicitly defer the task From b591b3ebec4886e9c1c2219a6c0e9fd3e1ac63ee Mon Sep 17 00:00:00 2001 From: Josh Tsuji Date: Mon, 4 Oct 2021 15:23:59 -0400 Subject: [PATCH 2/8] [DO NOT MERGE] Improve brightness handling during screen off timeout. - Align doze brightness logic with DisplayPowerController, so that the 'minimum dim amount' is taken into account by DozeScreenBrightness. - Clamp brightness to the now-correct dim value during the entire screen off animation, rather than sometimes transitioning to the sensor value. Apply the sensor brightness value on changing to the DOZE Display state, which happens after the screen off animation. Bug: 194972547 Test: at 0%, 45%, and 100% brightness, allow the screen to time out in bright and dark rooms, observe minimal brightness changes Change-Id: I528a944e04f8906cd8c7740eea97dd8fba7c3d3e (cherry picked from commit 2c26ea64bc74c7c75e3f65bd9e8cebd6494571d5) --- .../systemui/doze/DozeScreenBrightness.java | 36 +++++++++++++++---- .../systemui/doze/DozeScreenState.java | 11 +++++- .../doze/DozeScreenBrightnessTest.java | 12 +++++-- .../systemui/doze/DozeScreenStateTest.java | 5 ++- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index da7b389fbd36e..058f37a2ef389 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -36,6 +36,7 @@ import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.doze.dagger.WrappedService; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.util.sensors.AsyncSensorManager; import java.io.PrintWriter; @@ -55,6 +56,16 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi "com.android.systemui.doze.AOD_BRIGHTNESS"; protected static final String BRIGHTNESS_BUCKET = "brightness_bucket"; + /** + * Just before the screen times out from user inactivity, DisplayPowerController dims the screen + * brightness to the lower of {@link #mScreenBrightnessDim}, or the current brightness minus + * DisplayPowerController#SCREEN_DIM_MINIMUM_REDUCTION_FLOAT. + * + * This value is 0.04f * 255, which converts SCREEN_DIM_MINIMUM_REDUCTION_FLOAT to the integer + * brightness values used by doze. + */ + private static final int SCREEN_DIM_MINIMUM_REDUCTION_INT = 10; + private final Context mContext; private final DozeMachine.Service mDozeService; private final DozeHost mDozeHost; @@ -82,6 +93,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi */ private int mDebugBrightnessBucket = -1; + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Inject public DozeScreenBrightness(Context context, @WrappedService DozeMachine.Service service, AsyncSensorManager sensorManager, @@ -89,7 +102,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi AlwaysOnDisplayPolicy alwaysOnDisplayPolicy, WakefulnessLifecycle wakefulnessLifecycle, DozeParameters dozeParameters, - DockManager dockManager) { + DockManager dockManager, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { mContext = context; mDozeService = service; mSensorManager = sensorManager; @@ -99,6 +113,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi mDozeHost = host; mHandler = handler; mDockManager = dockManager; + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness; mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness; @@ -148,14 +163,15 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } } - private void updateBrightnessAndReady(boolean force) { + public void updateBrightnessAndReady(boolean force) { if (force || mRegistered || mDebugBrightnessBucket != -1) { int sensorValue = mDebugBrightnessBucket == -1 ? mLastSensorValue : mDebugBrightnessBucket; int brightness = computeBrightness(sensorValue); boolean brightnessReady = brightness > 0; if (brightnessReady) { - mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness)); + mDozeService.setDozeScreenBrightness( + clampToDimBrightnessForScreenOff(clampToUserSetting(brightness))); } int scrimOpacity = -1; @@ -207,13 +223,21 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi /** * Clamp the brightness to the dim brightness value used by PowerManagerService just before the * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we - * don't raise the brightness back to the user setting before playing the screen off animation. + * don't raise the brightness back to the user setting before or during the screen off + * animation. */ private int clampToDimBrightnessForScreenOff(int brightness) { - if (mDozeParameters.shouldControlUnlockedScreenOff() + if (mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() && mWakefulnessLifecycle.getLastSleepReason() == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { - return Math.min(mScreenBrightnessDim, brightness); + return Math.max( + PowerManager.BRIGHTNESS_OFF, + // Use the lower of either the dim brightness, or the current brightness reduced + // by the minimum dim amount. This is the same logic used in + // DisplayPowerController#updatePowerState to apply a minimum dim amount. + Math.min( + brightness - SCREEN_DIM_MINIMUM_REDUCTION_INT, + mScreenBrightnessDim)); } else { return brightness; } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 8f1486b0c7cbb..038be48b53eeb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -77,6 +77,7 @@ public class DozeScreenState implements DozeMachine.Part { private final Provider mUdfpsControllerProvider; @Nullable private UdfpsController mUdfpsController; private final DozeLog mDozeLog; + private final DozeScreenBrightness mDozeScreenBrightness; private int mPendingScreenState = Display.STATE_UNKNOWN; private SettableWakeLock mWakeLock; @@ -90,7 +91,8 @@ public class DozeScreenState implements DozeMachine.Part { WakeLock wakeLock, AuthController authController, Provider udfpsControllerProvider, - DozeLog dozeLog) { + DozeLog dozeLog, + DozeScreenBrightness dozeScreenBrightness) { mDozeService = service; mHandler = handler; mParameters = parameters; @@ -99,6 +101,7 @@ public class DozeScreenState implements DozeMachine.Part { mAuthController = authController; mUdfpsControllerProvider = udfpsControllerProvider; mDozeLog = dozeLog; + mDozeScreenBrightness = dozeScreenBrightness; updateUdfpsController(); if (mUdfpsController == null) { @@ -204,6 +207,12 @@ public class DozeScreenState implements DozeMachine.Part { if (screenState != Display.STATE_UNKNOWN) { if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")"); mDozeService.setDozeScreenState(screenState); + if (screenState == Display.STATE_DOZE) { + // If we're entering doze, update the doze screen brightness. We might have been + // clamping it to the dim brightness during the screen off animation, and we should + // now change it to the brightness we actually want according to the sensor. + mDozeScreenBrightness.updateBrightnessAndReady(false /* force */); + } mPendingScreenState = Display.STATE_UNKNOWN; mWakeLock.setAcquired(false); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index e0520b406a0ae..1d00531af42cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -51,6 +51,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeThreadFactory; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -86,6 +87,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { DozeParameters mDozeParameters; @Mock DockManager mDockManager; + @Mock + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor); @@ -113,7 +116,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensor = fakeSensorManager.getFakeLightSensor(); mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.of(mSensor.getSensor()), mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, + mUnlockedScreenOffAnimationController); } @Test @@ -211,7 +215,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testPulsing_withoutLightSensor_setsAoDDimmingScrimTransparent() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, + mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); reset(mDozeHost); @@ -240,7 +245,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { public void testNullSensor() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, Optional.empty() /* sensor */, mDozeHost, null /* handler */, - mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager); + mAlwaysOnDisplayPolicy, mWakefulnessLifecycle, mDozeParameters, mDockManager, + mUnlockedScreenOffAnimationController); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 150ab7700e4be..3e19cc436dca6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -82,6 +82,8 @@ public class DozeScreenStateTest extends SysuiTestCase { private UdfpsController mUdfpsController; @Mock private DozeLog mDozeLog; + @Mock + private DozeScreenBrightness mDozeScreenBrightness; @Before public void setUp() throws Exception { @@ -96,7 +98,8 @@ public class DozeScreenStateTest extends SysuiTestCase { mHandlerFake = new FakeHandler(Looper.getMainLooper()); mWakeLock = new WakeLockFake(); mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters, - mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog); + mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog, + mDozeScreenBrightness); } @Test From 75e876b5480bb382b222a5d983ddaabf108a2dc6 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Wed, 6 Oct 2021 23:43:46 +0800 Subject: [PATCH 3/8] Continue the pausing process after automatically entering pip Or the activity remained in PAUSING state and prevents the activity to stop after screen off until stop timeout. Bug: 202345179 Test: atest PinnedStackTests Change-Id: Ibb8b3c48d483dcb96207ec2395a87b31d8eb107e Merged-In: Ibb8b3c48d483dcb96207ec2395a87b31d8eb107e (cherry picked from commit e84bd0d141b31d9504edf2d73591b2b8266f02e3) (cherry picked from commit 2c2860f0c53da530c3b7e24e94a0836b695f8dbd) --- .../server/wm/ActivityTaskManagerService.java | 12 ++++-- .../core/java/com/android/server/wm/Task.java | 38 ++++++++++--------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f3ba56a03aef9..08f3b1a8c6e01 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3387,9 +3387,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final List actions = r.pictureInPictureArgs.getActions(); mRootWindowContainer.moveActivityToPinnedRootTask( r, "enterPictureInPictureMode"); - final Task rootTask = r.getRootTask(); - rootTask.setPictureInPictureAspectRatio(aspectRatio); - rootTask.setPictureInPictureActions(actions); + final Task task = r.getTask(); + task.setPictureInPictureAspectRatio(aspectRatio); + task.setPictureInPictureActions(actions); + + // Continue the pausing process after entering pip. + if (task.getPausingActivity() == r) { + task.schedulePauseActivity(r, false /* userLeaving */, + false /* pauseImmediately */, "auto-pip"); + } } }; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index c3074fab0a1a5..c068fd1a5f6e3 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -5771,23 +5771,8 @@ class Task extends WindowContainer { + "directly: %s", prev); didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs); - mPausingActivity = null; } else { - ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev); - try { - EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), - prev.shortComponentName, "userLeaving=" + userLeaving, reason); - - mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), - prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, - prev.configChangeFlags, pauseImmediately)); - } catch (Exception e) { - // Ignore exception, if process died other code will cleanup. - Slog.w(TAG, "Exception thrown during pause", e); - mPausingActivity = null; - mLastPausedActivity = null; - mTaskSupervisor.mNoHistoryActivities.remove(prev); - } + schedulePauseActivity(prev, userLeaving, pauseImmediately, reason); } } else { mPausingActivity = null; @@ -5802,7 +5787,7 @@ class Task extends WindowContainer { } // If already entered PIP mode, no need to keep pausing. - if (mPausingActivity != null && !didAutoPip) { + if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt @@ -5835,6 +5820,25 @@ class Task extends WindowContainer { } } + void schedulePauseActivity(ActivityRecord prev, boolean userLeaving, + boolean pauseImmediately, String reason) { + ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev); + try { + EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), + prev.shortComponentName, "userLeaving=" + userLeaving, reason); + + mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), + prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, + prev.configChangeFlags, pauseImmediately)); + } catch (Exception e) { + // Ignore exception, if process died other code will cleanup. + Slog.w(TAG, "Exception thrown during pause", e); + mPausingActivity = null; + mLastPausedActivity = null; + mTaskSupervisor.mNoHistoryActivities.remove(prev); + } + } + @VisibleForTesting void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { // Complete the pausing process of a pausing activity, so it doesn't make sense to From 66f93c5c6b5dc888641ec60ad812334a3f814d61 Mon Sep 17 00:00:00 2001 From: Josh Tsuji Date: Wed, 6 Oct 2021 16:37:04 +0000 Subject: [PATCH 4/8] [DO NOT MERGE] Fix DozeScreenBrightnessTest. This was broken by ag/15974634, but the presubmits did not catch that for some reason. That CL changed the brightness logic to be <= the dim value, so this failure (and fix) make sense. Test: atest SystemUITests, since apparently treehugger won't do that and will +2 this anyway Fixes: 202212576 Change-Id: Ibe18322fbe1e1fbae86c5274615ad0b6f727c8e2 (cherry picked from commit 20d85a91d4d2ac22760111483b4bdeaecace6c5f) (cherry picked from commit fc534e4f63a4ac9953394cb69d2f8f25ca508464) --- .../android/systemui/doze/DozeScreenBrightnessTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 1d00531af42cb..b8d465a8c8817 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -319,13 +319,14 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); // If we're dozing after a timeout, and playing the unlocked screen animation, we should - // stay at dim brightness, because the screen dims just before timeout. - assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS); + // stay at or below dim brightness, because the screen dims just before timeout. + assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS); } @Test @@ -333,6 +334,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); @@ -347,6 +349,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn( PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false); + when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE); From 8b770aef8d4cee3dc139001d3be28d48fe2e47f0 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Wed, 13 Oct 2021 21:24:50 +0800 Subject: [PATCH 5/8] [RESTRICT AUTOMERGE] Add WiFi scan notify message (QS Internet Dialog) Bug: 202323013 Test: add new string only, unnecessary to test. Change-Id: I54bc60793f317390a78ce1e9dc96ee31c861ad63 (cherry picked from commit 6baf1dad31398d150402085809cbe71ab3b0e453) --- packages/SystemUI/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7aacb702b75a4..4ad4fa9d08543 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3033,4 +3033,6 @@ See all To switch networks, disconnect ethernet + + To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. Change From 148d7fe341bc509eb97af9660d9ee966eb08042c Mon Sep 17 00:00:00 2001 From: Ashwini Oruganti Date: Tue, 12 Oct 2021 15:06:57 -0700 Subject: [PATCH 6/8] Update the BroadcastQueue logic for runtime permissions Previously, we were skipping a broadcast when either the permission or the app op was granted. However, for runtime permissions to be considered "granted" both the permission and the app op need to be granted. This change updates taking this into account. Test: manual Bug: 202436287 Bug: 183537857 Change-Id: I9f12f9e17e61246d723d18ead93c6115bbf6d5cf Merged-In: I9f12f9e17e61246d723d18ead93c6115bbf6d5cf (cherry picked from commit 1e6a9681266986e1d8ceba55646199c02223c7b8) (cherry picked from commit 400ff61cff478ad0a2e79509aaa254d2341c5e3f) --- .../com/android/server/am/BroadcastQueue.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 503b3a93b31f8..94bf62f8b9b79 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1568,17 +1568,23 @@ public final class BroadcastQueue { perm = PackageManager.PERMISSION_DENIED; } - if (perm == PackageManager.PERMISSION_GRANTED) { - skip = true; - break; - } - int appOp = AppOpsManager.permissionToOpCode(excludedPermission); if (appOp != AppOpsManager.OP_NONE) { - if (mService.getAppOpsManager().checkOpNoThrow(appOp, + // When there is an app op associated with the permission, + // skip when both the permission and the app op are + // granted. + if ((perm == PackageManager.PERMISSION_GRANTED) && ( + mService.getAppOpsManager().checkOpNoThrow(appOp, info.activityInfo.applicationInfo.uid, info.activityInfo.packageName) - == AppOpsManager.MODE_ALLOWED) { + == AppOpsManager.MODE_ALLOWED)) { + skip = true; + break; + } + } else { + // When there is no app op associated with the permission, + // skip when permission is granted. + if (perm == PackageManager.PERMISSION_GRANTED) { skip = true; break; } From 7a42ab512f12d0a9821a4097aeb981faea325a87 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Thu, 14 Oct 2021 02:18:03 +0800 Subject: [PATCH 7/8] [RESTRICT AUTOMERGE] Add Wi-Fi Scanning notify to QS Internet Dialog - Show message when Wi-Fi is OFF and Wi-Fi Scanning is ON - Don't show message when device is locked - Show a "Change" link to launch Wi-Fi Scanning Settings Bug: 202323013 Test: manual test to verify on the device. atest -c InternetDialogControllerTest \ InternetDialogTest Change-Id: I5eb4563a69e85050532c8b4fe3748e01cc7d9ca5 (cherry picked from commit 8c0847b0fe8df54c35fe747220d2c76ffe8a59c7) --- .../layout/internet_connectivity_dialog.xml | 40 ++++++++++++++++ .../floatingmenu/AnnotationLinkSpan.java | 10 ++-- .../qs/tiles/dialog/InternetDialog.java | 26 ++++++++++ .../dialog/InternetDialogController.java | 9 ++++ .../qs/tiles/dialog/InternetDialogTest.java | 47 +++++++++++++++++++ 5 files changed, 127 insertions(+), 5 deletions(-) diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml index 918635d666faa..c88e95f07f122 100644 --- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -323,6 +323,46 @@ + + + + + + + + + + + mClickListener; private AnnotationLinkSpan(View.OnClickListener listener) { @@ -50,7 +50,7 @@ class AnnotationLinkSpan extends ClickableSpan { * @param linkInfos used to attach the click action into the corresponding span * @return the text attached with the span */ - static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) { + public static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) { final SpannableString msg = new SpannableString(text); final Annotation[] spans = msg.getSpans(/* queryStart= */ 0, msg.length(), Annotation.class); @@ -78,12 +78,12 @@ class AnnotationLinkSpan extends ClickableSpan { /** * Data class to store the annotation and the click action. */ - static class LinkInfo { - static final String DEFAULT_ANNOTATION = "link"; + public static class LinkInfo { + public static final String DEFAULT_ANNOTATION = "link"; private final Optional mAnnotation; private final Optional mListener; - LinkInfo(@NonNull String annotation, View.OnClickListener listener) { + public LinkInfo(@NonNull String annotation, View.OnClickListener listener) { mAnnotation = Optional.of(annotation); mListener = Optional.ofNullable(listener); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index dc54e1b52f2e1..dae357e9e36be 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -36,6 +36,7 @@ import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.text.Html; import android.text.TextUtils; +import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; @@ -63,6 +64,7 @@ import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -110,6 +112,8 @@ public class InternetDialog extends SystemUIDialog implements private LinearLayout mTurnWifiOnLayout; private LinearLayout mEthernetLayout; private TextView mWifiToggleTitleText; + private LinearLayout mWifiScanNotifyLayout; + private TextView mWifiScanNotifyText; private LinearLayout mSeeAllLayout; private RecyclerView mWifiRecyclerView; private ImageView mConnectedWifiIcon; @@ -220,6 +224,8 @@ public class InternetDialog extends SystemUIDialog implements mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout); mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout); mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title); + mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); + mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout); mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon); mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title); @@ -313,8 +319,10 @@ public class InternetDialog extends SystemUIDialog implements showProgressBar(); final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked(); final boolean isWifiEnabled = mWifiManager.isWifiEnabled(); + final boolean isWifiScanEnabled = mWifiManager.isScanAlwaysAvailable(); updateWifiToggle(isWifiEnabled, isDeviceLocked); updateConnectedWifi(isWifiEnabled, isDeviceLocked); + updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked); final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0) ? View.GONE : View.VISIBLE; @@ -411,6 +419,24 @@ public class InternetDialog extends SystemUIDialog implements mContext.getColor(R.color.connected_network_primary_color)); } + @MainThread + private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled, + boolean isDeviceLocked) { + if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) { + mWifiScanNotifyLayout.setVisibility(View.GONE); + return; + } + if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) { + final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo( + AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION, + v -> mInternetDialogController.launchWifiScanningSetting()); + mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify( + getContext().getText(R.string.wifi_scan_notify_message), linkInfo)); + mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance()); + } + mWifiScanNotifyLayout.setVisibility(View.VISIBLE); + } + void onClickConnectedWifi() { if (mConnectedWifiEntry == null) { return; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index aaba5efc92f67..276c0be530638 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -103,6 +103,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, private static final String TAG = "InternetDialogController"; private static final String ACTION_NETWORK_PROVIDER_SETTINGS = "android.settings.NETWORK_PROVIDER_SETTINGS"; + private static final String ACTION_WIFI_SCANNING_SETTINGS = + "android.settings.WIFI_SCANNING_SETTINGS"; private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key"; public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT); public static final int NO_CELL_DATA_TYPE_ICON = 0; @@ -603,6 +605,13 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, } } + void launchWifiScanningSetting() { + mCallback.dismissDialog(); + final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); + } + void connectCarrierNetwork() { final MergedCarrierEntry mergedCarrierEntry = mAccessPointController.getMergedCarrierEntry(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index c42b64a09985f..7cea430e146f5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import androidx.test.filters.SmallTest; @@ -73,6 +74,7 @@ public class InternetDialogTest extends SysuiTestCase { private LinearLayout mConnectedWifi; private RecyclerView mWifiList; private LinearLayout mSeeAll; + private LinearLayout mWifiScanNotify; @Before public void setUp() { @@ -104,6 +106,7 @@ public class InternetDialogTest extends SysuiTestCase { mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout); mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout); mSeeAll = mDialogView.requireViewById(R.id.see_all_layout); + mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); } @After @@ -263,6 +266,50 @@ public class InternetDialogTest extends SysuiTestCase { assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); } + @Test + public void updateDialog_wifiOn_hideWifiScanNotify() { + // The preconditions WiFi ON and Internet WiFi are already in setUp() + + mInternetDialog.updateDialog(); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false); + + mInternetDialog.updateDialog(); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true); + when(mInternetDialogController.isDeviceLocked()).thenReturn(true); + + mInternetDialog.updateDialog(); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() { + when(mWifiManager.isWifiEnabled()).thenReturn(false); + when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true); + when(mInternetDialogController.isDeviceLocked()).thenReturn(false); + + mInternetDialog.updateDialog(); + + assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE); + TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text); + assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0); + assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull(); + } + @Test public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() { mSeeAll.performClick(); From 43d9106a2c916ce8587b3b3b5006d3762511bf2d Mon Sep 17 00:00:00 2001 From: Tyler Gunn Date: Wed, 27 Oct 2021 14:24:49 -0700 Subject: [PATCH 8/8] Add config to detect e-call call based on dialed sim emerg # list. We normally use the combined emergency number list from the emergency number lists of both sims when placing emergency calls, with the provision that the routing may be unspecified if a dialed number is an emergency number on one sim but not the other. This config allows a carrier to mandate that calls are only treated as an emergency call on their network based on their own emergency number list. Test: TBD Bug: 203947159 Change-Id: Id5cd4123f1bb7bdd85e564fc6997dfbc50652a5f (cherry picked from commit 11dd6452d6621328b0bd430eeebacb55fd478cf3) --- .../android/telephony/CarrierConfigManager.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 68ef7543c33fe..45fd7a3467c40 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -962,6 +962,21 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool"; + /** + * When {@code true}, the determination of whether to place a call as an emergency call will be + * based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which + * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * it will not be treated as an emergency call in this case. + * When {@code false}, the determination is based on the emergency numbers from all device SIMs, + * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * the call will be dialed as an emergency number, but with an unspecified routing. + * @hide + */ + public static final String KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL = + "use_only_dialed_sim_ecc_list_bool"; + /** * When IMS instant lettering is available for a carrier (see * {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters @@ -5230,6 +5245,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true); + sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");