summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java12
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java3
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml8
-rw-r--r--media/java/android/media/projection/MediaProjection.java11
-rw-r--r--media/jni/android_media_ImageWriter.cpp14
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt19
14 files changed, 234 insertions, 53 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fe3d4f6b39bf..07efad89010a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4380,7 +4380,7 @@
modes dimensions {@link config_minPercentageMultiWindowSupportWidth} the device
supports to determine if the activity can be shown in multi windowing modes.
-->
- <integer name="config_respectsActivityMinWidthHeightMultiWindow">0</integer>
+ <integer name="config_respectsActivityMinWidthHeightMultiWindow">-1</integer>
<!-- This value is only used when the device checks activity min height to determine if it
can be shown in multi windowing modes.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 74cce68f270b..dcc2d93060c9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -377,8 +377,16 @@ class TaskContainer {
@Nullable
TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
- return getContainer(container -> container.hasAppearedActivity(activityToken)
- || container.hasPendingAppearedActivity(activityToken));
+ // When the new activity is launched to the topmost TF because the source activity
+ // was in that TF, and the source activity is finished before resolving the new activity,
+ // we will try to see if the new activity match a rule with the split activities below.
+ // If matched, it can be reparented.
+ final TaskFragmentContainer taskFragmentContainer
+ = getContainer(container -> container.hasPendingAppearedActivity(activityToken));
+ if (taskFragmentContainer != null) {
+ return taskFragmentContainer;
+ }
+ return getContainer(container -> container.hasAppearedActivity(activityToken));
}
@Nullable
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 7fab371cb790..bc4916a607a3 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -535,7 +535,8 @@ public class TaskFragmentContainerTest {
// container1.
container2.setInfo(mTransaction, mInfo);
- assertTrue(container2.hasActivity(mActivity.getActivityToken()));
+ assertTrue(container1.hasActivity(mActivity.getActivityToken()));
+ assertFalse(container2.hasActivity(mActivity.getActivityToken()));
// When the pending appeared record is removed from container1, we respect the appeared
// record in container2.
container1.removePendingAppearedActivity(mActivity.getActivityToken());
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index 045b975a854e..462a49ccb1eb 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -99,11 +99,11 @@
</LinearLayout>
- <FrameLayout
+
+ <LinearLayout
android:minHeight="@dimen/letterbox_restart_dialog_button_height"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="?android:attr/buttonBarButtonStyle"
android:layout_gravity="end">
<Button
@@ -133,7 +133,7 @@
android:text="@string/letterbox_restart_restart"
android:contentDescription="@string/letterbox_restart_restart"/>
- </FrameLayout>
+ </LinearLayout>
</LinearLayout>
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 31f89960836b..ef4c3ef0d321 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -16,6 +16,8 @@
package android.media.projection;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
@@ -29,6 +31,7 @@ import android.hardware.display.VirtualDisplayConfig;
import android.os.Build;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -70,6 +73,7 @@ public final class MediaProjection {
private final DisplayManager mDisplayManager;
@NonNull
private final Map<Callback, CallbackRecord> mCallbacks = new ArrayMap<>();
+ private final int mDisplayId;
/** @hide */
public MediaProjection(Context context, IMediaProjection impl) {
@@ -88,6 +92,11 @@ public final class MediaProjection {
throw new RuntimeException("Failed to start media projection", e);
}
mDisplayManager = displayManager;
+
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ mDisplayId = userManager.isVisibleBackgroundUsersSupported()
+ ? userManager.getMainDisplayIdAssignedToUser()
+ : DEFAULT_DISPLAY;
}
/**
@@ -156,6 +165,7 @@ public final class MediaProjection {
if (surface != null) {
builder.setSurface(surface);
}
+ builder.setDisplayIdToMirror(mDisplayId);
return createVirtualDisplay(builder, callback, handler);
}
@@ -234,6 +244,7 @@ public final class MediaProjection {
if (surface != null) {
builder.setSurface(surface);
}
+ builder.setDisplayIdToMirror(mDisplayId);
return createVirtualDisplay(builder, callback, handler);
}
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 6776f611559c..33650d91e6a3 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -735,10 +735,15 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j
}
static status_t attachAndQeueuGraphicBuffer(JNIEnv* env, JNIImageWriterContext *ctx,
- sp<Surface> surface, sp<GraphicBuffer> gb, jlong timestampNs, jint dataSpace,
+ sp<GraphicBuffer> gb, jlong timestampNs, jint dataSpace,
jint left, jint top, jint right, jint bottom, jint transform, jint scalingMode) {
status_t res = OK;
// Step 1. Attach Image
+ sp<Surface> surface = ctx->getProducer();
+ if (surface == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Producer surface is null, ImageWriter seems already closed");
+ }
res = surface->attachBuffer(gb.get());
if (res != OK) {
ALOGE("Attach image failed: %s (%d)", strerror(-res), res);
@@ -835,7 +840,6 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
return -1;
}
- sp<Surface> surface = ctx->getProducer();
if (isFormatOpaque(ctx->getBufferFormat()) != isFormatOpaque(nativeHalFormat)) {
jniThrowException(env, "java/lang/IllegalStateException",
"Trying to attach an opaque image into a non-opaque ImageWriter, or vice versa");
@@ -851,7 +855,7 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
return -1;
}
- return attachAndQeueuGraphicBuffer(env, ctx, surface, buffer->mGraphicBuffer, timestampNs,
+ return attachAndQeueuGraphicBuffer(env, ctx, buffer->mGraphicBuffer, timestampNs,
dataSpace, left, top, right, bottom, transform, scalingMode);
}
@@ -866,7 +870,6 @@ static jint ImageWriter_attachAndQueueGraphicBuffer(JNIEnv* env, jobject thiz, j
return -1;
}
- sp<Surface> surface = ctx->getProducer();
if (isFormatOpaque(ctx->getBufferFormat()) != isFormatOpaque(nativeHalFormat)) {
jniThrowException(env, "java/lang/IllegalStateException",
"Trying to attach an opaque image into a non-opaque ImageWriter, or vice versa");
@@ -880,7 +883,8 @@ static jint ImageWriter_attachAndQueueGraphicBuffer(JNIEnv* env, jobject thiz, j
"Trying to attach an invalid graphic buffer");
return -1;
}
- return attachAndQeueuGraphicBuffer(env, ctx, surface, graphicBuffer, timestampNs,
+
+ return attachAndQeueuGraphicBuffer(env, ctx, graphicBuffer, timestampNs,
dataSpace, left, top, right, bottom, transform, scalingMode);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
index 1ec78742f0dd..4d81317b7755 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.StatusBarState.KEYGUARD
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat as assertThatRepository
@@ -81,7 +82,7 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() {
assertThat(values)
.containsExactly(
- null, // LOCKSCREEN -> AOD does not have any specific surface visibility.
+ null // LOCKSCREEN -> AOD does not have any specific surface visibility.
)
transitionRepository.sendTransitionStep(
@@ -118,6 +119,53 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() {
}
@Test
+ fun draggingToPrimaryBouncerUpdateIsSent() =
+ testScope.runTest {
+ underTest.start()
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.OFF,
+ to = KeyguardState.LOCKSCREEN,
+ testScope,
+ )
+
+ val steps by collectValues(transitionRepository.transitions)
+
+ shadeRepository.setLegacyShadeExpansion(0f)
+ shadeRepository.setLegacyShadeTracking(true)
+ keyguardRepository.setKeyguardDismissible(false)
+ keyguardRepository.setStatusBarState(KEYGUARD)
+ runCurrent()
+
+ // User starts dragging up
+ shadeRepository.setLegacyShadeExpansion(0.1f)
+ runCurrent()
+
+ assertThatRepository(transitionRepository)
+ .startedTransition(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ )
+
+ // FakeKeyguardRepository doesn't send the step, so do that
+ transitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.PRIMARY_BOUNCER,
+ value = 0f,
+ )
+ )
+ runCurrent()
+
+ // Update is sent
+ shadeRepository.setLegacyShadeExpansion(0.2f)
+ runCurrent()
+
+ assertThatRepository(transitionRepository)
+ .updatedTransition(value = 1f, state = TransitionState.RUNNING)
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
fun testTransitionsToGone_whenDismissFlingWhileDismissable_flagEnabled() =
testScope.runTest {
@@ -132,10 +180,7 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() {
runCurrent()
assertThatRepository(transitionRepository)
- .startedTransition(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- )
+ .startedTransition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE)
}
@Test
@@ -184,15 +229,12 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() {
true,
ActivityManager.RunningTaskInfo().apply {
topActivityType = WindowConfiguration.ACTIVITY_TYPE_STANDARD
- }
+ },
)
runCurrent()
assertThatRepository(transitionRepository)
- .startedTransition(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.OCCLUDED,
- )
+ .startedTransition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.OCCLUDED)
}
@Test
@@ -207,14 +249,11 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() {
true,
ActivityManager.RunningTaskInfo().apply {
topActivityType = WindowConfiguration.ACTIVITY_TYPE_DREAM
- }
+ },
)
runCurrent()
assertThatRepository(transitionRepository)
- .startedTransition(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.DREAMING,
- )
+ .startedTransition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
index 76df9c96c801..fb00d6e16dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -75,6 +75,9 @@ import javax.inject.Named;
* touches are consumed.
*/
public class TouchMonitor {
+ // An incrementing id used to identify the touch monitor instance.
+ private static int sNextInstanceId = 0;
+
private final Logger mLogger;
// This executor is used to protect {@code mActiveTouchSessions} from being modified
// concurrently. Any operation that adds or removes values should use this executor.
@@ -138,7 +141,7 @@ public class TouchMonitor {
completer.set(predecessor);
}
- if (mActiveTouchSessions.isEmpty()) {
+ if (mActiveTouchSessions.isEmpty() && mInitialized) {
if (mStopMonitoringPending) {
stopMonitoring(false);
} else {
@@ -271,7 +274,7 @@ public class TouchMonitor {
@Override
public void onDestroy(LifecycleOwner owner) {
- stopMonitoring(true);
+ destroy();
}
};
@@ -279,6 +282,11 @@ public class TouchMonitor {
* When invoked, instantiates a new {@link InputSession} to monitor touch events.
*/
private void startMonitoring() {
+ if (!mInitialized) {
+ mLogger.w("attempting to startMonitoring when not initialized");
+ return;
+ }
+
mLogger.i("startMonitoring(): monitoring started");
stopMonitoring(true);
@@ -587,7 +595,7 @@ public class TouchMonitor {
mDisplayHelper = displayHelper;
mWindowManagerService = windowManagerService;
mConfigurationInteractor = configurationInteractor;
- mLoggingName = loggingName + ":TouchMonitor";
+ mLoggingName = loggingName + ":TouchMonitor[" + sNextInstanceId++ + "]";
mLogger = new Logger(logBuffer, mLoggingName);
}
@@ -613,7 +621,8 @@ public class TouchMonitor {
*/
public void destroy() {
if (!mInitialized) {
- throw new IllegalStateException("TouchMonitor not initialized");
+ // In the case that we've already been destroyed, this is a no-op
+ return;
}
stopMonitoring(true);
diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt b/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt
index ec0322736f4b..cafa74faf1a1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt
@@ -26,6 +26,7 @@ import com.android.systemui.communal.widgets.CommunalAppWidgetHost
import com.android.systemui.communal.widgets.CommunalAppWidgetHostView
import com.android.systemui.communal.widgets.WidgetInteractionHandler
import com.android.systemui.dagger.qualifiers.UiBackground
+import java.util.concurrent.Executor
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
@@ -34,6 +35,7 @@ class WidgetViewFactory
@Inject
constructor(
@UiBackground private val uiBgContext: CoroutineContext,
+ @UiBackground private val uiBgExecutor: Executor,
private val appWidgetHost: CommunalAppWidgetHost,
private val interactionHandler: WidgetInteractionHandler,
private val listenerFactory: AppWidgetHostListenerDelegate.Factory,
@@ -44,8 +46,11 @@ constructor(
size: SizeF,
): CommunalAppWidgetHostView =
withContext("$TAG#createWidget", uiBgContext) {
- val view = CommunalAppWidgetHostView(context, interactionHandler)
- view.setAppWidget(model.appWidgetId, model.providerInfo)
+ val view =
+ CommunalAppWidgetHostView(context, interactionHandler).apply {
+ setExecutor(uiBgExecutor)
+ setAppWidget(model.appWidgetId, model.providerInfo)
+ }
// Instead of setting the view as the listener directly, we wrap the view in a delegate
// which ensures the callbacks always get called on the main thread.
appWidgetHost.setListener(model.appWidgetId, listenerFactory.create(view))
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index cd5daf9a99f0..1e9541e1923e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -210,13 +210,18 @@ constructor(
} else {
TransitionState.RUNNING
}
- transitionRepository.updateTransition(
- id,
- // This maps the shadeExpansion to a much faster curve, to match
- // the existing logic
- 1f - MathUtils.constrainedMap(0f, 1f, 0.95f, 1f, shadeExpansion),
- nextState,
- )
+
+ // startTransition below will issue the CANCELED directly
+ if (nextState != TransitionState.CANCELED) {
+ transitionRepository.updateTransition(
+ id,
+ // This maps the shadeExpansion to a much faster curve, to match
+ // the existing logic
+ 1f -
+ MathUtils.constrainedMap(0f, 1f, 0.95f, 1f, shadeExpansion),
+ nextState,
+ )
+ }
if (
nextState == TransitionState.CANCELED ||
@@ -234,11 +239,12 @@ constructor(
ownerName = name,
from = KeyguardState.PRIMARY_BOUNCER,
to = KeyguardState.LOCKSCREEN,
+ modeOnCanceled = TransitionModeOnCanceled.REVERSE,
animator =
getDefaultAnimatorForTransitionsToState(
KeyguardState.LOCKSCREEN
)
- .apply { duration = 0 },
+ .apply { duration = 100L },
)
)
}
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 5ea9e6ae0a70..301ab2bcdd65 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
@@ -311,10 +311,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi
mConfig = MobileMappings.Config.readConfig(mContext);
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
mSubIdTelephonyManagerMap.put(mDefaultDataSubId, mTelephonyManager);
- InternetTelephonyCallback telephonyCallback =
- new InternetTelephonyCallback(mDefaultDataSubId);
- mSubIdTelephonyCallbackMap.put(mDefaultDataSubId, telephonyCallback);
- mTelephonyManager.registerTelephonyCallback(mExecutor, telephonyCallback);
+ registerInternetTelephonyCallback(mTelephonyManager, mDefaultDataSubId);
// Listen the connectivity changes
mConnectivityManager.registerDefaultNetworkCallback(mConnectivityManagerNetworkCallback);
mCanConfigWifi = canConfigWifi;
@@ -346,6 +343,23 @@ public class InternetDialogController implements AccessPointController.AccessPoi
mCallback = null;
}
+ /**
+ * This is to generate and register the new callback to Telephony for uncached subscription id,
+ * then cache it. Telephony also cached this callback into
+ * {@link com.android.server.TelephonyRegistry}, so if subscription id and callback were cached
+ * already, it shall do nothing to avoid registering redundant callback to Telephony.
+ */
+ private void registerInternetTelephonyCallback(
+ TelephonyManager telephonyManager, int subId) {
+ if (mSubIdTelephonyCallbackMap.containsKey(subId)) {
+ // Avoid to generate and register unnecessary callback to Telephony.
+ return;
+ }
+ InternetTelephonyCallback telephonyCallback = new InternetTelephonyCallback(subId);
+ mSubIdTelephonyCallbackMap.put(subId, telephonyCallback);
+ telephonyManager.registerTelephonyCallback(mExecutor, telephonyCallback);
+ }
+
boolean isAirplaneModeEnabled() {
return mGlobalSettings.getInt(Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
@@ -673,9 +687,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi
int subId = subInfo.getSubscriptionId();
if (mSubIdTelephonyManagerMap.get(subId) == null) {
TelephonyManager secondaryTm = mTelephonyManager.createForSubscriptionId(subId);
- InternetTelephonyCallback telephonyCallback = new InternetTelephonyCallback(subId);
- secondaryTm.registerTelephonyCallback(mExecutor, telephonyCallback);
- mSubIdTelephonyCallbackMap.put(subId, telephonyCallback);
+ registerInternetTelephonyCallback(secondaryTm, subId);
mSubIdTelephonyManagerMap.put(subId, secondaryTm);
}
return subId;
@@ -1351,6 +1363,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi
if (DEBUG) {
Log.d(TAG, "DDS: defaultDataSubId:" + defaultDataSubId);
}
+
if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) {
// clean up old defaultDataSubId
TelephonyCallback oldCallback = mSubIdTelephonyCallbackMap.get(mDefaultDataSubId);
@@ -1366,9 +1379,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi
// create for new defaultDataSubId
mTelephonyManager = mTelephonyManager.createForSubscriptionId(defaultDataSubId);
mSubIdTelephonyManagerMap.put(defaultDataSubId, mTelephonyManager);
- InternetTelephonyCallback newCallback = new InternetTelephonyCallback(defaultDataSubId);
- mSubIdTelephonyCallbackMap.put(defaultDataSubId, newCallback);
- mTelephonyManager.registerTelephonyCallback(mHandler::post, newCallback);
+ registerInternetTelephonyCallback(mTelephonyManager, defaultDataSubId);
mCallback.onSubscriptionsChanged(defaultDataSubId);
}
mDefaultDataSubId = defaultDataSubId;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
index aa8c6b7a8a5f..e160ff17a6ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.content.res.Configuration;
@@ -643,6 +644,46 @@ public class TouchMonitorTest extends SysuiTestCase {
environment.verifyInputSessionDispose();
}
+ @Test
+ public void testSessionPopAfterDestroy() {
+ final TouchHandler touchHandler = createTouchHandler();
+
+ final Environment environment = new Environment(Stream.of(touchHandler)
+ .collect(Collectors.toCollection(HashSet::new)), mKosmos);
+
+ final InputEvent initialEvent = Mockito.mock(InputEvent.class);
+ environment.publishInputEvent(initialEvent);
+
+ // Ensure session started
+ final InputChannelCompat.InputEventListener eventListener =
+ registerInputEventListener(touchHandler);
+
+ // First event will be missed since we register after the execution loop,
+ final InputEvent event = Mockito.mock(InputEvent.class);
+ environment.publishInputEvent(event);
+ verify(eventListener).onInputEvent(eq(event));
+
+ final ArgumentCaptor<TouchHandler.TouchSession> touchSessionArgumentCaptor =
+ ArgumentCaptor.forClass(TouchHandler.TouchSession.class);
+
+ verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
+
+ environment.updateLifecycle(Lifecycle.State.DESTROYED);
+
+ // Check to make sure the input session is now disposed.
+ environment.verifyInputSessionDispose();
+
+ clearInvocations(environment.mInputFactory);
+
+ // Pop the session
+ touchSessionArgumentCaptor.getValue().pop();
+
+ environment.executeAll();
+
+ // Ensure no input sessions were created due to the session reset.
+ verifyNoMoreInteractions(environment.mInputFactory);
+ }
+
@Test
public void testPilfering() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
index eea02eec7099..2f8f45cb0197 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -887,6 +888,34 @@ public class InternetDialogDelegateControllerTest extends SysuiTestCase {
}
@Test
+ public void getActiveAutoSwitchNonDdsSubId_registerCallbackForExistedSubId_notRegister() {
+ mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
+
+ // Adds non DDS subId
+ SubscriptionInfo info = mock(SubscriptionInfo.class);
+ doReturn(SUB_ID2).when(info).getSubscriptionId();
+ doReturn(false).when(info).isOpportunistic();
+ when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info);
+
+ mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+
+ // 1st time is onStart(), 2nd time is getActiveAutoSwitchNonDdsSubId()
+ verify(mTelephonyManager, times(2)).registerTelephonyCallback(any(), any());
+ assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size() == 2);
+
+ // Adds non DDS subId again
+ doReturn(SUB_ID2).when(info).getSubscriptionId();
+ doReturn(false).when(info).isOpportunistic();
+ when(mSubscriptionManager.getActiveSubscriptionInfo(anyInt())).thenReturn(info);
+
+ mInternetDialogController.getActiveAutoSwitchNonDdsSubId();
+
+ // Does not add due to cached subInfo in mSubIdTelephonyCallbackMap.
+ verify(mTelephonyManager, times(2)).registerTelephonyCallback(any(), any());
+ assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size() == 2);
+ }
+
+ @Test
public void getMobileNetworkSummary() {
mFlags.set(Flags.QS_SECONDARY_DATA_SUB_INFO, true);
Resources res1 = mock(Resources.class);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
index 450f08f1fe3f..11f0c19ffa67 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
@@ -21,17 +21,20 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
-import com.android.systemui.util.mockito.any
+import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.FailureMetadata
import com.google.common.truth.Subject
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertAbout
+import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import org.junit.Assert.fail
import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
/** [Subject] used to make assertions about a [Mockito.spy] KeyguardTransitionRepository. */
class KeyguardTransitionRepositorySpySubject
@@ -89,6 +92,20 @@ private constructor(
}
}
+ /**
+ * Asserts that we started a transition to the given state, optionally verifying additional
+ * params.
+ */
+ suspend fun updatedTransition(value: Float, state: TransitionState) {
+ val valueCaptor = argumentCaptor<Float>()
+ val stateCaptor = argumentCaptor<TransitionState>()
+
+ verify(repository).updateTransition(any(), valueCaptor.capture(), stateCaptor.capture())
+
+ assertThat(value).isEqualTo(valueCaptor.firstValue)
+ assertThat(state).isEqualTo(stateCaptor.firstValue)
+ }
+
/** Verifies that [KeyguardTransitionRepository.startTransition] was never called. */
suspend fun noTransitionsStarted() {
verify(repository, never()).startTransition(any())