summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2023-12-07 15:54:29 -0800
committerXin Li <delphij@google.com>2023-12-07 15:54:29 -0800
commit5da189e0a77b4cd3dd6d3e43e41fc6e35ee471e9 (patch)
tree933c599eff794a7bf16b3669fddf282779ac0f22
parent6ffb03a3238a6eeef95e0ef42aa6320cc661ad11 (diff)
parent6ff78c3641350f2daf37de18e45dbc3e34c96686 (diff)
downloadbase-5da189e0a77b4cd3dd6d3e43e41fc6e35ee471e9.tar.gz
Merge UQ1A.231205.015
Bug: 308969284 Merged-In: I64897baeaa0b5d81c904d75f2b1e17c0eefec3bf Change-Id: I455d7c3e6ae8dd9d7618410843ed4b488289ac41
-rw-r--r--core/java/android/window/TransitionInfo.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java26
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java24
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java10
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java8
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java17
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java11
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/RemoteDisplayChangeController.java35
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java48
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java10
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, "");