diff options
author | Xin Li <delphij@google.com> | 2023-12-07 15:54:29 -0800 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2023-12-07 15:54:29 -0800 |
commit | 5da189e0a77b4cd3dd6d3e43e41fc6e35ee471e9 (patch) | |
tree | 933c599eff794a7bf16b3669fddf282779ac0f22 | |
parent | 6ffb03a3238a6eeef95e0ef42aa6320cc661ad11 (diff) | |
parent | 6ff78c3641350f2daf37de18e45dbc3e34c96686 (diff) | |
download | base-5da189e0a77b4cd3dd6d3e43e41fc6e35ee471e9.tar.gz |
Merge UQ1A.231205.015
Bug: 308969284
Merged-In: I64897baeaa0b5d81c904d75f2b1e17c0eefec3bf
Change-Id: I455d7c3e6ae8dd9d7618410843ed4b488289ac41
15 files changed, 221 insertions, 49 deletions
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index d2a16a3a9212..61f340a856c4 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -29,6 +29,7 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_OPEN; @@ -361,6 +362,15 @@ public final class TransitionInfo implements Parcelable { } /** + * Whether this transition contains any changes to the window hierarchy, + * including keyguard visibility. + */ + public boolean hasChangesOrSideEffects() { + return !mChanges.isEmpty() || isKeyguardGoingAway() + || (mFlags & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0; + } + + /** * Whether this transition includes keyguard going away. */ public boolean isKeyguardGoingAway() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 3b1801b8d821..c95c9f099f20 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -23,6 +23,7 @@ import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVIT import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT; import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.RemoteAnimationTarget.MODE_OPENING; @@ -392,6 +393,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mMainStage.isActive(); } + /** @return whether this transition-request has the launch-adjacent flag. */ + public boolean requestHasLaunchAdjacentFlag(TransitionRequestInfo request) { + final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask(); + return triggerTask != null && triggerTask.baseIntent != null + && (triggerTask.baseIntent.getFlags() & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0; + } + /** @return whether the transition-request implies entering pip from split. */ public boolean requestImpliesSplitToPip(TransitionRequestInfo request) { if (!isSplitActive() || !mMixedHandler.requestHasPipEnter(request)) { @@ -2434,10 +2442,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP); } - // When split in the background, it should be only opening/dismissing transition and - // would keep out not empty. Prevent intercepting all transitions for split screen when - // it is in the background and not identify to handle it. - return (!out.isEmpty() || isSplitScreenVisible()) ? out : null; + if (!out.isEmpty()) { + // One of the cases above handled it + return out; + } else if (isSplitScreenVisible()) { + // If split is visible, only defer handling this transition if it's launching + // adjacent while there is already a split pair -- this may trigger PIP and + // that should be handled by the mixed handler. + final boolean deferTransition = requestHasLaunchAdjacentFlag(request) + && mMainStage.getChildCount() != 0 && mSideStage.getChildCount() != 0; + return !deferTransition ? out : null; + } + // Don't intercept the transition if we are not handling it as a part of one of the + // cases above and it is not already visible + return null; } else { if (isOpening && getStageOfTask(triggerTask) != null) { // One task is appearing into split, prepare to enter split screen. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java index 87c438a5b37d..ba0ef20c412e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java @@ -19,13 +19,12 @@ package com.android.wm.shell.transition; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.IBinder; +import android.util.Slog; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; -import java.util.ArrayList; - /** * A Simple handler that tracks SLEEP transitions. We track them specially since we (ab)use these * as sentinels for fast-forwarding through animations when the screen is off. @@ -34,30 +33,25 @@ import java.util.ArrayList; * don't register it like a normal handler. */ class SleepHandler implements Transitions.TransitionHandler { - final ArrayList<IBinder> mSleepTransitions = new ArrayList<>(); - @Override public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - mSleepTransitions.remove(transition); - startTransaction.apply(); - finishCallback.onTransitionFinished(null); - return true; + if (info.hasChangesOrSideEffects()) { + Slog.e(Transitions.TAG, "Real changes included in a SLEEP transition"); + return false; + } else { + startTransaction.apply(); + finishCallback.onTransitionFinished(null); + return true; + } } @Override @Nullable public WindowContainerTransaction handleRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { - mSleepTransitions.add(transition); return new WindowContainerTransaction(); } - - @Override - public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted, - @Nullable SurfaceControl.Transaction finishTransaction) { - mSleepTransitions.remove(transition); - } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index 99a1ac663286..b32e0d6b4b39 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -1152,7 +1152,7 @@ public class ShellTransitionTests extends ShellTestCase { } @Test - public void testEmptyTransitionStillReportsKeyguardGoingAway() { + public void testEmptyTransition_withKeyguardGoingAway_plays() { Transitions transitions = createTestTransitions(); transitions.replaceDefaultHandlerForTest(mDefaultHandler); @@ -1171,6 +1171,65 @@ public class ShellTransitionTests extends ShellTestCase { } @Test + public void testSleepTransition_withKeyguardGoingAway_plays(){ + Transitions transitions = createTestTransitions(); + transitions.replaceDefaultHandlerForTest(mDefaultHandler); + + IBinder transitToken = new Binder(); + transitions.requestStartTransition(transitToken, + new TransitionRequestInfo(TRANSIT_SLEEP, null /* trigger */, null /* remote */)); + + // Make a no-op transition + TransitionInfo info = new TransitionInfoBuilder( + TRANSIT_SLEEP, TRANSIT_FLAG_KEYGUARD_GOING_AWAY, true /* noOp */).build(); + transitions.onTransitionReady(transitToken, info, new StubTransaction(), + new StubTransaction()); + + // If keyguard-going-away flag set, then it shouldn't be aborted. + assertEquals(1, mDefaultHandler.activeCount()); + } + + @Test + public void testSleepTransition_withChanges_plays(){ + Transitions transitions = createTestTransitions(); + transitions.replaceDefaultHandlerForTest(mDefaultHandler); + + IBinder transitToken = new Binder(); + transitions.requestStartTransition(transitToken, + new TransitionRequestInfo(TRANSIT_SLEEP, null /* trigger */, null /* remote */)); + + // Make a transition with some changes + TransitionInfo info = new TransitionInfoBuilder(TRANSIT_SLEEP) + .addChange(TRANSIT_OPEN).build(); + info.setTrack(0); + transitions.onTransitionReady(transitToken, info, new StubTransaction(), + new StubTransaction()); + + // If there is an actual change, then it shouldn't be aborted. + assertEquals(1, mDefaultHandler.activeCount()); + } + + + @Test + public void testSleepTransition_empty_SyncBySleepHandler() { + Transitions transitions = createTestTransitions(); + transitions.replaceDefaultHandlerForTest(mDefaultHandler); + + IBinder transitToken = new Binder(); + transitions.requestStartTransition(transitToken, + new TransitionRequestInfo(TRANSIT_SLEEP, null /* trigger */, null /* remote */)); + + // Make a no-op transition + TransitionInfo info = new TransitionInfoBuilder( + TRANSIT_SLEEP, 0x0, true /* noOp */).build(); + transitions.onTransitionReady(transitToken, info, new StubTransaction(), + new StubTransaction()); + + // If there is nothing to actually play, it should not be offered to handlers. + assertEquals(0, mDefaultHandler.activeCount()); + } + + @Test public void testMultipleTracks() { Transitions transitions = createTestTransitions(); transitions.replaceDefaultHandlerForTest(mDefaultHandler); diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index ddd9463affd9..9a5f43b0d6f3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -554,6 +554,12 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { if (shouldNotRunAnimation(tilesToReveal)) { return; } + // This method has side effects (beings the fake drag, if it returns true). If we have + // decided that we want to do a tile reveal, we do a last check to verify that we can + // actually perform a fake drag. + if (!beginFakeDrag()) { + return; + } final int lastPageNumber = mPages.size() - 1; final TileLayout lastPage = mPages.get(lastPageNumber); @@ -588,8 +594,10 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } private boolean shouldNotRunAnimation(Set<String> tilesToReveal) { + // None of these have side effects. That way, we don't need to rely on short-circuiting + // behavior boolean noAnimationNeeded = tilesToReveal.isEmpty() || mPages.size() < 2; - boolean scrollingInProgress = getScrollX() != 0 || !beginFakeDrag(); + boolean scrollingInProgress = getScrollX() != 0 || !isFakeDragging(); // isRunningInTestHarness() to disable animation in functional testing as it caused // flakiness and is not needed there. Alternative solutions were more complex and would // still be either potentially flaky or modify internal data. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 8e7d27795c07..2519f4e7f3e3 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -388,11 +388,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo @Override public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent, int policyFlags) { + if (!mInstalled) { + Slog.w(TAG, "onMotionEvent called before input filter installed!"); + return; + } sendInputEvent(transformedEvent, policyFlags); } @Override public void onKeyEvent(KeyEvent event, int policyFlags) { + if (!mInstalled) { + Slog.w(TAG, "onKeyEvent called before input filter installed!"); + return; + } sendInputEvent(event, policyFlags); } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 423b85f9305f..4688658bf1c3 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -56,7 +56,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; - private FillServiceCallbacks mCallbacks; + private final FillServiceCallbacks mCallbacks; private final Object mLock = new Object(); private CompletableFuture<FillResponse> mPendingFillRequest; private int mPendingFillRequestId = INVALID_REQUEST_ID; @@ -128,12 +128,9 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { */ public int cancelCurrentRequest() { synchronized (mLock) { - int canceledRequestId = mPendingFillRequest != null && mPendingFillRequest.cancel(false) + return mPendingFillRequest != null && mPendingFillRequest.cancel(false) ? mPendingFillRequestId : INVALID_REQUEST_ID; - mPendingFillRequest = null; - mPendingFillRequestId = INVALID_REQUEST_ID; - return canceledRequestId; } } @@ -187,10 +184,6 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { mPendingFillRequest = null; mPendingFillRequestId = INVALID_REQUEST_ID; } - if (mCallbacks == null) { - Slog.w(TAG, "Error calling RemoteFillService - service already unbound"); - return; - } if (err == null) { mCallbacks.onFillRequestSuccess(request.getId(), res, mComponentName.getPackageName(), request.getFlags()); @@ -227,10 +220,6 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { return save; }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> Handler.getMain().post(() -> { - if (mCallbacks == null) { - Slog.w(TAG, "Error calling RemoteFillService - service already unbound"); - return; - } if (err == null) { mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName(), res); } else { @@ -245,8 +234,6 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { } public void destroy() { - cancelCurrentRequest(); unbind(); - mCallbacks = null; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f594caeecd14..9555ddc69932 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -561,7 +561,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int PROC_START_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait for a launched process to complete its app startup before we ANR. - static final int BIND_APPLICATION_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; + static final int BIND_APPLICATION_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // How long we wait to kill an application zygote, after the last process using // it has gone away. diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 6466b440b3a0..bc7e15635035 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2868,7 +2868,16 @@ public final class DisplayManagerService extends SystemService { // Check if the target app is in cached mode private boolean isUidCached(int uid) { - if (mActivityManagerInternal == null) { + // Only query procState and importance for Android apps, which have UIDs starting + // from FIRST_APPLICATION_UID. . + // + // Other processes with UID < FIRST_APPLICATION_UID can also register to DMS for + // display events. E.g. Android Studio executes a screen sharing process to provide + // display mirroring functionality. That process inherits the UID of adb. Depending + // on adb mode, it can be shell (2000) or root (0). Those processes are not Android + // apps and not managed by AMS. Treat them as non-cached so never ignore or defer + // display events to them. + if (mActivityManagerInternal == null || uid < FIRST_APPLICATION_UID) { return false; } int procState = mActivityManagerInternal.getUidProcessState(uid); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 81c4dcdd5f52..634138c5c2cc 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -3951,7 +3951,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (wallpaper == null) { // common case, this is the first lookup post-boot of the system or // unified lock, so we bring up the saved state lazily now and recheck. - int whichLoad = (which == FLAG_LOCK) ? FLAG_LOCK : FLAG_SYSTEM; + // if we're loading the system wallpaper for the first time, also load the lock + // wallpaper to determine if the system wallpaper is system+lock or system only. + int whichLoad = (which == FLAG_LOCK) ? FLAG_LOCK : FLAG_SYSTEM | FLAG_LOCK; loadSettingsLocked(userId, false, whichLoad); wallpaper = whichSet.get(userId); if (wallpaper == null) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 241ccbc2e227..833c29aeacc7 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1162,7 +1162,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this); mDisplaySwitchTransitionLauncher = new PhysicalDisplaySwitchTransitionLauncher(this, mTransitionController); - mRemoteDisplayChangeController = new RemoteDisplayChangeController(mWmService, mDisplayId); + mRemoteDisplayChangeController = new RemoteDisplayChangeController(this); final InputChannel inputChannel = mWmService.mInputManager.monitorInput( "PointerEventDispatcher" + mDisplayId, mDisplayId); diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java index e646f14a3e13..267c7d4065c7 100644 --- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java +++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java @@ -26,6 +26,7 @@ import android.view.IDisplayChangeWindowCallback; import android.window.DisplayAreaInfo; import android.window.WindowContainerTransaction; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import java.util.ArrayList; @@ -44,16 +45,16 @@ public class RemoteDisplayChangeController { private static final int REMOTE_DISPLAY_CHANGE_TIMEOUT_MS = 800; private final WindowManagerService mService; - private final int mDisplayId; + private final DisplayContent mDisplayContent; private final Runnable mTimeoutRunnable = this::onContinueTimedOut; // all remote changes that haven't finished yet. private final List<ContinueRemoteDisplayChangeCallback> mCallbacks = new ArrayList<>(); - public RemoteDisplayChangeController(WindowManagerService service, int displayId) { - mService = service; - mDisplayId = displayId; + RemoteDisplayChangeController(@NonNull DisplayContent displayContent) { + mService = displayContent.mWmService; + mDisplayContent = displayContent; } /** @@ -99,8 +100,8 @@ public class RemoteDisplayChangeController { try { mService.mH.removeCallbacks(mTimeoutRunnable); mService.mH.postDelayed(mTimeoutRunnable, REMOTE_DISPLAY_CHANGE_TIMEOUT_MS); - mService.mDisplayChangeController.onDisplayChange(mDisplayId, fromRotation, toRotation, - newDisplayAreaInfo, remoteCallback); + mService.mDisplayChangeController.onDisplayChange(mDisplayContent.mDisplayId, + fromRotation, toRotation, newDisplayAreaInfo, remoteCallback); return true; } catch (RemoteException e) { Slog.e(TAG, "Exception while dispatching remote display-change", e); @@ -123,10 +124,23 @@ public class RemoteDisplayChangeController { } callback.onContinueRemoteDisplayChange(null /* transaction */); } + onCompleted(); } } - private void continueDisplayChange(@NonNull ContinueRemoteDisplayChangeCallback callback, + /** Called when all remote callbacks are done. */ + private void onCompleted() { + // Because DisplayContent#sendNewConfiguration() will be skipped if there are pending remote + // changes, check again when all remote callbacks are done. E.g. callback X is done but + // there is a pending callback Y so its invocation is skipped, and when the callback Y is + // done, it doesn't call sendNewConfiguration(). + if (mDisplayContent.mWaitingForConfig) { + mDisplayContent.sendNewConfiguration(); + } + } + + @VisibleForTesting + void continueDisplayChange(@NonNull ContinueRemoteDisplayChangeCallback callback, @Nullable WindowContainerTransaction transaction) { synchronized (mService.mGlobalLock) { int idx = mCallbacks.indexOf(callback); @@ -139,11 +153,16 @@ public class RemoteDisplayChangeController { // ordering by continuing everything up until this one with empty transactions. mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */); } + // The "toIndex" is exclusive, so it needs +1 to clear the current calling callback. mCallbacks.subList(0, idx + 1).clear(); - if (mCallbacks.isEmpty()) { + final boolean completed = mCallbacks.isEmpty(); + if (completed) { mService.mH.removeCallbacks(mTimeoutRunnable); } callback.onContinueRemoteDisplayChange(transaction); + if (completed) { + onCompleted(); + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 795f4fd49783..2c3f846e6785 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -6509,7 +6509,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { KeyChain.bindAsUser(mContext, userHandle)) { IKeyChainService keyChain = keyChainConnection.getService(); return keyChain.setGrant(granteeUid, alias, hasGrant); - } catch (RemoteException e) { + } catch (RemoteException | AssertionError e) { Slogf.e(LOG_TAG, "Setting grant for package.", e); return false; } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 9b22efdae7da..89fc65a54ab3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -144,6 +144,7 @@ import android.window.DisplayAreaInfo; import android.window.IDisplayAreaOrganizer; import android.window.ScreenCapture; import android.window.WindowContainerToken; +import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; @@ -2013,6 +2014,53 @@ public class DisplayContentTests extends WindowTestsBase { } @Test + public void testRemoteDisplayChange() { + mWm.mDisplayChangeController = mock(IDisplayChangeWindowController.class); + final Boolean[] isWaitingForRemote = new Boolean[2]; + final var callbacks = new RemoteDisplayChangeController.ContinueRemoteDisplayChangeCallback[ + isWaitingForRemote.length]; + for (int i = 0; i < isWaitingForRemote.length; i++) { + final int index = i; + var callback = new RemoteDisplayChangeController.ContinueRemoteDisplayChangeCallback() { + @Override + public void onContinueRemoteDisplayChange(WindowContainerTransaction transaction) { + isWaitingForRemote[index] = + mDisplayContent.mRemoteDisplayChangeController + .isWaitingForRemoteDisplayChange(); + } + }; + mDisplayContent.mRemoteDisplayChangeController.performRemoteDisplayChange( + ROTATION_0, ROTATION_0, null /* newDisplayAreaInfo */, callback); + callbacks[i] = callback; + } + + // The last callback is completed, all callbacks should be notified. + mDisplayContent.mRemoteDisplayChangeController.continueDisplayChange(callbacks[1], + null /* transaction */); + // When notifying 0, the callback 1 still exists. + assertTrue(isWaitingForRemote[0]); + assertFalse(isWaitingForRemote[1]); + + // The first callback is completed, other callbacks after it should remain. + for (int i = 0; i < isWaitingForRemote.length; i++) { + isWaitingForRemote[i] = null; + mDisplayContent.mRemoteDisplayChangeController.performRemoteDisplayChange( + ROTATION_0, ROTATION_0, null /* newDisplayAreaInfo */, callbacks[i]); + } + mDisplayContent.mRemoteDisplayChangeController.continueDisplayChange(callbacks[0], + null /* transaction */); + assertTrue(isWaitingForRemote[0]); + assertNull(isWaitingForRemote[1]); + + // Complete the last callback. It should be able to consume pending config change. + mDisplayContent.mWaitingForConfig = true; + mDisplayContent.mRemoteDisplayChangeController.continueDisplayChange(callbacks[1], + null /* transaction */); + assertFalse(isWaitingForRemote[1]); + assertFalse(mDisplayContent.mWaitingForConfig); + } + + @Test public void testShellTransitRotation() { DisplayContent dc = createNewDisplay(); dc.setLastHasContent(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index bafa0d336054..7d9160a1c506 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1049,6 +1049,14 @@ public class CarrierConfigManager { "carrier_use_ims_first_for_emergency_bool"; /** + * When {@code true}, this carrier will preferentially dial normal routed emergency calls over + * an in-service SIM if one is available. + * @hide + */ + public static final String KEY_PREFER_IN_SERVICE_SIM_FOR_NORMAL_ROUTED_EMERGENCY_CALLS_BOOL = + "prefer_in_service_sim_for_normal_routed_emergency_calls_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 @@ -9858,6 +9866,8 @@ 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_PREFER_IN_SERVICE_SIM_FOR_NORMAL_ROUTED_EMERGENCY_CALLS_BOOL, + false); 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, ""); |