Merge "Add toast when non-resizable attempts is attempted to be snap resized" into main
diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java
index 81e9df6..8370c2e 100644
--- a/core/java/android/app/AppCompatTaskInfo.java
+++ b/core/java/android/app/AppCompatTaskInfo.java
@@ -95,6 +95,8 @@
private static final int FLAG_FULLSCREEN_OVERRIDE_SYSTEM = FLAG_BASE << 7;
/** Top activity flag for whether has activity has been overridden to fullscreen by user. */
private static final int FLAG_FULLSCREEN_OVERRIDE_USER = FLAG_BASE << 8;
+ /** Top activity flag for whether min aspect ratio of the activity has been overridden.*/
+ public static final int FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE = FLAG_BASE << 9;
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, value = {
@@ -108,7 +110,8 @@
FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP,
FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON,
FLAG_FULLSCREEN_OVERRIDE_SYSTEM,
- FLAG_FULLSCREEN_OVERRIDE_USER
+ FLAG_FULLSCREEN_OVERRIDE_USER,
+ FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE
})
public @interface TopActivityFlag {}
@@ -118,7 +121,7 @@
@TopActivityFlag
private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP
| FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM
- | FLAG_FULLSCREEN_OVERRIDE_USER;
+ | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE;
@TopActivityFlag
private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED
@@ -301,6 +304,21 @@
setTopActivityFlag(FLAG_LETTERBOXED, enable);
}
+ /**
+ * @return {@code true} if the top activity's min aspect ratio has been overridden.
+ */
+ public boolean hasMinAspectRatioOverride() {
+ return isTopActivityFlagEnabled(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE);
+ }
+
+ /**
+ * Sets the top activity flag for whether the min aspect ratio of the activity has been
+ * overridden.
+ */
+ public void setHasMinAspectRatioOverride(boolean enable) {
+ setTopActivityFlag(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, enable);
+ }
+
/** Clear all top activity flags and set to false. */
public void clearTopActivityFlags() {
mTopActivityFlags = FLAG_UNDEFINED;
@@ -392,6 +410,7 @@
+ " topActivityLetterboxAppHeight=" + topActivityLetterboxAppHeight
+ " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled()
+ " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled()
+ + " hasMinAspectRatioOverride=" + hasMinAspectRatioOverride()
+ " cameraCompatTaskInfo=" + cameraCompatTaskInfo.toString()
+ "}";
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 5903a7f..38f59ad 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1571,12 +1571,29 @@
*/
@Nullable
public Rect peekBitmapDimensions(@SetWallpaperFlags int which, boolean returnDefault) {
+ if (multiCrop()) {
+ return peekBitmapDimensionsAsUser(which, returnDefault, mContext.getUserId());
+ }
checkExactlyOneWallpaperFlagSet(which);
return sGlobals.peekWallpaperDimensions(mContext, returnDefault, which,
mContext.getUserId());
}
/**
+ * Overload of {@link #peekBitmapDimensions(int, boolean)} with a userId argument.
+ * TODO(b/360120606): remove the SuppressWarnings
+ * @hide
+ */
+ @SuppressWarnings("AndroidFrameworkContextUserId")
+ @FlaggedApi(FLAG_MULTI_CROP)
+ @Nullable
+ public Rect peekBitmapDimensionsAsUser(@SetWallpaperFlags int which, boolean returnDefault,
+ int userId) {
+ checkExactlyOneWallpaperFlagSet(which);
+ return sGlobals.peekWallpaperDimensions(mContext, returnDefault, which, userId);
+ }
+
+ /**
* For the current user, given a list of display sizes, return a list of rectangles representing
* the area of the current wallpaper that would be shown for each of these sizes.
*
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index d85e41d..c5d0caf22 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -336,6 +336,39 @@
}
/**
+ * Returns true if the touchpad visualizer is allowed to appear.
+ *
+ * @param context The application context.
+ * @return Whether it is allowed to show touchpad visualizer or not.
+ *
+ * @hide
+ */
+ public static boolean useTouchpadVisualizer(@NonNull Context context) {
+ if (!isTouchpadVisualizerFeatureFlagEnabled()) {
+ return false;
+ }
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.TOUCHPAD_VISUALIZER, 0, UserHandle.USER_CURRENT) == 1;
+ }
+
+ /**
+ * Sets the touchpad visualizer behaviour.
+ *
+ * @param context The application context.
+ * @param enabled Will enable touchpad visualizer if true, disable it if false
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+ public static void setTouchpadVisualizer(@NonNull Context context, boolean enabled) {
+ if (!isTouchpadVisualizerFeatureFlagEnabled()) {
+ return;
+ }
+ Settings.System.putIntForUser(context.getContentResolver(),
+ Settings.System.TOUCHPAD_VISUALIZER, enabled ? 1 : 0, UserHandle.USER_CURRENT);
+ }
+
+ /**
* Returns true if the touchpad should allow tap dragging.
*
* The returned value only applies to gesture-compatible touchpads.
diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig
index 53a1a67d..e3b1221 100644
--- a/core/java/android/os/vibrator/flags.aconfig
+++ b/core/java/android/os/vibrator/flags.aconfig
@@ -113,3 +113,14 @@
purpose: PURPOSE_FEATURE
}
}
+
+flag {
+ namespace: "haptics"
+ name: "normalized_pwle_effects"
+ is_exported: true
+ description: "Enables functionality to create PWLE effects using advanced and simple APIs"
+ bug: "341052318"
+ metadata {
+ purpose: PURPOSE_FEATURE
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 66d08f9..08e51a1 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -27,6 +27,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.window.flags.Flags.FLAG_OFFLOAD_COLOR_EXTRACTION;
+import static com.android.window.flags.Flags.noDuplicateSurfaceDestroyedEvents;
import static com.android.window.flags.Flags.noConsecutiveVisibilityEvents;
import static com.android.window.flags.Flags.noVisibilityEventOnDisplayStateChange;
import static com.android.window.flags.Flags.offloadColorExtraction;
@@ -255,6 +256,7 @@
*/
private boolean mIsScreenTurningOn;
boolean mReportedVisible;
+ boolean mReportedSurfaceCreated;
boolean mDestroyed;
// Set to true after receiving WallpaperManager#COMMAND_FREEZE. It's reset back to false
// after receiving WallpaperManager#COMMAND_UNFREEZE. COMMAND_FREEZE is fully applied once
@@ -1381,6 +1383,7 @@
if (surfaceCreating) {
mIsCreating = true;
didSurface = true;
+ mReportedSurfaceCreated = true;
if (DEBUG) Log.v(TAG, "onSurfaceCreated("
+ mSurfaceHolder + "): " + this);
Trace.beginSection("WPMS.Engine.onSurfaceCreated");
@@ -2264,8 +2267,10 @@
}
void reportSurfaceDestroyed() {
- if (mSurfaceCreated) {
+ if ((!noDuplicateSurfaceDestroyedEvents() && mSurfaceCreated)
+ || (noDuplicateSurfaceDestroyedEvents() && mReportedSurfaceCreated)) {
mSurfaceCreated = false;
+ mReportedSurfaceCreated = false;
mSurfaceHolder.ungetCallbacks();
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index d28c953..03a2672 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -474,7 +474,11 @@
private final AccessibilitySmartActions mA11ySmartActions;
private InsertModeController mInsertModeController;
- Editor(TextView textView) {
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public Editor(TextView textView) {
mTextView = textView;
// Synchronize the filter list, which places the undo input filter at the end.
mTextView.setFilters(mTextView.getFilters());
@@ -3206,16 +3210,6 @@
}
}
- final int menuItemOrderUndo = 2;
- final int menuItemOrderRedo = 3;
- final int menuItemOrderCut = 4;
- final int menuItemOrderCopy = 5;
- final int menuItemOrderPaste = 6;
- final int menuItemOrderPasteAsPlainText = 7;
- final int menuItemOrderSelectAll = 8;
- final int menuItemOrderShare = 9;
- final int menuItemOrderAutofill = 10;
-
menu.setOptionalIconsVisible(true);
menu.setGroupDividerEnabled(true);
@@ -3224,7 +3218,18 @@
final int keyboard = mTextView.getResources().getConfiguration().keyboard;
menu.setQwertyMode(keyboard == Configuration.KEYBOARD_QWERTY);
- final TypedArray a = mTextView.getContext().obtainStyledAttributes(new int[] {
+ setTextContextMenuItems(menu);
+
+ mPreserveSelection = true;
+
+ // No-op for the old context menu because it doesn't have icons.
+ adjustIconSpacing(menu);
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public void setTextContextMenuItems(ContextMenu menu) {
+ final TypedArray a = mTextView.getContext().obtainStyledAttributes(new int[]{
// TODO: Make Undo/Redo be public attribute.
com.android.internal.R.attr.actionModeUndoDrawable,
com.android.internal.R.attr.actionModeRedoDrawable,
@@ -3235,6 +3240,16 @@
android.R.attr.actionModeShareDrawable,
});
+ final int menuItemOrderUndo = 2;
+ final int menuItemOrderRedo = 3;
+ final int menuItemOrderCut = 4;
+ final int menuItemOrderCopy = 5;
+ final int menuItemOrderPaste = 6;
+ final int menuItemOrderPasteAsPlainText = 7;
+ final int menuItemOrderSelectAll = 8;
+ final int menuItemOrderShare = 9;
+ final int menuItemOrderAutofill = 10;
+
menu.add(CONTEXT_MENU_GROUP_UNDO_REDO, TextView.ID_UNDO, menuItemOrderUndo,
com.android.internal.R.string.undo)
.setAlphabeticShortcut('z')
@@ -3291,12 +3306,7 @@
.setEnabled(mTextView.canRequestAutofill()
&& (selected == null || selected.isEmpty()))
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
-
- mPreserveSelection = true;
a.recycle();
-
- // No-op for the old context menu because it doesn't have icons.
- adjustIconSpacing(menu);
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 61ecc62..72b268b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12255,7 +12255,11 @@
return selectionMin >= 0 && selectionMax > 0 && selectionMin != selectionMax;
}
- String getSelectedText() {
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public String getSelectedText() {
if (!hasSelection()) {
return null;
}
@@ -14080,7 +14084,11 @@
structure.setInputType(getInputType());
}
- boolean canRequestAutofill() {
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean canRequestAutofill() {
if (!isAutofillable()) {
return false;
}
diff --git a/core/java/android/window/flags/wallpaper_manager.aconfig b/core/java/android/window/flags/wallpaper_manager.aconfig
index 01c78a0..8c6721a 100644
--- a/core/java/android/window/flags/wallpaper_manager.aconfig
+++ b/core/java/android/window/flags/wallpaper_manager.aconfig
@@ -39,3 +39,13 @@
description: "Prevent the system from sending visibility event on display state change."
bug: "331725519"
}
+
+flag {
+ name: "no_duplicate_surface_destroyed_events"
+ namespace: "systemui"
+ description: "Prevent the system from sending onSurfaceDestroyed() twice."
+ bug: "344461715"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index cbcbf2db..79a5469 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -401,7 +401,9 @@
Log.e(LOG_TAG, "Failed to wait for tracing to finish", e);
}
- dumpViewerConfig();
+ if (!android.tracing.Flags.clientSideProtoLogging()) {
+ dumpViewerConfig();
+ }
Log.d(LOG_TAG, "Finished onTracingFlush");
}
@@ -497,7 +499,8 @@
os.write(GROUP_ID, pis.readInt(GROUP_ID));
break;
case (int) LOCATION:
- os.write(LOCATION, pis.readInt(LOCATION));
+ os.write(LOCATION, pis.readString(LOCATION));
+ break;
default:
throw new RuntimeException(
"Unexpected field id " + pis.getFieldNumber());
diff --git a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
index f9da832..b11307e 100644
--- a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
@@ -23,7 +23,9 @@
import static org.mockito.ArgumentMatchers.anyChar;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -251,8 +253,9 @@
when(menu.add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt()))
.thenReturn(mockAutofillMenuItem);
- EditText et = mActivity.findViewById(R.id.editText);
- et.setText("Test");
+ EditText et = spy(mActivity.findViewById(R.id.editText));
+ doReturn(true).when(et).canRequestAutofill();
+ doReturn(null).when(et).getSelectedText();
Editor editor = et.getEditorForTesting();
editor.onCreateContextMenu(menu);
@@ -271,11 +274,11 @@
when(menu.add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt()))
.thenReturn(mockAutofillMenuItem);
- EditText et = mActivity.findViewById(R.id.editText);
- et.setText("Test");
- et.selectAll();
- Editor editor = et.getEditorForTesting();
- editor.onCreateContextMenu(menu);
+ EditText et = spy(mActivity.findViewById(R.id.editText));
+ doReturn(true).when(et).canRequestAutofill();
+ doReturn("test").when(et).getSelectedText();
+ Editor editor = new Editor(et);
+ editor.setTextContextMenuItems(menu);
verify(menu).add(anyInt(), eq(TextView.ID_AUTOFILL), anyInt(), anyInt());
verify(mockAutofillMenuItem).setEnabled(false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
index 6c03dc3..b68b436 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
@@ -66,7 +66,7 @@
val initialSize: Size =
when (taskInfo.configuration.orientation) {
ORIENTATION_LANDSCAPE -> {
- if (taskInfo.isResizeable) {
+ if (taskInfo.canChangeAspectRatio) {
if (isFixedOrientationPortrait(topActivityInfo.screenOrientation)) {
// For portrait resizeable activities, respect apps fullscreen width but
// apply ideal size height.
@@ -85,7 +85,7 @@
ORIENTATION_PORTRAIT -> {
val customPortraitWidthForLandscapeApp =
screenBounds.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2)
- if (taskInfo.isResizeable) {
+ if (taskInfo.canChangeAspectRatio) {
if (isFixedOrientationLandscape(topActivityInfo.screenOrientation)) {
// For landscape resizeable activities, respect apps fullscreen height and
// apply custom app width.
@@ -189,6 +189,13 @@
}
/**
+ * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was
+ * unresizeable.
+ */
+private val TaskInfo.canChangeAspectRatio: Boolean
+ get() = isResizeable && !appCompatTaskInfo.hasMinAspectRatioOverride()
+
+/**
* Adjusts bounds to be positioned in the middle of the area provided, not necessarily the
* entire screen, as area can be offset by left and top start.
*/
@@ -204,7 +211,7 @@
return Rect(newLeft, newTop, newRight, newBottom)
}
-fun TaskInfo.hasPortraitTopActivity(): Boolean {
+private fun TaskInfo.hasPortraitTopActivity(): Boolean {
val topActivityScreenOrientation =
topActivityInfo?.screenOrientation ?: SCREEN_ORIENTATION_UNSPECIFIED
val appBounds = configuration.windowConfiguration.appBounds
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index a630cef..9530bdb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -867,6 +867,18 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ fun addMoveToDesktopChanges_landscapeDevice_portraitResizableApp_aspectRatioOverridden() {
+ setUpLandscapeDisplay()
+ val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_PORTRAIT,
+ shouldLetterbox = true, aspectRatioOverrideApplied = true)
+ val wct = WindowContainerTransaction()
+ controller.addMoveToDesktopChanges(wct, task)
+
+ assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_PORTRAIT_BOUNDS)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
fun addMoveToDesktopChanges_portraitDevice_userFullscreenOverride_defaultPortraitBounds() {
setUpPortraitDisplay()
val task = setUpFullscreenTask(enableUserFullscreenOverride = true)
@@ -888,6 +900,19 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ fun addMoveToDesktopChanges_portraitDevice_landscapeResizableApp_aspectRatioOverridden() {
+ setUpPortraitDisplay()
+ val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_LANDSCAPE,
+ deviceOrientation = ORIENTATION_PORTRAIT,
+ shouldLetterbox = true, aspectRatioOverrideApplied = true)
+ val wct = WindowContainerTransaction()
+ controller.addMoveToDesktopChanges(wct, task)
+
+ assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_LANDSCAPE_BOUNDS)
+ }
+
+ @Test
fun moveToDesktop_tdaFullscreen_windowingModeSetToFreeform() {
val task = setUpFullscreenTask()
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
@@ -2896,7 +2921,8 @@
shouldLetterbox: Boolean = false,
gravity: Int = Gravity.NO_GRAVITY,
enableUserFullscreenOverride: Boolean = false,
- enableSystemFullscreenOverride: Boolean = false
+ enableSystemFullscreenOverride: Boolean = false,
+ aspectRatioOverrideApplied: Boolean = false
): RunningTaskInfo {
val task = createFullscreenTask(displayId)
val activityInfo = ActivityInfo()
@@ -2911,6 +2937,7 @@
appCompatTaskInfo.isSystemFullscreenOverrideEnabled = enableSystemFullscreenOverride
if (shouldLetterbox) {
+ appCompatTaskInfo.setHasMinAspectRatioOverride(aspectRatioOverrideApplied)
if (deviceOrientation == ORIENTATION_LANDSCAPE &&
screenOrientation == SCREEN_ORIENTATION_PORTRAIT) {
// Letterbox to portrait size
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 9896f64..2d7db5e 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -131,7 +131,7 @@
private int mCasSystemId;
private int mUserId;
private TunerResourceManager mTunerResourceManager = null;
- private final Map<Session, Long> mSessionMap = new HashMap<>();
+ private final Map<Session, Integer> mSessionMap = new HashMap<>();
/**
* Scrambling modes used to open cas sessions.
@@ -1126,10 +1126,10 @@
}
}
- private long getSessionResourceHandle() throws MediaCasException {
+ private int getSessionResourceHandle() throws MediaCasException {
validateInternalStates();
- long[] sessionResourceHandle = new long[1];
+ int[] sessionResourceHandle = new int[1];
sessionResourceHandle[0] = -1;
if (mTunerResourceManager != null) {
CasSessionRequest casSessionRequest = new CasSessionRequest();
@@ -1144,7 +1144,8 @@
return sessionResourceHandle[0];
}
- private void addSessionToResourceMap(Session session, long sessionResourceHandle) {
+ private void addSessionToResourceMap(Session session, int sessionResourceHandle) {
+
if (sessionResourceHandle != TunerResourceManager.INVALID_RESOURCE_HANDLE) {
synchronized (mSessionMap) {
mSessionMap.put(session, sessionResourceHandle);
@@ -1177,14 +1178,13 @@
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
public Session openSession() throws MediaCasException {
- long sessionResourceHandle = getSessionResourceHandle();
+ int sessionResourceHandle = getSessionResourceHandle();
try {
if (mICas != null) {
try {
byte[] sessionId = mICas.openSessionDefault();
Session session = createFromSessionId(sessionId);
- addSessionToResourceMap(session, sessionResourceHandle);
Log.d(TAG, "Write Stats Log for succeed to Open Session.");
FrameworkStatsLog.write(
FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS,
@@ -1238,7 +1238,7 @@
@Nullable
public Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode)
throws MediaCasException {
- long sessionResourceHandle = getSessionResourceHandle();
+ int sessionResourceHandle = getSessionResourceHandle();
if (mICas != null) {
try {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 300ae5d..2c71ee0 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -293,13 +293,13 @@
private EventHandler mHandler;
@Nullable
private FrontendInfo mFrontendInfo;
- private Long mFrontendHandle;
+ private Integer mFrontendHandle;
private Tuner mFeOwnerTuner = null;
private int mFrontendType = FrontendSettings.TYPE_UNDEFINED;
private Integer mDesiredFrontendId = null;
private int mUserId;
private Lnb mLnb;
- private Long mLnbHandle;
+ private Integer mLnbHandle;
@Nullable
private OnTuneEventListener mOnTuneEventListener;
@Nullable
@@ -322,10 +322,10 @@
private final ReentrantLock mDemuxLock = new ReentrantLock();
private int mRequestedCiCamId;
- private Long mDemuxHandle;
- private Long mFrontendCiCamHandle;
+ private Integer mDemuxHandle;
+ private Integer mFrontendCiCamHandle;
private Integer mFrontendCiCamId;
- private Map<Long, WeakReference<Descrambler>> mDescramblers = new HashMap<>();
+ private Map<Integer, WeakReference<Descrambler>> mDescramblers = new HashMap<>();
private List<WeakReference<Filter>> mFilters = new ArrayList<WeakReference<Filter>>();
private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
@@ -947,7 +947,7 @@
private void releaseDescramblers() {
synchronized (mDescramblers) {
if (!mDescramblers.isEmpty()) {
- for (Map.Entry<Long, WeakReference<Descrambler>> d : mDescramblers.entrySet()) {
+ for (Map.Entry<Integer, WeakReference<Descrambler>> d : mDescramblers.entrySet()) {
Descrambler descrambler = d.getValue().get();
if (descrambler != null) {
descrambler.close();
@@ -1008,7 +1008,7 @@
/**
* Native method to open frontend of the given ID.
*/
- private native Frontend nativeOpenFrontendByHandle(long handle);
+ private native Frontend nativeOpenFrontendByHandle(int handle);
private native int nativeShareFrontend(int id);
private native int nativeUnshareFrontend();
private native void nativeRegisterFeCbListener(long nativeContext);
@@ -1037,21 +1037,21 @@
private native int nativeSetMaxNumberOfFrontends(int frontendType, int maxNumber);
private native int nativeGetMaxNumberOfFrontends(int frontendType);
private native int nativeRemoveOutputPid(int pid);
- private native Lnb nativeOpenLnbByHandle(long handle);
+ private native Lnb nativeOpenLnbByHandle(int handle);
private native Lnb nativeOpenLnbByName(String name);
private native FrontendStatusReadiness[] nativeGetFrontendStatusReadiness(int[] statusTypes);
- private native Descrambler nativeOpenDescramblerByHandle(long handle);
- private native int nativeOpenDemuxByhandle(long handle);
+ private native Descrambler nativeOpenDescramblerByHandle(int handle);
+ private native int nativeOpenDemuxByhandle(int handle);
private native DvrRecorder nativeOpenDvrRecorder(long bufferSize);
private native DvrPlayback nativeOpenDvrPlayback(long bufferSize);
private native DemuxCapabilities nativeGetDemuxCapabilities();
- private native DemuxInfo nativeGetDemuxInfo(long demuxHandle);
+ private native DemuxInfo nativeGetDemuxInfo(int demuxHandle);
- private native int nativeCloseDemux(long handle);
- private native int nativeCloseFrontend(long handle);
+ private native int nativeCloseDemux(int handle);
+ private native int nativeCloseFrontend(int handle);
private native int nativeClose();
private static native SharedFilter nativeOpenSharedFilter(String token);
@@ -1369,7 +1369,7 @@
}
private boolean requestFrontend() {
- long[] feHandle = new long[1];
+ int[] feHandle = new int[1];
boolean granted = false;
try {
TunerFrontendRequest request = new TunerFrontendRequest();
@@ -2377,7 +2377,7 @@
}
private boolean requestLnb() {
- long[] lnbHandle = new long[1];
+ int[] lnbHandle = new int[1];
TunerLnbRequest request = new TunerLnbRequest();
request.clientId = mClientId;
boolean granted = mTunerResourceManager.requestLnb(request, lnbHandle);
@@ -2660,7 +2660,7 @@
}
private boolean requestDemux() {
- long[] demuxHandle = new long[1];
+ int[] demuxHandle = new int[1];
TunerDemuxRequest request = new TunerDemuxRequest();
request.clientId = mClientId;
request.desiredFilterTypes = mDesiredDemuxInfo.getFilterTypes();
@@ -2673,14 +2673,14 @@
}
private Descrambler requestDescrambler() {
- long[] descramblerHandle = new long[1];
+ int[] descramblerHandle = new int[1];
TunerDescramblerRequest request = new TunerDescramblerRequest();
request.clientId = mClientId;
boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle);
if (!granted) {
return null;
}
- long handle = descramblerHandle[0];
+ int handle = descramblerHandle[0];
Descrambler descrambler = nativeOpenDescramblerByHandle(handle);
if (descrambler != null) {
synchronized (mDescramblers) {
@@ -2694,7 +2694,7 @@
}
private boolean requestFrontendCiCam(int ciCamId) {
- long[] ciCamHandle = new long[1];
+ int[] ciCamHandle = new int[1];
TunerCiCamRequest request = new TunerCiCamRequest();
request.clientId = mClientId;
request.ciCamId = ciCamId;
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index bb581eb..d268aeb 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -66,7 +66,7 @@
private static final String TAG = "TunerResourceManager";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final long INVALID_RESOURCE_HANDLE = -1;
+ public static final int INVALID_RESOURCE_HANDLE = -1;
public static final int INVALID_OWNER_ID = -1;
/**
* Tuner resource type to help generate resource handle
@@ -275,7 +275,7 @@
* Updates the current TRM of the TunerHAL Frontend information.
*
* <p><strong>Note:</strong> This update must happen before the first
- * {@link #requestFrontend(TunerFrontendRequest, long[])} and
+ * {@link #requestFrontend(TunerFrontendRequest, int[])} and
* {@link #releaseFrontend(int, int)} call.
*
* @param infos an array of the available {@link TunerFrontendInfo} information.
@@ -331,7 +331,7 @@
*
* @param lnbIds ids of the updating lnbs.
*/
- public void setLnbInfoList(long[] lnbIds) {
+ public void setLnbInfoList(int[] lnbIds) {
try {
mService.setLnbInfoList(lnbIds);
} catch (RemoteException e) {
@@ -406,8 +406,8 @@
*
* @return true if there is frontend granted.
*/
- public boolean requestFrontend(
- @NonNull TunerFrontendRequest request, @Nullable long[] frontendHandle) {
+ public boolean requestFrontend(@NonNull TunerFrontendRequest request,
+ @Nullable int[] frontendHandle) {
boolean result = false;
try {
result = mService.requestFrontend(request, frontendHandle);
@@ -511,7 +511,7 @@
*
* @return true if there is Demux granted.
*/
- public boolean requestDemux(@NonNull TunerDemuxRequest request, @NonNull long[] demuxHandle) {
+ public boolean requestDemux(@NonNull TunerDemuxRequest request, @NonNull int[] demuxHandle) {
boolean result = false;
try {
result = mService.requestDemux(request, demuxHandle);
@@ -544,8 +544,8 @@
*
* @return true if there is Descrambler granted.
*/
- public boolean requestDescrambler(
- @NonNull TunerDescramblerRequest request, @NonNull long[] descramblerHandle) {
+ public boolean requestDescrambler(@NonNull TunerDescramblerRequest request,
+ @NonNull int[] descramblerHandle) {
boolean result = false;
try {
result = mService.requestDescrambler(request, descramblerHandle);
@@ -577,8 +577,8 @@
*
* @return true if there is CAS session granted.
*/
- public boolean requestCasSession(
- @NonNull CasSessionRequest request, @NonNull long[] casSessionHandle) {
+ public boolean requestCasSession(@NonNull CasSessionRequest request,
+ @NonNull int[] casSessionHandle) {
boolean result = false;
try {
result = mService.requestCasSession(request, casSessionHandle);
@@ -610,7 +610,7 @@
*
* @return true if there is ciCam granted.
*/
- public boolean requestCiCam(TunerCiCamRequest request, long[] ciCamHandle) {
+ public boolean requestCiCam(TunerCiCamRequest request, int[] ciCamHandle) {
boolean result = false;
try {
result = mService.requestCiCam(request, ciCamHandle);
@@ -635,7 +635,7 @@
* <li>If no Lnb system can be granted, the API would return false.
* <ul>
*
- * <p><strong>Note:</strong> {@link #setLnbInfoList(long[])} must be called before this request.
+ * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this request.
*
* @param request {@link TunerLnbRequest} information of the current request.
* @param lnbHandle a one-element array to return the granted Lnb handle.
@@ -643,7 +643,7 @@
*
* @return true if there is Lnb granted.
*/
- public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull long[] lnbHandle) {
+ public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) {
boolean result = false;
try {
result = mService.requestLnb(request, lnbHandle);
@@ -664,7 +664,7 @@
* @param frontendHandle the handle of the released frontend.
* @param clientId the id of the client that is releasing the frontend.
*/
- public void releaseFrontend(long frontendHandle, int clientId) {
+ public void releaseFrontend(int frontendHandle, int clientId) {
try {
mService.releaseFrontend(frontendHandle, clientId);
} catch (RemoteException e) {
@@ -680,7 +680,7 @@
* @param demuxHandle the handle of the released Tuner Demux.
* @param clientId the id of the client that is releasing the demux.
*/
- public void releaseDemux(long demuxHandle, int clientId) {
+ public void releaseDemux(int demuxHandle, int clientId) {
try {
mService.releaseDemux(demuxHandle, clientId);
} catch (RemoteException e) {
@@ -696,7 +696,7 @@
* @param descramblerHandle the handle of the released Tuner Descrambler.
* @param clientId the id of the client that is releasing the descrambler.
*/
- public void releaseDescrambler(long descramblerHandle, int clientId) {
+ public void releaseDescrambler(int descramblerHandle, int clientId) {
try {
mService.releaseDescrambler(descramblerHandle, clientId);
} catch (RemoteException e) {
@@ -715,7 +715,7 @@
* @param casSessionHandle the handle of the released CAS session.
* @param clientId the id of the client that is releasing the cas session.
*/
- public void releaseCasSession(long casSessionHandle, int clientId) {
+ public void releaseCasSession(int casSessionHandle, int clientId) {
try {
mService.releaseCasSession(casSessionHandle, clientId);
} catch (RemoteException e) {
@@ -734,7 +734,7 @@
* @param ciCamHandle the handle of the releasing CiCam.
* @param clientId the id of the client that is releasing the CiCam.
*/
- public void releaseCiCam(long ciCamHandle, int clientId) {
+ public void releaseCiCam(int ciCamHandle, int clientId) {
try {
mService.releaseCiCam(ciCamHandle, clientId);
} catch (RemoteException e) {
@@ -747,12 +747,12 @@
*
* <p>Client must call this whenever it releases an Lnb.
*
- * <p><strong>Note:</strong> {@link #setLnbInfoList(long[])} must be called before this release.
+ * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this release.
*
* @param lnbHandle the handle of the released Tuner Lnb.
* @param clientId the id of the client that is releasing the lnb.
*/
- public void releaseLnb(long lnbHandle, int clientId) {
+ public void releaseLnb(int lnbHandle, int clientId) {
try {
mService.releaseLnb(lnbHandle, clientId);
} catch (RemoteException e) {
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index 109c791..5399697 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -149,7 +149,7 @@
*
* @param lnbIds ids of the updating lnbs.
*/
- void setLnbInfoList(in long[] lnbIds);
+ void setLnbInfoList(in int[] lnbIds);
/*
* This API is used by the Tuner framework to request a frontend from the TunerHAL.
@@ -185,7 +185,7 @@
*
* @return true if there is frontend granted.
*/
- boolean requestFrontend(in TunerFrontendRequest request, out long[] frontendHandle);
+ boolean requestFrontend(in TunerFrontendRequest request, out int[] frontendHandle);
/*
* Sets the maximum usable frontends number of a given frontend type. It is used to enable or
@@ -253,7 +253,7 @@
*
* @return true if there is demux granted.
*/
- boolean requestDemux(in TunerDemuxRequest request, out long[] demuxHandle);
+ boolean requestDemux(in TunerDemuxRequest request, out int[] demuxHandle);
/*
* This API is used by the Tuner framework to request an available descrambler from the
@@ -277,7 +277,7 @@
*
* @return true if there is Descrambler granted.
*/
- boolean requestDescrambler(in TunerDescramblerRequest request, out long[] descramblerHandle);
+ boolean requestDescrambler(in TunerDescramblerRequest request, out int[] descramblerHandle);
/*
* This API is used by the Tuner framework to request an available Cas session. This session
@@ -303,7 +303,7 @@
*
* @return true if there is CAS session granted.
*/
- boolean requestCasSession(in CasSessionRequest request, out long[] casSessionHandle);
+ boolean requestCasSession(in CasSessionRequest request, out int[] casSessionHandle);
/*
* This API is used by the Tuner framework to request an available CuCam.
@@ -328,7 +328,7 @@
*
* @return true if there is CiCam granted.
*/
- boolean requestCiCam(in TunerCiCamRequest request, out long[] ciCamHandle);
+ boolean requestCiCam(in TunerCiCamRequest request, out int[] ciCamHandle);
/*
* This API is used by the Tuner framework to request an available Lnb from the TunerHAL.
@@ -352,7 +352,7 @@
*
* @return true if there is Lnb granted.
*/
- boolean requestLnb(in TunerLnbRequest request, out long[] lnbHandle);
+ boolean requestLnb(in TunerLnbRequest request, out int[] lnbHandle);
/*
* Notifies the TRM that the given frontend has been released.
@@ -365,7 +365,7 @@
* @param frontendHandle the handle of the released frontend.
* @param clientId the id of the client that is releasing the frontend.
*/
- void releaseFrontend(in long frontendHandle, int clientId);
+ void releaseFrontend(in int frontendHandle, int clientId);
/*
* Notifies the TRM that the Demux with the given handle was released.
@@ -375,7 +375,7 @@
* @param demuxHandle the handle of the released Tuner Demux.
* @param clientId the id of the client that is releasing the demux.
*/
- void releaseDemux(in long demuxHandle, int clientId);
+ void releaseDemux(in int demuxHandle, int clientId);
/*
* Notifies the TRM that the Descrambler with the given handle was released.
@@ -385,7 +385,7 @@
* @param descramblerHandle the handle of the released Tuner Descrambler.
* @param clientId the id of the client that is releasing the descrambler.
*/
- void releaseDescrambler(in long descramblerHandle, int clientId);
+ void releaseDescrambler(in int descramblerHandle, int clientId);
/*
* Notifies the TRM that the given Cas session has been released.
@@ -397,7 +397,7 @@
* @param casSessionHandle the handle of the released CAS session.
* @param clientId the id of the client that is releasing the cas session.
*/
- void releaseCasSession(in long casSessionHandle, int clientId);
+ void releaseCasSession(in int casSessionHandle, int clientId);
/**
* Notifies the TRM that the given CiCam has been released.
@@ -410,7 +410,7 @@
* @param ciCamHandle the handle of the releasing CiCam.
* @param clientId the id of the client that is releasing the CiCam.
*/
- void releaseCiCam(in long ciCamHandle, int clientId);
+ void releaseCiCam(in int ciCamHandle, int clientId);
/*
* Notifies the TRM that the Lnb with the given handle was released.
@@ -422,7 +422,7 @@
* @param lnbHandle the handle of the released Tuner Lnb.
* @param clientId the id of the client that is releasing the lnb.
*/
- void releaseLnb(in long lnbHandle, int clientId);
+ void releaseLnb(in int lnbHandle, int clientId);
/*
* Compare two clients' priority.
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxInfo.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxInfo.aidl
index 7984c38..c14caf5 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxInfo.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxInfo.aidl
@@ -26,7 +26,7 @@
/**
* Demux handle
*/
- long handle;
+ int handle;
/**
* Supported filter types (defined in {@link android.media.tv.tuner.filter.Filter})
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
index 274367e..8981ce0 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
@@ -26,7 +26,7 @@
/**
* Frontend Handle
*/
- long handle;
+ int handle;
/**
* Frontend Type
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 5eb2485..00b0e57 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1448,7 +1448,7 @@
return obj;
}
-jobject JTuner::openFrontendByHandle(jlong feHandle) {
+jobject JTuner::openFrontendByHandle(int feHandle) {
// TODO: Handle reopening frontend with different handle
sp<FrontendClient> feClient = sTunerClient->openFrontend(feHandle);
if (feClient == nullptr) {
@@ -1824,7 +1824,7 @@
return valObj;
}
-jobject JTuner::openLnbByHandle(jlong handle) {
+jobject JTuner::openLnbByHandle(int handle) {
if (sTunerClient == nullptr) {
return nullptr;
}
@@ -1833,7 +1833,7 @@
sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
lnbClient = sTunerClient->openLnb(handle);
if (lnbClient == nullptr) {
- ALOGD("Failed to open lnb, handle = %ld", handle);
+ ALOGD("Failed to open lnb, handle = %d", handle);
return nullptr;
}
@@ -1947,7 +1947,7 @@
return (int)result;
}
-Result JTuner::openDemux(jlong handle) {
+Result JTuner::openDemux(int handle) {
if (sTunerClient == nullptr) {
return Result::NOT_INITIALIZED;
}
@@ -2215,7 +2215,7 @@
numBytesInSectionFilter, filterCaps, filterCapsList, linkCaps, bTimeFilter);
}
-jobject JTuner::getDemuxInfo(jlong handle) {
+jobject JTuner::getDemuxInfo(int handle) {
if (sTunerClient == nullptr) {
ALOGE("tuner is not initialized");
return nullptr;
@@ -3768,8 +3768,8 @@
return tuner->getFrontendIds();
}
-static jobject android_media_tv_Tuner_open_frontend_by_handle(JNIEnv *env, jobject thiz,
- jlong handle) {
+static jobject android_media_tv_Tuner_open_frontend_by_handle(
+ JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openFrontendByHandle(handle);
}
@@ -3901,7 +3901,7 @@
return tuner->getFrontendInfo(id);
}
-static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jlong handle) {
+static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openLnbByHandle(handle);
}
@@ -4622,7 +4622,7 @@
return (int)r;
}
-static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jlong) {
+static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openDescrambler();
}
@@ -4690,12 +4690,12 @@
return tuner->getDemuxCaps();
}
-static jobject android_media_tv_Tuner_get_demux_info(JNIEnv *env, jobject thiz, jlong handle) {
+static jobject android_media_tv_Tuner_get_demux_info(JNIEnv* env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->getDemuxInfo(handle);
}
-static jint android_media_tv_Tuner_open_demux(JNIEnv *env, jobject thiz, jlong handle) {
+static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
return (jint)tuner->openDemux(handle);
}
@@ -4706,7 +4706,7 @@
return (jint)tuner->close();
}
-static jint android_media_tv_Tuner_close_demux(JNIEnv *env, jobject thiz, jlong /* handle */) {
+static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->closeDemux();
}
@@ -4766,7 +4766,7 @@
return tuner->getFrontendStatusReadiness(types);
}
-static jint android_media_tv_Tuner_close_frontend(JNIEnv *env, jobject thiz, jlong /* handle */) {
+static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->closeFrontend();
}
@@ -5035,7 +5035,7 @@
{ "nativeGetTunerVersion", "()I", (void *)android_media_tv_Tuner_native_get_tuner_version },
{ "nativeGetFrontendIds", "()Ljava/util/List;",
(void *)android_media_tv_Tuner_get_frontend_ids },
- { "nativeOpenFrontendByHandle", "(J)Landroid/media/tv/tuner/Tuner$Frontend;",
+ { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
(void *)android_media_tv_Tuner_open_frontend_by_handle },
{ "nativeShareFrontend", "(I)I",
(void *)android_media_tv_Tuner_share_frontend },
@@ -5074,11 +5074,11 @@
(void *)android_media_tv_Tuner_open_filter },
{ "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/filter/TimeFilter;",
(void *)android_media_tv_Tuner_open_time_filter },
- { "nativeOpenLnbByHandle", "(J)Landroid/media/tv/tuner/Lnb;",
+ { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;",
(void *)android_media_tv_Tuner_open_lnb_by_handle },
{ "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;",
(void *)android_media_tv_Tuner_open_lnb_by_name },
- { "nativeOpenDescramblerByHandle", "(J)Landroid/media/tv/tuner/Descrambler;",
+ { "nativeOpenDescramblerByHandle", "(I)Landroid/media/tv/tuner/Descrambler;",
(void *)android_media_tv_Tuner_open_descrambler },
{ "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
(void *)android_media_tv_Tuner_open_dvr_recorder },
@@ -5086,12 +5086,12 @@
(void *)android_media_tv_Tuner_open_dvr_playback },
{ "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
(void *)android_media_tv_Tuner_get_demux_caps },
- { "nativeGetDemuxInfo", "(J)Landroid/media/tv/tuner/DemuxInfo;",
+ { "nativeGetDemuxInfo", "(I)Landroid/media/tv/tuner/DemuxInfo;",
(void *)android_media_tv_Tuner_get_demux_info },
- { "nativeOpenDemuxByhandle", "(J)I", (void *)android_media_tv_Tuner_open_demux },
+ { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux },
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
- { "nativeCloseFrontend", "(J)I", (void *)android_media_tv_Tuner_close_frontend },
- { "nativeCloseDemux", "(J)I", (void *)android_media_tv_Tuner_close_demux },
+ { "nativeCloseFrontend", "(I)I", (void *)android_media_tv_Tuner_close_frontend },
+ { "nativeCloseDemux", "(I)I", (void *)android_media_tv_Tuner_close_demux },
{ "nativeOpenSharedFilter",
"(Ljava/lang/String;)Landroid/media/tv/tuner/filter/SharedFilter;",
(void *)android_media_tv_Tuner_open_shared_filter},
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 7af2cd7..3de3ab9 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -206,7 +206,7 @@
int disconnectCiCam();
int unlinkCiCam(jint id);
jobject getFrontendIds();
- jobject openFrontendByHandle(jlong feHandle);
+ jobject openFrontendByHandle(int feHandle);
int shareFrontend(int feId);
int unshareFrontend();
void registerFeCbListener(JTuner* jtuner);
@@ -221,16 +221,16 @@
int setLnb(sp<LnbClient> lnbClient);
bool isLnaSupported();
int setLna(bool enable);
- jobject openLnbByHandle(jlong handle);
+ jobject openLnbByHandle(int handle);
jobject openLnbByName(jstring name);
jobject openFilter(DemuxFilterType type, int bufferSize);
jobject openTimeFilter();
jobject openDescrambler();
jobject openDvr(DvrType type, jlong bufferSize);
jobject getDemuxCaps();
- jobject getDemuxInfo(jlong handle);
+ jobject getDemuxInfo(int handle);
jobject getFrontendStatus(jintArray types);
- Result openDemux(jlong handle);
+ Result openDemux(int handle);
jint close();
jint closeFrontend();
jint closeDemux();
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index 0097710..ea623d9 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -56,7 +56,7 @@
return ids;
}
-sp<FrontendClient> TunerClient::openFrontend(int64_t frontendHandle) {
+sp<FrontendClient> TunerClient::openFrontend(int32_t frontendHandle) {
if (mTunerService != nullptr) {
shared_ptr<ITunerFrontend> tunerFrontend;
Status s = mTunerService->openFrontend(frontendHandle, &tunerFrontend);
@@ -94,7 +94,7 @@
return nullptr;
}
-sp<DemuxClient> TunerClient::openDemux(int64_t demuxHandle) {
+sp<DemuxClient> TunerClient::openDemux(int32_t demuxHandle) {
if (mTunerService != nullptr) {
shared_ptr<ITunerDemux> tunerDemux;
Status s = mTunerService->openDemux(demuxHandle, &tunerDemux);
@@ -107,7 +107,7 @@
return nullptr;
}
-shared_ptr<DemuxInfo> TunerClient::getDemuxInfo(int64_t demuxHandle) {
+shared_ptr<DemuxInfo> TunerClient::getDemuxInfo(int32_t demuxHandle) {
if (mTunerService != nullptr) {
DemuxInfo aidlDemuxInfo;
Status s = mTunerService->getDemuxInfo(demuxHandle, &aidlDemuxInfo);
@@ -141,7 +141,7 @@
return nullptr;
}
-sp<DescramblerClient> TunerClient::openDescrambler(int64_t descramblerHandle) {
+sp<DescramblerClient> TunerClient::openDescrambler(int32_t descramblerHandle) {
if (mTunerService != nullptr) {
shared_ptr<ITunerDescrambler> tunerDescrambler;
Status s = mTunerService->openDescrambler(descramblerHandle, &tunerDescrambler);
@@ -154,7 +154,7 @@
return nullptr;
}
-sp<LnbClient> TunerClient::openLnb(int64_t lnbHandle) {
+sp<LnbClient> TunerClient::openLnb(int32_t lnbHandle) {
if (mTunerService != nullptr) {
shared_ptr<ITunerLnb> tunerLnb;
Status s = mTunerService->openLnb(lnbHandle, &tunerLnb);
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index a348586..6ab120b 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -65,7 +65,7 @@
* @param frontendHandle the handle of the frontend granted by TRM.
* @return a newly created FrontendClient interface.
*/
- sp<FrontendClient> openFrontend(int64_t frontendHandle);
+ sp<FrontendClient> openFrontend(int32_t frontendHandle);
/**
* Retrieve the granted frontend's information.
@@ -81,7 +81,7 @@
* @param demuxHandle the handle of the demux granted by TRM.
* @return a newly created DemuxClient interface.
*/
- sp<DemuxClient> openDemux(int64_t demuxHandle);
+ sp<DemuxClient> openDemux(int32_t demuxHandle);
/**
* Retrieve the DemuxInfo of a specific demux
@@ -89,7 +89,7 @@
* @param demuxHandle the handle of the demux to query demux info for
* @return the demux info
*/
- shared_ptr<DemuxInfo> getDemuxInfo(int64_t demuxHandle);
+ shared_ptr<DemuxInfo> getDemuxInfo(int32_t demuxHandle);
/**
* Retrieve a list of demux info
@@ -111,7 +111,7 @@
* @param descramblerHandle the handle of the descrambler granted by TRM.
* @return a newly created DescramblerClient interface.
*/
- sp<DescramblerClient> openDescrambler(int64_t descramblerHandle);
+ sp<DescramblerClient> openDescrambler(int32_t descramblerHandle);
/**
* Open a new interface of LnbClient given an lnbHandle.
@@ -119,7 +119,7 @@
* @param lnbHandle the handle of the LNB granted by TRM.
* @return a newly created LnbClient interface.
*/
- sp<LnbClient> openLnb(int64_t lnbHandle);
+ sp<LnbClient> openLnb(int32_t lnbHandle);
/**
* Open a new interface of LnbClient given a LNB name.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index 79b3856..5e96381 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -245,9 +245,7 @@
interface ElementContentPicker {
/**
* Return the content in which [element] should be drawn (when using `Modifier.element(key)`) or
- * composed (when using `MovableElement(key)`) during the given [transition]. If this element
- * should not be drawn or composed in neither [transition.fromContent] nor
- * [transition.toContent], return `null`.
+ * composed (when using `MovableElement(key)`) during the given [transition].
*
* Important: For [MovableElements][ContentScope.MovableElement], this content picker will
* *always* be used during transitions to decide whether we should compose that element in a
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt
deleted file mode 100644
index b2f5765..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropStateTest.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.panels.ui.compose
-
-import androidx.compose.runtime.mutableStateOf
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.common.shared.model.Text
-import com.android.systemui.qs.panels.shared.model.SizedTile
-import com.android.systemui.qs.panels.shared.model.SizedTileImpl
-import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
-import com.android.systemui.qs.pipeline.shared.TileSpec
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class DragAndDropStateTest : SysuiTestCase() {
- private val listState = EditTileListState(TestEditTiles)
- private val underTest = DragAndDropState(mutableStateOf(null), listState)
-
- @Test
- fun isMoving_returnsCorrectValue() {
- // Asserts no tiles is moving
- TestEditTiles.forEach { assertThat(underTest.isMoving(it.tile.tileSpec)).isFalse() }
-
- // Start the drag movement
- underTest.onStarted(TestEditTiles[0])
-
- // Assert that the correct tile is marked as moving
- TestEditTiles.forEach {
- assertThat(underTest.isMoving(it.tile.tileSpec))
- .isEqualTo(TestEditTiles[0].tile.tileSpec == it.tile.tileSpec)
- }
- }
-
- @Test
- fun onMoved_updatesList() {
- // Start the drag movement
- underTest.onStarted(TestEditTiles[0])
-
- // Move the tile to the end of the list
- underTest.onMoved(listState.tiles[5].tile.tileSpec)
- assertThat(underTest.currentPosition()).isEqualTo(5)
-
- // Move the tile to the middle of the list
- underTest.onMoved(listState.tiles[2].tile.tileSpec)
- assertThat(underTest.currentPosition()).isEqualTo(2)
- }
-
- @Test
- fun onDrop_resetsMovingTile() {
- // Start the drag movement
- underTest.onStarted(TestEditTiles[0])
-
- // Move the tile to the end of the list
- underTest.onMoved(listState.tiles[5].tile.tileSpec)
-
- // Drop the tile
- underTest.onDrop()
-
- // Asserts no tiles is moving
- TestEditTiles.forEach { assertThat(underTest.isMoving(it.tile.tileSpec)).isFalse() }
- }
-
- @Test
- fun onMoveOutOfBounds_removeMovingTileFromCurrentList() {
- // Start the drag movement
- underTest.onStarted(TestEditTiles[0])
-
- // Move the tile outside of the list
- underTest.movedOutOfBounds()
-
- // Asserts the moving tile is not current
- assertThat(
- listState.tiles.firstOrNull { it.tile.tileSpec == TestEditTiles[0].tile.tileSpec }
- )
- .isNull()
- }
-
- companion object {
- private fun createEditTile(tileSpec: String): SizedTile<EditTileViewModel> {
- return SizedTileImpl(
- EditTileViewModel(
- tileSpec = TileSpec.create(tileSpec),
- icon = Icon.Resource(0, null),
- label = Text.Loaded("unused"),
- appName = null,
- isCurrent = true,
- availableEditActions = emptySet(),
- ),
- 1,
- )
- }
-
- private val TestEditTiles =
- listOf(
- createEditTile("tileA"),
- createEditTile("tileB"),
- createEditTile("tileC"),
- createEditTile("tileD"),
- createEditTile("tileE"),
- createEditTile("tileF"),
- )
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
new file mode 100644
index 0000000..4d1dd1c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.panels.ui.compose
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.hasContentDescription
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onChildren
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.common.shared.model.Text
+import com.android.systemui.qs.panels.shared.model.SizedTile
+import com.android.systemui.qs.panels.shared.model.SizedTileImpl
+import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DragAndDropTest : SysuiTestCase() {
+ @get:Rule val composeRule = createComposeRule()
+
+ // TODO(ostonge): Investigate why drag isn't detected when using performTouchInput
+ @Composable
+ private fun EditTileGridUnderTest(
+ listState: EditTileListState,
+ onSetTiles: (List<TileSpec>) -> Unit
+ ) {
+ DefaultEditTileGrid(
+ currentListState = listState,
+ otherTiles = listOf(),
+ columns = 4,
+ modifier = Modifier.fillMaxSize(),
+ onAddTile = { _, _ -> },
+ onRemoveTile = {},
+ onSetTiles = onSetTiles,
+ onResize = {},
+ )
+ }
+
+ @Test
+ fun draggedTile_shouldDisappear() {
+ var tiles by mutableStateOf(TestEditTiles)
+ val listState = EditTileListState(tiles, 4)
+ composeRule.setContent {
+ EditTileGridUnderTest(listState) {
+ tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) }
+ }
+ }
+ composeRule.waitForIdle()
+
+ listState.onStarted(TestEditTiles[0])
+
+ // Tile is being dragged, it should be replaced with a placeholder
+ composeRule.onNodeWithContentDescription("tileA").assertDoesNotExist()
+
+ // Available tiles should disappear
+ composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertDoesNotExist()
+
+ // Remove drop zone should appear
+ composeRule.onNodeWithText("Remove").assertExists()
+
+ // Every other tile should still be in the same order
+ composeRule.assertTileGridContainsExactly(listOf("tileB", "tileC", "tileD_large", "tileE"))
+ }
+
+ @Test
+ fun draggedTile_shouldChangePosition() {
+ var tiles by mutableStateOf(TestEditTiles)
+ val listState = EditTileListState(tiles, 4)
+ composeRule.setContent {
+ EditTileGridUnderTest(listState) {
+ tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) }
+ }
+ }
+ composeRule.waitForIdle()
+
+ listState.onStarted(TestEditTiles[0])
+ listState.onMoved(1, false)
+ listState.onDrop()
+
+ // Available tiles should re-appear
+ composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists()
+
+ // Remove drop zone should disappear
+ composeRule.onNodeWithText("Remove").assertDoesNotExist()
+
+ // Tile A and B should swap places
+ composeRule.assertTileGridContainsExactly(
+ listOf("tileB", "tileA", "tileC", "tileD_large", "tileE")
+ )
+ }
+
+ @Test
+ fun draggedTileOut_shouldBeRemoved() {
+ var tiles by mutableStateOf(TestEditTiles)
+ val listState = EditTileListState(tiles, 4)
+ composeRule.setContent {
+ EditTileGridUnderTest(listState) {
+ tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) }
+ }
+ }
+ composeRule.waitForIdle()
+
+ listState.onStarted(TestEditTiles[0])
+ listState.movedOutOfBounds()
+ listState.onDrop()
+
+ // Available tiles should re-appear
+ composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists()
+
+ // Remove drop zone should disappear
+ composeRule.onNodeWithText("Remove").assertDoesNotExist()
+
+ // Tile A is gone
+ composeRule.assertTileGridContainsExactly(listOf("tileB", "tileC", "tileD_large", "tileE"))
+ }
+
+ @Test
+ fun draggedNewTileIn_shouldBeAdded() {
+ var tiles by mutableStateOf(TestEditTiles)
+ val listState = EditTileListState(tiles, 4)
+ composeRule.setContent {
+ EditTileGridUnderTest(listState) {
+ tiles = it.map { tileSpec -> createEditTile(tileSpec.spec) }
+ }
+ }
+ composeRule.waitForIdle()
+
+ listState.onStarted(createEditTile("newTile"))
+ // Insert after tileD, which is at index 4
+ // [ a ] [ b ] [ c ] [ empty ]
+ // [ tile d ] [ e ]
+ listState.onMoved(4, insertAfter = true)
+ listState.onDrop()
+
+ // Available tiles should re-appear
+ composeRule.onNodeWithTag(AVAILABLE_TILES_GRID_TEST_TAG).assertExists()
+
+ // Remove drop zone should disappear
+ composeRule.onNodeWithText("Remove").assertDoesNotExist()
+
+ // newTile is added after tileD
+ composeRule.assertTileGridContainsExactly(
+ listOf("tileA", "tileB", "tileC", "tileD_large", "newTile", "tileE")
+ )
+ }
+
+ private fun ComposeContentTestRule.assertTileGridContainsExactly(specs: List<String>) {
+ onNodeWithTag(CURRENT_TILES_GRID_TEST_TAG).onChildren().apply {
+ fetchSemanticsNodes().forEachIndexed { index, _ ->
+ get(index).onChildAt(0).assert(hasContentDescription(specs[index]))
+ }
+ }
+ }
+
+ companion object {
+ private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid"
+ private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid"
+
+ private fun createEditTile(tileSpec: String): SizedTile<EditTileViewModel> {
+ return SizedTileImpl(
+ EditTileViewModel(
+ tileSpec = TileSpec.create(tileSpec),
+ icon =
+ Icon.Resource(
+ android.R.drawable.star_on,
+ ContentDescription.Loaded(tileSpec)
+ ),
+ label = Text.Loaded(tileSpec),
+ appName = null,
+ isCurrent = true,
+ availableEditActions = emptySet(),
+ ),
+ getWidth(tileSpec),
+ )
+ }
+
+ private fun getWidth(tileSpec: String): Int {
+ return if (tileSpec.endsWith("large")) {
+ 2
+ } else {
+ 1
+ }
+ }
+
+ private val TestEditTiles =
+ listOf(
+ createEditTile("tileA"),
+ createEditTile("tileB"),
+ createEditTile("tileC"),
+ createEditTile("tileD_large"),
+ createEditTile("tileE"),
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt
index a3a6a33..7f01fad 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/EditTileListStateTest.kt
@@ -23,6 +23,9 @@
import com.android.systemui.common.shared.model.Text
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.shared.model.SizedTileImpl
+import com.android.systemui.qs.panels.ui.model.GridCell
+import com.android.systemui.qs.panels.ui.model.SpacerGridCell
+import com.android.systemui.qs.panels.ui.model.TileGridCell
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.google.common.truth.Truth.assertThat
@@ -32,80 +35,130 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class EditTileListStateTest : SysuiTestCase() {
- val underTest = EditTileListState(TestEditTiles)
+ private val underTest = EditTileListState(TestEditTiles, 4)
@Test
- fun movingNonExistentTile_tileAdded() {
- val newTile = createEditTile("other_tile", false)
- underTest.move(newTile, TestEditTiles[0].tile.tileSpec)
-
- assertThat(underTest.tiles[0]).isEqualTo(newTile)
- assertThat(underTest.tiles.subList(1, underTest.tiles.size))
- .containsExactly(*TestEditTiles.toTypedArray())
+ fun noDrag_listUnchanged() {
+ underTest.tiles.forEach { assertThat(it).isNotInstanceOf(SpacerGridCell::class.java) }
+ assertThat(underTest.tiles.map { (it as TileGridCell).tile.tileSpec })
+ .containsExactly(*TestEditTiles.map { it.tile.tileSpec }.toTypedArray())
}
@Test
- fun movingTileToNonExistentTarget_listUnchanged() {
- underTest.move(TestEditTiles[0], TileSpec.create("other_tile"))
+ fun startDrag_listHasSpacers() {
+ underTest.onStarted(TestEditTiles[0])
- assertThat(underTest.tiles).containsExactly(*TestEditTiles.toTypedArray())
+ // [ a ] [ b ] [ c ] [ X ]
+ // [ Large D ] [ e ] [ X ]
+ assertThat(underTest.tiles.toStrings())
+ .isEqualTo(listOf("a", "b", "c", "spacer", "d", "e", "spacer"))
+ assertThat(underTest.isMoving(TestEditTiles[0].tile.tileSpec)).isTrue()
+ assertThat(underTest.dragInProgress).isTrue()
}
@Test
- fun movingTileToItself_listUnchanged() {
- underTest.move(TestEditTiles[0], TestEditTiles[0].tile.tileSpec)
+ fun moveDrag_listChanges() {
+ underTest.onStarted(TestEditTiles[4])
+ underTest.onMoved(3, false)
- assertThat(underTest.tiles).containsExactly(*TestEditTiles.toTypedArray())
+ // Tile E goes to index 3
+ // [ a ] [ b ] [ c ] [ e ]
+ // [ Large D ] [ X ] [ X ]
+ assertThat(underTest.tiles.toStrings())
+ .isEqualTo(listOf("a", "b", "c", "e", "d", "spacer", "spacer"))
}
@Test
- fun movingTileToSameSection_listUpdates() {
- // Move tile at index 0 to index 1. Tile 0 should remain current.
- underTest.move(TestEditTiles[0], TestEditTiles[1].tile.tileSpec)
+ fun moveDragOnSidesOfLargeTile_listChanges() {
+ val draggedCell = TestEditTiles[4]
- // Assert the tiles 0 and 1 have changed places.
- assertThat(underTest.tiles[0]).isEqualTo(TestEditTiles[1])
- assertThat(underTest.tiles[1]).isEqualTo(TestEditTiles[0])
+ underTest.onStarted(draggedCell)
+ underTest.onMoved(4, true)
- // Assert the rest of the list is unchanged
- assertThat(underTest.tiles.subList(2, 5))
- .containsExactly(*TestEditTiles.subList(2, 5).toTypedArray())
+ // Tile E goes to the right side of tile D, list is unchanged
+ // [ a ] [ b ] [ c ] [ X ]
+ // [ Large D ] [ e ] [ X ]
+ assertThat(underTest.tiles.toStrings())
+ .isEqualTo(listOf("a", "b", "c", "spacer", "d", "e", "spacer"))
+
+ underTest.onMoved(4, false)
+
+ // Tile E goes to the left side of tile D, they swap positions
+ // [ a ] [ b ] [ c ] [ e ]
+ // [ Large D ] [ X ] [ X ]
+ assertThat(underTest.tiles.toStrings())
+ .isEqualTo(listOf("a", "b", "c", "e", "d", "spacer", "spacer"))
}
- fun removingTile_listUpdates() {
- // Remove tile at index 0
- underTest.remove(TestEditTiles[0].tile.tileSpec)
+ @Test
+ fun moveNewTile_tileIsAdded() {
+ val newTile = createEditTile("newTile", 2)
- // Assert the tile was removed
- assertThat(underTest.tiles).containsExactly(*TestEditTiles.subList(1, 6).toTypedArray())
+ underTest.onStarted(newTile)
+ underTest.onMoved(5, false)
+
+ // New tile goes to index 5
+ // [ a ] [ b ] [ c ] [ X ]
+ // [ Large D ] [ newTile ]
+ // [ e ] [ X ] [ X ] [ X ]
+ assertThat(underTest.tiles.toStrings())
+ .isEqualTo(
+ listOf("a", "b", "c", "spacer", "d", "newTile", "e", "spacer", "spacer", "spacer")
+ )
+ }
+
+ @Test
+ fun droppedNewTile_spacersDisappear() {
+ underTest.onStarted(TestEditTiles[0])
+ underTest.onDrop()
+
+ assertThat(underTest.tiles.toStrings()).isEqualTo(listOf("a", "b", "c", "d", "e"))
+ assertThat(underTest.isMoving(TestEditTiles[0].tile.tileSpec)).isFalse()
+ assertThat(underTest.dragInProgress).isFalse()
+ }
+
+ @Test
+ fun movedTileOutOfBounds_tileDisappears() {
+ underTest.onStarted(TestEditTiles[0])
+ underTest.movedOutOfBounds()
+
+ assertThat(underTest.tiles.toStrings()).doesNotContain(TestEditTiles[0].tile.tileSpec.spec)
+ }
+
+ private fun List<GridCell>.toStrings(): List<String> {
+ return map {
+ if (it is TileGridCell) {
+ it.tile.tileSpec.spec
+ } else {
+ "spacer"
+ }
+ }
}
companion object {
- private fun createEditTile(
- tileSpec: String,
- isCurrent: Boolean
- ): SizedTile<EditTileViewModel> {
+ private fun createEditTile(tileSpec: String, width: Int): SizedTile<EditTileViewModel> {
return SizedTileImpl(
EditTileViewModel(
tileSpec = TileSpec.create(tileSpec),
icon = Icon.Resource(0, null),
label = Text.Loaded("unused"),
appName = null,
- isCurrent = isCurrent,
+ isCurrent = true,
availableEditActions = emptySet(),
),
- 1,
+ width,
)
}
+ // [ a ] [ b ] [ c ]
+ // [ Large D ] [ e ] [ f ]
private val TestEditTiles =
listOf(
- createEditTile("tileA", true),
- createEditTile("tileB", true),
- createEditTile("tileC", true),
- createEditTile("tileD", false),
- createEditTile("tileE", false),
- createEditTile("tileF", false),
+ createEditTile("a", 1),
+ createEditTile("b", 1),
+ createEditTile("c", 1),
+ createEditTile("d", 2),
+ createEditTile("e", 1),
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index a301155..baf8f5a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -139,6 +140,7 @@
@Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
@Inject Lazy<CommandQueue> mCommandQueue;
@Inject Lazy<UiEventLogger> mUiEventLogger;
+ @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
@Inject Lazy<NotificationSectionsManager> mNotificationSectionsManagerLazy;
@Inject Lazy<ScreenOffAnimationController> mScreenOffAnimationController;
@@ -184,6 +186,7 @@
mProviders.put(CommandQueue.class, mCommandQueue::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
+ mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
mProviders.put(NotificationSectionsManager.class, mNotificationSectionsManagerLazy::get);
mProviders.put(ScreenOffAnimationController.class, mScreenOffAnimationController::get);
mProviders.put(AmbientState.class, mAmbientStateLazy::get);
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt
deleted file mode 100644
index 3e382d6..0000000
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.inputdevice.tutorial.ui.view
-
-import android.os.Bundle
-import android.view.WindowManager
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.enableEdgeToEdge
-import androidx.activity.viewModels
-import androidx.compose.runtime.Composable
-import com.android.compose.theme.PlatformTheme
-import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider
-import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel
-import java.util.Optional
-import javax.inject.Inject
-
-/**
- * Activity for out of the box experience for keyboard and touchpad. Note that it's possible that
- * either of them are actually not connected when this is launched
- */
-class KeyboardTouchpadTutorialActivity
-@Inject
-constructor(
- private val viewModelFactory: KeyboardTouchpadTutorialViewModel.Factory,
- private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>,
-) : ComponentActivity() {
-
- private val vm by
- viewModels<KeyboardTouchpadTutorialViewModel>(factoryProducer = { viewModelFactory })
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContent {
- PlatformTheme {
- KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) { finish() }
- }
- }
- // required to handle 3+ fingers on touchpad
- window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
- }
-
- override fun onResume() {
- super.onResume()
- vm.onOpened()
- }
-
- override fun onPause() {
- super.onPause()
- vm.onClosed()
- }
-}
-
-@Composable
-fun KeyboardTouchpadTutorialContainer(
- vm: KeyboardTouchpadTutorialViewModel,
- touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>,
- closeTutorial: () -> Unit
-) {}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt
deleted file mode 100644
index 39b1ec0..0000000
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.inputdevice.tutorial.ui.viewmodel
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
-import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
-import java.util.Optional
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-class KeyboardTouchpadTutorialViewModel(
- private val gesturesInteractor: Optional<TouchpadGesturesInteractor>
-) : ViewModel() {
-
- private val _screen = MutableStateFlow(Screen.BACK_GESTURE)
- val screen: StateFlow<Screen> = _screen
-
- fun goTo(screen: Screen) {
- _screen.value = screen
- }
-
- fun onOpened() {
- gesturesInteractor.ifPresent { it.disableGestures() }
- }
-
- fun onClosed() {
- gesturesInteractor.ifPresent { it.enableGestures() }
- }
-
- class Factory
- @Inject
- constructor(private val gesturesInteractor: Optional<TouchpadGesturesInteractor>) :
- ViewModelProvider.Factory {
-
- @Suppress("UNCHECKED_CAST")
- override fun <T : ViewModel> create(modelClass: Class<T>): T {
- return KeyboardTouchpadTutorialViewModel(gesturesInteractor) as T
- }
- }
-}
-
-enum class Screen {
- BACK_GESTURE,
- HOME_GESTURE,
- ACTION_KEY
-}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadTutorialModule.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialModule.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/KeyboardTouchpadTutorialModule.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialModule.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/TouchpadTutorialScreensProvider.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/TouchpadTutorialScreensProvider.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/TouchpadTutorialScreensProvider.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt
new file mode 100644
index 0000000..3f1f68a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/KeyboardTouchpadConnectionInteractor.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.touchpad.data.repository.TouchpadRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+
+@SysUISingleton
+class KeyboardTouchpadConnectionInteractor
+@Inject
+constructor(
+ keyboardRepository: KeyboardRepository,
+ touchpadRepository: TouchpadRepository,
+) {
+
+ val connectionState: Flow<ConnectionState> =
+ combine(
+ keyboardRepository.isAnyKeyboardConnected,
+ touchpadRepository.isAnyTouchpadConnected
+ ) { keyboardConnected, touchpadConnected ->
+ ConnectionState(keyboardConnected, touchpadConnected)
+ }
+}
+
+data class ConnectionState(val keyboardConnected: Boolean, val touchpadConnected: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionKeyTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionKeyTutorialScreen.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionTutorialContent.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/ActionTutorialContent.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialComponents.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialComponents.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialComponents.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialScreenConfig.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/oobe/ui/composable/TutorialScreenConfig.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/TutorialScreenConfig.kt
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
new file mode 100644
index 0000000..34ecc95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.ui.view
+
+import android.os.Bundle
+import android.view.WindowManager
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.lifecycle.Lifecycle.State.STARTED
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import com.android.compose.theme.PlatformTheme
+import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider
+import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel.Factory.ViewModelFactoryAssistedProvider
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE
+import java.util.Optional
+import javax.inject.Inject
+import kotlinx.coroutines.launch
+
+/**
+ * Activity for out of the box experience for keyboard and touchpad. Note that it's possible that
+ * either of them are actually not connected when this is launched
+ */
+class KeyboardTouchpadTutorialActivity
+@Inject
+constructor(
+ private val viewModelFactoryAssistedProvider: ViewModelFactoryAssistedProvider,
+ private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>,
+) : ComponentActivity() {
+
+ companion object {
+ const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type"
+ const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad"
+ const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard"
+ }
+
+ private val vm by
+ viewModels<KeyboardTouchpadTutorialViewModel>(
+ factoryProducer = {
+ viewModelFactoryAssistedProvider.create(touchpadTutorialScreensProvider.isPresent)
+ }
+ )
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ // required to handle 3+ fingers on touchpad
+ window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
+ lifecycle.addObserver(vm)
+ lifecycleScope.launch {
+ vm.closeActivity.collect { finish ->
+ if (finish) {
+ finish()
+ }
+ }
+ }
+ setContent {
+ PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) }
+ }
+ }
+}
+
+@Composable
+fun KeyboardTouchpadTutorialContainer(
+ vm: KeyboardTouchpadTutorialViewModel,
+ touchpadScreens: Optional<TouchpadTutorialScreensProvider>,
+) {
+ val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED)
+ when (activeScreen) {
+ BACK_GESTURE ->
+ touchpadScreens
+ .get()
+ .BackGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
+ HOME_GESTURE ->
+ touchpadScreens
+ .get()
+ .HomeGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
+ ACTION_KEY ->
+ ActionKeyTutorialScreen(
+ onDoneButtonClicked = vm::onDoneButtonClicked,
+ onBack = vm::onBack
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt
new file mode 100644
index 0000000..315c102
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.ui.viewmodel
+
+import androidx.lifecycle.AbstractSavedStateViewModelFactory
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState
+import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.TOUCHPAD
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE
+import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import java.util.Optional
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNot
+import kotlinx.coroutines.flow.runningFold
+import kotlinx.coroutines.launch
+
+class KeyboardTouchpadTutorialViewModel(
+ private val gesturesInteractor: Optional<TouchpadGesturesInteractor>,
+ private val keyboardTouchpadConnectionInteractor: KeyboardTouchpadConnectionInteractor,
+ private val hasTouchpadTutorialScreens: Boolean,
+ handle: SavedStateHandle
+) : ViewModel(), DefaultLifecycleObserver {
+
+ private fun startingScreen(handle: SavedStateHandle): Screen {
+ val tutorialType: String? = handle[INTENT_TUTORIAL_TYPE_KEY]
+ return if (tutorialType == INTENT_TUTORIAL_TYPE_KEYBOARD) ACTION_KEY else BACK_GESTURE
+ }
+
+ private val _screen = MutableStateFlow(startingScreen(handle))
+ val screen: Flow<Screen> = _screen.filter { it.canBeShown() }
+
+ private val _closeActivity: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ val closeActivity: StateFlow<Boolean> = _closeActivity
+
+ private val screensBackStack = ArrayDeque(listOf(_screen.value))
+
+ private var connectionState: ConnectionState =
+ ConnectionState(keyboardConnected = false, touchpadConnected = false)
+
+ init {
+ viewModelScope.launch {
+ keyboardTouchpadConnectionInteractor.connectionState.collect { connectionState = it }
+ }
+
+ viewModelScope.launch {
+ screen
+ .runningFold<Screen, Pair<Screen?, Screen?>>(null to null) {
+ previousScreensPair,
+ currentScreen ->
+ previousScreensPair.second to currentScreen
+ }
+ .collect { (previousScreen, currentScreen) ->
+ // ignore first empty emission
+ if (currentScreen != null) {
+ setupDeviceState(previousScreen, currentScreen)
+ }
+ }
+ }
+
+ viewModelScope.launch {
+ // close activity if screen requires touchpad but we don't have it. This can only happen
+ // when current sysui build doesn't contain touchpad module dependency
+ _screen.filterNot { it.canBeShown() }.collect { _closeActivity.value = true }
+ }
+ }
+
+ override fun onCleared() {
+ // this shouldn't be needed as onTutorialInvisible should already clear device state but
+ // it'd be really bad if we'd block gestures/shortcuts after leaving tutorial so just to be
+ // extra sure...
+ clearDeviceStateForScreen(_screen.value)
+ }
+
+ override fun onStart(owner: LifecycleOwner) {
+ setupDeviceState(previousScreen = null, currentScreen = _screen.value)
+ }
+
+ override fun onStop(owner: LifecycleOwner) {
+ clearDeviceStateForScreen(_screen.value)
+ }
+
+ fun onDoneButtonClicked() {
+ var nextScreen = _screen.value.next()
+ while (nextScreen != null) {
+ if (requiredHardwarePresent(nextScreen)) {
+ break
+ }
+ nextScreen = nextScreen.next()
+ }
+ if (nextScreen == null) {
+ _closeActivity.value = true
+ } else {
+ _screen.value = nextScreen
+ screensBackStack.add(nextScreen)
+ }
+ }
+
+ private fun Screen.canBeShown() = requiredHardware != TOUCHPAD || hasTouchpadTutorialScreens
+
+ private fun setupDeviceState(previousScreen: Screen?, currentScreen: Screen) {
+ if (previousScreen?.requiredHardware == currentScreen.requiredHardware) return
+ previousScreen?.let { clearDeviceStateForScreen(it) }
+ when (currentScreen.requiredHardware) {
+ TOUCHPAD -> gesturesInteractor.get().disableGestures()
+ KEYBOARD -> {} // TODO(b/358587037) disabled keyboard shortcuts
+ }
+ }
+
+ private fun clearDeviceStateForScreen(screen: Screen) {
+ when (screen.requiredHardware) {
+ TOUCHPAD -> gesturesInteractor.get().enableGestures()
+ KEYBOARD -> {} // TODO(b/358587037) enable keyboard shortcuts
+ }
+ }
+
+ private fun requiredHardwarePresent(screen: Screen): Boolean =
+ when (screen.requiredHardware) {
+ KEYBOARD -> connectionState.keyboardConnected
+ TOUCHPAD -> connectionState.touchpadConnected
+ }
+
+ fun onBack() {
+ if (screensBackStack.size <= 1) {
+ _closeActivity.value = true
+ } else {
+ screensBackStack.removeLast()
+ _screen.value = screensBackStack.last()
+ }
+ }
+
+ class Factory
+ @AssistedInject
+ constructor(
+ private val gesturesInteractor: Optional<TouchpadGesturesInteractor>,
+ private val keyboardTouchpadConnected: KeyboardTouchpadConnectionInteractor,
+ @Assisted private val hasTouchpadTutorialScreens: Boolean,
+ ) : AbstractSavedStateViewModelFactory() {
+
+ @AssistedFactory
+ fun interface ViewModelFactoryAssistedProvider {
+ fun create(@Assisted hasTouchpadTutorialScreens: Boolean): Factory
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ override fun <T : ViewModel> create(
+ key: String,
+ modelClass: Class<T>,
+ handle: SavedStateHandle
+ ): T =
+ KeyboardTouchpadTutorialViewModel(
+ gesturesInteractor,
+ keyboardTouchpadConnected,
+ hasTouchpadTutorialScreens,
+ handle
+ )
+ as T
+ }
+}
+
+enum class RequiredHardware {
+ TOUCHPAD,
+ KEYBOARD
+}
+
+enum class Screen(val requiredHardware: RequiredHardware) {
+ BACK_GESTURE(requiredHardware = TOUCHPAD),
+ HOME_GESTURE(requiredHardware = TOUCHPAD),
+ ACTION_KEY(requiredHardware = KEYBOARD);
+
+ fun next(): Screen? =
+ when (this) {
+ BACK_GESTURE -> HOME_GESTURE
+ HOME_GESTURE -> ACTION_KEY
+ ACTION_KEY -> null
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index d119ed4..28a17ef 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -94,7 +94,7 @@
val disposableHandle =
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch("$TAG#viewModel") {
+ launch {
viewModel.collect { buttonModel ->
updateButton(
view = button,
@@ -104,7 +104,7 @@
}
}
- launch("$TAG#updateButtonAlpha") {
+ launch {
updateButtonAlpha(
view = button,
viewModel = viewModel,
@@ -112,7 +112,7 @@
)
}
- launch("$TAG#configurationBasedDimensions") {
+ launch {
configurationBasedDimensions.collect { dimensions ->
button.updateLayoutParams<ViewGroup.LayoutParams> {
width = dimensions.buttonSizePx.width
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
index 62759a4..3c25e62 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
@@ -54,7 +54,6 @@
import com.android.systemui.media.controls.ui.viewmodel.MediaOutputSwitcherViewModel
import com.android.systemui.media.controls.ui.viewmodel.MediaPlayerViewModel
import com.android.systemui.media.controls.util.MediaDataUtils
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.monet.ColorScheme
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
@@ -76,7 +75,6 @@
falsingManager: FalsingManager,
@Background backgroundDispatcher: CoroutineDispatcher,
@Main mainDispatcher: CoroutineDispatcher,
- mediaFlags: MediaFlags,
) {
val mediaCard = viewHolder.player
mediaCard.repeatWhenAttached {
@@ -91,7 +89,6 @@
falsingManager,
backgroundDispatcher,
mainDispatcher,
- mediaFlags
)
}
}
@@ -107,7 +104,6 @@
falsingManager: FalsingManager,
backgroundDispatcher: CoroutineDispatcher,
mainDispatcher: CoroutineDispatcher,
- mediaFlags: MediaFlags,
) {
// Set up media control location and its listener.
viewModel.onLocationChanged(viewController.currentEndLocation)
@@ -164,18 +160,6 @@
isSongUpdated
)
- // TODO: We don't need to refresh this state constantly, only if the
- // state actually changed to something which might impact the
- // measurement. State refresh interferes with the translation
- // animation, only run it if it's not running.
- if (!viewController.metadataAnimationHandler.isRunning) {
- // Don't refresh in scene framework, because it will calculate
- // with invalid layout sizes
- if (!mediaFlags.isSceneContainerEnabled()) {
- viewController.refreshState()
- }
- }
-
if (viewModel.playTurbulenceNoise) {
viewController.setUpTurbulenceNoise()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index c21301c..fb2bbde 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -746,7 +746,6 @@
falsingManager,
backgroundDispatcher,
mainDispatcher,
- mediaFlags
)
mediaContent.addView(viewHolder.player, position)
controllerById[commonViewModel.instanceId.toString()] = viewController
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt
index 2c57813..0b9cd96 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt
@@ -20,103 +20,40 @@
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.draganddrop.dragAndDropTarget
import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.lazy.grid.LazyGridItemInfo
+import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.draganddrop.DragAndDropEvent
import androidx.compose.ui.draganddrop.DragAndDropTarget
import androidx.compose.ui.draganddrop.DragAndDropTransferData
import androidx.compose.ui.draganddrop.mimeTypes
+import androidx.compose.ui.draganddrop.toAndroidDragEvent
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.unit.IntRect
+import androidx.compose.ui.unit.center
+import androidx.compose.ui.unit.toRect
import com.android.systemui.qs.panels.shared.model.SizedTile
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
-@Composable
-fun rememberDragAndDropState(listState: EditTileListState): DragAndDropState {
- val draggedCell: MutableState<SizedTile<EditTileViewModel>?> = remember { mutableStateOf(null) }
- return remember(listState) { DragAndDropState(draggedCell, listState) }
-}
-
-/**
- * Holds the [TileSpec] of the tile being moved and modify the [EditTileListState] based on drag and
- * drop events.
- */
-class DragAndDropState(
- val draggedCell: MutableState<SizedTile<EditTileViewModel>?>,
- private val listState: EditTileListState,
-) {
+/** Holds the [TileSpec] of the tile being moved and receives drag and drop events. */
+interface DragAndDropState {
+ val draggedCell: SizedTile<EditTileViewModel>?
val dragInProgress: Boolean
- get() = draggedCell.value != null
- /** Returns index of the dragged tile if it's present in the list. Returns -1 if not. */
- fun currentPosition(): Int {
- return draggedCell.value?.let { listState.indexOf(it.tile.tileSpec) } ?: -1
- }
+ fun isMoving(tileSpec: TileSpec): Boolean
- fun isMoving(tileSpec: TileSpec): Boolean {
- return draggedCell.value?.let { it.tile.tileSpec == tileSpec } ?: false
- }
+ fun onStarted(cell: SizedTile<EditTileViewModel>)
- fun onStarted(cell: SizedTile<EditTileViewModel>) {
- draggedCell.value = cell
- }
+ fun onMoved(target: Int, insertAfter: Boolean)
- fun onMoved(targetSpec: TileSpec) {
- draggedCell.value?.let { listState.move(it, targetSpec) }
- }
+ fun movedOutOfBounds()
- fun movedOutOfBounds() {
- // Removing the tiles from the current tile grid if it moves out of bounds. This clears
- // the spacer and makes it apparent that dropping the tile at that point would remove it.
- draggedCell.value?.let { listState.remove(it.tile.tileSpec) }
- }
-
- fun onDrop() {
- draggedCell.value = null
- }
-}
-
-/**
- * Registers a tile as a [DragAndDropTarget] to receive drag events and update the
- * [DragAndDropState] with the tile's position, which can be used to insert a temporary placeholder.
- *
- * @param dragAndDropState The [DragAndDropState] using the tiles list
- * @param tileSpec The [TileSpec] of the tile
- * @param acceptDrops Whether the tile should accept a drop based on a given [TileSpec]
- * @param onDrop Action to be executed when a [TileSpec] is dropped on the tile
- */
-@Composable
-fun Modifier.dragAndDropTile(
- dragAndDropState: DragAndDropState,
- tileSpec: TileSpec,
- acceptDrops: (TileSpec) -> Boolean,
- onDrop: (TileSpec, Int) -> Unit,
-): Modifier {
- val target =
- remember(dragAndDropState) {
- object : DragAndDropTarget {
- override fun onDrop(event: DragAndDropEvent): Boolean {
- return dragAndDropState.draggedCell.value?.let {
- onDrop(it.tile.tileSpec, dragAndDropState.currentPosition())
- dragAndDropState.onDrop()
- true
- } ?: false
- }
-
- override fun onEntered(event: DragAndDropEvent) {
- dragAndDropState.onMoved(tileSpec)
- }
- }
- }
- return dragAndDropTarget(
- shouldStartDragAndDrop = { event ->
- event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE) &&
- dragAndDropState.draggedCell.value?.let { acceptDrops(it.tile.tileSpec) } ?: false
- },
- target = target,
- )
+ fun onDrop()
}
/**
@@ -135,7 +72,7 @@
remember(dragAndDropState) {
object : DragAndDropTarget {
override fun onDrop(event: DragAndDropEvent): Boolean {
- return dragAndDropState.draggedCell.value?.let {
+ return dragAndDropState.draggedCell?.let {
onDrop(it.tile.tileSpec)
dragAndDropState.onDrop()
true
@@ -156,19 +93,22 @@
}
/**
- * Registers a tile list as a [DragAndDropTarget] to receive drop events. Use this on list
- * containers to catch drops outside of tiles.
+ * Registers a tile list as a [DragAndDropTarget] to receive drop events. Use this on the lazy tile
+ * grid to receive drag and drops events.
*
+ * @param gridState The [LazyGridState] of the tile list
+ * @param contentOffset The [Offset] of the tile list
* @param dragAndDropState The [DragAndDropState] using the tiles list
- * @param acceptDrops Whether the tile should accept a drop based on a given [TileSpec]
- * @param onDrop Action to be executed when a [TileSpec] is dropped on the tile
+ * @param onDrop Callback when a tile is dropped
*/
@Composable
fun Modifier.dragAndDropTileList(
+ gridState: LazyGridState,
+ contentOffset: Offset,
dragAndDropState: DragAndDropState,
- acceptDrops: (TileSpec) -> Boolean,
- onDrop: (TileSpec, Int) -> Unit,
+ onDrop: () -> Unit,
): Modifier {
+ val currentContentOffset by rememberUpdatedState(contentOffset)
val target =
remember(dragAndDropState) {
object : DragAndDropTarget {
@@ -176,9 +116,23 @@
dragAndDropState.onDrop()
}
+ override fun onMoved(event: DragAndDropEvent) {
+ // Drag offset relative to the list's top left corner
+ val relativeDragOffset = event.dragOffsetRelativeTo(currentContentOffset)
+ val targetItem =
+ gridState.layoutInfo.visibleItemsInfo.firstOrNull { item ->
+ // Check if the drag is on this item
+ IntRect(item.offset, item.size).toRect().contains(relativeDragOffset)
+ }
+
+ targetItem?.let {
+ dragAndDropState.onMoved(it.index, insertAfter(it, relativeDragOffset))
+ }
+ }
+
override fun onDrop(event: DragAndDropEvent): Boolean {
- return dragAndDropState.draggedCell.value?.let {
- onDrop(it.tile.tileSpec, dragAndDropState.currentPosition())
+ return dragAndDropState.draggedCell?.let {
+ onDrop()
dragAndDropState.onDrop()
true
} ?: false
@@ -188,12 +142,22 @@
return dragAndDropTarget(
target = target,
shouldStartDragAndDrop = { event ->
- event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE) &&
- dragAndDropState.draggedCell.value?.let { acceptDrops(it.tile.tileSpec) } ?: false
+ event.mimeTypes().contains(QsDragAndDrop.TILESPEC_MIME_TYPE)
},
)
}
+private fun DragAndDropEvent.dragOffsetRelativeTo(offset: Offset): Offset {
+ return toAndroidDragEvent().run { Offset(x, y) } - offset
+}
+
+private fun insertAfter(item: LazyGridItemInfo, offset: Offset): Boolean {
+ // We want to insert the tile after the target if we're aiming at the right side of a large tile
+ // TODO(ostonge): Verify this behavior in RTL
+ val itemCenter = item.offset + item.size.center
+ return item.span != 1 && offset.x > itemCenter.x
+}
+
fun Modifier.dragAndDropTileSource(
sizedTile: SizedTile<EditTileViewModel>,
onTap: (TileSpec) -> Unit,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt
index 3bda775..1674865 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditMode.kt
@@ -43,6 +43,7 @@
Modifier,
viewModel::addTile,
viewModel::removeTile,
+ viewModel::setTiles,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt
index fa3008e..4830ba7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditTileListState.kt
@@ -17,46 +17,106 @@
package com.android.systemui.qs.panels.ui.compose
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList
import com.android.systemui.qs.panels.shared.model.SizedTile
+import com.android.systemui.qs.panels.ui.model.GridCell
+import com.android.systemui.qs.panels.ui.model.TileGridCell
+import com.android.systemui.qs.panels.ui.model.toGridCells
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.pipeline.shared.TileSpec
+/**
+ * Creates the edit tile list state that is remembered across compositions.
+ *
+ * Changes to the tiles or columns will recreate the state.
+ */
@Composable
fun rememberEditListState(
tiles: List<SizedTile<EditTileViewModel>>,
+ columns: Int,
): EditTileListState {
- return remember(tiles) { EditTileListState(tiles) }
+ return remember(tiles, columns) { EditTileListState(tiles, columns) }
}
/** Holds the temporary state of the tile list during a drag movement where we move tiles around. */
-class EditTileListState(tiles: List<SizedTile<EditTileViewModel>>) {
- val tiles: SnapshotStateList<SizedTile<EditTileViewModel>> = tiles.toMutableStateList()
+class EditTileListState(
+ tiles: List<SizedTile<EditTileViewModel>>,
+ private val columns: Int,
+) : DragAndDropState {
+ private val _draggedCell = mutableStateOf<SizedTile<EditTileViewModel>?>(null)
+ override val draggedCell
+ get() = _draggedCell.value
- fun move(sizedTile: SizedTile<EditTileViewModel>, target: TileSpec) {
- val fromIndex = indexOf(sizedTile.tile.tileSpec)
- val toIndex = indexOf(target)
+ override val dragInProgress: Boolean
+ get() = _draggedCell.value != null
- if (toIndex == -1 || fromIndex == toIndex) {
- return
- }
+ private val _tiles: SnapshotStateList<GridCell> =
+ tiles.toGridCells(columns).toMutableStateList()
+ val tiles: List<GridCell>
+ get() = _tiles.toList()
- if (fromIndex == -1) {
- // If tile isn't in the list, simply insert it
- tiles.add(toIndex, sizedTile)
- } else {
- // If tile is present in the list, move it
- tiles.apply { add(toIndex, removeAt(fromIndex)) }
- }
- }
-
- fun remove(tileSpec: TileSpec) {
- tiles.removeIf { it.tile.tileSpec == tileSpec }
+ fun tileSpecs(): List<TileSpec> {
+ return _tiles.filterIsInstance<TileGridCell>().map { it.tile.tileSpec }
}
fun indexOf(tileSpec: TileSpec): Int {
- return tiles.indexOfFirst { it.tile.tileSpec == tileSpec }
+ return _tiles.indexOfFirst { it is TileGridCell && it.tile.tileSpec == tileSpec }
+ }
+
+ override fun isMoving(tileSpec: TileSpec): Boolean {
+ return _draggedCell.value?.let { it.tile.tileSpec == tileSpec } ?: false
+ }
+
+ override fun onStarted(cell: SizedTile<EditTileViewModel>) {
+ _draggedCell.value = cell
+
+ // Add visible spacers to the grid to indicate where the user can move a tile
+ regenerateGrid(includeSpacers = true)
+ }
+
+ override fun onMoved(target: Int, insertAfter: Boolean) {
+ val draggedTile = _draggedCell.value ?: return
+
+ val fromIndex = indexOf(draggedTile.tile.tileSpec)
+ if (fromIndex == target) {
+ return
+ }
+
+ val insertionIndex = if (insertAfter) target + 1 else target
+ if (fromIndex != -1) {
+ val cell = _tiles.removeAt(fromIndex)
+ regenerateGrid(includeSpacers = true)
+ _tiles.add(insertionIndex.coerceIn(0, _tiles.size), cell)
+ } else {
+ // Add the tile with a temporary row which will get reassigned when regenerating spacers
+ _tiles.add(insertionIndex.coerceIn(0, _tiles.size), TileGridCell(draggedTile, 0))
+ }
+
+ regenerateGrid(includeSpacers = true)
+ }
+
+ override fun movedOutOfBounds() {
+ val draggedTile = _draggedCell.value ?: return
+
+ _tiles.removeIf { cell ->
+ cell is TileGridCell && cell.tile.tileSpec == draggedTile.tile.tileSpec
+ }
+ }
+
+ override fun onDrop() {
+ _draggedCell.value = null
+
+ // Remove the spacers
+ regenerateGrid(includeSpacers = false)
+ }
+
+ private fun regenerateGrid(includeSpacers: Boolean) {
+ _tiles.filterIsInstance<TileGridCell>().toGridCells(columns, includeSpacers).let {
+ _tiles.clear()
+ _tiles.addAll(it)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
index e2f6bcf..fd276c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
@@ -39,6 +39,7 @@
modifier: Modifier,
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit,
+ onSetTiles: (List<TileSpec>) -> Unit,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
index bd925fe..d948dfd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt
@@ -76,6 +76,7 @@
modifier: Modifier,
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit,
+ onSetTiles: (List<TileSpec>) -> Unit,
) {
val columns by gridSizeViewModel.columns.collectAsStateWithLifecycle()
val largeTiles by iconTilesViewModel.largeTiles.collectAsStateWithLifecycle()
@@ -91,12 +92,16 @@
}
}
+ val (currentTiles, otherTiles) = sizedTiles.partition { it.tile.isCurrent }
+ val currentListState = rememberEditListState(currentTiles, columns)
DefaultEditTileGrid(
- sizedTiles = sizedTiles,
+ currentListState = currentListState,
+ otherTiles = otherTiles,
columns = columns,
modifier = modifier,
onAddTile = onAddTile,
onRemoveTile = onRemoveTile,
+ onSetTiles = onSetTiles,
onResize = iconTilesViewModel::resize,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
index 9c0701e..c06d6d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt
@@ -52,8 +52,11 @@
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.foundation.lazy.grid.LazyGridScope
+import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -75,9 +78,13 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.onClick
@@ -89,6 +96,7 @@
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.Expandable
+import com.android.compose.modifiers.background
import com.android.compose.modifiers.thenIf
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.Icon
@@ -96,8 +104,10 @@
import com.android.systemui.common.ui.compose.load
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.panels.shared.model.SizedTile
+import com.android.systemui.qs.panels.shared.model.SizedTileImpl
+import com.android.systemui.qs.panels.ui.model.GridCell
+import com.android.systemui.qs.panels.ui.model.SpacerGridCell
import com.android.systemui.qs.panels.ui.model.TileGridCell
-import com.android.systemui.qs.panels.ui.model.toTileGridCells
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.panels.ui.viewmodel.toUiState
@@ -269,10 +279,12 @@
@Composable
fun TileLazyGrid(
modifier: Modifier = Modifier,
+ state: LazyGridState = rememberLazyGridState(),
columns: GridCells,
content: LazyGridScope.() -> Unit,
) {
LazyVerticalGrid(
+ state = state,
columns = columns,
verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)),
horizontalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_horizontal)),
@@ -283,23 +295,18 @@
@Composable
fun DefaultEditTileGrid(
- sizedTiles: List<SizedTile<EditTileViewModel>>,
+ currentListState: EditTileListState,
+ otherTiles: List<SizedTile<EditTileViewModel>>,
columns: Int,
modifier: Modifier,
onAddTile: (TileSpec, Int) -> Unit,
onRemoveTile: (TileSpec) -> Unit,
+ onSetTiles: (List<TileSpec>) -> Unit,
onResize: (TileSpec) -> Unit,
) {
- val (currentTiles, otherTiles) = sizedTiles.partition { it.tile.isCurrent }
- val currentListState = rememberEditListState(currentTiles)
- val dragAndDropState = rememberDragAndDropState(currentListState)
-
val addTileToEnd: (TileSpec) -> Unit by rememberUpdatedState {
onAddTile(it, CurrentTilesInteractor.POSITION_AT_END)
}
- val onDropAdd: (TileSpec, Int) -> Unit by rememberUpdatedState { tileSpec, position ->
- onAddTile(tileSpec, position)
- }
val tilePadding = dimensionResource(R.dimen.qs_tile_margin_vertical)
CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
@@ -309,10 +316,10 @@
modifier = modifier.fillMaxSize().verticalScroll(rememberScrollState())
) {
AnimatedContent(
- targetState = dragAndDropState.dragInProgress,
+ targetState = currentListState.dragInProgress,
modifier = Modifier.wrapContentSize()
) { dragIsInProgress ->
- EditGridHeader(Modifier.dragAndDropRemoveZone(dragAndDropState, onRemoveTile)) {
+ EditGridHeader(Modifier.dragAndDropRemoveZone(currentListState, onRemoveTile)) {
if (dragIsInProgress) {
RemoveTileTarget()
} else {
@@ -322,18 +329,17 @@
}
CurrentTilesGrid(
- currentListState.tiles,
+ currentListState,
columns,
tilePadding,
onRemoveTile,
onResize,
- dragAndDropState,
- onDropAdd,
+ onSetTiles,
)
// Hide available tiles when dragging
AnimatedVisibility(
- visible = !dragAndDropState.dragInProgress,
+ visible = !currentListState.dragInProgress,
enter = fadeIn(),
exit = fadeOut()
) {
@@ -349,7 +355,7 @@
columns,
tilePadding,
addTileToEnd,
- dragAndDropState,
+ currentListState,
)
}
}
@@ -359,7 +365,7 @@
modifier =
Modifier.fillMaxWidth()
.weight(1f)
- .dragAndDropRemoveZone(dragAndDropState, onRemoveTile)
+ .dragAndDropRemoveZone(currentListState, onRemoveTile)
)
}
}
@@ -375,7 +381,7 @@
) {
Box(
contentAlignment = Alignment.Center,
- modifier = modifier.fillMaxWidth().height(TileDefaults.EditGridHeaderHeight)
+ modifier = modifier.fillMaxWidth().height(EditModeTileDefaults.EditGridHeaderHeight)
) {
content()
}
@@ -414,35 +420,42 @@
@Composable
private fun CurrentTilesGrid(
- tiles: List<SizedTile<EditTileViewModel>>,
+ listState: EditTileListState,
columns: Int,
tilePadding: Dp,
onClick: (TileSpec) -> Unit,
onResize: (TileSpec) -> Unit,
- dragAndDropState: DragAndDropState,
- onDrop: (TileSpec, Int) -> Unit
+ onSetTiles: (List<TileSpec>) -> Unit,
) {
- // Current tiles
+ val currentListState by rememberUpdatedState(listState)
+
CurrentTilesContainer {
- val cells = tiles.toTileGridCells(columns)
val tileHeight = tileHeight()
- val totalRows = cells.lastOrNull()?.row ?: 0
+ val totalRows = listState.tiles.lastOrNull()?.row ?: 0
val totalHeight = gridHeight(totalRows + 1, tileHeight, tilePadding)
+ val gridState = rememberLazyGridState()
+ var gridContentOffset by remember { mutableStateOf(Offset(0f, 0f)) }
+
TileLazyGrid(
+ state = gridState,
modifier =
Modifier.height(totalHeight)
- .dragAndDropTileList(dragAndDropState, { true }, onDrop),
+ .dragAndDropTileList(gridState, gridContentOffset, listState) {
+ onSetTiles(currentListState.tileSpecs())
+ }
+ .onGloballyPositioned { coordinates ->
+ gridContentOffset = coordinates.positionInRoot()
+ }
+ .testTag(CURRENT_TILES_GRID_TEST_TAG),
columns = GridCells.Fixed(columns)
) {
editTiles(
- cells,
+ listState.tiles,
ClickAction.REMOVE,
onClick,
- dragAndDropState,
+ listState,
onResize = onResize,
indicatePosition = true,
- acceptDrops = { true },
- onDrop = onDrop,
)
}
}
@@ -464,7 +477,7 @@
// Available tiles
TileLazyGrid(
- modifier = Modifier.height(availableGridHeight),
+ modifier = Modifier.height(availableGridHeight).testTag(AVAILABLE_TILES_GRID_TEST_TAG),
columns = GridCells.Fixed(columns)
) {
editTiles(
@@ -472,7 +485,6 @@
ClickAction.ADD,
onClick,
dragAndDropState = dragAndDropState,
- acceptDrops = { false },
showLabels = true,
)
editTiles(
@@ -480,7 +492,6 @@
ClickAction.ADD,
onClick,
dragAndDropState = dragAndDropState,
- acceptDrops = { false },
showLabels = true,
)
}
@@ -495,64 +506,109 @@
return ((tileHeight + padding) * rows) - padding
}
+private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any {
+ return if (this is TileGridCell && !dragAndDropState.isMoving(tile.tileSpec)) {
+ key
+ } else {
+ index
+ }
+}
+
fun LazyGridScope.editTiles(
- cells: List<TileGridCell>,
+ cells: List<GridCell>,
clickAction: ClickAction,
onClick: (TileSpec) -> Unit,
dragAndDropState: DragAndDropState,
- acceptDrops: (TileSpec) -> Boolean,
onResize: (TileSpec) -> Unit = {},
- onDrop: (TileSpec, Int) -> Unit = { _, _ -> },
showLabels: Boolean = false,
indicatePosition: Boolean = false,
) {
items(
count = cells.size,
- key = { cells[it].key },
+ key = { cells[it].key(it, dragAndDropState) },
span = { cells[it].span },
contentType = { TileType }
) { index ->
- val cell = cells[index]
- val tileHeight = tileHeight(cell.isIcon && showLabels)
-
- if (!dragAndDropState.isMoving(cell.tile.tileSpec)) {
- val onClickActionName =
- when (clickAction) {
- ClickAction.ADD ->
- stringResource(id = R.string.accessibility_qs_edit_tile_add_action)
- ClickAction.REMOVE ->
- stringResource(id = R.string.accessibility_qs_edit_remove_tile_action)
- }
- val stateDescription =
- if (indicatePosition) {
- stringResource(id = R.string.accessibility_qs_edit_position, index + 1)
+ when (val cell = cells[index]) {
+ is TileGridCell ->
+ if (dragAndDropState.isMoving(cell.tile.tileSpec)) {
+ // If the tile is being moved, replace it with a visible spacer
+ SpacerGridCell(
+ Modifier.background(
+ color = MaterialTheme.colorScheme.secondary,
+ alpha = { EditModeTileDefaults.PLACEHOLDER_ALPHA },
+ shape = TileDefaults.TileShape
+ )
+ .animateItem()
+ )
} else {
- ""
+ TileGridCell(
+ cell = cell,
+ index = index,
+ dragAndDropState = dragAndDropState,
+ clickAction = clickAction,
+ onClick = onClick,
+ onResize = onResize,
+ showLabels = showLabels,
+ indicatePosition = indicatePosition
+ )
}
- EditTile(
- tileViewModel = cell.tile,
- iconOnly = cell.isIcon,
- showLabels = showLabels,
- modifier =
- Modifier.height(tileHeight)
- .animateItem()
- .semantics {
- onClick(onClickActionName) { false }
- this.stateDescription = stateDescription
- }
- .dragAndDropTile(dragAndDropState, cell.tile.tileSpec, acceptDrops, onDrop)
- .dragAndDropTileSource(
- cell,
- onClick,
- onResize,
- dragAndDropState,
- )
- )
+ is SpacerGridCell -> SpacerGridCell()
}
}
}
@Composable
+private fun LazyGridItemScope.TileGridCell(
+ cell: TileGridCell,
+ index: Int,
+ dragAndDropState: DragAndDropState,
+ clickAction: ClickAction,
+ onClick: (TileSpec) -> Unit,
+ onResize: (TileSpec) -> Unit = {},
+ showLabels: Boolean = false,
+ indicatePosition: Boolean = false,
+) {
+ val tileHeight = tileHeight(cell.isIcon && showLabels)
+ val onClickActionName =
+ when (clickAction) {
+ ClickAction.ADD -> stringResource(id = R.string.accessibility_qs_edit_tile_add_action)
+ ClickAction.REMOVE ->
+ stringResource(id = R.string.accessibility_qs_edit_remove_tile_action)
+ }
+ val stateDescription =
+ if (indicatePosition) {
+ stringResource(id = R.string.accessibility_qs_edit_position, index + 1)
+ } else {
+ ""
+ }
+ EditTile(
+ tileViewModel = cell.tile,
+ iconOnly = cell.isIcon,
+ showLabels = showLabels,
+ modifier =
+ Modifier.height(tileHeight)
+ .animateItem()
+ .semantics {
+ onClick(onClickActionName) { false }
+ this.stateDescription = stateDescription
+ }
+ .dragAndDropTileSource(
+ SizedTileImpl(cell.tile, cell.width),
+ onClick,
+ onResize,
+ dragAndDropState,
+ )
+ )
+}
+
+@Composable
+private fun SpacerGridCell(modifier: Modifier = Modifier) {
+ // By default, spacers are invisible and exist purely to catch drag movements
+ Box(modifier.height(tileHeight()).fillMaxWidth().tilePadding())
+}
+
+@Composable
fun EditTile(
tileViewModel: EditTileViewModel,
iconOnly: Boolean,
@@ -641,7 +697,7 @@
}
Image(
painter = painter,
- contentDescription = null,
+ contentDescription = icon.contentDescription?.load(),
colorFilter = ColorFilter.tint(color = color),
modifier = iconModifier
)
@@ -678,10 +734,14 @@
val icon: Color,
)
+private object EditModeTileDefaults {
+ const val PLACEHOLDER_ALPHA = .3f
+ val EditGridHeaderHeight = 60.dp
+}
+
private object TileDefaults {
val TileShape = CircleShape
val IconTileWithLabelHeight = 140.dp
- val EditGridHeaderHeight = 60.dp
@Composable
fun activeTileColors(): TileColors =
@@ -722,3 +782,6 @@
}
}
}
+
+private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid"
+private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt
index c241fd8..8ca8de7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt
@@ -22,6 +22,12 @@
import com.android.systemui.qs.panels.shared.model.splitInRowsSequence
import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
+/** Represents an item from a grid associated with a row and a span */
+interface GridCell {
+ val row: Int
+ val span: GridItemSpan
+}
+
/**
* Represents a [EditTileViewModel] from a grid associated with a tile format and the row it's
* positioned at
@@ -29,10 +35,12 @@
@Immutable
data class TileGridCell(
override val tile: EditTileViewModel,
- val row: Int,
- val key: String = "${tile.tileSpec.spec}-$row",
+ override val row: Int,
override val width: Int,
-) : SizedTile<EditTileViewModel> {
+ override val span: GridItemSpan = GridItemSpan(width)
+) : GridCell, SizedTile<EditTileViewModel> {
+ val key: String = "${tile.tileSpec.spec}-$row"
+
constructor(
sizedTile: SizedTile<EditTileViewModel>,
row: Int
@@ -41,12 +49,30 @@
row = row,
width = sizedTile.width,
)
-
- val span = GridItemSpan(width)
}
-fun List<SizedTile<EditTileViewModel>>.toTileGridCells(columns: Int): List<TileGridCell> {
+/** Represents an empty space used to fill incomplete rows. Will always display as a 1x1 tile */
+@Immutable
+data class SpacerGridCell(
+ override val row: Int,
+ override val span: GridItemSpan = GridItemSpan(1)
+) : GridCell
+
+fun List<SizedTile<EditTileViewModel>>.toGridCells(
+ columns: Int,
+ includeSpacers: Boolean = false
+): List<GridCell> {
return splitInRowsSequence(this, columns)
- .flatMapIndexed { index, sizedTiles -> sizedTiles.map { TileGridCell(it, index) } }
+ .flatMapIndexed { rowIndex, sizedTiles ->
+ val row: List<GridCell> = sizedTiles.map { TileGridCell(it, rowIndex) }
+
+ if (includeSpacers) {
+ // Fill the incomplete rows with spacers
+ val numSpacers = columns - sizedTiles.sumOf { it.width }
+ row.toMutableList().apply { repeat(numSpacers) { add(SpacerGridCell(rowIndex)) } }
+ } else {
+ row
+ }
+ }
.toList()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
index ef2c8bf..42715be 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeViewModel.kt
@@ -179,6 +179,10 @@
currentTilesInteractor.removeTiles(listOf(tileSpec))
}
+ fun setTiles(tileSpecs: List<TileSpec>) {
+ currentTilesInteractor.setTiles(tileSpecs)
+ }
+
/** Immediately resets the current tiles to the default list. */
fun resetCurrentTilesToDefault() {
throw NotImplementedError("This is not supported yet")
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
index 2a33a16..5f10b38 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt
@@ -20,6 +20,7 @@
import android.content.Intent
import android.os.Handler
import android.os.Looper
+import android.service.quicksettings.Tile
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
@@ -94,7 +95,13 @@
override fun getTileLabel(): CharSequence = tileState.label
- override fun newTileState() = QSTile.State()
+ override fun newTileState(): QSTile.State {
+ return QSTile.State().apply {
+ label = mContext.getString(R.string.quick_settings_modes_label)
+ icon = ResourceIcon.get(R.drawable.qs_dnd_icon_off)
+ state = Tile.STATE_INACTIVE
+ }
+ }
override fun handleClick(expandable: Expandable?) = runBlocking {
userActionInteractor.handleClick(expandable)
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 b2873c5..5ea9e6a 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
@@ -346,7 +346,6 @@
mCallback = null;
}
- @VisibleForTesting
boolean isAirplaneModeEnabled() {
return mGlobalSettings.getInt(Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
index f018336..71f8639 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
@@ -30,7 +30,6 @@
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyDisplayInfo;
-import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.Layout;
import android.text.TextUtils;
@@ -50,9 +49,14 @@
import android.widget.TextView;
import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -110,7 +114,6 @@
protected boolean mCanConfigWifi;
private final InternetDialogManager mInternetDialogManager;
- private TelephonyManager mTelephonyManager;
@Nullable
private AlertDialog mAlertDialog;
private final UiEventLogger mUiEventLogger;
@@ -169,6 +172,13 @@
@Nullable
private Job mClickJob;
+ // These are to reduce the UI janky frame duration. b/323286540
+ private LifecycleRegistry mLifecycleRegistry;
+ @VisibleForTesting
+ LifecycleOwner mLifecycleOwner;
+ @VisibleForTesting
+ MutableLiveData<InternetContent> mDataInternetContent = new MutableLiveData<>();
+
@AssistedFactory
public interface Factory {
InternetDialogDelegate create(
@@ -205,7 +215,6 @@
mInternetDialogManager = internetDialogManager;
mInternetDialogController = internetDialogController;
mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId();
- mTelephonyManager = mInternetDialogController.getTelephonyManager();
mCanConfigMobileData = canConfigMobileData;
mCanConfigWifi = canConfigWifi;
mCanChangeWifiState = WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context);
@@ -227,6 +236,14 @@
mDialog.dismiss();
}
mDialog = dialog;
+ mLifecycleOwner = new LifecycleOwner() {
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycleRegistry;
+ }
+ };
+ mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
return dialog;
}
@@ -249,7 +266,9 @@
mWifiNetworkHeight = context.getResources()
.getDimensionPixelSize(R.dimen.internet_dialog_wifi_network_height);
-
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
+ mDataInternetContent.observe(
+ mLifecycleOwner, (internetContent) -> updateDialogUI(internetContent));
mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle);
mDivider = mDialogView.requireViewById(R.id.divider);
@@ -294,6 +313,8 @@
if (DEBUG) {
Log.d(TAG, "onStart");
}
+
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED);
mInternetDialogController.onStart(this, mCanConfigWifi);
if (!mCanConfigWifi) {
hideWifiViews();
@@ -315,6 +336,7 @@
if (DEBUG) {
Log.d(TAG, "onStop");
}
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
mMobileNetworkLayout.setOnClickListener(null);
mConnectedWifListLayout.setOnClickListener(null);
if (mSecondaryMobileNetworkLayout != null) {
@@ -348,31 +370,50 @@
* otherwise {@code false}.
*/
void updateDialog(boolean shouldUpdateMobileNetwork) {
- if (DEBUG) {
- Log.d(TAG, "updateDialog");
- }
- mInternetDialogTitle.setText(getDialogTitleText());
- mInternetDialogSubTitle.setText(getSubtitleText());
- mAirplaneModeButton.setVisibility(
- mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE);
+ mBackgroundExecutor.execute(() -> {
+ mDataInternetContent.postValue(getInternetContent(shouldUpdateMobileNetwork));
+ });
+ }
- updateEthernet();
- if (shouldUpdateMobileNetwork) {
- setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular(),
- mInternetDialogController.isCarrierNetworkActive());
+ private void updateDialogUI(InternetContent internetContent) {
+ if (DEBUG) {
+ Log.d(TAG, "updateDialog ");
}
+ mInternetDialogTitle.setText(internetContent.mInternetDialogTitleString);
+ mInternetDialogSubTitle.setText(internetContent.mInternetDialogSubTitle);
+ mAirplaneModeButton.setVisibility(
+ internetContent.mIsAirplaneModeEnabled ? View.VISIBLE : View.GONE);
+
+ updateEthernet(internetContent);
+ setMobileDataLayout(internetContent);
+
if (!mCanConfigWifi) {
return;
}
+ updateWifiToggle(internetContent);
+ updateConnectedWifi(internetContent);
+ updateWifiListAndSeeAll(internetContent);
+ updateWifiScanNotify(internetContent);
+ }
- final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
- final boolean isWifiEnabled = mInternetDialogController.isWifiEnabled();
- final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
- updateWifiToggle(isWifiEnabled, isDeviceLocked);
- updateConnectedWifi(isWifiEnabled, isDeviceLocked);
- updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked);
- updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
+ private InternetContent getInternetContent(boolean shouldUpdateMobileNetwork) {
+ InternetContent internetContent = new InternetContent();
+ internetContent.mShouldUpdateMobileNetwork = shouldUpdateMobileNetwork;
+ internetContent.mInternetDialogTitleString = getDialogTitleText();
+ internetContent.mInternetDialogSubTitle = getSubtitleText();
+ internetContent.mActiveNetworkIsCellular =
+ mInternetDialogController.activeNetworkIsCellular();
+ internetContent.mIsCarrierNetworkActive =
+ mInternetDialogController.isCarrierNetworkActive();
+ internetContent.mIsAirplaneModeEnabled = mInternetDialogController.isAirplaneModeEnabled();
+ internetContent.mHasEthernet = mInternetDialogController.hasEthernet();
+ internetContent.mIsWifiEnabled = mInternetDialogController.isWifiEnabled();
+ internetContent.mHasActiveSubIdOnDds = mInternetDialogController.hasActiveSubIdOnDds();
+ internetContent.mIsMobileDataEnabled = mInternetDialogController.isMobileDataEnabled();
+ internetContent.mIsDeviceLocked = mInternetDialogController.isDeviceLocked();
+ internetContent.mIsWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
+ return internetContent;
}
private void setOnClickListener(SystemUIDialog dialog) {
@@ -436,39 +477,39 @@
}
@MainThread
- private void updateEthernet() {
+ private void updateEthernet(InternetContent internetContent) {
mEthernetLayout.setVisibility(
- mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE);
+ internetContent.mHasEthernet ? View.VISIBLE : View.GONE);
}
- private void setMobileDataLayout(boolean activeNetworkIsCellular,
- boolean isCarrierNetworkActive) {
-
- if (mDialog != null) {
- setMobileDataLayout(mDialog, activeNetworkIsCellular, isCarrierNetworkActive);
+ private void setMobileDataLayout(InternetContent internetContent) {
+ if (!internetContent.mShouldUpdateMobileNetwork && mDialog == null) {
+ return;
}
+ setMobileDataLayout(mDialog, internetContent);
}
- private void setMobileDataLayout(SystemUIDialog dialog, boolean activeNetworkIsCellular,
- boolean isCarrierNetworkActive) {
- boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive;
+ private void setMobileDataLayout(SystemUIDialog dialog, InternetContent internetContent) {
+ boolean isNetworkConnected =
+ internetContent.mActiveNetworkIsCellular
+ || internetContent.mIsCarrierNetworkActive;
// 1. Mobile network should be gone if airplane mode ON or the list of active
// subscriptionId is null.
// 2. Carrier network should be gone if airplane mode ON and Wi-Fi is OFF.
if (DEBUG) {
- Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + isCarrierNetworkActive);
+ Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = "
+ + internetContent.mIsCarrierNetworkActive);
}
- boolean isWifiEnabled = mInternetDialogController.isWifiEnabled();
- if (!mInternetDialogController.hasActiveSubIdOnDds()
- && (!isWifiEnabled || !isCarrierNetworkActive)) {
+ if (!internetContent.mHasActiveSubIdOnDds && (!internetContent.mIsWifiEnabled
+ || !internetContent.mIsCarrierNetworkActive)) {
mMobileNetworkLayout.setVisibility(View.GONE);
if (mSecondaryMobileNetworkLayout != null) {
mSecondaryMobileNetworkLayout.setVisibility(View.GONE);
}
} else {
mMobileNetworkLayout.setVisibility(View.VISIBLE);
- mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled());
+ mMobileDataToggle.setChecked(internetContent.mIsMobileDataEnabled);
mMobileTitleText.setText(getMobileNetworkTitle(mDefaultDataSubId));
String summary = getMobileNetworkSummary(mDefaultDataSubId);
if (!TextUtils.isEmpty(summary)) {
@@ -508,7 +549,7 @@
if (stub != null) {
stub.inflate();
}
- mSecondaryMobileNetworkLayout = dialog.findViewById(
+ mSecondaryMobileNetworkLayout = mDialogView.findViewById(
R.id.secondary_mobile_network_layout);
mSecondaryMobileNetworkLayout.setOnClickListener(
this::onClickConnectedSecondarySub);
@@ -567,7 +608,7 @@
}
// Set airplane mode to the summary for carrier network
- if (mInternetDialogController.isAirplaneModeEnabled()) {
+ if (internetContent.mIsAirplaneModeEnabled) {
mAirplaneModeSummaryText.setVisibility(View.VISIBLE);
mAirplaneModeSummaryText.setText(
dialog.getContext().getText(R.string.airplane_mode));
@@ -579,17 +620,18 @@
}
@MainThread
- private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
- if (mWiFiToggle.isChecked() != isWifiEnabled) {
- mWiFiToggle.setChecked(isWifiEnabled);
+ private void updateWifiToggle(InternetContent internetContent) {
+ if (mWiFiToggle.isChecked() != internetContent.mIsWifiEnabled) {
+ mWiFiToggle.setChecked(internetContent.mIsWifiEnabled);
}
- if (isDeviceLocked) {
+ if (internetContent.mIsDeviceLocked) {
mWifiToggleTitleText.setTextAppearance((mConnectedWifiEntry != null)
? R.style.TextAppearance_InternetDialog_Active
: R.style.TextAppearance_InternetDialog);
}
mTurnWifiOnLayout.setBackground(
- (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
+ (internetContent.mIsDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn
+ : null);
if (!mCanChangeWifiState && mWiFiToggle.isEnabled()) {
mWiFiToggle.setEnabled(false);
@@ -601,8 +643,9 @@
}
@MainThread
- private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) {
- if (mDialog == null || !isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) {
+ private void updateConnectedWifi(InternetContent internetContent) {
+ if (mDialog == null || !internetContent.mIsWifiEnabled || mConnectedWifiEntry == null
+ || internetContent.mIsDeviceLocked) {
mConnectedWifListLayout.setVisibility(View.GONE);
mShareWifiButton.setVisibility(View.GONE);
return;
@@ -627,8 +670,8 @@
}
@MainThread
- private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) {
- if (!isWifiEnabled || isDeviceLocked) {
+ private void updateWifiListAndSeeAll(InternetContent internetContent) {
+ if (!internetContent.mIsWifiEnabled || internetContent.mIsDeviceLocked) {
mWifiRecyclerView.setVisibility(View.GONE);
mSeeAllLayout.setVisibility(View.GONE);
return;
@@ -670,9 +713,10 @@
}
@MainThread
- private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
- boolean isDeviceLocked) {
- if (mDialog == null || isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
+ private void updateWifiScanNotify(InternetContent internetContent) {
+ if (mDialog == null || internetContent.mIsWifiEnabled
+ || !internetContent.mIsWifiScanEnabled
+ || internetContent.mIsDeviceLocked) {
mWifiScanNotifyLayout.setVisibility(View.GONE);
return;
}
@@ -805,62 +849,62 @@
@Override
public void onRefreshCarrierInfo() {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onSimStateChanged() {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
@WorkerThread
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
@WorkerThread
public void onLost(Network network) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onSubscriptionsChanged(int defaultDataSubId) {
mDefaultDataSubId = defaultDataSubId;
- mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onUserMobileDataStateChanged(boolean enabled) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onServiceStateChanged(ServiceState serviceState) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
@WorkerThread
public void onDataConnectionStateChanged(int state, int networkType) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
public void onCarrierNetworkChange(boolean active) {
- mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+
+ updateDialog(true /* shouldUpdateMobileNetwork */);
}
@Override
@@ -912,4 +956,20 @@
return mId;
}
}
+
+ @VisibleForTesting
+ static class InternetContent {
+ CharSequence mInternetDialogTitleString = "";
+ CharSequence mInternetDialogSubTitle = "";
+ boolean mIsAirplaneModeEnabled = false;
+ boolean mHasEthernet = false;
+ boolean mShouldUpdateMobileNetwork = false;
+ boolean mActiveNetworkIsCellular = false;
+ boolean mIsCarrierNetworkActive = false;
+ boolean mIsWifiEnabled = false;
+ boolean mHasActiveSubIdOnDds = false;
+ boolean mIsMobileDataEnabled = false;
+ boolean mIsDeviceLocked = false;
+ boolean mIsWifiScanEnabled = false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index dda02db..e7d5cd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -32,8 +32,6 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import androidx.annotation.NonNull;
-
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Flags;
@@ -49,6 +47,7 @@
public class PhoneStatusBarView extends FrameLayout {
private static final String TAG = "PhoneStatusBarView";
+ private final StatusBarContentInsetsProvider mContentInsetsProvider;
private final StatusBarWindowController mStatusBarWindowController;
private int mRotationOrientation = -1;
@@ -61,10 +60,6 @@
private int mStatusBarHeight;
@Nullable
private Gefingerpoken mTouchEventHandler;
- @Nullable
- private HasCornerCutoutFetcher mHasCornerCutoutFetcher;
- @Nullable
- private InsetsFetcher mInsetsFetcher;
private int mDensity;
private float mFontScale;
@@ -75,6 +70,7 @@
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
}
@@ -82,14 +78,6 @@
mTouchEventHandler = handler;
}
- void setHasCornerCutoutFetcher(@NonNull HasCornerCutoutFetcher cornerCutoutFetcher) {
- mHasCornerCutoutFetcher = cornerCutoutFetcher;
- }
-
- void setInsetsFetcher(@NonNull InsetsFetcher insetsFetcher) {
- mInsetsFetcher = insetsFetcher;
- }
-
void init(StatusBarUserChipViewModel viewModel) {
StatusBarUserSwitcherContainer container = findViewById(R.id.user_switcher_container);
StatusBarUserChipViewBinder.bind(container, viewModel);
@@ -282,14 +270,7 @@
return;
}
- boolean hasCornerCutout;
- if (mHasCornerCutoutFetcher != null) {
- hasCornerCutout = mHasCornerCutoutFetcher.fetchHasCornerCutout();
- } else {
- Log.e(TAG, "mHasCornerCutoutFetcher unexpectedly null");
- hasCornerCutout = true;
- }
-
+ boolean hasCornerCutout = mContentInsetsProvider.currentRotationHasCornerCutout();
if (mDisplayCutout == null || mDisplayCutout.isEmpty() || hasCornerCutout) {
mCutoutSpace.setVisibility(View.GONE);
return;
@@ -307,12 +288,8 @@
}
private void updateSafeInsets() {
- if (mInsetsFetcher == null) {
- Log.e(TAG, "mInsetsFetcher unexpectedly null");
- return;
- }
-
- Insets insets = mInsetsFetcher.fetchInsets();
+ Insets insets = mContentInsetsProvider
+ .getStatusBarContentInsetsForCurrentRotation();
setPadding(
insets.left,
insets.top,
@@ -326,12 +303,4 @@
}
mStatusBarWindowController.refreshStatusBarHeight();
}
-
- interface HasCornerCutoutFetcher {
- boolean fetchHasCornerCutout();
- }
-
- interface InsetsFetcher {
- Insets fetchInsets();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 456265b..468a3c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -73,7 +73,6 @@
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
private val darkIconDispatcher: DarkIconDispatcher,
- private val statusBarContentInsetsProvider: StatusBarContentInsetsProvider,
) : ViewController<PhoneStatusBarView>(view) {
private lateinit var battery: BatteryMeterView
@@ -156,14 +155,7 @@
}
init {
- // These should likely be done in `onInit`, not `init`.
mView.setTouchEventHandler(PhoneStatusBarViewTouchHandler())
- mView.setHasCornerCutoutFetcher {
- statusBarContentInsetsProvider.currentRotationHasCornerCutout()
- }
- mView.setInsetsFetcher {
- statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()
- }
mView.init(userChipViewModel)
}
@@ -318,7 +310,6 @@
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
private val darkIconDispatcher: DarkIconDispatcher,
- private val statusBarContentInsetsProvider: StatusBarContentInsetsProvider,
) {
fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
@@ -344,7 +335,6 @@
configurationController,
statusOverlayHoverListenerFactory,
darkIconDispatcher,
- statusBarContentInsetsProvider,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 2e29bbd..b1c6455 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -21,6 +21,7 @@
import static android.app.WallpaperManager.SetWallpaperFlags;
import static com.android.systemui.Flags.fixImageWallpaperCrashSurfaceAlreadyReleased;
+import static com.android.window.flags.Flags.multiCrop;
import static com.android.window.flags.Flags.offloadColorExtraction;
import android.annotation.Nullable;
@@ -190,7 +191,10 @@
}
mWallpaperManager = getDisplayContext().getSystemService(WallpaperManager.class);
mSurfaceHolder = surfaceHolder;
- Rect dimensions = mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true);
+ Rect dimensions = !multiCrop()
+ ? mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true)
+ : mWallpaperManager.peekBitmapDimensionsAsUser(getSourceFlag(), true,
+ mUserTracker.getUserId());
int width = Math.max(MIN_SURFACE_WIDTH, dimensions.width());
int height = Math.max(MIN_SURFACE_HEIGHT, dimensions.height());
mSurfaceHolder.setFixedSize(width, height);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt
new file mode 100644
index 0000000..0c716137
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.ui.viewmodel
+
+import androidx.lifecycle.Lifecycle.Event
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
+import androidx.lifecycle.SavedStateHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE
+import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE
+import com.android.systemui.keyboard.data.repository.keyboardRepository
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.model.sysUiState
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.data.repository.TouchpadRepository
+import com.android.systemui.touchpad.tutorial.touchpadGesturesInteractor
+import com.android.systemui.util.coroutines.MainDispatcherRule
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val sysUiState = kosmos.sysUiState
+ private val touchpadRepo = PrettyFakeTouchpadRepository()
+ private val keyboardRepo = kosmos.keyboardRepository
+ private var startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD
+ private val viewModel by lazy { createViewModel(startingPeripheral) }
+
+ // createUnsafe so its methods don't have to be called on Main thread
+ private val lifecycle = LifecycleRegistry.createUnsafe(mock(LifecycleOwner::class.java))
+
+ @get:Rule val mainDispatcherRule = MainDispatcherRule(kosmos.testDispatcher)
+
+ private fun createViewModel(
+ startingPeripheral: String = INTENT_TUTORIAL_TYPE_TOUCHPAD,
+ hasTouchpadTutorialScreens: Boolean = true,
+ ): KeyboardTouchpadTutorialViewModel {
+ val viewModel =
+ KeyboardTouchpadTutorialViewModel(
+ Optional.of(kosmos.touchpadGesturesInteractor),
+ KeyboardTouchpadConnectionInteractor(keyboardRepo, touchpadRepo),
+ hasTouchpadTutorialScreens,
+ SavedStateHandle(mapOf(INTENT_TUTORIAL_TYPE_KEY to startingPeripheral))
+ )
+ lifecycle.addObserver(viewModel)
+ return viewModel
+ }
+
+ @Test
+ fun screensOrder_whenTouchpadAndKeyboardConnected() =
+ testScope.runTest {
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+ peripheralsState(keyboardConnected = true, touchpadConnected = true)
+
+ goToNextScreen()
+ goToNextScreen()
+ // reached the last screen
+
+ assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY).inOrder()
+ assertThat(closeActivity).isFalse()
+ }
+
+ @Test
+ fun screensOrder_whenKeyboardDisconnectsDuringTutorial() =
+ testScope.runTest {
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+ peripheralsState(keyboardConnected = true, touchpadConnected = true)
+
+ // back gesture screen
+ goToNextScreen()
+ // home gesture screen
+ peripheralsState(keyboardConnected = false, touchpadConnected = true)
+ goToNextScreen()
+ // no action key screen because keyboard disconnected
+
+ assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun screensOrderUntilFinish_whenTouchpadAndKeyboardConnected() =
+ testScope.runTest {
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+
+ peripheralsState(keyboardConnected = true, touchpadConnected = true)
+
+ goToNextScreen()
+ goToNextScreen()
+ // we're at the last screen so "next screen" should be actually closing activity
+ goToNextScreen()
+
+ assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY).inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun screensOrder_whenGoingBackToPreviousScreens() =
+ testScope.runTest {
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+ peripheralsState(keyboardConnected = true, touchpadConnected = true)
+
+ // back gesture
+ goToNextScreen()
+ // home gesture
+ goToNextScreen()
+ // action key
+
+ goBack()
+ // home gesture
+ goBack()
+ // back gesture
+ goBack()
+ // finish activity
+
+ assertThat(screens)
+ .containsExactly(BACK_GESTURE, HOME_GESTURE, ACTION_KEY, HOME_GESTURE, BACK_GESTURE)
+ .inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun screensOrder_whenGoingBackAndOnlyKeyboardConnected() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+ peripheralsState(keyboardConnected = true, touchpadConnected = false)
+
+ // action key screen
+ goBack()
+ // activity finished
+
+ assertThat(screens).containsExactly(ACTION_KEY).inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun screensOrder_whenTouchpadConnected() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+
+ peripheralsState(keyboardConnected = false, touchpadConnected = true)
+
+ goToNextScreen()
+ goToNextScreen()
+ goToNextScreen()
+
+ assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun screensOrder_whenKeyboardConnected() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+
+ peripheralsState(keyboardConnected = true)
+
+ goToNextScreen()
+ goToNextScreen()
+
+ assertThat(screens).containsExactly(ACTION_KEY).inOrder()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun touchpadGesturesDisabled_onlyDuringTouchpadTutorial() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD
+ collectValues(viewModel.screen) // just to initialize viewModel
+ peripheralsState(keyboardConnected = true, touchpadConnected = true)
+
+ assertGesturesDisabled()
+ goToNextScreen()
+ goToNextScreen()
+ // end of touchpad tutorial, keyboard tutorial starts
+ assertGesturesNotDisabled()
+ }
+
+ @Test
+ fun activityFinishes_ifTouchpadModuleIsNotPresent() =
+ testScope.runTest {
+ val viewModel =
+ createViewModel(
+ startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD,
+ hasTouchpadTutorialScreens = false
+ )
+ val screens by collectValues(viewModel.screen)
+ val closeActivity by collectLastValue(viewModel.closeActivity)
+ peripheralsState(touchpadConnected = true)
+
+ assertThat(screens).isEmpty()
+ assertThat(closeActivity).isTrue()
+ }
+
+ @Test
+ fun touchpadGesturesDisabled_whenTutorialGoesToForeground() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD
+ collectValues(viewModel.screen) // just to initialize viewModel
+ peripheralsState(touchpadConnected = true)
+
+ lifecycle.handleLifecycleEvent(Event.ON_START)
+
+ assertGesturesDisabled()
+ }
+
+ @Test
+ fun touchpadGesturesNotDisabled_whenTutorialGoesToBackground() =
+ testScope.runTest {
+ startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD
+ collectValues(viewModel.screen)
+ peripheralsState(touchpadConnected = true)
+
+ lifecycle.handleLifecycleEvent(Event.ON_START)
+ lifecycle.handleLifecycleEvent(Event.ON_STOP)
+
+ assertGesturesNotDisabled()
+ }
+
+ @Test
+ fun keyboardShortcutsDisabled_onlyDuringKeyboardTutorial() =
+ testScope.runTest {
+ // TODO(b/358587037)
+ }
+
+ private fun TestScope.goToNextScreen() {
+ viewModel.onDoneButtonClicked()
+ runCurrent()
+ }
+
+ private fun TestScope.goBack() {
+ viewModel.onBack()
+ runCurrent()
+ }
+
+ private fun TestScope.peripheralsState(
+ keyboardConnected: Boolean = false,
+ touchpadConnected: Boolean = false
+ ) {
+ keyboardRepo.setIsAnyKeyboardConnected(keyboardConnected)
+ touchpadRepo.setIsAnyTouchpadConnected(touchpadConnected)
+ runCurrent()
+ }
+
+ private fun TestScope.assertGesturesNotDisabled() = assertFlagEnabled(enabled = false)
+
+ private fun TestScope.assertGesturesDisabled() = assertFlagEnabled(enabled = true)
+
+ private fun TestScope.assertFlagEnabled(enabled: Boolean) {
+ // sysui state is changed on background scope so let's make sure it's executed
+ runCurrent()
+ assertThat(sysUiState.isFlagEnabled(SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED))
+ .isEqualTo(enabled)
+ }
+
+ // replace below when we have better fake
+ internal class PrettyFakeTouchpadRepository : TouchpadRepository {
+
+ private val _isAnyTouchpadConnected = MutableStateFlow(false)
+ override val isAnyTouchpadConnected: Flow<Boolean> = _isAnyTouchpadConnected
+
+ fun setIsAnyTouchpadConnected(connected: Boolean) {
+ _isAnyTouchpadConnected.value = connected
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
index ff8c448..643debf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
@@ -6,20 +6,20 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.testing.TestableLooper;
+import android.testing.UiThreadTest;
import android.view.View;
+import android.view.Window;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
@@ -44,20 +44,18 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.util.List;
-@Ignore("b/257089187")
@SmallTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@UiThreadTest
public class InternetDialogDelegateTest extends SysuiTestCase {
private static final String MOBILE_NETWORK_TITLE = "Mobile Title";
@@ -87,6 +85,8 @@
private SystemUIDialog.Factory mSystemUIDialogFactory;
@Mock
private SystemUIDialog mSystemUIDialog;
+ @Mock
+ private Window mWindow;
private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock());
private InternetDialogDelegate mInternetDialogDelegate;
@@ -121,13 +121,16 @@
when(mInternetDialogController.getMobileNetworkSummary(anyInt()))
.thenReturn(MOBILE_NETWORK_SUMMARY);
when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
-
+ when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(WifiEnterpriseRestrictionUtils.class)
.startMocking();
when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true);
when(mSystemUIDialogFactory.create(any(SystemUIDialog.Delegate.class)))
.thenReturn(mSystemUIDialog);
+ when(mSystemUIDialog.getContext()).thenReturn(mContext);
+ when(mSystemUIDialog.getWindow()).thenReturn(mWindow);
createInternetDialog();
}
@@ -146,6 +149,8 @@
mBgExecutor,
mKeyguard,
mSystemUIDialogFactory);
+ mInternetDialogDelegate.createDialog();
+ mInternetDialogDelegate.onCreate(mSystemUIDialog, null);
mInternetDialogDelegate.mAdapter = mInternetAdapter;
mInternetDialogDelegate.mConnectedWifiEntry = mInternetWifiEntry;
mInternetDialogDelegate.mWifiEntriesCount = mWifiEntries.size();
@@ -163,10 +168,12 @@
mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
mAirplaneModeSummaryText = mDialogView.requireViewById(R.id.airplane_mode_summary);
+ mInternetDialogDelegate.onStart(mSystemUIDialog);
}
@After
public void tearDown() {
+ mInternetDialogDelegate.onStop(mSystemUIDialog);
mInternetDialogDelegate.dismissDialog();
mMockitoSession.finishMocking();
}
@@ -191,59 +198,77 @@
@Test
public void updateDialog_withApmOn_internetDialogSubTitleGone() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
public void updateDialog_withApmOff_internetDialogSubTitleVisible() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
public void updateDialog_apmOffAndHasEthernet_showEthernet() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
when(mInternetDialogController.hasEthernet()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
public void updateDialog_apmOffAndNoEthernet_hideEthernet() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
when(mInternetDialogController.hasEthernet()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_apmOnAndHasEthernet_showEthernet() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
when(mInternetDialogController.hasEthernet()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
public void updateDialog_apmOnAndNoEthernet_hideEthernet() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
when(mInternetDialogController.hasEthernet()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -252,41 +277,56 @@
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
when(mInternetDialogController.hasActiveSubIdOnDds()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
- public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayout() {
- // Carrier network should be gone if airplane mode ON and Wi-Fi is off.
- when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
- when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
- when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
-
- mInternetDialogDelegate.updateDialog(true);
-
- assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
-
+ public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayoutVisible() {
// Carrier network should be visible if airplane mode ON and Wi-Fi is ON.
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ });
+ }
+
+ @Test
+ public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayoutGone() {
+ // Carrier network should be gone if airplane mode ON and Wi-Fi is off.
+ when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
+ when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
+ when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
+ mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
+
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_apmOnAndNoCarrierNetwork_mobileDataLayoutGone() {
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -295,11 +335,14 @@
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
mInternetDialogDelegate.mConnectedWifiEntry = null;
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileDataLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
@@ -308,30 +351,39 @@
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
mInternetDialogDelegate.mConnectedWifiEntry = null;
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_apmOffAndHasCarrierNetwork_notShowApmSummary() {
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_apmOnAndNoCarrierNetwork_notShowApmSummary() {
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -340,10 +392,13 @@
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
when(mInternetDialogController.isMobileDataEnabled()).thenReturn(true);
mMobileToggleSwitch.setChecked(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileToggleSwitch.isChecked()).isTrue();
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileToggleSwitch.isChecked()).isTrue();
+ });
}
@Test
@@ -352,26 +407,32 @@
when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
when(mInternetDialogController.isMobileDataEnabled()).thenReturn(false);
mMobileToggleSwitch.setChecked(false);
-
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mMobileToggleSwitch.isChecked()).isFalse();
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mMobileToggleSwitch.isChecked()).isFalse();
+ });
}
@Test
public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() {
- mInternetDialogDelegate.dismissDialog();
+ when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn(1);
doReturn(true).when(mInternetDialogController).hasActiveSubIdOnDds();
- createInternetDialog();
// The preconditions WiFi ON and Internet WiFi are already in setUp()
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
- LinearLayout secondaryLayout = mDialogView.requireViewById(
- R.id.secondary_mobile_network_layout);
- assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+ LinearLayout secondaryLayout = mDialogView.requireViewById(
+ R.id.secondary_mobile_network_layout);
+ assertThat(secondaryLayout.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -379,10 +440,13 @@
// The precondition WiFi ON is already in setUp()
mInternetDialogDelegate.mConnectedWifiEntry = null;
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -390,14 +454,17 @@
// The precondition WiFi ON is already in setUp()
mInternetDialogDelegate.mConnectedWifiEntry = null;
mInternetDialogDelegate.mWifiEntriesCount = 0;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- // Show a blank block to fix the dialog height even if there is no WiFi list
- assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
- verify(mInternetAdapter).setMaxEntriesCount(3);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ // Show a blank block to fix the dialog height even if there is no WiFi list
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mInternetAdapter).setMaxEntriesCount(3);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ });
}
@Test
@@ -405,28 +472,34 @@
// The precondition WiFi ON is already in setUp()
mInternetDialogDelegate.mConnectedWifiEntry = null;
mInternetDialogDelegate.mWifiEntriesCount = 1;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- // Show a blank block to fix the dialog height even if there is no WiFi list
- assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
- verify(mInternetAdapter).setMaxEntriesCount(3);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ // Show a blank block to fix the dialog height even if there is no WiFi list
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mInternetAdapter).setMaxEntriesCount(3);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ });
}
@Test
public void updateDialog_wifiOnAndHasConnectedWifi_showAllWifiAndSeeAllArea() {
// The preconditions WiFi ON and WiFi entries are already in setUp()
mInternetDialogDelegate.mWifiEntriesCount = 0;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
- // Show a blank block to fix the dialog height even if there is no WiFi list
- assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
- verify(mInternetAdapter).setMaxEntriesCount(2);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+ // Show a blank block to fix the dialog height even if there is no WiFi list
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mInternetAdapter).setMaxEntriesCount(2);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
+ });
}
@Test
@@ -435,13 +508,16 @@
mInternetDialogDelegate.mConnectedWifiEntry = null;
mInternetDialogDelegate.mWifiEntriesCount = MAX_WIFI_ENTRY_COUNT;
mInternetDialogDelegate.mHasMoreWifiEntries = true;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
- verify(mInternetAdapter).setMaxEntriesCount(3);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mInternetAdapter).setMaxEntriesCount(3);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
@@ -449,13 +525,16 @@
// The preconditions WiFi ON and WiFi entries are already in setUp()
mInternetDialogDelegate.mWifiEntriesCount = MAX_WIFI_ENTRY_COUNT - 1;
mInternetDialogDelegate.mHasMoreWifiEntries = true;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
- verify(mInternetAdapter).setMaxEntriesCount(2);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ verify(mInternetAdapter).setMaxEntriesCount(2);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ });
}
@Test
@@ -463,32 +542,38 @@
// The preconditions WiFi entries are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
mInternetDialogDelegate.mConnectedWifiEntry = null;
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- // Show WiFi Toggle without background
- assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mWifiToggle.getBackground()).isNull();
- // Hide Wi-Fi networks and See all
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ // Show WiFi Toggle without background
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNull();
+ // Hide Wi-Fi networks and See all
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_deviceLockedAndHasConnectedWifi_showWifiToggleWithBackground() {
// The preconditions WiFi ON and WiFi entries are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- // Show WiFi Toggle with highlight background
- assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mWifiToggle.getBackground()).isNotNull();
- // Hide Wi-Fi networks and See all
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
- assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ // Show WiFi Toggle with highlight background
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNotNull();
+ // Hide Wi-Fi networks and See all
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
@@ -496,13 +581,16 @@
mInternetDialogDelegate.dismissDialog();
when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(false);
createInternetDialog();
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- // Disable Wi-Fi switch and show restriction message in summary.
- assertThat(mWifiToggleSwitch.isEnabled()).isFalse();
- assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ // Disable Wi-Fi switch and show restriction message in summary.
+ assertThat(mWifiToggleSwitch.isEnabled()).isFalse();
+ assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0);
+ });
}
@Test
@@ -510,50 +598,38 @@
mInternetDialogDelegate.dismissDialog();
when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true);
createInternetDialog();
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- // Enable Wi-Fi switch and hide restriction message in summary.
- assertThat(mWifiToggleSwitch.isEnabled()).isTrue();
- assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ // Enable Wi-Fi switch and hide restriction message in summary.
+ assertThat(mWifiToggleSwitch.isEnabled()).isTrue();
+ assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE);
+ });
}
@Test
public void updateDialog_showSecondaryDataSub() {
- mInternetDialogDelegate.dismissDialog();
+ when(mInternetDialogController.getActiveAutoSwitchNonDdsSubId()).thenReturn(1);
doReturn(1).when(mInternetDialogController).getActiveAutoSwitchNonDdsSubId();
doReturn(true).when(mInternetDialogController).hasActiveSubIdOnDds();
doReturn(false).when(mInternetDialogController).isAirplaneModeEnabled();
- createInternetDialog();
-
clearInvocations(mInternetDialogController);
mInternetDialogDelegate.updateDialog(true);
+ mBgExecutor.runAllReady();
- LinearLayout primaryLayout = mDialogView.requireViewById(
- R.id.mobile_network_layout);
- LinearLayout secondaryLayout = mDialogView.requireViewById(
- R.id.secondary_mobile_network_layout);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ LinearLayout primaryLayout = mDialogView.requireViewById(
+ R.id.mobile_network_layout);
+ LinearLayout secondaryLayout = mDialogView.requireViewById(
+ R.id.secondary_mobile_network_layout);
- verify(mInternetDialogController).getMobileNetworkSummary(1);
- assertThat(primaryLayout.getBackground()).isNotEqualTo(secondaryLayout.getBackground());
-
- // Tap the primary sub info
- primaryLayout.performClick();
- ArgumentCaptor<AlertDialog> dialogArgumentCaptor =
- ArgumentCaptor.forClass(AlertDialog.class);
- verify(mDialogTransitionAnimator).showFromDialog(dialogArgumentCaptor.capture(),
- eq(mSystemUIDialog), eq(null), eq(false));
- AlertDialog dialog = dialogArgumentCaptor.getValue();
- dialog.show();
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
- TestableLooper.get(this).processAllMessages();
- verify(mInternetDialogController).setAutoDataSwitchMobileDataPolicy(1, false);
-
- // Tap the secondary sub info
- secondaryLayout.performClick();
- verify(mInternetDialogController).launchMobileNetworkSettings(any(View.class));
-
- dialog.dismiss();
+ verify(mInternetDialogController).getMobileNetworkSummary(1);
+ assertThat(primaryLayout.getBackground()).isNotEqualTo(
+ secondaryLayout.getBackground());
+ });
}
@Test
@@ -561,6 +637,12 @@
// The preconditions WiFi ON and WiFi entries are already in setUp()
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
+
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ });
assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
}
@@ -569,8 +651,13 @@
public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
+
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ });
assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
}
@@ -580,8 +667,13 @@
when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
+
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ });
assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
}
@@ -591,33 +683,43 @@
when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE);
- TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
- assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0);
- assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull();
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE);
+ TextView wifiScanNotifyText = mDialogView.requireViewById(
+ R.id.wifi_scan_notify_text);
+ assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0);
+ assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull();
+ });
}
@Test
public void updateDialog_wifiIsDisabled_uncheckWifiSwitch() {
when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
mWifiToggleSwitch.setChecked(true);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mWifiToggleSwitch.isChecked()).isFalse();
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiToggleSwitch.isChecked()).isFalse();
+ });
}
@Test
- public void updateDialog_wifiIsEnabled_checkWifiSwitch() {
+ public void updateDialog_wifiIsEnabled_checkWifiSwitch() throws Exception {
when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
mWifiToggleSwitch.setChecked(false);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mWifiToggleSwitch.isChecked()).isTrue();
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mWifiToggleSwitch.isChecked()).isTrue();
+ });
}
@Test
@@ -699,21 +801,28 @@
public void updateDialog_shareWifiIntentNull_hideButton() {
when(mInternetDialogController.getConfiguratorQrCodeGeneratorIntentOrNull(any()))
.thenReturn(null);
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility()).isEqualTo(
+ View.GONE);
+ });
}
@Test
public void updateDialog_shareWifiShareable_showButton() {
when(mInternetDialogController.getConfiguratorQrCodeGeneratorIntentOrNull(any()))
.thenReturn(new Intent());
-
mInternetDialogDelegate.updateDialog(false);
+ mBgExecutor.runAllReady();
- assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility())
- .isEqualTo(View.VISIBLE);
+ mInternetDialogDelegate.mDataInternetContent.observe(
+ mInternetDialogDelegate.mLifecycleOwner, i -> {
+ assertThat(mInternetDialogDelegate.mShareWifiButton.getVisibility())
+ .isEqualTo(View.VISIBLE);
+ });
}
private void setNetworkVisible(boolean ethernetVisible, boolean mobileDataVisible,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 70ac31d..30e7247 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -391,7 +391,6 @@
configurationController,
mStatusOverlayHoverListenerFactory,
fakeDarkIconDispatcher,
- mock(StatusBarContentInsetsProvider::class.java),
)
.create(view)
.also { it.init() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index 648ddf8..575b051 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -56,14 +56,21 @@
private val systemIconsContainer: View
get() = view.requireViewById(R.id.system_icons)
+ private val contentInsetsProvider = mock<StatusBarContentInsetsProvider>()
private val windowController = mock<StatusBarWindowController>()
@Before
fun setUp() {
+ mDependency.injectTestDependency(
+ StatusBarContentInsetsProvider::class.java,
+ contentInsetsProvider
+ )
mDependency.injectTestDependency(StatusBarWindowController::class.java, windowController)
context.ensureTestableResources()
view = spy(createStatusBarView())
whenever(view.rootWindowInsets).thenReturn(emptyWindowInsets())
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(Insets.NONE)
}
@Test
@@ -234,7 +241,8 @@
@Test
fun onAttachedToWindow_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40)
- view.setInsetsFetcher { insets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(insets)
view.onAttachedToWindow()
@@ -245,23 +253,10 @@
}
@Test
- fun onAttachedToWindow_noInsetsFetcher_noCrash() {
- // Don't call `PhoneStatusBarView.setInsetsFetcher`
-
- // WHEN the view is attached
- view.onAttachedToWindow()
-
- // THEN there's no crash, and the padding stays as it was
- assertThat(view.paddingLeft).isEqualTo(0)
- assertThat(view.paddingTop).isEqualTo(0)
- assertThat(view.paddingRight).isEqualTo(0)
- assertThat(view.paddingBottom).isEqualTo(0)
- }
-
- @Test
fun onConfigurationChanged_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- view.setInsetsFetcher { insets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(insets)
view.onConfigurationChanged(Configuration())
@@ -272,31 +267,17 @@
}
@Test
- fun onConfigurationChanged_noInsetsFetcher_noCrash() {
- // Don't call `PhoneStatusBarView.setInsetsFetcher`
-
- // WHEN the view is attached
- view.onConfigurationChanged(Configuration())
-
- // THEN there's no crash, and the padding stays as it was
- assertThat(view.paddingLeft).isEqualTo(0)
- assertThat(view.paddingTop).isEqualTo(0)
- assertThat(view.paddingRight).isEqualTo(0)
- assertThat(view.paddingBottom).isEqualTo(0)
- }
-
- @Test
fun onConfigurationChanged_noRelevantChange_doesNotUpdateInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- view.setInsetsFetcher { previousInsets }
-
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(previousInsets)
context.orCreateTestableResources.overrideConfiguration(Configuration())
view.onAttachedToWindow()
val newInsets = Insets.NONE
- view.setInsetsFetcher { newInsets }
-
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(newInsets)
view.onConfigurationChanged(Configuration())
assertThat(view.paddingLeft).isEqualTo(previousInsets.left)
@@ -309,14 +290,16 @@
fun onConfigurationChanged_densityChanged_updatesInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- view.setInsetsFetcher { previousInsets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(previousInsets)
val configuration = Configuration()
configuration.densityDpi = 123
context.orCreateTestableResources.overrideConfiguration(configuration)
view.onAttachedToWindow()
val newInsets = Insets.NONE
- view.setInsetsFetcher { newInsets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(newInsets)
configuration.densityDpi = 456
view.onConfigurationChanged(configuration)
@@ -330,14 +313,16 @@
fun onConfigurationChanged_fontScaleChanged_updatesInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- view.setInsetsFetcher { previousInsets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(previousInsets)
val configuration = Configuration()
configuration.fontScale = 1f
context.orCreateTestableResources.overrideConfiguration(configuration)
view.onAttachedToWindow()
val newInsets = Insets.NONE
- view.setInsetsFetcher { newInsets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(newInsets)
configuration.fontScale = 2f
view.onConfigurationChanged(configuration)
@@ -363,7 +348,8 @@
@Test
fun onApplyWindowInsets_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 90, /* top= */ 10, /* right= */ 45, /* bottom= */ 50)
- view.setInsetsFetcher { insets }
+ whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(insets)
view.onApplyWindowInsets(WindowInsets(Rect()))
@@ -404,7 +390,7 @@
/* typeVisibilityMap = */ booleanArrayOf(),
/* isRound = */ false,
/* forceConsumingTypes = */ 0,
- /* forceConsumingOpaqueCaptionBar = */ false,
+ /* forceConsumingCaptionBar = */ false,
/* suppressScrimTypes = */ 0,
/* displayCutout = */ DisplayCutout.NO_CUTOUT,
/* roundedCorners = */ RoundedCorners.NO_ROUNDED_CORNERS,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index 6fb70de..60a15915f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -223,8 +223,11 @@
}
private void setBitmapDimensions(int bitmapWidth, int bitmapHeight) {
+ // TODO(b/281648899) remove the when(mWallpaperManager.peekBitmapDimensions(...))
when(mWallpaperManager.peekBitmapDimensions(anyInt(), anyBoolean()))
.thenReturn(new Rect(0, 0, bitmapWidth, bitmapHeight));
+ when(mWallpaperManager.peekBitmapDimensionsAsUser(anyInt(), anyBoolean(), anyInt()))
+ .thenReturn(new Rect(0, 0, bitmapWidth, bitmapHeight));
when(mWallpaperBitmap.getWidth()).thenReturn(bitmapWidth);
when(mWallpaperBitmap.getHeight()).thenReturn(bitmapHeight);
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
index 0b309b5..4dd3ae7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
@@ -62,7 +62,9 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.CoordinateOnClickListener
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpandableNotificationRowLogger
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger
@@ -80,8 +82,6 @@
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.wmshell.BubblesManager
-import com.google.common.util.concurrent.MoreExecutors
-import com.google.common.util.concurrent.SettableFuture
import java.util.Optional
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -309,7 +309,7 @@
entry.ranking = rb.build()
}
- return generateRow(entry, FLAG_CONTENT_VIEW_ALL)
+ return generateRow(entry, INFLATION_FLAGS)
}
private fun generateRow(
@@ -374,7 +374,8 @@
private const val PKG = "com.android.systemui"
private const val UID = 1000
private val USER_HANDLE = UserHandle.of(ActivityManager.getCurrentUser())
-
+ private val INFLATION_FLAGS =
+ FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP
private const val IS_CONVERSATION_FLAG = "test.isConversation"
private val Notification.isConversationStyleNotification
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt
new file mode 100644
index 0000000..f502df0
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialKosmos.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.model.sysUiState
+import com.android.systemui.settings.displayTracker
+import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
+
+var Kosmos.touchpadGesturesInteractor: TouchpadGesturesInteractor by
+ Kosmos.Fixture {
+ TouchpadGesturesInteractor(sysUiState, displayTracker, testScope.backgroundScope)
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt
new file mode 100644
index 0000000..5776203
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/coroutines/MainDispatcherRule.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.coroutines
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.setMain
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+
+/**
+ * Overrides main dispatcher to passed testDispatcher. You probably want to use it when using
+ * viewModelScope which has hardcoded main dispatcher.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+class MainDispatcherRule(val testDispatcher: TestDispatcher) : TestWatcher() {
+ override fun starting(description: Description) {
+ Dispatchers.setMain(testDispatcher)
+ }
+
+ override fun finished(description: Description) {
+ Dispatchers.resetMain()
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 000f312..ef61d02 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -71,6 +71,8 @@
(reason) -> updateTouchpadTapToClickEnabled()),
Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_DRAGGING),
(reason) -> updateTouchpadTapDraggingEnabled()),
+ Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_VISUALIZER),
+ (reason) -> updateTouchpadHardwareStateNotificationsEnabled()),
Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE),
(reason) -> updateTouchpadRightClickZoneEnabled()),
Map.entry(Settings.System.getUriFor(Settings.System.SHOW_TOUCHES),
@@ -177,6 +179,10 @@
mNative.setTouchpadTapDraggingEnabled(InputSettings.useTouchpadTapDragging(mContext));
}
+ private void updateTouchpadHardwareStateNotificationsEnabled() {
+ mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext));
+ }
+
private void updateTouchpadRightClickZoneEnabled() {
mNative.setTouchpadRightClickZoneEnabled(InputSettings.useTouchpadRightClickZone(mContext));
}
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index a9d40bb..69a9f4d 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -135,6 +135,8 @@
void setTouchpadTapDraggingEnabled(boolean enabled);
+ void setShouldNotifyTouchpadHardwareState(boolean enabled);
+
void setTouchpadRightClickZoneEnabled(boolean enabled);
void setShowTouches(boolean enabled);
@@ -395,6 +397,9 @@
public native void setTouchpadTapDraggingEnabled(boolean enabled);
@Override
+ public native void setShouldNotifyTouchpadHardwareState(boolean enabled);
+
+ @Override
public native void setTouchpadRightClickZoneEnabled(boolean enabled);
@Override
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
index 0962319..8e37527 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
@@ -67,19 +67,19 @@
/**
* The handle of the primary frontend resource
*/
- private long mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ private int mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
/**
* List of the frontend handles that are used by the current client.
*/
- private Set<Long> mUsingFrontendHandles = new HashSet<>();
+ private Set<Integer> mUsingFrontendHandles = new HashSet<>();
/**
* List of the client ids that share frontend with the current client.
*/
private Set<Integer> mShareFeClientIds = new HashSet<>();
- private Set<Long> mUsingDemuxHandles = new HashSet<>();
+ private Set<Integer> mUsingDemuxHandles = new HashSet<>();
/**
* Client id sharee that has shared frontend with the current client.
@@ -89,7 +89,7 @@
/**
* List of the Lnb handles that are used by the current client.
*/
- private Set<Long> mUsingLnbHandles = new HashSet<>();
+ private Set<Integer> mUsingLnbHandles = new HashSet<>();
/**
* List of the Cas system ids that are used by the current client.
@@ -184,7 +184,7 @@
*
* @param frontendHandle being used.
*/
- public void useFrontend(long frontendHandle) {
+ public void useFrontend(int frontendHandle) {
mUsingFrontendHandles.add(frontendHandle);
}
@@ -193,14 +193,14 @@
*
* @param frontendHandle being used.
*/
- public void setPrimaryFrontend(long frontendHandle) {
+ public void setPrimaryFrontend(int frontendHandle) {
mPrimaryUsingFrontendHandle = frontendHandle;
}
/**
* Get the primary frontend used by the client
*/
- public long getPrimaryFrontend() {
+ public int getPrimaryFrontend() {
return mPrimaryUsingFrontendHandle;
}
@@ -222,7 +222,7 @@
mShareFeClientIds.remove(clientId);
}
- public Set<Long> getInUseFrontendHandles() {
+ public Set<Integer> getInUseFrontendHandles() {
return mUsingFrontendHandles;
}
@@ -253,14 +253,14 @@
*
* @param demuxHandle the demux being used.
*/
- public void useDemux(long demuxHandle) {
+ public void useDemux(int demuxHandle) {
mUsingDemuxHandles.add(demuxHandle);
}
/**
* Get the set of demux handles in use.
*/
- public Set<Long> getInUseDemuxHandles() {
+ public Set<Integer> getInUseDemuxHandles() {
return mUsingDemuxHandles;
}
@@ -269,7 +269,7 @@
*
* @param demuxHandle the demux handl being released.
*/
- public void releaseDemux(long demuxHandle) {
+ public void releaseDemux(int demuxHandle) {
mUsingDemuxHandles.remove(demuxHandle);
}
@@ -278,11 +278,11 @@
*
* @param lnbHandle being used.
*/
- public void useLnb(long lnbHandle) {
+ public void useLnb(int lnbHandle) {
mUsingLnbHandles.add(lnbHandle);
}
- public Set<Long> getInUseLnbHandles() {
+ public Set<Integer> getInUseLnbHandles() {
return mUsingLnbHandles;
}
@@ -291,7 +291,7 @@
*
* @param lnbHandle being released.
*/
- public void releaseLnb(long lnbHandle) {
+ public void releaseLnb(int lnbHandle) {
mUsingLnbHandles.remove(lnbHandle);
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/DemuxResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/DemuxResource.java
index 14bc216..df73565 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/DemuxResource.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/DemuxResource.java
@@ -69,7 +69,7 @@
public static class Builder extends TunerResourceBasic.Builder {
private int mFilterTypes;
- Builder(long handle) {
+ Builder(int handle) {
super(handle);
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java
index 953d974..7ef75e3 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java
@@ -42,7 +42,7 @@
/**
* An array to save all the FE handles under the same exclisive group.
*/
- private Set<Long> mExclusiveGroupMemberHandles = new HashSet<>();
+ private Set<Integer> mExclusiveGroupMemberHandles = new HashSet<>();
private FrontendResource(Builder builder) {
super(builder);
@@ -58,7 +58,7 @@
return mExclusiveGroupId;
}
- public Set<Long> getExclusiveGroupMemberFeHandles() {
+ public Set<Integer> getExclusiveGroupMemberFeHandles() {
return mExclusiveGroupMemberHandles;
}
@@ -67,7 +67,7 @@
*
* @param handle the handle to be added.
*/
- public void addExclusiveGroupMemberFeHandle(long handle) {
+ public void addExclusiveGroupMemberFeHandle(int handle) {
mExclusiveGroupMemberHandles.add(handle);
}
@@ -76,7 +76,7 @@
*
* @param handles the handle collection to be added.
*/
- public void addExclusiveGroupMemberFeHandles(Collection<Long> handles) {
+ public void addExclusiveGroupMemberFeHandles(Collection<Integer> handles) {
mExclusiveGroupMemberHandles.addAll(handles);
}
@@ -85,7 +85,7 @@
*
* @param id the id to be removed.
*/
- public void removeExclusiveGroupMemberFeId(long handle) {
+ public void removeExclusiveGroupMemberFeId(int handle) {
mExclusiveGroupMemberHandles.remove(handle);
}
@@ -104,7 +104,7 @@
@Type private int mType;
private int mExclusiveGroupId;
- Builder(long handle) {
+ Builder(int handle) {
super(handle);
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java
index ab28371..41cacea 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java
@@ -37,7 +37,8 @@
* Builder class for {@link LnbResource}.
*/
public static class Builder extends TunerResourceBasic.Builder {
- Builder(long handle) {
+
+ Builder(int handle) {
super(handle);
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java
index d2ff8fa..07853fc 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java
@@ -28,7 +28,7 @@
* Handle of the current resource. Should not be changed and should be aligned with the driver
* level implementation.
*/
- final long mHandle;
+ final int mHandle;
/**
* If the current resource is in use.
@@ -44,7 +44,7 @@
this.mHandle = builder.mHandle;
}
- public long getHandle() {
+ public int getHandle() {
return mHandle;
}
@@ -78,9 +78,9 @@
* Builder class for {@link TunerResourceBasic}.
*/
public static class Builder {
- private final long mHandle;
+ private final int mHandle;
- Builder(long handle) {
+ Builder(int handle) {
this.mHandle = handle;
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 45a40ed..0afb049 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -78,18 +78,12 @@
private static final int INVALID_FE_COUNT = -1;
- private static final int RESOURCE_ID_SHIFT = 24;
- private static final int RESOURCE_TYPE_SHIFT = 56;
- private static final long RESOURCE_COUNT_MASK = 0xffffff;
- private static final long RESOURCE_ID_MASK = 0xffffffff;
- private static final long RESOURCE_TYPE_MASK = 0xff;
-
// Map of the registered client profiles
private Map<Integer, ClientProfile> mClientProfiles = new HashMap<>();
private int mNextUnusedClientId = 0;
// Map of the current available frontend resources
- private Map<Long, FrontendResource> mFrontendResources = new HashMap<>();
+ private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>();
// SparseIntArray of the max usable number for each frontend resource type
private SparseIntArray mFrontendMaxUsableNums = new SparseIntArray();
// SparseIntArray of the currently used number for each frontend resource type
@@ -99,15 +93,15 @@
// Backups for the frontend resource maps for enabling testing with custom resource maps
// such as TunerTest.testHasUnusedFrontend1()
- private Map<Long, FrontendResource> mFrontendResourcesBackup = new HashMap<>();
+ private Map<Integer, FrontendResource> mFrontendResourcesBackup = new HashMap<>();
private SparseIntArray mFrontendMaxUsableNumsBackup = new SparseIntArray();
private SparseIntArray mFrontendUsedNumsBackup = new SparseIntArray();
private SparseIntArray mFrontendExistingNumsBackup = new SparseIntArray();
// Map of the current available demux resources
- private Map<Long, DemuxResource> mDemuxResources = new HashMap<>();
+ private Map<Integer, DemuxResource> mDemuxResources = new HashMap<>();
// Map of the current available lnb resources
- private Map<Long, LnbResource> mLnbResources = new HashMap<>();
+ private Map<Integer, LnbResource> mLnbResources = new HashMap<>();
// Map of the current available Cas resources
private Map<Integer, CasResource> mCasResources = new HashMap<>();
// Map of the current available CiCam resources
@@ -278,7 +272,7 @@
}
@Override
- public void setLnbInfoList(long[] lnbHandles) throws RemoteException {
+ public void setLnbInfoList(int[] lnbHandles) throws RemoteException {
enforceTrmAccessPermission("setLnbInfoList");
if (lnbHandles == null) {
throw new RemoteException("Lnb handle list can't be null");
@@ -289,8 +283,8 @@
}
@Override
- public boolean requestFrontend(
- @NonNull TunerFrontendRequest request, @NonNull long[] frontendHandle) {
+ public boolean requestFrontend(@NonNull TunerFrontendRequest request,
+ @NonNull int[] frontendHandle) {
enforceTunerAccessPermission("requestFrontend");
enforceTrmAccessPermission("requestFrontend");
if (frontendHandle == null) {
@@ -375,8 +369,8 @@
}
@Override
- public boolean requestDemux(@NonNull TunerDemuxRequest request, @NonNull long[] demuxHandle)
- throws RemoteException {
+ public boolean requestDemux(@NonNull TunerDemuxRequest request,
+ @NonNull int[] demuxHandle) throws RemoteException {
enforceTunerAccessPermission("requestDemux");
enforceTrmAccessPermission("requestDemux");
if (demuxHandle == null) {
@@ -393,7 +387,7 @@
@Override
public boolean requestDescrambler(@NonNull TunerDescramblerRequest request,
- @NonNull long[] descramblerHandle) throws RemoteException {
+ @NonNull int[] descramblerHandle) throws RemoteException {
enforceDescramblerAccessPermission("requestDescrambler");
enforceTrmAccessPermission("requestDescrambler");
if (descramblerHandle == null) {
@@ -410,7 +404,7 @@
@Override
public boolean requestCasSession(@NonNull CasSessionRequest request,
- @NonNull long[] casSessionHandle) throws RemoteException {
+ @NonNull int[] casSessionHandle) throws RemoteException {
enforceTrmAccessPermission("requestCasSession");
if (casSessionHandle == null) {
throw new RemoteException("casSessionHandle can't be null");
@@ -425,8 +419,8 @@
}
@Override
- public boolean requestCiCam(@NonNull TunerCiCamRequest request, @NonNull long[] ciCamHandle)
- throws RemoteException {
+ public boolean requestCiCam(@NonNull TunerCiCamRequest request,
+ @NonNull int[] ciCamHandle) throws RemoteException {
enforceTrmAccessPermission("requestCiCam");
if (ciCamHandle == null) {
throw new RemoteException("ciCamHandle can't be null");
@@ -441,7 +435,7 @@
}
@Override
- public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull long[] lnbHandle)
+ public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle)
throws RemoteException {
enforceTunerAccessPermission("requestLnb");
enforceTrmAccessPermission("requestLnb");
@@ -458,7 +452,7 @@
}
@Override
- public void releaseFrontend(long frontendHandle, int clientId) throws RemoteException {
+ public void releaseFrontend(int frontendHandle, int clientId) throws RemoteException {
enforceTunerAccessPermission("releaseFrontend");
enforceTrmAccessPermission("releaseFrontend");
if (!validateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND,
@@ -487,7 +481,7 @@
}
@Override
- public void releaseDemux(long demuxHandle, int clientId) throws RemoteException {
+ public void releaseDemux(int demuxHandle, int clientId) throws RemoteException {
enforceTunerAccessPermission("releaseDemux");
enforceTrmAccessPermission("releaseDemux");
if (DEBUG) {
@@ -518,7 +512,7 @@
}
@Override
- public void releaseDescrambler(long descramblerHandle, int clientId) {
+ public void releaseDescrambler(int descramblerHandle, int clientId) {
enforceTunerAccessPermission("releaseDescrambler");
enforceTrmAccessPermission("releaseDescrambler");
if (DEBUG) {
@@ -527,7 +521,7 @@
}
@Override
- public void releaseCasSession(long casSessionHandle, int clientId) throws RemoteException {
+ public void releaseCasSession(int casSessionHandle, int clientId) throws RemoteException {
enforceTrmAccessPermission("releaseCasSession");
if (!validateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_CAS_SESSION, casSessionHandle)) {
@@ -551,7 +545,7 @@
}
@Override
- public void releaseCiCam(long ciCamHandle, int clientId) throws RemoteException {
+ public void releaseCiCam(int ciCamHandle, int clientId) throws RemoteException {
enforceTrmAccessPermission("releaseCiCam");
if (!validateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCamHandle)) {
@@ -579,7 +573,7 @@
}
@Override
- public void releaseLnb(long lnbHandle, int clientId) throws RemoteException {
+ public void releaseLnb(int lnbHandle, int clientId) throws RemoteException {
enforceTunerAccessPermission("releaseLnb");
enforceTrmAccessPermission("releaseLnb");
if (!validateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, lnbHandle)) {
@@ -877,7 +871,7 @@
// A set to record the frontends pending on updating. Ids will be removed
// from this set once its updating finished. Any frontend left in this set when all
// the updates are done will be removed from mFrontendResources.
- Set<Long> updatingFrontendHandles = new HashSet<>(getFrontendResources().keySet());
+ Set<Integer> updatingFrontendHandles = new HashSet<>(getFrontendResources().keySet());
// Update frontendResources map and other mappings accordingly
for (int i = 0; i < infos.length; i++) {
@@ -896,7 +890,7 @@
}
}
- for (long removingHandle : updatingFrontendHandles) {
+ for (int removingHandle : updatingFrontendHandles) {
// update the exclusive group id member list
removeFrontendResource(removingHandle);
}
@@ -914,7 +908,7 @@
// A set to record the demuxes pending on updating. Ids will be removed
// from this set once its updating finished. Any demux left in this set when all
// the updates are done will be removed from mDemuxResources.
- Set<Long> updatingDemuxHandles = new HashSet<>(getDemuxResources().keySet());
+ Set<Integer> updatingDemuxHandles = new HashSet<>(getDemuxResources().keySet());
// Update demuxResources map and other mappings accordingly
for (int i = 0; i < infos.length; i++) {
@@ -932,13 +926,13 @@
}
}
- for (long removingHandle : updatingDemuxHandles) {
+ for (int removingHandle : updatingDemuxHandles) {
// update the exclusive group id member list
removeDemuxResource(removingHandle);
}
}
@VisibleForTesting
- protected void setLnbInfoListInternal(long[] lnbHandles) {
+ protected void setLnbInfoListInternal(int[] lnbHandles) {
if (DEBUG) {
for (int i = 0; i < lnbHandles.length; i++) {
Slog.d(TAG, "updateLnbInfo(lnbHanle=" + lnbHandles[i] + ")");
@@ -948,7 +942,7 @@
// A set to record the Lnbs pending on updating. Handles will be removed
// from this set once its updating finished. Any lnb left in this set when all
// the updates are done will be removed from mLnbResources.
- Set<Long> updatingLnbHandles = new HashSet<>(getLnbResources().keySet());
+ Set<Integer> updatingLnbHandles = new HashSet<>(getLnbResources().keySet());
// Update lnbResources map and other mappings accordingly
for (int i = 0; i < lnbHandles.length; i++) {
@@ -964,7 +958,7 @@
}
}
- for (long removingHandle : updatingLnbHandles) {
+ for (int removingHandle : updatingLnbHandles) {
removeLnbResource(removingHandle);
}
}
@@ -1009,7 +1003,7 @@
}
@VisibleForTesting
- protected boolean requestFrontendInternal(TunerFrontendRequest request, long[] frontendHandle) {
+ protected boolean requestFrontendInternal(TunerFrontendRequest request, int[] frontendHandle) {
if (DEBUG) {
Slog.d(TAG, "requestFrontend(request=" + request + ")");
}
@@ -1021,8 +1015,8 @@
return false;
}
clientPriorityUpdateOnRequest(requestClient);
- long grantingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- long inUseLowestPriorityFrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int grantingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int inUseLowestPriorityFrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
// Priority max value is 1000
int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
boolean isRequestFromSameProcess = false;
@@ -1056,7 +1050,7 @@
// we need to check the max used num if the target frontend type is not
// currently in primary use (and simply blocked due to exclusive group)
ClientProfile targetOwnerProfile = getClientProfile(fr.getOwnerClientId());
- long primaryFeId = targetOwnerProfile.getPrimaryFrontend();
+ int primaryFeId = targetOwnerProfile.getPrimaryFrontend();
FrontendResource primaryFe = getFrontendResource(primaryFeId);
if (fr.getType() != primaryFe.getType()
&& isFrontendMaxNumUseReached(fr.getType())) {
@@ -1108,7 +1102,7 @@
getClientProfile(shareeFeClientId).stopSharingFrontend(selfClientId);
getClientProfile(selfClientId).releaseFrontend();
}
- for (long feId : getClientProfile(targetClientId).getInUseFrontendHandles()) {
+ for (int feId : getClientProfile(targetClientId).getInUseFrontendHandles()) {
getClientProfile(selfClientId).useFrontend(feId);
}
getClientProfile(selfClientId).setShareeFeClientId(targetClientId);
@@ -1123,14 +1117,14 @@
currentOwnerProfile.stopSharingFrontend(newOwnerId);
newOwnerProfile.setShareeFeClientId(ClientProfile.INVALID_RESOURCE_ID);
currentOwnerProfile.setShareeFeClientId(newOwnerId);
- for (long inUseHandle : newOwnerProfile.getInUseFrontendHandles()) {
+ for (int inUseHandle : newOwnerProfile.getInUseFrontendHandles()) {
getFrontendResource(inUseHandle).setOwner(newOwnerId);
}
// change the primary frontend
newOwnerProfile.setPrimaryFrontend(currentOwnerProfile.getPrimaryFrontend());
currentOwnerProfile.setPrimaryFrontend(TunerResourceManager.INVALID_RESOURCE_HANDLE);
// double check there is no other resources tied to the previous owner
- for (long inUseHandle : currentOwnerProfile.getInUseFrontendHandles()) {
+ for (int inUseHandle : currentOwnerProfile.getInUseFrontendHandles()) {
int ownerId = getFrontendResource(inUseHandle).getOwnerClientId();
if (ownerId != newOwnerId) {
Slog.e(TAG, "something is wrong in transferFeOwner:" + inUseHandle
@@ -1162,8 +1156,8 @@
ClientProfile currentOwnerProfile = getClientProfile(currentOwnerId);
ClientProfile newOwnerProfile = getClientProfile(newOwnerId);
- Set<Long> inUseLnbHandles = new HashSet<>();
- for (Long lnbHandle : currentOwnerProfile.getInUseLnbHandles()) {
+ Set<Integer> inUseLnbHandles = new HashSet<>();
+ for (Integer lnbHandle : currentOwnerProfile.getInUseLnbHandles()) {
// link lnb handle to the new profile
newOwnerProfile.useLnb(lnbHandle);
@@ -1175,7 +1169,7 @@
}
// unlink lnb handles from the original owner
- for (Long lnbHandle : inUseLnbHandles) {
+ for (Integer lnbHandle : inUseLnbHandles) {
currentOwnerProfile.releaseLnb(lnbHandle);
}
@@ -1198,7 +1192,7 @@
}
@VisibleForTesting
- protected boolean requestLnbInternal(TunerLnbRequest request, long[] lnbHandle) {
+ protected boolean requestLnbInternal(TunerLnbRequest request, int[] lnbHandle) {
if (DEBUG) {
Slog.d(TAG, "requestLnb(request=" + request + ")");
}
@@ -1206,8 +1200,8 @@
lnbHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE;
ClientProfile requestClient = getClientProfile(request.clientId);
clientPriorityUpdateOnRequest(requestClient);
- long grantingLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- long inUseLowestPriorityLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int grantingLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int inUseLowestPriorityLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
// Priority max value is 1000
int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
boolean isRequestFromSameProcess = false;
@@ -1254,8 +1248,7 @@
}
@VisibleForTesting
- protected boolean requestCasSessionInternal(
- CasSessionRequest request, long[] casSessionHandle) {
+ protected boolean requestCasSessionInternal(CasSessionRequest request, int[] casSessionHandle) {
if (DEBUG) {
Slog.d(TAG, "requestCasSession(request=" + request + ")");
}
@@ -1308,7 +1301,7 @@
}
@VisibleForTesting
- protected boolean requestCiCamInternal(TunerCiCamRequest request, long[] ciCamHandle) {
+ protected boolean requestCiCamInternal(TunerCiCamRequest request, int[] ciCamHandle) {
if (DEBUG) {
Slog.d(TAG, "requestCiCamInternal(TunerCiCamRequest=" + request + ")");
}
@@ -1331,7 +1324,6 @@
ciCamHandle[0] = generateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId());
updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId);
- Slog.e(TAG, "requestCiCamInternal(ciCamHandle=" + ciCamHandle[0] + ")");
return true;
}
for (int ownerId : ciCam.getOwnerClientIds()) {
@@ -1357,7 +1349,6 @@
ciCamHandle[0] = generateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId());
updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId);
- Slog.e(TAG, "requestCiCamInternal(ciCamHandle=" + ciCamHandle[0] + ")");
return true;
}
return false;
@@ -1441,7 +1432,7 @@
}
@VisibleForTesting
- protected boolean requestDemuxInternal(TunerDemuxRequest request, long[] demuxHandle) {
+ protected boolean requestDemuxInternal(TunerDemuxRequest request, int[] demuxHandle) {
if (DEBUG) {
Slog.d(TAG, "requestDemux(request=" + request + ")");
}
@@ -1464,8 +1455,8 @@
}
clientPriorityUpdateOnRequest(requestClient);
- long grantingDemuxHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- long inUseLowestPriorityDrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int grantingDemuxHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ int inUseLowestPriorityDrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
// Priority max value is 1000
int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
boolean isRequestFromSameProcess = false;
@@ -1559,7 +1550,7 @@
@VisibleForTesting
protected boolean requestDescramblerInternal(
- TunerDescramblerRequest request, long[] descramblerHandle) {
+ TunerDescramblerRequest request, int[] descramblerHandle) {
if (DEBUG) {
Slog.d(TAG, "requestDescrambler(request=" + request + ")");
}
@@ -1878,20 +1869,20 @@
return false;
}
- private void updateFrontendClientMappingOnNewGrant(long grantingHandle, int ownerClientId) {
+ private void updateFrontendClientMappingOnNewGrant(int grantingHandle, int ownerClientId) {
FrontendResource grantingFrontend = getFrontendResource(grantingHandle);
ClientProfile ownerProfile = getClientProfile(ownerClientId);
grantingFrontend.setOwner(ownerClientId);
increFrontendNum(mFrontendUsedNums, grantingFrontend.getType());
ownerProfile.useFrontend(grantingHandle);
- for (long exclusiveGroupMember : grantingFrontend.getExclusiveGroupMemberFeHandles()) {
+ for (int exclusiveGroupMember : grantingFrontend.getExclusiveGroupMemberFeHandles()) {
getFrontendResource(exclusiveGroupMember).setOwner(ownerClientId);
ownerProfile.useFrontend(exclusiveGroupMember);
}
ownerProfile.setPrimaryFrontend(grantingHandle);
}
- private void updateDemuxClientMappingOnNewGrant(long grantingHandle, int ownerClientId) {
+ private void updateDemuxClientMappingOnNewGrant(int grantingHandle, int ownerClientId) {
DemuxResource grantingDemux = getDemuxResource(grantingHandle);
if (grantingDemux != null) {
ClientProfile ownerProfile = getClientProfile(ownerClientId);
@@ -1906,7 +1897,7 @@
ownerProfile.releaseDemux(releasingDemux.getHandle());
}
- private void updateLnbClientMappingOnNewGrant(long grantingHandle, int ownerClientId) {
+ private void updateLnbClientMappingOnNewGrant(int grantingHandle, int ownerClientId) {
LnbResource grantingLnb = getLnbResource(grantingHandle);
ClientProfile ownerProfile = getClientProfile(ownerClientId);
grantingLnb.setOwner(ownerClientId);
@@ -1990,23 +1981,23 @@
@VisibleForTesting
@Nullable
- protected FrontendResource getFrontendResource(long frontendHandle) {
+ protected FrontendResource getFrontendResource(int frontendHandle) {
return mFrontendResources.get(frontendHandle);
}
@VisibleForTesting
- protected Map<Long, FrontendResource> getFrontendResources() {
+ protected Map<Integer, FrontendResource> getFrontendResources() {
return mFrontendResources;
}
@VisibleForTesting
@Nullable
- protected DemuxResource getDemuxResource(long demuxHandle) {
+ protected DemuxResource getDemuxResource(int demuxHandle) {
return mDemuxResources.get(demuxHandle);
}
@VisibleForTesting
- protected Map<Long, DemuxResource> getDemuxResources() {
+ protected Map<Integer, DemuxResource> getDemuxResources() {
return mDemuxResources;
}
@@ -2065,8 +2056,8 @@
}
}
- private void replaceFeResourceMap(
- Map<Long, FrontendResource> srcMap, Map<Long, FrontendResource> dstMap) {
+ private void replaceFeResourceMap(Map<Integer, FrontendResource> srcMap, Map<Integer,
+ FrontendResource> dstMap) {
if (dstMap != null) {
dstMap.clear();
if (srcMap != null && srcMap.size() > 0) {
@@ -2119,7 +2110,7 @@
if (fe.getExclusiveGroupId() == newFe.getExclusiveGroupId()) {
newFe.addExclusiveGroupMemberFeHandle(fe.getHandle());
newFe.addExclusiveGroupMemberFeHandles(fe.getExclusiveGroupMemberFeHandles());
- for (long excGroupmemberFeHandle : fe.getExclusiveGroupMemberFeHandles()) {
+ for (int excGroupmemberFeHandle : fe.getExclusiveGroupMemberFeHandles()) {
getFrontendResource(excGroupmemberFeHandle)
.addExclusiveGroupMemberFeHandle(newFe.getHandle());
}
@@ -2137,7 +2128,7 @@
mDemuxResources.put(newDemux.getHandle(), newDemux);
}
- private void removeFrontendResource(long removingHandle) {
+ private void removeFrontendResource(int removingHandle) {
FrontendResource fe = getFrontendResource(removingHandle);
if (fe == null) {
return;
@@ -2149,7 +2140,7 @@
}
clearFrontendAndClientMapping(ownerClient);
}
- for (long excGroupmemberFeHandle : fe.getExclusiveGroupMemberFeHandles()) {
+ for (int excGroupmemberFeHandle : fe.getExclusiveGroupMemberFeHandles()) {
getFrontendResource(excGroupmemberFeHandle)
.removeExclusiveGroupMemberFeId(fe.getHandle());
}
@@ -2157,7 +2148,7 @@
mFrontendResources.remove(removingHandle);
}
- private void removeDemuxResource(long removingHandle) {
+ private void removeDemuxResource(int removingHandle) {
DemuxResource demux = getDemuxResource(removingHandle);
if (demux == null) {
return;
@@ -2170,12 +2161,12 @@
@VisibleForTesting
@Nullable
- protected LnbResource getLnbResource(long lnbHandle) {
+ protected LnbResource getLnbResource(int lnbHandle) {
return mLnbResources.get(lnbHandle);
}
@VisibleForTesting
- protected Map<Long, LnbResource> getLnbResources() {
+ protected Map<Integer, LnbResource> getLnbResources() {
return mLnbResources;
}
@@ -2184,7 +2175,7 @@
mLnbResources.put(newLnb.getHandle(), newLnb);
}
- private void removeLnbResource(long removingHandle) {
+ private void removeLnbResource(int removingHandle) {
LnbResource lnb = getLnbResource(removingHandle);
if (lnb == null) {
return;
@@ -2288,7 +2279,7 @@
if (profile == null) {
return;
}
- for (Long feId : profile.getInUseFrontendHandles()) {
+ for (Integer feId : profile.getInUseFrontendHandles()) {
FrontendResource fe = getFrontendResource(feId);
int ownerClientId = fe.getOwnerClientId();
if (ownerClientId == profile.getId()) {
@@ -2299,9 +2290,10 @@
if (ownerClientProfile != null) {
ownerClientProfile.stopSharingFrontend(profile.getId());
}
+
}
- long primaryFeId = profile.getPrimaryFrontend();
+ int primaryFeId = profile.getPrimaryFrontend();
if (primaryFeId != TunerResourceManager.INVALID_RESOURCE_HANDLE) {
FrontendResource primaryFe = getFrontendResource(primaryFeId);
if (primaryFe != null) {
@@ -2318,7 +2310,7 @@
return;
}
// Clear Lnb
- for (Long lnbHandle : profile.getInUseLnbHandles()) {
+ for (Integer lnbHandle : profile.getInUseLnbHandles()) {
getLnbResource(lnbHandle).removeOwner();
}
// Clear Cas
@@ -2330,7 +2322,7 @@
getCiCamResource(profile.getInUseCiCamId()).removeOwner(profile.getId());
}
// Clear Demux
- for (Long demuxHandle : profile.getInUseDemuxHandles()) {
+ for (Integer demuxHandle : profile.getInUseDemuxHandles()) {
getDemuxResource(demuxHandle).removeOwner();
}
// Clear Frontend
@@ -2343,31 +2335,24 @@
return mClientProfiles.keySet().contains(clientId);
}
- /**
- * Generate resource handle for resourceType and resourceId
- * Resource Handle Allotment : 64 bits (long)
- * 8 bits - resourceType
- * 32 bits - resourceId
- * 24 bits - resourceRequestCount
- */
- private long generateResourceHandle(
+ private int generateResourceHandle(
@TunerResourceManager.TunerResourceType int resourceType, int resourceId) {
- return (resourceType & RESOURCE_TYPE_MASK) << RESOURCE_TYPE_SHIFT
- | (resourceId & RESOURCE_ID_MASK) << RESOURCE_ID_SHIFT
- | (mResourceRequestCount++ & RESOURCE_COUNT_MASK);
+ return (resourceType & 0x000000ff) << 24
+ | (resourceId << 16)
+ | (mResourceRequestCount++ & 0xffff);
}
@VisibleForTesting
- protected int getResourceIdFromHandle(long resourceHandle) {
+ protected int getResourceIdFromHandle(int resourceHandle) {
if (resourceHandle == TunerResourceManager.INVALID_RESOURCE_HANDLE) {
- return (int) resourceHandle;
+ return resourceHandle;
}
- return (int) ((resourceHandle >> RESOURCE_ID_SHIFT) & RESOURCE_ID_MASK);
+ return (resourceHandle & 0x00ff0000) >> 16;
}
- private boolean validateResourceHandle(int resourceType, long resourceHandle) {
+ private boolean validateResourceHandle(int resourceType, int resourceHandle) {
if (resourceHandle == TunerResourceManager.INVALID_RESOURCE_HANDLE
- || ((resourceHandle >> RESOURCE_TYPE_SHIFT) & RESOURCE_TYPE_MASK) != resourceType) {
+ || ((resourceHandle & 0xff000000) >> 24) != resourceType) {
return false;
}
return true;
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
index 4427605..cd795ae 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
@@ -233,7 +233,8 @@
return mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled();
}
- private float getDisplaySizeMinAspectRatio() {
+ @VisibleForTesting
+ float getDisplaySizeMinAspectRatio() {
final DisplayArea displayArea = mActivityRecord.getDisplayArea();
if (displayArea == null) {
return mActivityRecord.info.getMinAspectRatio();
@@ -270,7 +271,6 @@
return !mAllowUserAspectRatioOverrideOptProp.isFalse();
}
- @VisibleForTesting
int getUserMinAspectRatioOverrideCode() {
try {
return mActivityRecord.mAtmService.getPackageManager()
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index 94ad61f..e3ff851 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -187,6 +187,8 @@
appCompatTaskInfo.setTopActivityLetterboxed(top.areBoundsLetterboxed());
appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = top.mAppCompatController
.getAppCompatCameraOverrides().getFreeformCameraCompatMode();
+ appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController
+ .getDesktopAppCompatAspectRatioPolicy().hasMinAspectRatioOverride(task));
}
/**
diff --git a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java
index 8477c6c..b936556 100644
--- a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java
+++ b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java
@@ -258,7 +258,7 @@
* Whether we should apply the user aspect ratio override to the min aspect ratio for the
* current app.
*/
- private boolean shouldApplyUserMinAspectRatioOverride(@NonNull Task task) {
+ boolean shouldApplyUserMinAspectRatioOverride(@NonNull Task task) {
if (!shouldEnableUserAspectRatioSettings(task)) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
index 8f1828d..c3db7dd 100644
--- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
+++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
@@ -16,31 +16,28 @@
package com.android.server.wm;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.isFixedOrientation;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
-import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
-import static com.android.server.wm.AppCompatUtils.computeAspectRatio;
import static com.android.server.wm.LaunchParamsUtil.applyLayoutGravity;
import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
-import android.app.AppCompatTaskInfo;
import android.app.TaskInfo;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
+import android.content.pm.ActivityInfo.ScreenOrientation;
+import android.content.pm.ActivityInfo.WindowLayout;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.Size;
import android.view.Gravity;
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.utils.DesktopModeFlagsUtil;
import java.util.function.Consumer;
@@ -60,7 +57,7 @@
* Updates launch bounds for an activity with respect to its activity options, window layout,
* android manifest and task configuration.
*/
- static void updateInitialBounds(@NonNull Task task, @Nullable ActivityInfo.WindowLayout layout,
+ static void updateInitialBounds(@NonNull Task task, @Nullable WindowLayout layout,
@Nullable ActivityRecord activity, @Nullable ActivityOptions options,
@NonNull Rect outBounds, @NonNull Consumer<String> logger) {
// Use stable frame instead of raw frame to avoid launching freeform windows on top of
@@ -98,7 +95,8 @@
* fullscreen size, aspect ratio, orientation and resizability to calculate an area this is
* compatible with the applications previous configuration.
*/
- private static @NonNull Rect calculateInitialBounds(@NonNull Task task,
+ @NonNull
+ private static Rect calculateInitialBounds(@NonNull Task task,
@NonNull ActivityRecord activity, @NonNull Rect stableBounds
) {
final TaskInfo taskInfo = task.getTaskInfo();
@@ -116,18 +114,19 @@
// applied.
return centerInScreen(idealSize, screenBounds);
}
- // TODO(b/353457301): Replace with app compat aspect ratio method when refactoring complete.
- float appAspectRatio = calculateAspectRatio(task, activity);
+ final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy =
+ activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy();
+ float appAspectRatio = desktopAppCompatAspectRatioPolicy.calculateAspectRatio(task);
final float tdaWidth = stableBounds.width();
final float tdaHeight = stableBounds.height();
- final int activityOrientation = activity.getOverrideOrientation();
+ final int activityOrientation = getActivityOrientation(activity, task);
final Size initialSize = switch (taskInfo.configuration.orientation) {
case ORIENTATION_LANDSCAPE -> {
// Device in landscape orientation.
if (appAspectRatio == 0) {
appAspectRatio = 1;
}
- if (taskInfo.isResizeable) {
+ if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) {
if (isFixedOrientationPortrait(activityOrientation)) {
// For portrait resizeable activities, respect apps fullscreen width but
// apply ideal size height.
@@ -139,14 +138,13 @@
}
// If activity is unresizeable, regardless of orientation, calculate maximum size
// (within the ideal size) maintaining original aspect ratio.
- yield maximizeSizeGivenAspectRatio(
- activity.getOverrideOrientation(), idealSize, appAspectRatio);
+ yield maximizeSizeGivenAspectRatio(activityOrientation, idealSize, appAspectRatio);
}
case ORIENTATION_PORTRAIT -> {
// Device in portrait orientation.
final int customPortraitWidthForLandscapeApp = screenBounds.width()
- (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2);
- if (taskInfo.isResizeable) {
+ if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) {
if (isFixedOrientationLandscape(activityOrientation)) {
if (appAspectRatio == 0) {
appAspectRatio = tdaWidth / (tdaWidth - 1);
@@ -180,11 +178,38 @@
}
/**
+ * Whether the activity's aspect ratio can be changed or if it should be maintained as if it was
+ * unresizeable.
+ */
+ private static boolean canChangeAspectRatio(
+ @NonNull DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy,
+ @NonNull TaskInfo taskInfo, @NonNull Task task) {
+ return taskInfo.isResizeable
+ && !desktopAppCompatAspectRatioPolicy.hasMinAspectRatioOverride(task);
+ }
+
+ private static @ScreenOrientation int getActivityOrientation(
+ @NonNull ActivityRecord activity, @NonNull Task task) {
+ final int activityOrientation = activity.getOverrideOrientation();
+ final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy =
+ activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy();
+ if (desktopAppCompatAspectRatioPolicy.shouldApplyUserMinAspectRatioOverride(task)
+ && (!isFixedOrientation(activityOrientation)
+ || activityOrientation == SCREEN_ORIENTATION_LOCKED)) {
+ // If a user aspect ratio override should be applied, treat the activity as portrait if
+ // it has not specified a fix orientation.
+ return SCREEN_ORIENTATION_PORTRAIT;
+ }
+ return activityOrientation;
+ }
+
+ /**
* Calculates the largest size that can fit in a given area while maintaining a specific aspect
* ratio.
*/
- private static @NonNull Size maximizeSizeGivenAspectRatio(
- @ActivityInfo.ScreenOrientation int orientation,
+ @NonNull
+ private static Size maximizeSizeGivenAspectRatio(
+ @ScreenOrientation int orientation,
@NonNull Size targetArea,
float aspectRatio
) {
@@ -229,68 +254,11 @@
}
/**
- * Calculates the aspect ratio of an activity from its fullscreen bounds.
- */
- @VisibleForTesting
- static float calculateAspectRatio(@NonNull Task task, @NonNull ActivityRecord activity) {
- final TaskInfo taskInfo = task.getTaskInfo();
- final float fullscreenWidth = task.getDisplayArea().getBounds().width();
- final float fullscreenHeight = task.getDisplayArea().getBounds().height();
- final float maxAspectRatio = activity.getMaxAspectRatio();
- final float minAspectRatio = activity.getMinAspectRatio();
- float desiredAspectRatio = 0;
- if (taskInfo.isRunning) {
- final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo;
- final int appLetterboxWidth =
- taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth;
- final int appLetterboxHeight =
- taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight;
- if (appCompatTaskInfo.isTopActivityLetterboxed()) {
- desiredAspectRatio = (float) Math.max(appLetterboxWidth, appLetterboxHeight)
- / Math.min(appLetterboxWidth, appLetterboxHeight);
- } else {
- desiredAspectRatio = Math.max(fullscreenHeight, fullscreenWidth)
- / Math.min(fullscreenHeight, fullscreenWidth);
- }
- } else {
- final float letterboxAspectRatioOverride =
- getFixedOrientationLetterboxAspectRatio(activity, task);
- if (!task.mDisplayContent.getIgnoreOrientationRequest()) {
- desiredAspectRatio = DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
- } else if (letterboxAspectRatioOverride
- > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) {
- desiredAspectRatio = letterboxAspectRatioOverride;
- }
- }
- // If the activity matches display orientation, the display aspect ratio should be used
- if (activityMatchesDisplayOrientation(
- taskInfo.configuration.orientation,
- activity.getOverrideOrientation())) {
- desiredAspectRatio = Math.max(fullscreenWidth, fullscreenHeight)
- / Math.min(fullscreenWidth, fullscreenHeight);
- }
- if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) {
- desiredAspectRatio = maxAspectRatio;
- } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) {
- desiredAspectRatio = minAspectRatio;
- }
- return desiredAspectRatio;
- }
-
- private static boolean activityMatchesDisplayOrientation(
- @Configuration.Orientation int deviceOrientation,
- @ActivityInfo.ScreenOrientation int activityOrientation) {
- if (deviceOrientation == ORIENTATION_PORTRAIT) {
- return isFixedOrientationPortrait(activityOrientation);
- }
- return isFixedOrientationLandscape(activityOrientation);
- }
-
- /**
* Calculates the desired initial bounds for applications in desktop windowing. This is done as
* a scale of the screen bounds.
*/
- private static @NonNull Size calculateIdealSize(@NonNull Rect screenBounds, float scale) {
+ @NonNull
+ private static Size calculateIdealSize(@NonNull Rect screenBounds, float scale) {
final int width = (int) (screenBounds.width() * scale);
final int height = (int) (screenBounds.height() * scale);
return new Size(width, height);
@@ -299,7 +267,8 @@
/**
* Adjusts bounds to be positioned in the middle of the screen.
*/
- private static @NonNull Rect centerInScreen(@NonNull Size desiredSize,
+ @NonNull
+ private static Rect centerInScreen(@NonNull Size desiredSize,
@NonNull Rect screenBounds) {
// TODO(b/325240051): Position apps with bottom heavy offset
final int heightOffset = (screenBounds.height() - desiredSize.getHeight()) / 2;
@@ -309,57 +278,4 @@
resultBounds.offset(screenBounds.left + widthOffset, screenBounds.top + heightOffset);
return resultBounds;
}
-
- private static float getFixedOrientationLetterboxAspectRatio(@NonNull ActivityRecord activity,
- @NonNull Task task) {
- return activity.shouldCreateCompatDisplayInsets()
- ? getDefaultMinAspectRatioForUnresizableApps(activity, task)
- : activity.mAppCompatController.getAppCompatAspectRatioOverrides()
- .getDefaultMinAspectRatio();
- }
-
- private static float getDefaultMinAspectRatioForUnresizableApps(
- @NonNull ActivityRecord activity,
- @NonNull Task task) {
- final AppCompatAspectRatioOverrides appCompatAspectRatioOverrides =
- activity.mAppCompatController.getAppCompatAspectRatioOverrides();
- if (appCompatAspectRatioOverrides.isSplitScreenAspectRatioForUnresizableAppsEnabled()) {
- // Default letterbox aspect ratio for unresizable apps.
- return getSplitScreenAspectRatio(activity, task);
- }
-
- if (appCompatAspectRatioOverrides.getDefaultMinAspectRatioForUnresizableAppsFromConfig()
- > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) {
- return appCompatAspectRatioOverrides
- .getDefaultMinAspectRatioForUnresizableAppsFromConfig();
- }
-
- return appCompatAspectRatioOverrides.getDefaultMinAspectRatio();
- }
-
- /**
- * Calculates the aspect ratio of the available display area when an app enters split-screen on
- * a given device, taking into account any dividers and insets.
- */
- private static float getSplitScreenAspectRatio(@NonNull ActivityRecord activity,
- @NonNull Task task) {
- final int dividerWindowWidth =
- activity.mWmService.mContext.getResources().getDimensionPixelSize(
- R.dimen.docked_stack_divider_thickness);
- final int dividerInsets =
- activity.mWmService.mContext.getResources().getDimensionPixelSize(
- R.dimen.docked_stack_divider_insets);
- final int dividerSize = dividerWindowWidth - dividerInsets * 2;
- final Rect bounds = new Rect(0, 0,
- task.mDisplayContent.getDisplayInfo().appWidth,
- task.mDisplayContent.getDisplayInfo().appHeight);
- if (bounds.width() >= bounds.height()) {
- bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0);
- bounds.right = bounds.centerX();
- } else {
- bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2);
- bounds.bottom = bounds.centerY();
- }
- return computeAspectRatio(bounds);
- }
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 4d6a90c..07d39d9 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -291,6 +291,7 @@
void setTouchpadNaturalScrollingEnabled(bool enabled);
void setTouchpadTapToClickEnabled(bool enabled);
void setTouchpadTapDraggingEnabled(bool enabled);
+ void setShouldNotifyTouchpadHardwareState(bool enabled);
void setTouchpadRightClickZoneEnabled(bool enabled);
void setInputDeviceEnabled(uint32_t deviceId, bool enabled);
void setShowTouches(bool enabled);
@@ -440,6 +441,9 @@
// True to enable tap dragging on touchpads.
bool touchpadTapDraggingEnabled{false};
+ // True if hardware state update notifications should be sent to the policy.
+ bool shouldNotifyTouchpadHardwareState{false};
+
// True to enable a zone on the right-hand side of touchpads where clicks will be turned
// into context (a.k.a. "right") clicks.
bool touchpadRightClickZoneEnabled{false};
@@ -698,6 +702,7 @@
outConfig->touchpadNaturalScrollingEnabled = mLocked.touchpadNaturalScrollingEnabled;
outConfig->touchpadTapToClickEnabled = mLocked.touchpadTapToClickEnabled;
outConfig->touchpadTapDraggingEnabled = mLocked.touchpadTapDraggingEnabled;
+ outConfig->shouldNotifyTouchpadHardwareState = mLocked.shouldNotifyTouchpadHardwareState;
outConfig->touchpadRightClickZoneEnabled = mLocked.touchpadRightClickZoneEnabled;
outConfig->disabledDevices = mLocked.disabledInputDevices;
@@ -1260,6 +1265,22 @@
InputReaderConfiguration::Change::TOUCHPAD_SETTINGS);
}
+void NativeInputManager::setShouldNotifyTouchpadHardwareState(bool enabled) {
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ if (mLocked.shouldNotifyTouchpadHardwareState == enabled) {
+ return;
+ }
+
+ ALOGI("Should touchpad hardware state be notified: %s.", toString(enabled));
+ mLocked.shouldNotifyTouchpadHardwareState = enabled;
+ } // release lock
+
+ mInputManager->getReader().requestRefreshConfiguration(
+ InputReaderConfiguration::Change::TOUCHPAD_SETTINGS);
+}
+
void NativeInputManager::setTouchpadRightClickZoneEnabled(bool enabled) {
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -2144,6 +2165,13 @@
im->setTouchpadTapDraggingEnabled(enabled);
}
+static void nativeSetShouldNotifyTouchpadHardwareState(JNIEnv* env, jobject nativeImplObj,
+ jboolean enabled) {
+ NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+
+ im->setShouldNotifyTouchpadHardwareState(enabled);
+}
+
static void nativeSetTouchpadRightClickZoneEnabled(JNIEnv* env, jobject nativeImplObj,
jboolean enabled) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
@@ -2762,6 +2790,8 @@
(void*)nativeSetTouchpadNaturalScrollingEnabled},
{"setTouchpadTapToClickEnabled", "(Z)V", (void*)nativeSetTouchpadTapToClickEnabled},
{"setTouchpadTapDraggingEnabled", "(Z)V", (void*)nativeSetTouchpadTapDraggingEnabled},
+ {"setShouldNotifyTouchpadHardwareState", "(Z)V",
+ (void*)nativeSetShouldNotifyTouchpadHardwareState},
{"setTouchpadRightClickZoneEnabled", "(Z)V", (void*)nativeSetTouchpadRightClickZoneEnabled},
{"setShowTouches", "(Z)V", (void*)nativeSetShowTouches},
{"setInteractive", "(Z)V", (void*)nativeSetInteractive},
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9ed645b..d5013517 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12215,34 +12215,30 @@
* permittedList or are a system app.
*/
private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
- List<String> permittedList, int userIdToCheck) {
+ List<String> permittedList, int userId) {
long id = mInjector.binderClearCallingIdentity();
try {
- // If we have an enabled packages list for a managed profile the packages
- // we should check are installed for the parent user.
- UserInfo user = getUserInfo(userIdToCheck);
- if (user.isManagedProfile()) {
- userIdToCheck = user.profileGroupId;
- }
-
for (String enabledPackage : enabledPackages) {
- boolean systemService = false;
+ if (permittedList.contains(enabledPackage)) {
+ continue;
+ }
try {
ApplicationInfo applicationInfo = mIPackageManager.getApplicationInfo(
- enabledPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES,
- userIdToCheck);
+ enabledPackage, PackageManager.MATCH_ANY_USER, userId);
if (applicationInfo == null) {
+ Slogf.wtf(LOG_TAG, "Can't find ApplicationInfo for %s", enabledPackage);
return false;
}
- systemService = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ if (!applicationInfo.isSystemApp()) {
+ Slogf.w(LOG_TAG,
+ "Enabled package neither permitted nor system: %s", enabledPackage);
+ return false;
+ }
} catch (RemoteException e) {
Slogf.i(LOG_TAG, "Can't talk to package managed", e);
}
- if (!systemService && !permittedList.contains(enabledPackage)) {
- return false;
- }
}
} finally {
mInjector.binderRestoreCallingIdentity(id);
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
index 6393e11..1db9e8d 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/Android.bp
@@ -1,7 +1,7 @@
aconfig_declarations {
name: "device_state_flags",
package: "com.android.server.policy.feature.flags",
- container: "system",
+ container: "system_ext",
srcs: [
"device_state_flags.aconfig",
],
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
index 21e33dd..f827b55 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
@@ -1,5 +1,5 @@
package: "com.android.server.policy.feature.flags"
-container: "system"
+container: "system_ext"
flag {
name: "enable_dual_display_blocking"
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index e72d9e7..b7483d6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -70,14 +70,14 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.longThat;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -1733,12 +1733,20 @@
pi.applicationInfo.flags = flags;
doReturn(pi).when(getServices().ipackageManager).getPackageInfo(
eq(packageName),
- anyLong(),
+ longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) == 0),
+ eq(userId));
+ doReturn(pi).when(getServices().ipackageManager).getPackageInfo(
+ eq(packageName),
+ longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) != 0),
+ anyInt());
+ doReturn(pi.applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
+ eq(packageName),
+ longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) == 0),
eq(userId));
doReturn(pi.applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
eq(packageName),
- anyLong(),
- eq(userId));
+ longThat(flg -> (flg & PackageManager.MATCH_ANY_USER) != 0),
+ anyInt());
doReturn(true).when(getServices().ipackageManager).isPackageAvailable(packageName, userId);
// Setup application UID with the PackageManager
getServices().addTestPackageUid(packageName, uid);
@@ -1757,7 +1765,7 @@
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.applicationInfo = new ApplicationInfo();
mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+ when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE);
StringParceledListSlice oneCert = asSlice(new String[] {"1"});
StringParceledListSlice fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
@@ -4551,7 +4559,7 @@
mContext.packageName = admin1.getPackageName();
mContext.applicationInfo = new ApplicationInfo();
- when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+ when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE);
// setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the
// feature is disabled because there are non-affiliated secondary users.
@@ -4597,12 +4605,12 @@
setupDeviceOwner();
mContext.packageName = admin1.getPackageName();
mContext.applicationInfo = new ApplicationInfo();
- when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+ when(mContext.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE);
// setUp() adds a secondary user for CALLER_USER_HANDLE. Remove it as otherwise the
// feature is disabled because there are non-affiliated secondary users.
getServices().removeUser(CALLER_USER_HANDLE);
- when(getServices().iipConnectivityMetrics.addNetdEventCallback(anyInt(), anyObject()))
+ when(getServices().iipConnectivityMetrics.addNetdEventCallback(anyInt(), any()))
.thenReturn(true);
// No logs were retrieved so far.
@@ -4667,7 +4675,7 @@
mContext.packageName = admin1.getPackageName();
addManagedProfile(admin1, managedProfileAdminUid, admin1, VERSION_CODES.S);
when(getServices().iipConnectivityMetrics
- .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true);
+ .addNetdEventCallback(anyInt(), any())).thenReturn(true);
// Check no logs have been retrieved so far.
assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
@@ -4699,7 +4707,7 @@
mContext.packageName = admin1.getPackageName();
mContext.applicationInfo = new ApplicationInfo();
when(getServices().iipConnectivityMetrics
- .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true);
+ .addNetdEventCallback(anyInt(), any())).thenReturn(true);
// Check no logs have been retrieved so far.
assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
@@ -6296,13 +6304,13 @@
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
assertThat(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue();
+ nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue();
assertThat(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
assertThat(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+ nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
assertThat(dpms.isNotificationListenerServicePermitted(
- systemListener, UserHandle.USER_SYSTEM)).isTrue();
+ systemListener, UserHandle.USER_SYSTEM)).isTrue();
// Setting an empty allowlist - only system listeners allowed in managed profile, but
// all allowed in primary profile
@@ -6313,13 +6321,13 @@
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
assertThat(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse();
+ nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse();
assertThat(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
assertThat(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+ nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
assertThat(dpms.isNotificationListenerServicePermitted(
- systemListener, UserHandle.USER_SYSTEM)).isTrue();
+ systemListener, UserHandle.USER_SYSTEM)).isTrue();
}
@Test
@@ -6455,7 +6463,7 @@
if (admin1.getPackageName().equals(callerContext.getPackageName())) {
admin1Context = callerContext;
}
- when(admin1Context.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+ when(admin1Context.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE);
// caller: device admin or delegated certificate installer
callerContext.applicationInfo = new ApplicationInfo();
@@ -6528,7 +6536,7 @@
if (admin1.getPackageName().equals(callerContext.getPackageName())) {
admin1Context = callerContext;
}
- when(admin1Context.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+ when(admin1Context.resources.getColor(anyInt(), any())).thenReturn(Color.WHITE);
// caller: device admin or delegated certificate installer
callerContext.applicationInfo = new ApplicationInfo();
diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
index 8e36335..963b27e 100644
--- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
@@ -119,7 +119,8 @@
tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
- Map<Long, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources();
+ Map<Integer, FrontendResource> resources =
+ mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos.length; id++) {
assertThat(resources.get(infos[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
@@ -146,14 +147,15 @@
tunerFrontendInfo(3 /*handle*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
- Map<Long, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources();
+ Map<Integer, FrontendResource> resources =
+ mTunerResourceManagerService.getFrontendResources();
assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE)
.containsExactlyElementsIn(Arrays.asList(infos));
- assertThat(resources.get(0L).getExclusiveGroupMemberFeHandles()).isEmpty();
- assertThat(resources.get(1L).getExclusiveGroupMemberFeHandles()).containsExactly(2L, 3L);
- assertThat(resources.get(2L).getExclusiveGroupMemberFeHandles()).containsExactly(1L, 3L);
- assertThat(resources.get(3L).getExclusiveGroupMemberFeHandles()).containsExactly(1L, 2L);
+ assertThat(resources.get(0).getExclusiveGroupMemberFeHandles()).isEmpty();
+ assertThat(resources.get(1).getExclusiveGroupMemberFeHandles()).containsExactly(2, 3);
+ assertThat(resources.get(2).getExclusiveGroupMemberFeHandles()).containsExactly(1, 3);
+ assertThat(resources.get(3).getExclusiveGroupMemberFeHandles()).containsExactly(1, 2);
}
@Test
@@ -166,11 +168,11 @@
tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
- Map<Long, FrontendResource> resources0 =
+ Map<Integer, FrontendResource> resources0 =
mTunerResourceManagerService.getFrontendResources();
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
- Map<Long, FrontendResource> resources1 =
+ Map<Integer, FrontendResource> resources1 =
mTunerResourceManagerService.getFrontendResources();
assertThat(resources0).isEqualTo(resources1);
@@ -193,7 +195,8 @@
tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos1);
- Map<Long, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources();
+ Map<Integer, FrontendResource> resources =
+ mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos1.length; id++) {
assertThat(resources.get(infos1[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
@@ -219,7 +222,8 @@
tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos1);
- Map<Long, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources();
+ Map<Integer, FrontendResource> resources =
+ mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos1.length; id++) {
assertThat(resources.get(infos1[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
@@ -236,7 +240,7 @@
mTunerResourceManagerService.setFrontendInfoListInternal(infos0);
TunerFrontendRequest request =
tunerFrontendRequest(0 /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
assertThat(frontendHandle[0]).isEqualTo(TunerResourceManager.INVALID_RESOURCE_HANDLE);
@@ -259,7 +263,7 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
assertThat(frontendHandle[0]).isEqualTo(TunerResourceManager.INVALID_RESOURCE_HANDLE);
@@ -292,7 +296,7 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
assertThat(frontendHandle[0]).isEqualTo(0);
@@ -329,7 +333,7 @@
1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
TunerFrontendRequest request =
tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
assertThat(mTunerResourceManagerService
@@ -381,7 +385,7 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
@@ -431,13 +435,13 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
+ .getInUseFrontendHandles()).isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle, infos[1].handle)));
request =
tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
@@ -476,7 +480,7 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
@@ -521,7 +525,7 @@
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
CasSessionRequest request = casSessionRequest(clientId0[0], 1 /*casSystemId*/);
- long[] casSessionHandle = new long[1];
+ int[] casSessionHandle = new int[1];
// Request for 2 cas sessions.
assertThat(mTunerResourceManagerService
.requestCasSessionInternal(request, casSessionHandle)).isTrue();
@@ -577,7 +581,7 @@
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
TunerCiCamRequest request = tunerCiCamRequest(clientId0[0], 1 /*ciCamId*/);
- long[] ciCamHandle = new long[1];
+ int[] ciCamHandle = new int[1];
// Request for 2 ciCam sessions.
assertThat(mTunerResourceManagerService
.requestCiCamInternal(request, ciCamHandle)).isTrue();
@@ -621,7 +625,7 @@
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
CasSessionRequest request = casSessionRequest(clientId[0], 1 /*casSystemId*/);
- long[] casSessionHandle = new long[1];
+ int[] casSessionHandle = new int[1];
// Request for 1 cas sessions.
assertThat(mTunerResourceManagerService
.requestCasSessionInternal(request, casSessionHandle)).isTrue();
@@ -658,7 +662,7 @@
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
TunerCiCamRequest request = tunerCiCamRequest(clientId[0], 1 /*ciCamId*/);
- long[] ciCamHandle = new long[1];
+ int[] ciCamHandle = new int[1];
// Request for 1 ciCam sessions.
assertThat(mTunerResourceManagerService
.requestCiCamInternal(request, ciCamHandle)).isTrue();
@@ -704,17 +708,17 @@
clientId1[0], clientPriorities[1], 0/*niceValue*/);
// Init lnb resources.
- long[] lnbHandles = {1};
+ int[] lnbHandles = {1};
mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles);
TunerLnbRequest request = new TunerLnbRequest();
request.clientId = clientId0[0];
- long[] lnbHandle = new long[1];
+ int[] lnbHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestLnbInternal(request, lnbHandle)).isTrue();
assertThat(lnbHandle[0]).isEqualTo(lnbHandles[0]);
assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]).getInUseLnbHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(lnbHandles[0])));
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(lnbHandles[0])));
request = new TunerLnbRequest();
request.clientId = clientId1[0];
@@ -743,12 +747,12 @@
assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
// Init lnb resources.
- long[] lnbHandles = {0};
+ int[] lnbHandles = {0};
mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles);
TunerLnbRequest request = new TunerLnbRequest();
request.clientId = clientId[0];
- long[] lnbHandle = new long[1];
+ int[] lnbHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestLnbInternal(request, lnbHandle)).isTrue();
assertThat(lnbHandle[0]).isEqualTo(lnbHandles[0]);
@@ -782,7 +786,7 @@
TunerFrontendRequest request =
tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
@@ -819,12 +823,12 @@
infos[2] = tunerDemuxInfo(2 /* handle */, Filter.TYPE_TS);
mTunerResourceManagerService.setDemuxInfoListInternal(infos);
- long[] demuxHandle0 = new long[1];
+ int[] demuxHandle0 = new int[1];
// first with undefined type (should be the first one with least # of caps)
TunerDemuxRequest request = tunerDemuxRequest(clientId0[0], Filter.TYPE_UNDEFINED);
assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle0))
.isTrue();
- assertThat(demuxHandle0[0]).isEqualTo(1L);
+ assertThat(demuxHandle0[0]).isEqualTo(1);
DemuxResource dr = mTunerResourceManagerService.getDemuxResource(demuxHandle0[0]);
mTunerResourceManagerService.releaseDemuxInternal(dr);
@@ -833,20 +837,20 @@
demuxHandle0[0] = -1;
assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle0))
.isFalse();
- assertThat(demuxHandle0[0]).isEqualTo(-1L);
+ assertThat(demuxHandle0[0]).isEqualTo(-1);
// now with TS (should be the one with least # of caps that supports TS)
request.desiredFilterTypes = Filter.TYPE_TS;
assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle0))
.isTrue();
- assertThat(demuxHandle0[0]).isEqualTo(2L);
+ assertThat(demuxHandle0[0]).isEqualTo(2);
// request for another TS
int[] clientId1 = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
profile1, null /*listener*/, clientId1);
assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
- long[] demuxHandle1 = new long[1];
+ int[] demuxHandle1 = new int[1];
TunerDemuxRequest request1 = tunerDemuxRequest(clientId1[0], Filter.TYPE_TS);
assertThat(mTunerResourceManagerService.requestDemuxInternal(request1, demuxHandle1))
.isTrue();
@@ -895,14 +899,14 @@
// let clientId0(prio:100) request for IP - should succeed
TunerDemuxRequest request0 = tunerDemuxRequest(clientId0[0], Filter.TYPE_IP);
- long[] demuxHandle0 = new long[1];
+ int[] demuxHandle0 = new int[1];
assertThat(mTunerResourceManagerService
.requestDemuxInternal(request0, demuxHandle0)).isTrue();
assertThat(demuxHandle0[0]).isEqualTo(0);
// let clientId1(prio:50) request for IP - should fail
TunerDemuxRequest request1 = tunerDemuxRequest(clientId1[0], Filter.TYPE_IP);
- long[] demuxHandle1 = new long[1];
+ int[] demuxHandle1 = new int[1];
demuxHandle1[0] = -1;
assertThat(mTunerResourceManagerService
.requestDemuxInternal(request1, demuxHandle1)).isFalse();
@@ -922,7 +926,7 @@
// let clientId2(prio:50) request for TS - should succeed
TunerDemuxRequest request2 = tunerDemuxRequest(clientId2[0], Filter.TYPE_TS);
- long[] demuxHandle2 = new long[1];
+ int[] demuxHandle2 = new int[1];
assertThat(mTunerResourceManagerService
.requestDemuxInternal(request2, demuxHandle2)).isTrue();
assertThat(demuxHandle2[0]).isEqualTo(0);
@@ -947,7 +951,7 @@
profile, null /*listener*/, clientId);
assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
- long[] desHandle = new long[1];
+ int[] desHandle = new int[1];
TunerDescramblerRequest request = new TunerDescramblerRequest();
request.clientId = clientId[0];
assertThat(mTunerResourceManagerService.requestDescramblerInternal(request, desHandle))
@@ -1057,7 +1061,7 @@
1 /*exclusiveGroupId*/);
/**** Init Lnb Resources ****/
- long[] lnbHandles = {1};
+ int[] lnbHandles = {1};
mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles);
// Update frontend list in TRM
@@ -1066,7 +1070,7 @@
/**** Request Frontend ****/
// Predefined frontend request and array to save returned frontend handle
- long[] frontendHandle = new long[1];
+ int[] frontendHandle = new int[1];
TunerFrontendRequest request = tunerFrontendRequest(
ownerClientId0[0] /*clientId*/,
FrontendSettings.TYPE_DVBT);
@@ -1076,9 +1080,12 @@
.requestFrontendInternal(request, frontendHandle))
.isTrue();
assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
- assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(ownerClientId0[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
/**** Share Frontend ****/
@@ -1106,15 +1113,24 @@
shareClientId0[0],
shareClientId1[0])));
// Verify in use frontend list in all the primary owner and share owner clients
- assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
- assertThat(mTunerResourceManagerService.getClientProfile(shareClientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
- assertThat(mTunerResourceManagerService.getClientProfile(shareClientId1[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(ownerClientId0[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(shareClientId0[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(shareClientId1[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
/**** Remove Frontend Share Owner ****/
@@ -1126,12 +1142,18 @@
.getShareFeClientIds())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
shareClientId0[0])));
- assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
- assertThat(mTunerResourceManagerService.getClientProfile(shareClientId0[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(ownerClientId0[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(shareClientId0[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
/**** Request Shared Frontend with Higher Priority Client ****/
@@ -1151,9 +1173,12 @@
.getOwnerClientId()).isEqualTo(ownerClientId1[0]);
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.getOwnerClientId()).isEqualTo(ownerClientId1[0]);
- assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId1[0])
- .getInUseFrontendHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(infos[0].handle, infos[1].handle)));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(ownerClientId1[0])
+ .getInUseFrontendHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ infos[0].handle,
+ infos[1].handle)));
assertThat(mTunerResourceManagerService
.getClientProfile(ownerClientId0[0])
.getInUseFrontendHandles()
@@ -1210,7 +1235,7 @@
// Predefined Lnb request and handle array
TunerLnbRequest requestLnb = new TunerLnbRequest();
requestLnb.clientId = shareClientId0[0];
- long[] lnbHandle = new long[1];
+ int[] lnbHandle = new int[1];
// Request for an Lnb
assertThat(mTunerResourceManagerService
@@ -1239,13 +1264,15 @@
.getInUseFrontendHandles()
.isEmpty())
.isTrue();
- assertThat(mTunerResourceManagerService.getClientProfile(shareClientId0[0])
- .getInUseLnbHandles())
- .isEqualTo(new HashSet<Long>(Arrays.asList(lnbHandles[0])));
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(shareClientId0[0])
+ .getInUseLnbHandles())
+ .isEqualTo(new HashSet<Integer>(Arrays.asList(
+ lnbHandles[0])));
}
private TunerFrontendInfo tunerFrontendInfo(
- long handle, int frontendType, int exclusiveGroupId) {
+ int handle, int frontendType, int exclusiveGroupId) {
TunerFrontendInfo info = new TunerFrontendInfo();
info.handle = handle;
info.type = frontendType;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 07e95d8..6d508ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -21,11 +21,19 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_4_3;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_DISPLAY_SIZE;
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCREEN;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
@@ -34,7 +42,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_INITIAL_BOUNDS_SCALE;
import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_LANDSCAPE_APP_PADDING;
-import static com.android.server.wm.DesktopModeBoundsCalculator.calculateAspectRatio;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
@@ -44,6 +51,8 @@
import static org.mockito.Mockito.mock;
import android.app.ActivityOptions;
+import android.compat.testing.PlatformCompatChangeRule;
+import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
@@ -55,8 +64,12 @@
import com.android.window.flags.Flags;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
/**
@@ -74,6 +87,9 @@
private static final Rect PORTRAIT_DISPLAY_BOUNDS = new Rect(0, 0, 1600, 2560);
private static final float LETTERBOX_ASPECT_RATIO = 1.3f;
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
@Before
public void setUp() throws Exception {
mActivity = new ActivityBuilder(mAtm).build();
@@ -199,14 +215,17 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
final int desiredWidth =
(int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -219,14 +238,17 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
final int desiredWidth =
(int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -239,7 +261,9 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides());
doReturn(true).when(
@@ -251,7 +275,8 @@
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -264,7 +289,9 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides());
doReturn(true).when(
@@ -276,7 +303,8 @@
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -285,19 +313,466 @@
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
public void testResizablePortraitBounds_landscapeDevice_resizable_portraitOrientation() {
setupDesktopModeLaunchParamsModifier();
- doReturn(LETTERBOX_ASPECT_RATIO).when(()
- -> calculateAspectRatio(any(), any()));
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
+
+ spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy());
+ doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController
+ .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any());
final int desiredWidth =
(int) ((LANDSCAPE_DISPLAY_BOUNDS.height() / LETTERBOX_ASPECT_RATIO) + 0.5f);
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL})
+ public void testSmallAspectRatioOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth =
+ (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+ public void testMediumAspectRatioOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth =
+ (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
+ public void testLargeAspectRatioOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth =
+ (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
+ public void testSplitScreenAspectRatioOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth =
+ (int) (desiredHeight / activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio());
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL})
+ public void testSmallAspectRatioOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+ // Mock desired aspect ratio so min override can take effect.
+ setDesiredAspectRatio(activity, /* aspectRatio */ 1f);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+ public void testMediumAspectRatioOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+ // Mock desired aspect ratio so min override can take effect.
+ setDesiredAspectRatio(activity, /* aspectRatio */ 1f);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
+ public void testLargeAspectRatioOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+ // Mock desired aspect ratio so min override can take effect.
+ setDesiredAspectRatio(activity, /* aspectRatio */ 1f);
+
+ final int desiredHeight =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
+ public void testSplitScreenAspectRatioOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ false);
+ // Mock desired aspect ratio so min override can take effect.
+ setDesiredAspectRatio(activity, /* aspectRatio */ 1f);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio());
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio32Override_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue3_2 = 3 / 2f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_3_2,
+ userAspectRatioOverrideValue3_2);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue3_2);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio43Override_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue4_3 = 4 / 3f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_4_3,
+ userAspectRatioOverrideValue4_3);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue4_3);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio169Override_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue16_9 = 16 / 9f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_16_9,
+ userAspectRatioOverrideValue16_9);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue16_9);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatioSplitScreenOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValueSplitScreen = activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio();
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
+ userAspectRatioOverrideValueSplitScreen);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValueSplitScreen);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatioDisplaySizeOverride_landscapeDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
+ LANDSCAPE_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValueDisplaySize = activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getDisplaySizeMinAspectRatio();
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE,
+ userAspectRatioOverrideValueDisplaySize);
+
+ final int desiredHeight =
+ (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValueDisplaySize);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio32Override_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue3_2 = 3 / 2f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_3_2,
+ userAspectRatioOverrideValue3_2);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValue3_2);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio43Override_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue4_3 = 4 / 3f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_4_3,
+ userAspectRatioOverrideValue4_3);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValue4_3);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatio169Override_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValue16_9 = 16 / 9f;
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_16_9,
+ userAspectRatioOverrideValue16_9);
+
+ final int desiredHeight =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredWidth = (int) (desiredHeight / userAspectRatioOverrideValue16_9);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatioSplitScreenOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValueSplitScreen = activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getSplitScreenAspectRatio();
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_SPLIT_SCREEN,
+ userAspectRatioOverrideValueSplitScreen);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValueSplitScreen);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
+ assertEquals(desiredWidth, mResult.mBounds.width());
+ assertEquals(desiredHeight, mResult.mBounds.height());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
+ public void testUserAspectRatioDisplaySizeOverride_portraitDevice() {
+ setupDesktopModeLaunchParamsModifier();
+
+ final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
+ PORTRAIT_DISPLAY_BOUNDS);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
+ final float userAspectRatioOverrideValueDisplaySize = activity.mAppCompatController
+ .getAppCompatAspectRatioOverrides().getDisplaySizeMinAspectRatio();
+ applyUserMinAspectRatioOverride(activity, USER_MIN_ASPECT_RATIO_DISPLAY_SIZE,
+ userAspectRatioOverrideValueDisplaySize);
+
+ final int desiredWidth =
+ (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (desiredWidth * userAspectRatioOverrideValueDisplaySize);
+
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -310,14 +785,18 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false);
+ final Task task = createTask(display, /* isResizeable */ false);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
+
final int desiredWidth =
(int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -326,18 +805,23 @@
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
public void testUnResizablePortraitBounds_landscapeDevice_unResizable_portraitOrientation() {
setupDesktopModeLaunchParamsModifier();
- doReturn(LETTERBOX_ASPECT_RATIO).when(()
- -> calculateAspectRatio(any(), any()));
final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE,
LANDSCAPE_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false);
+ final Task task = createTask(display, /* isResizeable */ false);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
+
+ spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy());
+ doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController
+ .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any());
final int desiredHeight =
(int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredWidth = (int) (desiredHeight / LETTERBOX_ASPECT_RATIO);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -350,14 +834,17 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_UNSPECIFIED,
+ task, /* ignoreOrientationRequest */ true);
final int desiredWidth =
(int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -370,14 +857,17 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
final int desiredWidth =
(int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -390,11 +880,13 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
- spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides());
+ spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides());
doReturn(true).when(
- mActivity.mAppCompatController.getAppCompatAspectRatioOverrides())
+ activity.mAppCompatController.getAppCompatAspectRatioOverrides())
.isUserFullscreenOverrideEnabled();
final int desiredWidth =
@@ -402,7 +894,8 @@
final int desiredHeight =
(int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -415,11 +908,13 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
- spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides());
+ spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides());
doReturn(true).when(
- mActivity.mAppCompatController.getAppCompatAspectRatioOverrides())
+ activity.mAppCompatController.getAppCompatAspectRatioOverrides())
.isSystemOverrideToFullscreenEnabled();
final int desiredWidth =
@@ -427,7 +922,8 @@
final int desiredHeight =
(int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -436,19 +932,24 @@
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
public void testResizableLandscapeBounds_portraitDevice_resizable_landscapeOrientation() {
setupDesktopModeLaunchParamsModifier();
- doReturn(LETTERBOX_ASPECT_RATIO).when(()
- -> calculateAspectRatio(any(), any()));
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true);
+ final Task task = createTask(display, /* isResizeable */ true);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
+
+ spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy());
+ doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController
+ .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any());
final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width()
- (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2);
final int desiredHeight = (int)
((PORTRAIT_DISPLAY_BOUNDS.width() / LETTERBOX_ASPECT_RATIO) + 0.5f);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -461,14 +962,18 @@
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false);
+ final Task task = createTask(display, /* isResizeable */ false);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_PORTRAIT,
+ task, /* ignoreOrientationRequest */ true);
+
final int desiredWidth =
(int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
final int desiredHeight =
(int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -477,18 +982,23 @@
@EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS)
public void testUnResizableLandscapeBounds_portraitDevice_unResizable_landscapeOrientation() {
setupDesktopModeLaunchParamsModifier();
- doReturn(LETTERBOX_ASPECT_RATIO).when(()
- -> calculateAspectRatio(any(), any()));
final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT,
PORTRAIT_DISPLAY_BOUNDS);
- final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false);
+ final Task task = createTask(display, /* isResizeable */ false);
+ final ActivityRecord activity = createActivity(display, SCREEN_ORIENTATION_LANDSCAPE,
+ task, /* ignoreOrientationRequest */ true);
+
+ spyOn(activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy());
+ doReturn(LETTERBOX_ASPECT_RATIO).when(activity.mAppCompatController
+ .getDesktopAppCompatAspectRatioPolicy()).calculateAspectRatio(any());
final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width()
- (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2);
final int desiredHeight = (int) (desiredWidth / LETTERBOX_ASPECT_RATIO);
- assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate());
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task)
+ .setActivity(activity).calculate());
assertEquals(desiredWidth, mResult.mBounds.width());
assertEquals(desiredHeight, mResult.mBounds.height());
}
@@ -755,24 +1265,64 @@
assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
}
- private Task createTask(DisplayContent display, int orientation, Boolean isResizeable) {
+ private Task createTask(DisplayContent display, Boolean isResizeable) {
final int resizeMode = isResizeable ? RESIZE_MODE_RESIZEABLE
: RESIZE_MODE_UNRESIZEABLE;
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).setDisplay(display).build();
task.setResizeMode(resizeMode);
- mActivity = new ActivityBuilder(task.mAtmService)
+ return task;
+ }
+
+ private ActivityRecord createActivity(DisplayContent display, int orientation, Task task,
+ boolean ignoreOrientationRequest) {
+ final ActivityRecord activity = new ActivityBuilder(task.mAtmService)
.setTask(task)
+ .setComponent(ComponentName.createRelative(task.mAtmService.mContext,
+ DesktopModeLaunchParamsModifierTests.class.getName()))
+ .setUid(android.os.Process.myUid())
.setScreenOrientation(orientation)
.setOnTop(true).build();
+ activity.onDisplayChanged(display);
+ activity.setOccludesParent(true);
+ activity.setVisible(true);
+ activity.setVisibleRequested(true);
+ activity.mDisplayContent.setIgnoreOrientationRequest(ignoreOrientationRequest);
- mActivity.onDisplayChanged(display);
- mActivity.setOccludesParent(true);
- mActivity.setVisible(true);
- mActivity.setVisibleRequested(true);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(/* ignoreOrientationRequest */ true);
+ return activity;
+ }
- return task;
+ private void setDesiredAspectRatio(ActivityRecord activity, float aspectRatio) {
+ final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy =
+ activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy();
+ spyOn(desktopAppCompatAspectRatioPolicy);
+ doReturn(aspectRatio).when(desktopAppCompatAspectRatioPolicy)
+ .getDesiredAspectRatio(any());
+ }
+
+ private void applyUserMinAspectRatioOverride(ActivityRecord activity, int overrideCode,
+ float overrideValue) {
+ // Set desired aspect ratio to be below minimum so override can take effect.
+ final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy =
+ activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy();
+ spyOn(desktopAppCompatAspectRatioPolicy);
+ doReturn(1f).when(desktopAppCompatAspectRatioPolicy)
+ .getDesiredAspectRatio(any());
+
+ // Enable user aspect ratio settings
+ final AppCompatConfiguration appCompatConfiguration =
+ activity.mWmService.mAppCompatConfiguration;
+ spyOn(appCompatConfiguration);
+ doReturn(true).when(appCompatConfiguration)
+ .isUserAppAspectRatioSettingsEnabled();
+
+ // Simulate user min aspect ratio override being set.
+ final AppCompatAspectRatioOverrides appCompatAspectRatioOverrides =
+ activity.mAppCompatController.getAppCompatAspectRatioOverrides();
+ spyOn(appCompatAspectRatioOverrides);
+ doReturn(overrideValue).when(appCompatAspectRatioOverrides).getUserMinAspectRatio();
+ doReturn(overrideCode).when(appCompatAspectRatioOverrides)
+ .getUserMinAspectRatioOverrideCode();
}
private TestDisplayContent createDisplayContent(int orientation, Rect displayBounds) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 65e3baa..1e1055b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -2394,7 +2394,13 @@
private void testUserOverrideAspectRatio(boolean isUnresizable, int screenOrientation,
float expectedAspectRatio, @PackageManager.UserMinAspectRatio int aspectRatio,
boolean enabled) {
- final ActivityRecord activity = getActivityBuilderOnSameTask().build();
+ final ActivityRecord activity = getActivityBuilderWithoutTask().build();
+ final DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy =
+ activity.mAppCompatController.getDesktopAppCompatAspectRatioPolicy();
+ spyOn(desktopAppCompatAspectRatioPolicy);
+ doReturn(enabled).when(desktopAppCompatAspectRatioPolicy)
+ .hasMinAspectRatioOverride(any());
+ mTask.addChild(activity);
activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
spyOn(activity.mWmService.mAppCompatConfiguration);
doReturn(enabled).when(activity.mWmService.mAppCompatConfiguration)
@@ -4944,8 +4950,11 @@
}
private ActivityBuilder getActivityBuilderOnSameTask() {
+ return getActivityBuilderWithoutTask().setTask(mTask);
+ }
+
+ private ActivityBuilder getActivityBuilderWithoutTask() {
return new ActivityBuilder(mAtm)
- .setTask(mTask)
.setComponent(ComponentName.createRelative(mContext,
SizeCompatTests.class.getName()))
.setUid(android.os.Process.myUid());
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index 3c72498..8829f74 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -151,6 +151,7 @@
verify(native).setTouchpadNaturalScrollingEnabled(anyBoolean())
verify(native).setTouchpadTapToClickEnabled(anyBoolean())
verify(native).setTouchpadTapDraggingEnabled(anyBoolean())
+ verify(native).setShouldNotifyTouchpadHardwareState(anyBoolean())
verify(native).setTouchpadRightClickZoneEnabled(anyBoolean())
verify(native).setShowTouches(anyBoolean())
verify(native).setMotionClassifierEnabled(anyBoolean())