diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java index b77ac8a2b951e..e46ee28b3ddba 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SingleInstanceRemoteListener.java @@ -29,6 +29,9 @@ import java.util.function.Consumer; * Manages the lifecycle of a single instance of a remote listener, including the clean up if the * remote process dies. All calls on this class should happen on the main shell thread. * + * Any external interface using this listener should also unregister the listener when it is + * invalidated, otherwise it may leak binder death recipients. + * * @param The controller (must be RemoteCallable) * @param The remote listener interface type */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index efe938f0a2746..01d81ff4e436d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -207,7 +207,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb private Consumer mOnIsInPipStateChangedListener; - private interface PipAnimationListener { + @VisibleForTesting + interface PipAnimationListener { /** * Notifies the listener that the Pip animation is started. */ @@ -434,11 +435,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb Optional oneHandedController, ShellExecutor mainExecutor ) { - // Ensure that we are the primary user's SystemUI. - final int processUser = UserManager.get(context).getProcessUserId(); - if (processUser != UserHandle.USER_SYSTEM) { - throw new IllegalStateException("Non-primary Pip component not currently supported."); - } + mContext = context; mShellCommandHandler = shellCommandHandler; @@ -872,11 +869,17 @@ public class PipController implements PipTransitionController.PipTransitionCallb animationType == PipAnimationController.ANIM_TYPE_BOUNDS); } - private void setPinnedStackAnimationListener(PipAnimationListener callback) { + @VisibleForTesting + void setPinnedStackAnimationListener(PipAnimationListener callback) { mPinnedStackAnimationRecentsCallback = callback; onPipResourceDimensionsChanged(); } + @VisibleForTesting + boolean hasPinnedStackAnimationListener() { + return mPinnedStackAnimationRecentsCallback != null; + } + private void onPipResourceDimensionsChanged() { if (mPinnedStackAnimationRecentsCallback != null) { mPinnedStackAnimationRecentsCallback.onPipResourceDimensionsChanged( @@ -1166,6 +1169,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb @Override public void invalidate() { mController = null; + // Unregister the listener to ensure any registered binder death recipients are unlinked + mListener.unregister(); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index db0f0bf6fda8f..8490f9f156c70 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -280,14 +280,21 @@ public class RecentTasksController implements TaskStackListenerCallback, } } - private void registerRecentTasksListener(IRecentTasksListener listener) { + @VisibleForTesting + void registerRecentTasksListener(IRecentTasksListener listener) { mListener = listener; } - private void unregisterRecentTasksListener() { + @VisibleForTesting + void unregisterRecentTasksListener() { mListener = null; } + @VisibleForTesting + boolean hasRecentTasksListener() { + return mListener != null; + } + @VisibleForTesting ArrayList getRecentTasks(int maxNum, int flags, int userId) { // Note: the returned task list is from the most-recent to least-recent order @@ -442,6 +449,8 @@ public class RecentTasksController implements TaskStackListenerCallback, @Override public void invalidate() { mController = null; + // Unregister the listener to ensure any registered binder death recipients are unlinked + mListener.unregister(); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index ef70d9bd84eee..38099fc51d815 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -954,6 +954,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Override public void invalidate() { mController = null; + // Unregister the listener to ensure any registered binder death recipients are unlinked + mListener.unregister(); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index 0c23f109feaf1..be2e79342d074 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -39,6 +39,7 @@ import android.window.TaskOrganizer; import android.window.TaskSnapshot; import androidx.annotation.BinderThread; +import androidx.annotation.VisibleForTesting; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.TriConsumer; @@ -138,10 +139,16 @@ public class StartingWindowController implements RemoteCallable listener) { mTaskLaunchingCallback = listener; } + @VisibleForTesting + boolean hasStartingWindowListener() { + return mTaskLaunchingCallback != null; + } + /** * Called when a task need a starting window. */ @@ -281,6 +288,8 @@ public class StartingWindowController implements RemoteCallable mIntentCaptor; + private ShellController mShellController; private SplitScreenController mSplitScreenController; @Before public void setup() { assumeTrue(ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)); MockitoAnnotations.initMocks(this); + mShellController = spy(new ShellController(mShellInit, mShellCommandHandler, + mMainExecutor)); mSplitScreenController = spy(new SplitScreenController(mContext, mShellInit, mShellCommandHandler, mShellController, mTaskOrganizer, mSyncQueue, mRootTDAOrganizer, mDisplayController, mDisplayImeController, @@ -118,7 +124,7 @@ public class SplitScreenControllerTests extends ShellTestCase { @Test public void instantiateController_addInitCallback() { - verify(mShellInit, times(1)).addInitCallback(any(), any()); + verify(mShellInit, times(1)).addInitCallback(any(), isA(SplitScreenController.class)); } @Test @@ -158,6 +164,19 @@ public class SplitScreenControllerTests extends ShellTestCase { eq(ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN), any(), any()); } + @Test + public void testInvalidateExternalInterface_unregistersListener() { + mSplitScreenController.onInit(); + mSplitScreenController.registerSplitScreenListener( + new SplitScreen.SplitScreenListener() {}); + verify(mStageCoordinator).registerSplitScreenListener(any()); + // Create initial interface + mShellController.createExternalInterfaces(new Bundle()); + // Recreate the interface to trigger invalidation of the previous instance + mShellController.createExternalInterfaces(new Bundle()); + verify(mStageCoordinator).unregisterSplitScreenListener(any()); + } + @Test public void testStartIntent_appendsNoUserActionFlag() { Intent startIntent = createStartIntent("startActivity"); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java index 90165d1cd1b2b..10dec9ef12f9e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java @@ -16,9 +16,12 @@ package com.android.wm.shell.startingsurface; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -27,16 +30,19 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.hardware.display.DisplayManager; +import android.os.Bundle; import android.view.Display; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.internal.util.function.TriConsumer; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.sysui.ShellSharedConstants; @@ -59,7 +65,7 @@ public class StartingWindowControllerTests extends ShellTestCase { private @Mock Context mContext; private @Mock DisplayManager mDisplayManager; - private @Mock ShellController mShellController; + private @Mock ShellCommandHandler mShellCommandHandler; private @Mock ShellTaskOrganizer mTaskOrganizer; private @Mock ShellExecutor mMainExecutor; private @Mock StartingWindowTypeAlgorithm mTypeAlgorithm; @@ -67,6 +73,7 @@ public class StartingWindowControllerTests extends ShellTestCase { private @Mock TransactionPool mTransactionPool; private StartingWindowController mController; private ShellInit mShellInit; + private ShellController mShellController; @Before public void setUp() { @@ -74,6 +81,8 @@ public class StartingWindowControllerTests extends ShellTestCase { doReturn(mock(Display.class)).when(mDisplayManager).getDisplay(anyInt()); doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class)); mShellInit = spy(new ShellInit(mMainExecutor)); + mShellController = spy(new ShellController(mShellInit, mShellCommandHandler, + mMainExecutor)); mController = new StartingWindowController(mContext, mShellInit, mShellController, mTaskOrganizer, mMainExecutor, mTypeAlgorithm, mIconProvider, mTransactionPool); mShellInit.init(); @@ -81,7 +90,7 @@ public class StartingWindowControllerTests extends ShellTestCase { @Test public void instantiateController_addInitCallback() { - verify(mShellInit, times(1)).addInitCallback(any(), any()); + verify(mShellInit, times(1)).addInitCallback(any(), isA(StartingWindowController.class)); } @Test @@ -89,4 +98,18 @@ public class StartingWindowControllerTests extends ShellTestCase { verify(mShellController, times(1)).addExternalInterface( eq(ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW), any(), any()); } + + @Test + public void testInvalidateExternalInterface_unregistersListener() { + mController.setStartingWindowListener(new TriConsumer() { + @Override + public void accept(Integer integer, Integer integer2, Integer integer3) {} + }); + assertTrue(mController.hasStartingWindowListener()); + // Create initial interface + mShellController.createExternalInterfaces(new Bundle()); + // Recreate the interface to trigger invalidation of the previous instance + mShellController.createExternalInterfaces(new Bundle()); + assertFalse(mController.hasStartingWindowListener()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java index 26bc3e3c09206..608bfa611ff02 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java @@ -189,7 +189,8 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh // for foldables that often go from large <=> small screen when folding/unfolding. ViewRootImpl.addConfigCallback(this); mDialogManager.setShowing(this, true); - mSysUiState.setFlag(QuickStepContract.SYSUI_STATE_DIALOG_SHOWING, true); + mSysUiState.setFlag(QuickStepContract.SYSUI_STATE_DIALOG_SHOWING, true) + .commitUpdate(mContext.getDisplayId()); } @Override @@ -202,7 +203,8 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh ViewRootImpl.removeConfigCallback(this); mDialogManager.setShowing(this, false); - mSysUiState.setFlag(QuickStepContract.SYSUI_STATE_DIALOG_SHOWING, false); + mSysUiState.setFlag(QuickStepContract.SYSUI_STATE_DIALOG_SHOWING, false) + .commitUpdate(mContext.getDisplayId()); } public void setShowForAllUsers(boolean show) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index b43d830e79353..d6e78a195be4a 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -818,8 +818,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadFromDisplayDeviceConfig(token, info); // Since the underlying display-device changed, we really don't know the - // last command that was sent to change it's state. Lets assume it is unknown so - // that we trigger a change immediately. + // last command that was sent to change it's state. Lets assume it is off and we + // trigger a change immediately. mPowerState.resetScreenState(); } if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) { diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java index f650b118b8159..7d1396d7e413c 100644 --- a/services/core/java/com/android/server/display/DisplayPowerState.java +++ b/services/core/java/com/android/server/display/DisplayPowerState.java @@ -340,12 +340,20 @@ final class DisplayPowerState { } /** - * Resets the screen state to unknown. Useful when the underlying display-device changes for the - * LogicalDisplay and we do not know the last state that was sent to it. + * Resets the screen state to {@link Display#STATE_OFF}. Even though we do not know the last + * state that was sent to the underlying display-device, we assume it is off. + * + * We do not set the screen state to {@link Display#STATE_UNKNOWN} to avoid getting in the state + * where PhotonicModulator holds onto the lock. This happens because we currently try to keep + * the mScreenState and mPendingState in sync, however if the screenState is set to + * {@link Display#STATE_UNKNOWN} here, mPendingState will get progressed to this, which will + * force the PhotonicModulator thread to wait onto the lock to take it out of that state. + * b/262294651 for more info. */ void resetScreenState() { - mScreenState = Display.STATE_UNKNOWN; + mScreenState = Display.STATE_OFF; mScreenReady = false; + scheduleScreenUpdate(); } private void scheduleScreenUpdate() { diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java index b5d97abdd3eb6..c2a986465b022 100644 --- a/telephony/java/android/telephony/AccessNetworkUtils.java +++ b/telephony/java/android/telephony/AccessNetworkUtils.java @@ -4,8 +4,8 @@ import static android.telephony.ServiceState.DUPLEX_MODE_FDD; import static android.telephony.ServiceState.DUPLEX_MODE_TDD; import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN; -import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.EutranBand; +import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.GeranBand; import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency; import android.telephony.AccessNetworkConstants.NgranArfcnFrequency; @@ -13,7 +13,6 @@ import android.telephony.AccessNetworkConstants.NgranBands; import android.telephony.AccessNetworkConstants.UtranBand; import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency; import android.telephony.ServiceState.DuplexMode; -import android.util.Log; import java.util.Arrays; import java.util.HashSet; @@ -231,6 +230,108 @@ public class AccessNetworkUtils { return INVALID_BAND; } + /** + * Gets the NR Operating band for a given downlink NRARFCN. + * + *

See 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1 and + * Table 5.2-2 NR operating bands in FR2 + * + * @param nrarfcn The downlink NRARFCN + * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists + */ + public static int getOperatingBandForNrarfcn(int nrarfcn) { + if (nrarfcn >= 422000 && nrarfcn <= 434000) { + return NgranBands.BAND_1; + } else if (nrarfcn >= 386000 && nrarfcn <= 398000) { + return NgranBands.BAND_2; + } else if (nrarfcn >= 361000 && nrarfcn <= 376000) { + return NgranBands.BAND_3; + } else if (nrarfcn >= 173800 && nrarfcn <= 178800) { + return NgranBands.BAND_5; + } else if (nrarfcn >= 524000 && nrarfcn <= 538000) { + return NgranBands.BAND_7; + } else if (nrarfcn >= 185000 && nrarfcn <= 192000) { + return NgranBands.BAND_8; + } else if (nrarfcn >= 145800 && nrarfcn <= 149200) { + return NgranBands.BAND_12; + } else if (nrarfcn >= 151600 && nrarfcn <= 153600) { + return NgranBands.BAND_14; + } else if (nrarfcn >= 172000 && nrarfcn <= 175000) { + return NgranBands.BAND_18; + } else if (nrarfcn >= 158200 && nrarfcn <= 164200) { + return NgranBands.BAND_20; + } else if (nrarfcn >= 386000 && nrarfcn <= 399000) { + return NgranBands.BAND_25; + } else if (nrarfcn >= 171800 && nrarfcn <= 178800) { + return NgranBands.BAND_26; + } else if (nrarfcn >= 151600 && nrarfcn <= 160600) { + return NgranBands.BAND_28; + } else if (nrarfcn >= 143400 && nrarfcn <= 145600) { + return NgranBands.BAND_29; + } else if (nrarfcn >= 470000 && nrarfcn <= 472000) { + return NgranBands.BAND_30; + } else if (nrarfcn >= 402000 && nrarfcn <= 405000) { + return NgranBands.BAND_34; + } else if (nrarfcn >= 514000 && nrarfcn <= 524000) { + return NgranBands.BAND_38; + } else if (nrarfcn >= 376000 && nrarfcn <= 384000) { + return NgranBands.BAND_39; + } else if (nrarfcn >= 460000 && nrarfcn <= 480000) { + return NgranBands.BAND_40; + } else if (nrarfcn >= 499200 && nrarfcn <= 537999) { + return NgranBands.BAND_41; + } else if (nrarfcn >= 743334 && nrarfcn <= 795000) { + return NgranBands.BAND_46; + } else if (nrarfcn >= 636667 && nrarfcn <= 646666) { + return NgranBands.BAND_48; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_50; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_51; + } else if (nrarfcn >= 496700 && nrarfcn <= 499000) { + return NgranBands.BAND_53; + } else if (nrarfcn >= 422000 && nrarfcn <= 440000) { + return NgranBands.BAND_65; // BAND_66 has the same channels + } else if (nrarfcn >= 399000 && nrarfcn <= 404000) { + return NgranBands.BAND_70; + } else if (nrarfcn >= 123400 && nrarfcn <= 130400) { + return NgranBands.BAND_71; + } else if (nrarfcn >= 295000 && nrarfcn <= 303600) { + return NgranBands.BAND_74; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_75; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_76; + } else if (nrarfcn >= 620000 && nrarfcn <= 680000) { + return NgranBands.BAND_77; + } else if (nrarfcn >= 620000 && nrarfcn <= 653333) { + return NgranBands.BAND_78; + } else if (nrarfcn >= 693334 && nrarfcn <= 733333) { + return NgranBands.BAND_79; + } else if (nrarfcn >= 499200 && nrarfcn <= 538000) { + return NgranBands.BAND_90; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_91; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_92; + } else if (nrarfcn >= 285400 && nrarfcn <= 286400) { + return NgranBands.BAND_93; + } else if (nrarfcn >= 286400 && nrarfcn <= 303400) { + return NgranBands.BAND_94; + } else if (nrarfcn >= 795000 && nrarfcn <= 875000) { + return NgranBands.BAND_96; + } else if (nrarfcn >= 2054166 && nrarfcn <= 2104165) { + return NgranBands.BAND_257; + } else if (nrarfcn >= 2016667 && nrarfcn <= 2070832) { + return NgranBands.BAND_258; + } else if (nrarfcn >= 2229166 && nrarfcn <= 2279165) { + return NgranBands.BAND_260; + } else if (nrarfcn >= 2070833 && nrarfcn <= 2084999) { + return NgranBands.BAND_261; + } + return INVALID_BAND; + } + /** * Gets the GERAN Operating band for a given ARFCN. * diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index 28307d2701341..4836c9f8610a8 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -1030,6 +1030,15 @@ public class SmsMessage { return mWrappedSmsMessage.getReceivedEncodingType(); } + /** + * Check if format of the message is 3GPP. + * + * @hide + */ + public boolean is3gpp() { + return (mWrappedSmsMessage instanceof com.android.internal.telephony.gsm.SmsMessage); + } + /** * Determines whether or not to use CDMA format for MO SMS. * If SMS over IMS is supported, then format is based on IMS SMS format,