Merge "Use safe calls for icons."
diff --git a/core/api/current.txt b/core/api/current.txt
index ed67679..de540bf 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -24032,6 +24032,7 @@
method @Nullable public android.net.Uri getIconUri();
method @NonNull public String getId();
method @NonNull public CharSequence getName();
+ method public int getType();
method public int getVolume();
method public int getVolumeHandling();
method public int getVolumeMax();
@@ -24048,6 +24049,22 @@
field public static final String FEATURE_REMOTE_VIDEO_PLAYBACK = "android.media.route.feature.REMOTE_VIDEO_PLAYBACK";
field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+ field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+ field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
+ field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
+ field public static final int TYPE_DOCK = 13; // 0xd
+ field public static final int TYPE_GROUP = 2000; // 0x7d0
+ field public static final int TYPE_HDMI = 9; // 0x9
+ field public static final int TYPE_HEARING_AID = 23; // 0x17
+ field public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003; // 0x3eb
+ field public static final int TYPE_REMOTE_SPEAKER = 1002; // 0x3ea
+ field public static final int TYPE_REMOTE_TV = 1001; // 0x3e9
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_USB_ACCESSORY = 12; // 0xc
+ field public static final int TYPE_USB_DEVICE = 11; // 0xb
+ field public static final int TYPE_USB_HEADSET = 22; // 0x16
+ field public static final int TYPE_WIRED_HEADPHONES = 4; // 0x4
+ field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
}
public static final class MediaRoute2Info.Builder {
@@ -24063,6 +24080,7 @@
method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence);
method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle);
method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri);
+ method @NonNull public android.media.MediaRoute2Info.Builder setType(int);
method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityPublic();
method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityRestricted(@NonNull java.util.Set<java.lang.String>);
method @NonNull public android.media.MediaRoute2Info.Builder setVolume(int);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index b3337b6..3b88257 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -343,6 +343,13 @@
"android:activity.applyActivityFlagsForBubbles";
/**
+ * Indicates to apply {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK} to the launching shortcut.
+ * @hide
+ */
+ private static final String KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT =
+ "android:activity.applyMultipleTaskFlagForShortcut";
+
+ /**
* For Activity transitions, the calling Activity's TransitionListener used to
* notify the called Activity when the shared element and the exit transitions
* complete.
@@ -476,6 +483,7 @@
private boolean mShareIdentity = false;
private boolean mDisallowEnterPictureInPictureWhileLaunching;
private boolean mApplyActivityFlagsForBubbles;
+ private boolean mApplyMultipleTaskFlagForShortcut;
private boolean mTaskAlwaysOnTop;
private boolean mTaskOverlay;
private boolean mTaskOverlayCanResume;
@@ -1278,6 +1286,8 @@
KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING, false);
mApplyActivityFlagsForBubbles = opts.getBoolean(
KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, false);
+ mApplyMultipleTaskFlagForShortcut = opts.getBoolean(
+ KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT, false);
if (opts.containsKey(KEY_ANIM_SPECS)) {
Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS);
mAnimSpecs = new AppTransitionAnimationSpec[specs.length];
@@ -1906,6 +1916,16 @@
return mApplyActivityFlagsForBubbles;
}
+ /** @hide */
+ public void setApplyMultipleTaskFlagForShortcut(boolean apply) {
+ mApplyMultipleTaskFlagForShortcut = apply;
+ }
+
+ /** @hide */
+ public boolean isApplyMultipleTaskFlagForShortcut() {
+ return mApplyMultipleTaskFlagForShortcut;
+ }
+
/**
* Sets a launch cookie that can be used to track the activity and task that are launch as a
* result of this option. If the launched activity is a trampoline that starts another activity
@@ -2262,6 +2282,10 @@
if (mApplyActivityFlagsForBubbles) {
b.putBoolean(KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, mApplyActivityFlagsForBubbles);
}
+ if (mApplyMultipleTaskFlagForShortcut) {
+ b.putBoolean(KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT,
+ mApplyMultipleTaskFlagForShortcut);
+ }
if (mAnimSpecs != null) {
b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 73f34eb..7d40a22 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1432,14 +1432,14 @@
.APP_OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION;
/**
- * Hide foreground service stop button in quick settings.
+ * Allows an application to start an activity while running in the background.
*
* Only to be used by the system.
*
* @hide
*/
- public static final int OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
- AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON;
+ public static final int OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
+ AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION;
/**
* Allows an application to capture bugreport directly without consent dialog when using the
@@ -2027,14 +2027,14 @@
"android:system_exempt_from_fgs_bg_start_while_in_use_permission_restriction";
/**
- * Hide foreground service stop button in quick settings.
+ * Allows an application to start an activity while running in the background.
*
* Only to be used by the system.
*
* @hide
*/
- public static final String OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
- "android:system_exempt_from_fgs_stop_button";
+ public static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
+ "android:system_exempt_from_activity_bg_start_restriction";
/**
* Allows an application to capture bugreport directly without consent dialog when using the
@@ -2562,9 +2562,9 @@
OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
"SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION")
.build(),
- new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
- OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
- "SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON").build(),
+ new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+ OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+ "SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION").build(),
new AppOpInfo.Builder(
OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d8ec7cc..b494a20 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -39,6 +39,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringDef;
+import android.annotation.SupportsCoexistence;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -8596,6 +8597,7 @@
* primary user, or a profile owner of an organization-owned managed profile or a holder of the
* permission {@link android.Manifest.permission#SET_TIME_ZONE}.
*/
+ @SupportsCoexistence
@RequiresPermission(value = SET_TIME_ZONE, conditional = true)
public void setAutoTimeZoneEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setAutoTimeZone");
@@ -9665,6 +9667,7 @@
* @param activity The Activity that is added as default intent handler.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
+ @SupportsCoexistence
public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
@NonNull ComponentName activity) {
throwIfParentInstance("addPersistentPreferredActivity");
@@ -10624,6 +10627,7 @@
* profile owner of an organization-owned managed profile and the
* list of permitted input method package names is not null or empty.
*/
+ @SupportsCoexistence
public boolean setPermittedInputMethods(
@NonNull ComponentName admin, List<String> packageNames) {
if (mService != null) {
@@ -11696,6 +11700,7 @@
* @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
* @see UserManager#DISALLOW_CREATE_WINDOWS
*/
+ @SupportsCoexistence
public void setLockTaskPackages(@NonNull ComponentName admin, @NonNull String[] packages)
throws SecurityException {
throwIfParentInstance("setLockTaskPackages");
@@ -11764,6 +11769,7 @@
* affiliated user or profile, or the profile owner when no device owner is set.
* @see #isAffiliatedUser
**/
+ @SupportsCoexistence
public void setLockTaskFeatures(@NonNull ComponentName admin, @LockTaskFeature int flags) {
throwIfParentInstance("setLockTaskFeatures");
if (mService != null) {
@@ -12267,6 +12273,7 @@
* @see #setDelegatedScopes
* @see #DELEGATION_BLOCK_UNINSTALL
*/
+ @SupportsCoexistence
public void setUninstallBlocked(@Nullable ComponentName admin, String packageName,
boolean uninstallBlocked) {
throwIfParentInstance("setUninstallBlocked");
@@ -12755,6 +12762,7 @@
* @see #setDelegatedScopes
* @see #DELEGATION_PERMISSION_GRANT
*/
+ @SupportsCoexistence
public boolean setPermissionGrantState(@NonNull ComponentName admin,
@NonNull String packageName, @NonNull String permission,
@PermissionGrantState int grantState) {
@@ -15301,6 +15309,7 @@
* @param packages The package names for the apps.
* @throws SecurityException if {@code admin} is not a device owner or a profile owner.
*/
+ @SupportsCoexistence
public void setUserControlDisabledPackages(@NonNull ComponentName admin,
@NonNull List<String> packages) {
throwIfParentInstance("setUserControlDisabledPackages");
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0efd264..1df45d1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1069,11 +1069,6 @@
* Specifies that windows besides app windows should not be
* created. This will block the creation of the following types of windows.
* <li>{@link LayoutParams#TYPE_TOAST}</li>
- * <li>{@link LayoutParams#TYPE_PHONE}</li>
- * <li>{@link LayoutParams#TYPE_PRIORITY_PHONE}</li>
- * <li>{@link LayoutParams#TYPE_SYSTEM_ALERT}</li>
- * <li>{@link LayoutParams#TYPE_SYSTEM_ERROR}</li>
- * <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
* <li>{@link LayoutParams#TYPE_APPLICATION_OVERLAY}</li>
*
* <p>This can only be set by device owners and profile owners on the primary user.
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index c80c57c..e5b76f6 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -1,7 +1,9 @@
# Bug component: 95221
+# Please assign new bugs to android-storage-triage@, not to individual people
+
# Android Storage Team
-abkaur@google.com
+alukin@google.com
corinac@google.com
dipankarb@google.com
krishang@google.com
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 70a7739..ba7d823 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -781,19 +781,6 @@
}
}
- public static boolean containsType(@InternalInsetsType int[] types,
- @InternalInsetsType int type) {
- if (types == null) {
- return false;
- }
- for (int t : types) {
- if (t == type) {
- return true;
- }
- }
- return false;
- }
-
public void dump(String prefix, PrintWriter pw) {
final String newPrefix = prefix + " ";
pw.println(prefix + "InsetsState");
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 7d1dc76..c8c910d 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -28,6 +28,7 @@
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Xml;
+import android.view.InflateException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -137,16 +138,9 @@
try {
parser = context.getResources().getAnimation(id);
return createAnimationFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
+ } catch (XmlPullParserException | IOException | InflateException ex) {
+ throw new NotFoundException(
+ "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
} finally {
if (parser != null) parser.close();
}
@@ -159,8 +153,9 @@
}
@UnsupportedAppUsage
- private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
- AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
+ private static Animation createAnimationFromXml(
+ Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)
+ throws XmlPullParserException, IOException, InflateException {
Animation anim = null;
@@ -168,8 +163,8 @@
int type;
int depth = parser.getDepth();
- while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
+ while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+ && type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
@@ -193,7 +188,7 @@
} else if (name.equals("extend")) {
anim = new ExtendAnimation(c, attrs);
} else {
- throw new RuntimeException("Unknown animation name: " + parser.getName());
+ throw new InflateException("Unknown animation name: " + parser.getName());
}
if (parent != null) {
@@ -220,29 +215,24 @@
try {
parser = context.getResources().getAnimation(id);
return createLayoutAnimationFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
+ } catch (XmlPullParserException | IOException | InflateException ex) {
+ throw new NotFoundException(
+ "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
} finally {
if (parser != null) parser.close();
}
}
- private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
- XmlPullParser parser) throws XmlPullParserException, IOException {
+ private static LayoutAnimationController createLayoutAnimationFromXml(
+ Context c, XmlPullParser parser)
+ throws XmlPullParserException, IOException, InflateException {
return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
}
- private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
- XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
+ private static LayoutAnimationController createLayoutAnimationFromXml(
+ Context c, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException, InflateException {
LayoutAnimationController controller = null;
@@ -263,7 +253,7 @@
} else if ("gridLayoutAnimation".equals(name)) {
controller = new GridLayoutAnimationController(c, attrs);
} else {
- throw new RuntimeException("Unknown layout animation name: " + name);
+ throw new InflateException("Unknown layout animation name: " + name);
}
}
@@ -342,16 +332,9 @@
try {
parser = context.getResources().getAnimation(id);
return createInterpolatorFromXml(context.getResources(), context.getTheme(), parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
+ } catch (XmlPullParserException | IOException | InflateException ex) {
+ throw new NotFoundException(
+ "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
} finally {
if (parser != null) parser.close();
}
@@ -372,25 +355,20 @@
try {
parser = res.getAnimation(id);
return createInterpolatorFromXml(res, theme, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
+ } catch (XmlPullParserException | IOException | InflateException ex) {
+ throw new NotFoundException(
+ "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
} finally {
- if (parser != null)
+ if (parser != null) {
parser.close();
+ }
}
}
- private static Interpolator createInterpolatorFromXml(Resources res, Theme theme, XmlPullParser parser)
- throws XmlPullParserException, IOException {
+ private static Interpolator createInterpolatorFromXml(
+ Resources res, Theme theme, XmlPullParser parser)
+ throws XmlPullParserException, IOException, InflateException {
BaseInterpolator interpolator = null;
@@ -430,7 +408,7 @@
} else if (name.equals("pathInterpolator")) {
interpolator = new PathInterpolator(res, theme, attrs);
} else {
- throw new RuntimeException("Unknown interpolator name: " + parser.getName());
+ throw new InflateException("Unknown interpolator name: " + parser.getName());
}
}
return interpolator;
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 681bc7a..1eecb41 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -202,12 +202,12 @@
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
- ri.userHandle = mInitialIntentsUserSpace;
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
ri.icon = 0;
}
+ ri.userHandle = mInitialIntentsUserSpace;
mCallerTargets.add(new DisplayResolveInfo(ii, ri, ii, makePresentationGetter(ri)));
if (mCallerTargets.size() == MAX_SUGGESTED_APP_TARGETS) break;
}
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 298230a..bcff907 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -563,18 +563,6 @@
String id = locale.toLanguageTag();
LocaleInfo result;
if (!sLocaleCache.containsKey(id)) {
- // Locale preferences can modify the language tag to current system languages, so we
- // need to check the input locale without extra u extension except numbering system.
- Locale filteredLocale = new Locale.Builder()
- .setLocale(locale.stripExtensions())
- .setUnicodeLocaleKeyword("nu", locale.getUnicodeLocaleType("nu"))
- .build();
- if (sLocaleCache.containsKey(filteredLocale.toLanguageTag())) {
- result = new LocaleInfo(locale);
- // This locale is included in supported locales, so set translated be true here.
- result.mIsTranslated = true;
- return result;
- }
result = new LocaleInfo(locale);
sLocaleCache.put(id, result);
} else {
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 0ea60a7..18c8eb4 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -447,13 +447,13 @@
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
- ri.userHandle = mInitialIntentsUserSpace;
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
ri.icon = 0;
}
+ ri.userHandle = mInitialIntentsUserSpace;
addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(mPm), null, ii, makePresentationGetter(ri)));
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 1c85ca2..b529a10 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -214,11 +214,11 @@
* bar and navigation bar which are temporarily visible to the user.
*
* @param displayId the ID of the display to notify.
- * @param types the internal insets types of the bars are about to show transiently.
+ * @param types the insets types of the bars are about to show transiently.
* @param isGestureOnSystemBar whether the gesture to show the transient bar was a gesture on
* one of the bars itself.
*/
- void showTransient(int displayId, in int[] types, boolean isGestureOnSystemBar);
+ void showTransient(int displayId, int types, boolean isGestureOnSystemBar);
/**
* Notifies System UI to abort the transient state of system bars, which prevents the bars being
@@ -226,9 +226,9 @@
* bars again.
*
* @param displayId the ID of the display to notify.
- * @param types the internal insets types of the bars are about to abort the transient state.
+ * @param types the insets types of the bars are about to abort the transient state.
*/
- void abortTransient(int displayId, in int[] types);
+ void abortTransient(int displayId, int types);
/**
* Show a warning that the device is about to go to sleep due to user inactivity.
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 54221ce..4f827cd 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,7 +16,6 @@
package com.android.internal.statusbar;
-import android.annotation.NonNull;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,15 +40,14 @@
public final int mBehavior;
public final int mRequestedVisibleTypes;
public final String mPackageName;
- public final int[] mTransientBarTypes;
+ public final int mTransientBarTypes;
public final LetterboxDetails[] mLetterboxDetails;
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
boolean navbarColorManagedByIme, int behavior, int requestedVisibleTypes,
- String packageName, @NonNull int[] transientBarTypes,
- LetterboxDetails[] letterboxDetails) {
+ String packageName, int transientBarTypes, LetterboxDetails[] letterboxDetails) {
mIcons = new ArrayMap<>(icons);
mDisabledFlags1 = disabledFlags1;
mAppearance = appearance;
@@ -87,7 +85,7 @@
dest.writeInt(mBehavior);
dest.writeInt(mRequestedVisibleTypes);
dest.writeString(mPackageName);
- dest.writeIntArray(mTransientBarTypes);
+ dest.writeInt(mTransientBarTypes);
dest.writeParcelableArray(mLetterboxDetails, flags);
}
@@ -113,7 +111,7 @@
final int behavior = source.readInt();
final int requestedVisibleTypes = source.readInt();
final String packageName = source.readString();
- final int[] transientBarTypes = source.createIntArray();
+ final int transientBarTypes = source.readInt();
final LetterboxDetails[] letterboxDetails =
source.readParcelableArray(null, LetterboxDetails.class);
return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index e56c381..5c3759f 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -1,10 +1,7 @@
package com.android.internal.widget;
-import static android.provider.DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION;
-
import android.annotation.NonNull;
import android.os.AsyncTask;
-import android.provider.DeviceConfig;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
@@ -120,8 +117,7 @@
@Override
protected void onPostExecute(Boolean result) {
callback.onChecked(result, mThrottleTimeout);
- if (DeviceConfig.getBoolean(NAMESPACE_AUTO_PIN_CONFIRMATION,
- "enable_auto_pin_confirmation", false)) {
+ if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()) {
utils.setPinLength(userId, credentialCopy.size());
}
credentialCopy.zeroize();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2f51479..4d820ac 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -681,7 +681,7 @@
* @return true, if deviceConfig flag is set to true or the flag is not propagated and
* defaultValue is true.
*/
- public boolean isAutoPinConfirmFeatureAvailable() {
+ public static boolean isAutoPinConfirmFeatureAvailable() {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION,
FLAG_ENABLE_AUTO_PIN_CONFIRMATION,
diff --git a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
new file mode 100644
index 0000000..d8298fd
--- /dev/null
+++ b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2023 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 android.app.admin;
+
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_ALLOWLIST;
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM;
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_BLOCKLIST;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class PackagePolicyTest {
+
+ private static final String TEST_PACKAGE_NAME = "com.example";
+
+ private static final String TEST_PACKAGE_NAME_2 = "com.example.2";
+
+ private static final String TEST_SYSTEM_PACKAGE_NAME = "com.system";
+
+
+ @Test
+ public void testParceling() {
+ final int policyType = PACKAGE_POLICY_BLOCKLIST;
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+
+ final Parcel parcel = Parcel.obtain();
+ PackagePolicy packagePolicy = new PackagePolicy(policyType, packageNames);
+ try {
+ packagePolicy.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ packagePolicy = PackagePolicy.CREATOR.createFromParcel(parcel);
+ } finally {
+ parcel.recycle();
+ }
+
+ assertEquals(policyType, packagePolicy.getPolicyType());
+ assertNotNull(packagePolicy.getPackageNames());
+ assertEquals(1, packagePolicy.getPackageNames().size());
+ assertTrue(packagePolicy.getPackageNames().contains(TEST_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testEmptyBlocklistCreation() {
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST);
+ assertEquals(PACKAGE_POLICY_BLOCKLIST, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertTrue(policy.getPackageNames().isEmpty());
+ }
+
+ @Test
+ public void testEmptyAllowlistCreation() {
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST);
+ assertEquals(PACKAGE_POLICY_ALLOWLIST, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertTrue(policy.getPackageNames().isEmpty());
+ }
+
+ @Test
+ public void testEmptyAllowlistAndSystemCreation() {
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM);
+ assertEquals(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertTrue(policy.getPackageNames().isEmpty());
+ }
+
+ @Test
+ public void testSuppliedBlocklistCreation() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST, packageNames);
+ assertEquals(PACKAGE_POLICY_BLOCKLIST, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertEquals(1, policy.getPackageNames().size());
+ assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testSuppliedAllowlistCreation() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST, packageNames);
+ assertEquals(PACKAGE_POLICY_ALLOWLIST, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertEquals(1, policy.getPackageNames().size());
+ assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testSuppliedAllowlistAndSystemCreation() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, packageNames);
+ assertEquals(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, policy.getPolicyType());
+ assertNotNull(policy.getPackageNames());
+ assertEquals(1, policy.getPackageNames().size());
+ assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testBlocklist_isPackageAllowed() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ final Set<String> systemPackages = new ArraySet<>();
+ systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST, packageNames);
+
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+ assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+ assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+ }
+
+ @Test
+ public void testAllowlist_isPackageAllowed() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ final Set<String> systemPackages = new ArraySet<>();
+ systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST, packageNames);
+
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+ assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+ assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+ }
+
+ @Test
+ public void testAllowlistAndSystem_isPackageAllowed() {
+ final Set<String> packageNames = new ArraySet<>();
+ packageNames.add(TEST_PACKAGE_NAME);
+ final Set<String> systemPackages = new ArraySet<>();
+ systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+ PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, packageNames);
+
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+ assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+ assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+ assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+ assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index 048c48b..f79ba28 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -67,7 +67,7 @@
BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
WindowInsets.Type.defaultVisible(),
"test" /* packageName */,
- new int[0] /* transientBarTypes */,
+ 0 /* transientBarTypes */,
new LetterboxDetails[] {letterboxDetails});
final RegisterStatusBarResult copy = clone(original);
diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar
index 9596c22..7cd5dd6 100644
--- a/libs/WindowManager/Jetpack/window-extensions-release.aar
+++ b/libs/WindowManager/Jetpack/window-extensions-release.aar
Binary files differ
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index e36dfc3..36c0cb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1058,6 +1058,11 @@
}
}
+ /** Sets the app bubble's taskId which is cached for SysUI. */
+ public void setAppBubbleTaskId(int taskId) {
+ mImpl.mCachedState.setAppBubbleTaskId(taskId);
+ }
+
/**
* Fills the overflow bubbles by loading them from disk.
*/
@@ -1636,6 +1641,7 @@
private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
+ private int mAppBubbleTaskId = INVALID_TASK_ID;
private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
@@ -1667,12 +1673,22 @@
mSuppressedBubbleKeys.clear();
mShortcutIdToBubble.clear();
+ mAppBubbleTaskId = INVALID_TASK_ID;
for (Bubble b : mTmpBubbles) {
mShortcutIdToBubble.put(b.getShortcutId(), b);
updateBubbleSuppressedState(b);
+
+ if (KEY_APP_BUBBLE.equals(b.getKey())) {
+ mAppBubbleTaskId = b.getTaskId();
+ }
}
}
+ /** Sets the app bubble's taskId which is cached for SysUI. */
+ synchronized void setAppBubbleTaskId(int taskId) {
+ mAppBubbleTaskId = taskId;
+ }
+
/**
* Updates a specific bubble suppressed state. This is used mainly because notification
* suppression changes don't go through the same BubbleData update mechanism.
@@ -1722,6 +1738,8 @@
for (String key : mSuppressedGroupToNotifKeys.keySet()) {
pw.println(" suppressing: " + key);
}
+
+ pw.print("mAppBubbleTaskId: " + mAppBubbleTaskId);
}
}
@@ -1773,8 +1791,7 @@
@Override
public boolean isAppBubbleTaskId(int taskId) {
- Bubble appBubble = mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE);
- return appBubble != null && appBubble.getTaskId() == taskId;
+ return mCachedState.mAppBubbleTaskId == taskId;
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 1feff18..57c7731 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -278,6 +278,11 @@
// The taskId is saved to use for removeTask, preventing appearance in recent tasks.
mTaskId = taskId;
+ if (Bubble.KEY_APP_BUBBLE.equals(getBubbleKey())) {
+ // Let the controller know sooner what the taskId is.
+ mController.setAppBubbleTaskId(mTaskId);
+ }
+
// With the task org, the taskAppeared callback will only happen once the task has
// already drawn
setContentVisibility(true);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 45b234a..f616e6f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -699,19 +699,6 @@
return bounds.width() > bounds.height();
}
- /** Reverse the split position. */
- @SplitPosition
- public static int reversePosition(@SplitPosition int position) {
- switch (position) {
- case SPLIT_POSITION_TOP_OR_LEFT:
- return SPLIT_POSITION_BOTTOM_OR_RIGHT;
- case SPLIT_POSITION_BOTTOM_OR_RIGHT:
- return SPLIT_POSITION_TOP_OR_LEFT;
- default:
- return SPLIT_POSITION_UNDEFINED;
- }
- }
-
/**
* Return if this layout is landscape.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
new file mode 100644
index 0000000..042721c9
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 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.wm.shell.common.split;
+
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.wm.shell.ShellTaskOrganizer;
+
+/** Helper utility class for split screen components to use. */
+public class SplitScreenUtils {
+ /** Reverse the split position. */
+ @SplitScreenConstants.SplitPosition
+ public static int reverseSplitPosition(@SplitScreenConstants.SplitPosition int position) {
+ switch (position) {
+ case SPLIT_POSITION_TOP_OR_LEFT:
+ return SPLIT_POSITION_BOTTOM_OR_RIGHT;
+ case SPLIT_POSITION_BOTTOM_OR_RIGHT:
+ return SPLIT_POSITION_TOP_OR_LEFT;
+ case SPLIT_POSITION_UNDEFINED:
+ default:
+ return SPLIT_POSITION_UNDEFINED;
+ }
+ }
+
+ /** Returns true if the task is valid for split screen. */
+ public static boolean isValidToSplit(ActivityManager.RunningTaskInfo taskInfo) {
+ return taskInfo != null && taskInfo.supportsMultiWindow
+ && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
+ && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
+ }
+
+ /** Retrieve package name from an intent */
+ @Nullable
+ public static String getPackageName(Intent intent) {
+ if (intent == null || intent.getComponent() == null) {
+ return null;
+ }
+ return intent.getComponent().getPackageName();
+ }
+
+ /** Retrieve package name from a PendingIntent */
+ @Nullable
+ public static String getPackageName(PendingIntent pendingIntent) {
+ if (pendingIntent == null || pendingIntent.getIntent() == null) {
+ return null;
+ }
+ return getPackageName(pendingIntent.getIntent());
+ }
+
+ /** Retrieve package name from a taskId */
+ @Nullable
+ public static String getPackageName(int taskId, ShellTaskOrganizer taskOrganizer) {
+ final ActivityManager.RunningTaskInfo taskInfo = taskOrganizer.getRunningTaskInfo(taskId);
+ return taskInfo != null ? getPackageName(taskInfo.baseIntent) : null;
+ }
+
+ /** Returns true if they are the same package. */
+ public static boolean samePackage(String packageName1, String packageName2) {
+ return packageName1 != null && packageName1.equals(packageName2);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 21eeaa2..7cb5cf2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -28,6 +28,9 @@
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
+import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
+import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
@@ -39,11 +42,8 @@
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.PendingIntent;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Bundle;
@@ -82,8 +82,8 @@
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.common.split.SplitLayout;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
+import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -318,10 +318,6 @@
return mStageCoordinator;
}
- public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
- return mStageCoordinator.isValidToEnterSplitScreen(taskInfo);
- }
-
@Nullable
public ActivityManager.RunningTaskInfo getTaskInfo(@SplitPosition int splitPosition) {
if (!isSplitScreenVisible() || splitPosition == SPLIT_POSITION_UNDEFINED) {
@@ -480,39 +476,54 @@
@Override
public void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
@Nullable Bundle options, UserHandle user) {
- IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
- @Override
- public void onAnimationStart(@WindowManager.TransitionOldType int transit,
- RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers,
- RemoteAnimationTarget[] nonApps,
- final IRemoteAnimationFinishedCallback finishedCallback) {
- try {
- finishedCallback.onAnimationFinished();
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to invoke onAnimationFinished", e);
- }
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- mStageCoordinator.prepareEvictNonOpeningChildTasks(position, apps, evictWct);
- mSyncQueue.queue(evictWct);
+ if (options == null) options = new Bundle();
+ final ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+
+ if (samePackage(packageName, getPackageName(reverseSplitPosition(position)))) {
+ if (supportMultiInstancesSplit(packageName)) {
+ activityOptions.setApplyMultipleTaskFlagForShortcut(true);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
+ } else if (isSplitScreenVisible()) {
+ mStageCoordinator.switchSplitPosition("startShortcut");
+ return;
+ } else {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+ "Cancel entering split as not supporting multi-instances");
+ Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
+ Toast.LENGTH_SHORT).show();
+ return;
}
- @Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
- }
- };
- options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
- null /* wct */);
- RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
- 0 /* duration */, 0 /* statusBarTransitionDelay */);
- ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
- activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
- try {
- LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
- launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
- activityOptions.toBundle(), user);
- } catch (ActivityNotFoundException e) {
- Slog.e(TAG, "Failed to launch shortcut", e);
}
+
+ mStageCoordinator.startShortcut(packageName, shortcutId, position,
+ activityOptions.toBundle(), user);
+ }
+
+ void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
+ @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
+ @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
+ InstanceId instanceId) {
+ if (options1 == null) options1 = new Bundle();
+ final ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
+
+ final String packageName1 = shortcutInfo.getPackage();
+ final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+ if (samePackage(packageName1, packageName2)) {
+ if (supportMultiInstancesSplit(shortcutInfo.getPackage())) {
+ activityOptions.setApplyMultipleTaskFlagForShortcut(true);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
+ } else {
+ taskId = INVALID_TASK_ID;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+ "Cancel entering split as not supporting multi-instances");
+ Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ mStageCoordinator.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
+ activityOptions.toBundle(), taskId, options2, splitPosition, splitRatio, adapter,
+ instanceId);
}
/**
@@ -530,8 +541,10 @@
@SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
InstanceId instanceId) {
Intent fillInIntent = null;
- if (launchSameAppAdjacently(pendingIntent, taskId)) {
- if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+ final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
+ final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+ if (samePackage(packageName1, packageName2)) {
+ if (supportMultiInstancesSplit(packageName1)) {
fillInIntent = new Intent();
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
@@ -551,8 +564,10 @@
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
Intent fillInIntent = null;
- if (launchSameAppAdjacently(pendingIntent, taskId)) {
- if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+ final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
+ final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+ if (samePackage(packageName1, packageName2)) {
+ if (supportMultiInstancesSplit(packageName1)) {
fillInIntent = new Intent();
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
@@ -573,8 +588,10 @@
float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
Intent fillInIntent1 = null;
Intent fillInIntent2 = null;
- if (launchSameAppAdjacently(pendingIntent1, pendingIntent2)) {
- if (supportMultiInstancesSplit(pendingIntent1.getIntent().getComponent())) {
+ final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent1);
+ final String packageName2 = SplitScreenUtils.getPackageName(pendingIntent2);
+ if (samePackage(packageName1, packageName2)) {
+ if (supportMultiInstancesSplit(packageName1)) {
fillInIntent1 = new Intent();
fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
fillInIntent2 = new Intent();
@@ -602,13 +619,15 @@
if (fillInIntent == null) fillInIntent = new Intent();
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
- if (launchSameAppAdjacently(position, intent)) {
- final ComponentName launching = intent.getIntent().getComponent();
- if (supportMultiInstancesSplit(launching)) {
+ final String packageName1 = SplitScreenUtils.getPackageName(intent);
+ final String packageName2 = getPackageName(reverseSplitPosition(position));
+ if (SplitScreenUtils.samePackage(packageName1, packageName2)) {
+ if (supportMultiInstancesSplit(packageName1)) {
// To prevent accumulating large number of instances in the background, reuse task
// in the background with priority.
final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional
- .map(recentTasks -> recentTasks.findTaskInBackground(launching))
+ .map(recentTasks -> recentTasks.findTaskInBackground(
+ intent.getIntent().getComponent()))
.orElse(null);
if (taskInfo != null) {
startTask(taskInfo.taskId, position, options);
@@ -636,63 +655,32 @@
mStageCoordinator.startIntent(intent, fillInIntent, position, options);
}
+ /** Retrieve package name of a specific split position if split screen is activated, otherwise
+ * returns the package name of the top running task. */
@Nullable
- private String getPackageName(Intent intent) {
- if (intent == null || intent.getComponent() == null) {
- return null;
- }
- return intent.getComponent().getPackageName();
- }
-
- private boolean launchSameAppAdjacently(@SplitPosition int position,
- PendingIntent pendingIntent) {
- ActivityManager.RunningTaskInfo adjacentTaskInfo = null;
+ private String getPackageName(@SplitPosition int position) {
+ ActivityManager.RunningTaskInfo taskInfo;
if (isSplitScreenVisible()) {
- adjacentTaskInfo = getTaskInfo(SplitLayout.reversePosition(position));
+ taskInfo = getTaskInfo(position);
} else {
- adjacentTaskInfo = mRecentTasksOptional
- .map(recentTasks -> recentTasks.getTopRunningTask()).orElse(null);
- if (!isValidToEnterSplitScreen(adjacentTaskInfo)) {
- return false;
+ taskInfo = mRecentTasksOptional
+ .map(recentTasks -> recentTasks.getTopRunningTask())
+ .orElse(null);
+ if (!isValidToSplit(taskInfo)) {
+ return null;
}
}
- if (adjacentTaskInfo == null) {
- return false;
- }
-
- final String targetPackageName = getPackageName(pendingIntent.getIntent());
- final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent);
- return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
- }
-
- private boolean launchSameAppAdjacently(PendingIntent pendingIntent, int taskId) {
- final ActivityManager.RunningTaskInfo adjacentTaskInfo =
- mTaskOrganizer.getRunningTaskInfo(taskId);
- if (adjacentTaskInfo == null) {
- return false;
- }
- final String targetPackageName = getPackageName(pendingIntent.getIntent());
- final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent);
- return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
- }
-
- private boolean launchSameAppAdjacently(PendingIntent pendingIntent1,
- PendingIntent pendingIntent2) {
- final String targetPackageName = getPackageName(pendingIntent1.getIntent());
- final String adjacentPackageName = getPackageName(pendingIntent2.getIntent());
- return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
+ return taskInfo != null ? SplitScreenUtils.getPackageName(taskInfo.baseIntent) : null;
}
@VisibleForTesting
- /** Returns {@code true} if the component supports multi-instances split. */
- boolean supportMultiInstancesSplit(@Nullable ComponentName launching) {
- if (launching == null) return false;
-
- final String packageName = launching.getPackageName();
- for (int i = 0; i < mAppsSupportMultiInstances.length; i++) {
- if (mAppsSupportMultiInstances[i].equals(packageName)) {
- return true;
+ boolean supportMultiInstancesSplit(String packageName) {
+ if (packageName != null) {
+ for (int i = 0; i < mAppsSupportMultiInstances.length; i++) {
+ if (mAppsSupportMultiInstances[i].equals(packageName)) {
+ return true;
+ }
}
}
@@ -1011,7 +999,7 @@
InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController,
"startShortcutAndTaskWithLegacyTransition", (controller) ->
- controller.mStageCoordinator.startShortcutAndTaskWithLegacyTransition(
+ controller.startShortcutAndTaskWithLegacyTransition(
shortcutInfo, options1, taskId, options2, splitPosition,
splitRatio, adapter, instanceId));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 9624ae9..5a9170b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -36,12 +36,11 @@
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
-import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
-import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -76,8 +75,10 @@
import android.app.IActivityTaskManager;
import android.app.PendingIntent;
import android.app.WindowConfiguration;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -87,6 +88,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import android.view.Choreographer;
@@ -370,7 +372,7 @@
int sideStagePosition;
if (stageType == STAGE_TYPE_MAIN) {
targetStage = mMainStage;
- sideStagePosition = SplitLayout.reversePosition(stagePosition);
+ sideStagePosition = reverseSplitPosition(stagePosition);
} else if (stageType == STAGE_TYPE_SIDE) {
targetStage = mSideStage;
sideStagePosition = stagePosition;
@@ -428,6 +430,72 @@
return mLogger;
}
+ void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
+ Bundle options, UserHandle user) {
+ final boolean isEnteringSplit = !isSplitActive();
+
+ IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
+ @Override
+ public void onAnimationStart(@WindowManager.TransitionOldType int transit,
+ RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers,
+ RemoteAnimationTarget[] nonApps,
+ final IRemoteAnimationFinishedCallback finishedCallback) {
+ boolean openingToSide = false;
+ if (apps != null) {
+ for (int i = 0; i < apps.length; ++i) {
+ if (apps[i].mode == MODE_OPENING
+ && mSideStage.containsTask(apps[i].taskId)) {
+ openingToSide = true;
+ break;
+ }
+ }
+ }
+
+ if (isEnteringSplit && !openingToSide) {
+ mMainExecutor.execute(() -> exitSplitScreen(
+ mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
+ EXIT_REASON_UNKNOWN));
+ }
+
+ if (finishedCallback != null) {
+ try {
+ finishedCallback.onAnimationFinished();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error finishing legacy transition: ", e);
+ }
+ }
+
+ if (!isEnteringSplit && openingToSide) {
+ final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+ prepareEvictNonOpeningChildTasks(position, apps, evictWct);
+ mSyncQueue.queue(evictWct);
+ }
+ }
+ @Override
+ public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ if (isEnteringSplit) {
+ mMainExecutor.execute(() -> exitSplitScreen(
+ mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
+ EXIT_REASON_UNKNOWN));
+ }
+ }
+ };
+ options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
+ null /* wct */);
+ RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
+ 0 /* duration */, 0 /* statusBarTransitionDelay */);
+ ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+ activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
+ try {
+ LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+ launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
+ activityOptions.toBundle(), user);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(TAG, "Failed to launch shortcut", e);
+ }
+ }
+
/** Launches an activity into split. */
void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
@Nullable Bundle options) {
@@ -899,7 +967,7 @@
case STAGE_TYPE_MAIN: {
if (position != SPLIT_POSITION_UNDEFINED) {
// Set the side stage opposite of what we want to the main stage.
- setSideStagePosition(SplitLayout.reversePosition(position), wct);
+ setSideStagePosition(reverseSplitPosition(position), wct);
} else {
position = getMainStagePosition();
}
@@ -923,7 +991,7 @@
@SplitPosition
int getMainStagePosition() {
- return SplitLayout.reversePosition(mSideStagePosition);
+ return reverseSplitPosition(mSideStagePosition);
}
int getTaskId(@SplitPosition int splitPosition) {
@@ -950,7 +1018,7 @@
mSplitLayout.splitSwitching(t, topLeftStage.mRootLeash, bottomRightStage.mRootLeash,
insets -> {
WindowContainerTransaction wct = new WindowContainerTransaction();
- setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), wct);
+ setSideStagePosition(reverseSplitPosition(mSideStagePosition), wct);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(st -> {
updateSurfaceBounds(mSplitLayout, st, false /* applyResizingOffset */);
@@ -1694,12 +1762,6 @@
}
}
- boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
- return taskInfo.supportsMultiWindow
- && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
- && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
- }
-
@Override
public void onSnappedToDismiss(boolean bottomOrRight, int reason) {
final boolean mainStageToTop =
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index ea3af9d..d0e2601 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -27,8 +27,6 @@
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -201,7 +199,6 @@
ActivityManager.RunningTaskInfo topRunningTask =
createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
- doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
@@ -222,7 +219,6 @@
ActivityManager.RunningTaskInfo topRunningTask =
createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
- doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
// Put the same component into a task in the background
ActivityManager.RecentTaskInfo sameTaskInfo = new ActivityManager.RecentTaskInfo();
doReturn(sameTaskInfo).when(mRecentTasks).findTaskInBackground(any());
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 28496f1..c5202dc 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -108,133 +108,148 @@
public static final int PLAYBACK_VOLUME_VARIABLE = 1;
/** @hide */
- @IntDef({
- TYPE_UNKNOWN, TYPE_BUILTIN_SPEAKER, TYPE_WIRED_HEADSET,
- TYPE_WIRED_HEADPHONES, TYPE_BLUETOOTH_A2DP, TYPE_HDMI, TYPE_USB_DEVICE,
- TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID, TYPE_BLE_HEADSET,
- TYPE_REMOTE_TV, TYPE_REMOTE_SPEAKER, TYPE_GROUP})
+ @IntDef(
+ prefix = {"TYPE_"},
+ value = {
+ TYPE_UNKNOWN,
+ TYPE_BUILTIN_SPEAKER,
+ TYPE_WIRED_HEADSET,
+ TYPE_WIRED_HEADPHONES,
+ TYPE_BLUETOOTH_A2DP,
+ TYPE_HDMI,
+ TYPE_USB_DEVICE,
+ TYPE_USB_ACCESSORY,
+ TYPE_DOCK,
+ TYPE_USB_HEADSET,
+ TYPE_HEARING_AID,
+ TYPE_BLE_HEADSET,
+ TYPE_REMOTE_TV,
+ TYPE_REMOTE_SPEAKER,
+ TYPE_REMOTE_AUDIO_VIDEO_RECEIVER,
+ TYPE_GROUP
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface Type {}
/**
- * The default route type indicating the type is unknown.
+ * Indicates the route's type is unknown or undefined.
*
* @see #getType
- * @hide
*/
public static final int TYPE_UNKNOWN = 0;
/**
- * A route type describing the speaker system (i.e. a mono speaker or stereo speakers) built
- * in a device.
+ * Indicates the route is the speaker system (i.e. a mono speaker or stereo speakers) built into
+ * the device.
*
* @see #getType
- * @hide
*/
public static final int TYPE_BUILTIN_SPEAKER = AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
/**
- * A route type describing a headset, which is the combination of a headphones and microphone.
+ * Indicates the route is a headset, which is the combination of a headphones and a microphone.
*
* @see #getType
- * @hide
*/
public static final int TYPE_WIRED_HEADSET = AudioDeviceInfo.TYPE_WIRED_HEADSET;
/**
- * A route type describing a pair of wired headphones.
+ * Indicates the route is a pair of wired headphones.
*
* @see #getType
- * @hide
*/
public static final int TYPE_WIRED_HEADPHONES = AudioDeviceInfo.TYPE_WIRED_HEADPHONES;
/**
- * A route type indicating the presentation of the media is happening
- * on a bluetooth device such as a bluetooth speaker.
+ * Indicates the route is a bluetooth device, such as a bluetooth speaker or headphones.
*
* @see #getType
- * @hide
*/
public static final int TYPE_BLUETOOTH_A2DP = AudioDeviceInfo.TYPE_BLUETOOTH_A2DP;
/**
- * A route type describing an HDMI connection.
+ * Indicates the route is an HDMI connection.
*
* @see #getType
- * @hide
*/
public static final int TYPE_HDMI = AudioDeviceInfo.TYPE_HDMI;
/**
- * A route type describing a USB audio device.
+ * Indicates the route is a USB audio device.
*
* @see #getType
- * @hide
*/
public static final int TYPE_USB_DEVICE = AudioDeviceInfo.TYPE_USB_DEVICE;
/**
- * A route type describing a USB audio device in accessory mode.
+ * Indicates the route is a USB audio device in accessory mode.
*
* @see #getType
- * @hide
*/
public static final int TYPE_USB_ACCESSORY = AudioDeviceInfo.TYPE_USB_ACCESSORY;
/**
- * A route type describing the audio device associated with a dock.
+ * Indicates the route is the audio device associated with a dock.
*
* @see #getType
- * @hide
*/
public static final int TYPE_DOCK = AudioDeviceInfo.TYPE_DOCK;
/**
- * A device type describing a USB audio headset.
+ * Indicates the route is a USB audio headset.
*
* @see #getType
- * @hide
*/
public static final int TYPE_USB_HEADSET = AudioDeviceInfo.TYPE_USB_HEADSET;
/**
- * A route type describing a Hearing Aid.
+ * Indicates the route is a hearing aid.
*
* @see #getType
- * @hide
*/
public static final int TYPE_HEARING_AID = AudioDeviceInfo.TYPE_HEARING_AID;
/**
- * A route type describing a BLE HEADSET.
+ * Indicates the route is a Bluetooth Low Energy (BLE) HEADSET.
*
* @see #getType
- * @hide
*/
public static final int TYPE_BLE_HEADSET = AudioDeviceInfo.TYPE_BLE_HEADSET;
/**
- * A route type indicating the presentation of the media is happening on a TV.
+ * Indicates the route is a remote TV.
+ *
+ * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+ * routing being done by the system.
*
* @see #getType
- * @hide
*/
public static final int TYPE_REMOTE_TV = 1001;
/**
- * A route type indicating the presentation of the media is happening on a speaker.
+ * Indicates the route is a remote speaker.
+ *
+ * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+ * routing being done by the system.
*
* @see #getType
- * @hide
*/
public static final int TYPE_REMOTE_SPEAKER = 1002;
/**
- * A route type indicating the presentation of the media is happening on multiple devices.
+ * Indicates the route is a remote Audio/Video Receiver (AVR).
+ *
+ * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+ * routing being done by the system.
*
* @see #getType
- * @hide
+ */
+ public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003;
+
+ /**
+ * Indicates the route is a group of devices.
+ *
+ * @see #getType
*/
public static final int TYPE_GROUP = 2000;
@@ -436,16 +451,23 @@
}
/**
- * Gets the type of this route.
+ * Returns the type of this route.
*
- * @return The type of this route:
- * {@link #TYPE_UNKNOWN},
- * {@link #TYPE_BUILTIN_SPEAKER}, {@link #TYPE_WIRED_HEADSET}, {@link #TYPE_WIRED_HEADPHONES},
- * {@link #TYPE_BLUETOOTH_A2DP}, {@link #TYPE_HDMI}, {@link #TYPE_DOCK},
- * {@Link #TYPE_USB_DEVICE}, {@link #TYPE_USB_ACCESSORY}, {@link #TYPE_USB_HEADSET}
- * {@link #TYPE_HEARING_AID},
- * {@link #TYPE_REMOTE_TV}, {@link #TYPE_REMOTE_SPEAKER}, {@link #TYPE_GROUP}.
- * @hide
+ * @see #TYPE_UNKNOWN
+ * @see #TYPE_BUILTIN_SPEAKER
+ * @see #TYPE_WIRED_HEADSET
+ * @see #TYPE_WIRED_HEADPHONES
+ * @see #TYPE_BLUETOOTH_A2DP
+ * @see #TYPE_HDMI
+ * @see #TYPE_DOCK
+ * @see #TYPE_USB_DEVICE
+ * @see #TYPE_USB_ACCESSORY
+ * @see #TYPE_USB_HEADSET
+ * @see #TYPE_HEARING_AID
+ * @see #TYPE_REMOTE_TV
+ * @see #TYPE_REMOTE_SPEAKER
+ * @see #TYPE_REMOTE_AUDIO_VIDEO_RECEIVER
+ * @see #TYPE_GROUP
*/
@Type
public int getType() {
@@ -657,6 +679,7 @@
pw.println(indent + "mId=" + mId);
pw.println(indent + "mName=" + mName);
pw.println(indent + "mFeatures=" + mFeatures);
+ pw.println(indent + "mType=" + getDeviceTypeString(mType));
pw.println(indent + "mIsSystem=" + mIsSystem);
pw.println(indent + "mIconUri=" + mIconUri);
pw.println(indent + "mDescription=" + mDescription);
@@ -787,6 +810,42 @@
dest.writeString8Array(mAllowedPackages.toArray(new String[0]));
}
+ private static String getDeviceTypeString(@Type int deviceType) {
+ switch (deviceType) {
+ case TYPE_BUILTIN_SPEAKER:
+ return "BUILTIN_SPEAKER";
+ case TYPE_WIRED_HEADSET:
+ return "WIRED_HEADSET";
+ case TYPE_WIRED_HEADPHONES:
+ return "WIRED_HEADPHONES";
+ case TYPE_BLUETOOTH_A2DP:
+ return "BLUETOOTH_A2DP";
+ case TYPE_HDMI:
+ return "HDMI";
+ case TYPE_DOCK:
+ return "DOCK";
+ case TYPE_USB_DEVICE:
+ return "USB_DEVICE";
+ case TYPE_USB_ACCESSORY:
+ return "USB_ACCESSORY";
+ case TYPE_USB_HEADSET:
+ return "USB_HEADSET";
+ case TYPE_HEARING_AID:
+ return "HEARING_AID";
+ case TYPE_REMOTE_TV:
+ return "REMOTE_TV";
+ case TYPE_REMOTE_SPEAKER:
+ return "REMOTE_SPEAKER";
+ case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
+ return "REMOTE_AUDIO_VIDEO_RECEIVER";
+ case TYPE_GROUP:
+ return "GROUP";
+ case TYPE_UNKNOWN:
+ default:
+ return TextUtils.formatSimple("UNKNOWN(%d)", deviceType);
+ }
+ }
+
/**
* Builder for {@link MediaRoute2Info media route info}.
*/
@@ -932,7 +991,8 @@
/**
* Sets the route's type.
- * @hide
+ *
+ * @see MediaRoute2Info#getType()
*/
@NonNull
public Builder setType(@Type int type) {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
index 4b73e94..b92729d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
@@ -24,10 +24,6 @@
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.remember
import com.android.settingslib.spa.framework.compose.LocalNavController
-import com.android.settingslib.spa.framework.util.genEntryId
-
-private const val INJECT_ENTRY_NAME = "INJECT"
-private const val ROOT_ENTRY_NAME = "ROOT"
interface EntryData {
val pageId: String?
@@ -164,143 +160,3 @@
}
}
}
-
-/**
- * The helper to build a Settings Entry instance.
- */
-class SettingsEntryBuilder(private val name: String, private val owner: SettingsPage) {
- private var displayName = name
- private var fromPage: SettingsPage? = null
- private var toPage: SettingsPage? = null
-
- // Attributes
- private var isAllowSearch: Boolean = false
- private var isSearchDataDynamic: Boolean = false
- private var hasMutableStatus: Boolean = false
- private var hasSliceSupport: Boolean = false
-
- // Functions
- private var uiLayoutFn: UiLayerRenderer = { }
- private var statusDataFn: StatusDataGetter = { null }
- private var searchDataFn: SearchDataGetter = { null }
- private var sliceDataFn: SliceDataGetter = { _: Uri, _: Bundle? -> null }
-
- fun build(): SettingsEntry {
- val page = fromPage ?: owner
- val isEnabled = page.isEnabled()
- return SettingsEntry(
- id = genEntryId(name, owner, fromPage, toPage),
- name = name,
- owner = owner,
- displayName = displayName,
-
- // linking data
- fromPage = fromPage,
- toPage = toPage,
-
- // attributes
- // TODO: set isEnabled & (isAllowSearch, hasSliceSupport) separately
- isAllowSearch = isEnabled && isAllowSearch,
- isSearchDataDynamic = isSearchDataDynamic,
- hasMutableStatus = hasMutableStatus,
- hasSliceSupport = isEnabled && hasSliceSupport,
-
- // functions
- statusDataImpl = statusDataFn,
- searchDataImpl = searchDataFn,
- sliceDataImpl = sliceDataFn,
- uiLayoutImpl = uiLayoutFn,
- )
- }
-
- fun setDisplayName(displayName: String): SettingsEntryBuilder {
- this.displayName = displayName
- return this
- }
-
- fun setLink(
- fromPage: SettingsPage? = null,
- toPage: SettingsPage? = null
- ): SettingsEntryBuilder {
- if (fromPage != null) this.fromPage = fromPage
- if (toPage != null) this.toPage = toPage
- return this
- }
-
- fun setIsSearchDataDynamic(isDynamic: Boolean): SettingsEntryBuilder {
- this.isSearchDataDynamic = isDynamic
- return this
- }
-
- fun setHasMutableStatus(hasMutableStatus: Boolean): SettingsEntryBuilder {
- this.hasMutableStatus = hasMutableStatus
- return this
- }
-
- fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
- setStatusDataFn { fn(it).getStatusData() }
- setSearchDataFn { fn(it).getSearchData() }
- setUiLayoutFn {
- val macro = remember { fn(it) }
- macro.UiLayout()
- }
- return this
- }
-
- fun setStatusDataFn(fn: StatusDataGetter): SettingsEntryBuilder {
- this.statusDataFn = fn
- return this
- }
-
- fun setSearchDataFn(fn: SearchDataGetter): SettingsEntryBuilder {
- this.searchDataFn = fn
- this.isAllowSearch = true
- return this
- }
-
- fun clearSearchDataFn(): SettingsEntryBuilder {
- this.searchDataFn = { null }
- this.isAllowSearch = false
- return this
- }
-
- fun setSliceDataFn(fn: SliceDataGetter): SettingsEntryBuilder {
- this.sliceDataFn = fn
- this.hasSliceSupport = true
- return this
- }
-
- fun setUiLayoutFn(fn: UiLayerRenderer): SettingsEntryBuilder {
- this.uiLayoutFn = fn
- return this
- }
-
- companion object {
- fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
- return SettingsEntryBuilder(entryName, owner)
- }
-
- fun createLinkFrom(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
- return create(entryName, owner).setLink(fromPage = owner)
- }
-
- fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
- return create(entryName, owner).setLink(toPage = owner)
- }
-
- fun create(owner: SettingsPage, entryName: String, displayName: String? = null):
- SettingsEntryBuilder {
- return SettingsEntryBuilder(entryName, owner).setDisplayName(displayName ?: entryName)
- }
-
- fun createInject(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
- val name = displayName ?: "${INJECT_ENTRY_NAME}_${owner.displayName}"
- return createLinkTo(INJECT_ENTRY_NAME, owner).setDisplayName(name)
- }
-
- fun createRoot(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
- val name = displayName ?: "${ROOT_ENTRY_NAME}_${owner.displayName}"
- return createLinkTo(ROOT_ENTRY_NAME, owner).setDisplayName(name)
- }
- }
-}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt
new file mode 100644
index 0000000..67f9ea5
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2023 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.settingslib.spa.framework.common
+
+import android.net.Uri
+import android.os.Bundle
+import androidx.compose.runtime.remember
+import com.android.settingslib.spa.framework.util.genEntryId
+
+private const val INJECT_ENTRY_NAME = "INJECT"
+private const val ROOT_ENTRY_NAME = "ROOT"
+
+/**
+ * The helper to build a Settings Entry instance.
+ */
+class SettingsEntryBuilder(private val name: String, private val owner: SettingsPage) {
+ private var displayName = name
+ private var fromPage: SettingsPage? = null
+ private var toPage: SettingsPage? = null
+
+ // Attributes
+ private var isAllowSearch: Boolean = false
+ private var isSearchDataDynamic: Boolean = false
+ private var hasMutableStatus: Boolean = false
+ private var hasSliceSupport: Boolean = false
+
+ // Functions
+ private var uiLayoutFn: UiLayerRenderer = { }
+ private var statusDataFn: StatusDataGetter = { null }
+ private var searchDataFn: SearchDataGetter = { null }
+ private var sliceDataFn: SliceDataGetter = { _: Uri, _: Bundle? -> null }
+
+ fun build(): SettingsEntry {
+ val page = fromPage ?: owner
+ val isEnabled = page.isEnabled()
+ return SettingsEntry(
+ id = genEntryId(name, owner, fromPage, toPage),
+ name = name,
+ owner = owner,
+ displayName = displayName,
+
+ // linking data
+ fromPage = fromPage,
+ toPage = toPage,
+
+ // attributes
+ // TODO: set isEnabled & (isAllowSearch, hasSliceSupport) separately
+ isAllowSearch = isEnabled && isAllowSearch,
+ isSearchDataDynamic = isSearchDataDynamic,
+ hasMutableStatus = hasMutableStatus,
+ hasSliceSupport = isEnabled && hasSliceSupport,
+
+ // functions
+ statusDataImpl = statusDataFn,
+ searchDataImpl = searchDataFn,
+ sliceDataImpl = sliceDataFn,
+ uiLayoutImpl = uiLayoutFn,
+ )
+ }
+
+ fun setDisplayName(displayName: String): SettingsEntryBuilder {
+ this.displayName = displayName
+ return this
+ }
+
+ fun setLink(
+ fromPage: SettingsPage? = null,
+ toPage: SettingsPage? = null
+ ): SettingsEntryBuilder {
+ if (fromPage != null) this.fromPage = fromPage
+ if (toPage != null) this.toPage = toPage
+ return this
+ }
+
+ fun setIsSearchDataDynamic(isDynamic: Boolean): SettingsEntryBuilder {
+ this.isSearchDataDynamic = isDynamic
+ return this
+ }
+
+ fun setHasMutableStatus(hasMutableStatus: Boolean): SettingsEntryBuilder {
+ this.hasMutableStatus = hasMutableStatus
+ return this
+ }
+
+ fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
+ setStatusDataFn { fn(it).getStatusData() }
+ setSearchDataFn { fn(it).getSearchData() }
+ setUiLayoutFn {
+ val macro = remember { fn(it) }
+ macro.UiLayout()
+ }
+ return this
+ }
+
+ fun setStatusDataFn(fn: StatusDataGetter): SettingsEntryBuilder {
+ this.statusDataFn = fn
+ return this
+ }
+
+ fun setSearchDataFn(fn: SearchDataGetter): SettingsEntryBuilder {
+ this.searchDataFn = fn
+ this.isAllowSearch = true
+ return this
+ }
+
+ fun clearSearchDataFn(): SettingsEntryBuilder {
+ this.searchDataFn = { null }
+ this.isAllowSearch = false
+ return this
+ }
+
+ fun setSliceDataFn(fn: SliceDataGetter): SettingsEntryBuilder {
+ this.sliceDataFn = fn
+ this.hasSliceSupport = true
+ return this
+ }
+
+ fun setUiLayoutFn(fn: UiLayerRenderer): SettingsEntryBuilder {
+ this.uiLayoutFn = fn
+ return this
+ }
+
+ companion object {
+ fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+ return SettingsEntryBuilder(entryName, owner)
+ }
+
+ fun createLinkFrom(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+ return create(entryName, owner).setLink(fromPage = owner)
+ }
+
+ fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+ return create(entryName, owner).setLink(toPage = owner)
+ }
+
+ fun create(owner: SettingsPage, entryName: String, displayName: String? = null):
+ SettingsEntryBuilder {
+ return SettingsEntryBuilder(entryName, owner).setDisplayName(displayName ?: entryName)
+ }
+
+ fun createInject(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
+ val name = displayName ?: "${INJECT_ENTRY_NAME}_${owner.displayName}"
+ return createLinkTo(INJECT_ENTRY_NAME, owner).setDisplayName(name)
+ }
+
+ fun createRoot(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
+ val name = displayName ?: "${ROOT_ENTRY_NAME}_${owner.displayName}"
+ return createLinkTo(ROOT_ENTRY_NAME, owner).setDisplayName(name)
+ }
+ }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
index 14dc785..429f97b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
@@ -30,14 +30,10 @@
val injectEntry: SettingsEntry,
)
-private fun SettingsPage.getTitle(sppRepository: SettingsPageProviderRepository): String {
- return sppRepository.getProviderOrNull(sppName)!!.getTitle(arguments)
-}
-
/**
* The repository to maintain all Settings entries
*/
-class SettingsEntryRepository(private val sppRepository: SettingsPageProviderRepository) {
+class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) {
// Map of entry unique Id to entry
private val entryMap: Map<String, SettingsEntry>
@@ -66,6 +62,9 @@
if (page == null || pageWithEntryMap.containsKey(page.id)) continue
val spp = sppRepository.getProviderOrNull(page.sppName) ?: continue
val newEntries = spp.buildEntry(page.arguments)
+ // The page id could be existed already, if there are 2+ pages go to the same one.
+ // For now, override the previous ones, which means only the last from-page is kept.
+ // TODO: support multiple from-pages if necessary.
pageWithEntryMap[page.id] = SettingsPageWithEntry(
page = page,
entries = newEntries,
@@ -123,7 +122,7 @@
if (it.toPage == null)
defaultTitle
else {
- it.toPage.getTitle(sppRepository)
+ it.toPage.getTitle()
}
}
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
index c810648..724588f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
@@ -81,6 +81,10 @@
return getPageProvider(sppName)?.isEnabled(arguments) ?: false
}
+ fun getTitle(): String {
+ return getPageProvider(sppName)?.getTitle(arguments) ?: ""
+ }
+
@Composable
fun UiLayout() {
getPageProvider(sppName)?.Page(arguments)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
index 32b283e..62189dc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -24,7 +24,12 @@
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.scale
+import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.LayoutDirection
import com.android.settingslib.spa.framework.compose.LocalNavController
/** Action that navigates back to last page. */
@@ -50,6 +55,7 @@
Icon(
imageVector = Icons.Outlined.ArrowBack,
contentDescription = contentDescription,
+ modifier = Modifier.autoMirrored(),
)
}
}
@@ -75,3 +81,10 @@
)
}
}
+
+private fun Modifier.autoMirrored() = composed {
+ when (LocalLayoutDirection.current) {
+ LayoutDirection.Rtl -> scale(scaleX = -1f, scaleY = 1f)
+ else -> this
+ }
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
index 730aa8f..379b9a7 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
@@ -113,6 +113,7 @@
@Test
fun testGetEntryPath() {
+ SpaEnvironmentFactory.reset(spaEnvironment)
assertThat(
entryRepository.getEntryPathWithDisplayName(
genEntryId("Layer2Entry1", SppLayer2.createSettingsPage())
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 6fb5555..c036fdb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -73,6 +73,8 @@
}
@VisibleForTesting
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
int getDrawableResId() {
int resId;
switch (mRouteInfo.getType()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index a97cbaf..77e514f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -443,6 +443,8 @@
dispatchDeviceListAdded();
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
private void buildAllRoutes() {
for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
if (DEBUG) {
@@ -462,6 +464,8 @@
return infos;
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
private synchronized void buildAvailableRoutes() {
for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
if (DEBUG) {
@@ -512,6 +516,8 @@
}
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
@VisibleForTesting
void addMediaDevice(MediaRoute2Info route) {
//TODO(b/258141461): Attach flag and disable reason in MediaDevice
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 2431080..d242198 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -114,6 +114,8 @@
setType(info);
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
private void setType(MediaRoute2Info info) {
if (info == null) {
mType = MediaDeviceType.TYPE_BLUETOOTH_DEVICE;
@@ -335,6 +337,8 @@
*
* @return true if the RouteInfo equals TYPE_BLE_HEADSET.
*/
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
public boolean isBLEDevice() {
return mRouteInfo.getType() == TYPE_BLE_HEADSET;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index de16d4a..1c82be9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -56,6 +56,8 @@
initDeviceRecord();
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
@Override
public String getName() {
CharSequence name;
@@ -94,11 +96,15 @@
return mContext.getDrawable(getDrawableResId());
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
@VisibleForTesting
int getDrawableResId() {
return mDeviceIconUtil.getIconResIdFromMediaRouteType(mRouteInfo.getType());
}
+ // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+ @SuppressWarnings("NewApi")
@Override
public String getId() {
String id;
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 5eb7831..d02eee0 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -525,7 +525,7 @@
// 1500 - chooser aka sharesheet
// TODO(b/254512507): Tracking Bug
- val CHOOSER_UNBUNDLED = releasedFlag(1500, "chooser_unbundled")
+ val CHOOSER_UNBUNDLED = unreleasedFlag(1500, "chooser_unbundled", teamfood = true)
// TODO(b/266983432) Tracking Bug
val SHARESHEET_CUSTOM_ACTIONS =
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 35423f4..d5d7325 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -30,7 +30,6 @@
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
-import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
@@ -85,7 +84,6 @@
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InsetsFrameProvider;
-import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
@@ -97,6 +95,7 @@
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
@@ -1150,12 +1149,11 @@
}
@Override
- public void showTransient(int displayId, @InternalInsetsType int[] types,
- boolean isGestureOnSystemBar) {
+ public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_NAVIGATION_BAR)) {
+ if ((types & WindowInsets.Type.navigationBars()) == 0) {
return;
}
if (!mTransientShown) {
@@ -1166,11 +1164,11 @@
}
@Override
- public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+ public void abortTransient(int displayId, @InsetsType int types) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_NAVIGATION_BAR)) {
+ if ((types & WindowInsets.Type.navigationBars()) == 0) {
return;
}
clearTransient();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index f3712e6..c3d7369 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -20,8 +20,6 @@
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -41,7 +39,6 @@
import android.app.StatusBarManager;
import android.app.StatusBarManager.WindowVisibleState;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -52,6 +49,7 @@
import android.util.Log;
import android.view.Display;
import android.view.View;
+import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
@@ -68,7 +66,6 @@
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -401,11 +398,11 @@
}
@Override
- public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) {
+ public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) {
+ if ((types & WindowInsets.Type.navigationBars()) == 0) {
return;
}
if (!mTaskbarTransientShowing) {
@@ -415,11 +412,11 @@
}
@Override
- public void abortTransient(int displayId, int[] types) {
+ public void abortTransient(int displayId, @InsetsType int types) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) {
+ if ((types & WindowInsets.Type.navigationBars()) == 0) {
return;
}
clearTransient();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 3aaad87..2cf1f53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -53,7 +53,6 @@
import android.os.RemoteException;
import android.util.Pair;
import android.util.SparseArray;
-import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
@@ -371,22 +370,22 @@
String packageName, LetterboxDetails[] letterboxDetails) { }
/**
- * @see IStatusBar#showTransient(int, int[], boolean).
+ * @see IStatusBar#showTransient(int, int, boolean).
*/
- default void showTransient(int displayId, @InternalInsetsType int[] types) { }
+ default void showTransient(int displayId, @InsetsType int types) { }
/**
- * @see IStatusBar#showTransient(int, int[], boolean).
+ * @see IStatusBar#showTransient(int, int, boolean).
*/
- default void showTransient(int displayId, @InternalInsetsType int[] types,
+ default void showTransient(int displayId, @InsetsType int types,
boolean isGestureOnSystemBar) {
showTransient(displayId, types);
}
/**
- * @see IStatusBar#abortTransient(int, int[]).
+ * @see IStatusBar#abortTransient(int, int).
*/
- default void abortTransient(int displayId, @InternalInsetsType int[] types) { }
+ default void abortTransient(int displayId, @InsetsType int types) { }
/**
* Called to notify System UI that a warning about the device going to sleep
@@ -1131,17 +1130,23 @@
}
@Override
- public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) {
+ public void showTransient(int displayId, int types, boolean isGestureOnSystemBar) {
synchronized (mLock) {
- mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, isGestureOnSystemBar ? 1 : 0,
- types).sendToTarget();
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = types;
+ args.argi3 = isGestureOnSystemBar ? 1 : 0;
+ mHandler.obtainMessage(MSG_SHOW_TRANSIENT, args).sendToTarget();
}
}
@Override
- public void abortTransient(int displayId, int[] types) {
+ public void abortTransient(int displayId, int types) {
synchronized (mLock) {
- mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget();
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = displayId;
+ args.argi2 = types;
+ mHandler.obtainMessage(MSG_ABORT_TRANSIENT, args).sendToTarget();
}
}
@@ -1644,17 +1649,21 @@
args.recycle();
break;
case MSG_SHOW_TRANSIENT: {
- final int displayId = msg.arg1;
- final int[] types = (int[]) msg.obj;
- final boolean isGestureOnSystemBar = msg.arg2 != 0;
+ args = (SomeArgs) msg.obj;
+ final int displayId = args.argi1;
+ final int types = args.argi2;
+ final boolean isGestureOnSystemBar = args.argi3 != 0;
+ args.recycle();
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).showTransient(displayId, types, isGestureOnSystemBar);
}
break;
}
case MSG_ABORT_TRANSIENT: {
- final int displayId = msg.arg1;
- final int[] types = (int[]) msg.obj;
+ args = (SomeArgs) msg.obj;
+ final int displayId = args.argi1;
+ final int types = args.argi2;
+ args.recycle();
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).abortTransient(displayId, types);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 856d7de..fecaa3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.containsType;
-
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
@@ -36,8 +33,8 @@
import android.os.Vibrator;
import android.util.Log;
import android.util.Slog;
-import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
+import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
@@ -168,11 +165,11 @@
}
@Override
- public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+ public void abortTransient(int displayId, @InsetsType int types) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_STATUS_BAR)) {
+ if ((types & WindowInsets.Type.statusBars()) == 0) {
return;
}
mCentralSurfaces.clearTransient();
@@ -489,12 +486,11 @@
}
@Override
- public void showTransient(int displayId, @InternalInsetsType int[] types,
- boolean isGestureOnSystemBar) {
+ public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
if (displayId != mDisplayId) {
return;
}
- if (!containsType(types, ITYPE_STATUS_BAR)) {
+ if ((types & WindowInsets.Type.statusBars()) == 0) {
return;
}
mCentralSurfaces.showTransientUnchecked();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index e595ddf..1966a66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -21,8 +21,6 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
@@ -100,6 +98,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -943,7 +942,7 @@
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
+ if ((result.mTransientBarTypes & WindowInsets.Type.statusBars()) != 0) {
showTransientUnchecked();
}
mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
index babbe45..32edf8f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
@@ -11,7 +11,6 @@
import com.android.systemui.flags.Flag
import com.android.systemui.flags.FlagListenable
import com.android.systemui.flags.Flags
-import com.android.systemui.flags.ReleasedFlag
import com.android.systemui.flags.UnreleasedFlag
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.any
@@ -103,7 +102,7 @@
@Test
fun initialize_enablesUnbundledChooser_whenFlagEnabled() {
// Arrange
- setFlagMock(true)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
// Act
chooserSelector.start()
@@ -119,7 +118,7 @@
@Test
fun initialize_disablesUnbundledChooser_whenFlagDisabled() {
// Arrange
- setFlagMock(false)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
// Act
chooserSelector.start()
@@ -135,7 +134,7 @@
@Test
fun enablesUnbundledChooser_whenFlagBecomesEnabled() {
// Arrange
- setFlagMock(false)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -148,7 +147,7 @@
)
// Act
- setFlagMock(true)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
// Assert
@@ -162,7 +161,7 @@
@Test
fun disablesUnbundledChooser_whenFlagBecomesDisabled() {
// Arrange
- setFlagMock(true)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -175,7 +174,7 @@
)
// Act
- setFlagMock(false)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
// Assert
@@ -189,7 +188,7 @@
@Test
fun doesNothing_whenAnotherFlagChanges() {
// Arrange
- setFlagMock(false)
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
chooserSelector.start()
verify(mockFeatureFlags).addListener(
eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -198,17 +197,13 @@
clearInvocations(mockPackageManager)
// Act
+ whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
flagListener.value.onFlagChanged(TestFlagEvent("other flag"))
// Assert
verifyZeroInteractions(mockPackageManager)
}
- private fun setFlagMock(enabled: Boolean) {
- whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(enabled)
- whenever(mockFeatureFlags.isEnabled(any<ReleasedFlag>())).thenReturn(enabled)
- }
-
private class TestFlagEvent(override val flagName: String) : FlagListenable.FlagEvent {
override fun requestNoRestart() {}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index b1ca1c0..f581154 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -18,8 +18,6 @@
import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -158,7 +156,7 @@
@Test
public void testShowTransient() {
- int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+ int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
mCommandQueue.showTransient(DEFAULT_DISPLAY, types, true /* isGestureOnSystemBar */);
waitForIdleSync();
verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types), eq(true));
@@ -166,7 +164,7 @@
@Test
public void testShowTransientForSecondaryDisplay() {
- int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+ int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
mCommandQueue.showTransient(SECONDARY_DISPLAY, types, true /* isGestureOnSystemBar */);
waitForIdleSync();
verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types), eq(true));
@@ -174,7 +172,7 @@
@Test
public void testAbortTransient() {
- int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+ int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
mCommandQueue.abortTransient(DEFAULT_DISPLAY, types);
waitForIdleSync();
verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types));
@@ -182,7 +180,7 @@
@Test
public void testAbortTransientForSecondaryDisplay() {
- int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+ int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
mCommandQueue.abortTransient(SECONDARY_DISPLAY, types);
waitForIdleSync();
verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types));
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index 969a174..0b5c1c1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -150,6 +150,13 @@
}
/**
+ * Returns if the sensor is side fps.
+ */
+ public boolean isSfps() {
+ return mSidefpsController.isPresent();
+ }
+
+ /**
* Consumer for a biometric overlay controller.
*
* This behaves like a normal {@link Consumer} except that it will trap and log
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a90679e..932c0b4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -236,8 +236,14 @@
@Override
public void onError(int errorCode, int vendorCode) {
- super.onError(errorCode, vendorCode);
-
+ if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR
+ && vendorCode == BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED
+ && mSensorOverlays.isSfps()) {
+ super.onError(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED,
+ 0 /* vendorCode */);
+ } else {
+ super.onError(errorCode, vendorCode);
+ }
if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION) {
BiometricNotificationUtils.showBadCalibrationNotification(getContext());
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 513b3e3..cf54662 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -146,7 +146,14 @@
}
});
mCallback.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
- super.onAcquired(acquiredInfo, vendorCode);
+ if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR
+ && vendorCode == BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED
+ && mSensorOverlays.isSfps()) {
+ super.onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
+ 0 /* vendorCode */);
+ } else {
+ super.onAcquired(acquiredInfo, vendorCode);
+ }
}
@Override
@@ -274,8 +281,5 @@
}
@Override
- public void onPowerPressed() {
- onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
- 0 /* vendorCode */);
- }
+ public void onPowerPressed() { }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 14b9121..740d2a3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2481,6 +2481,7 @@
Slog.w(TAG, "Local tv device not available to change arc mode.");
return;
}
+ tv.startArcAction(enabled);
}
});
}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 8ee3a72..a113d01 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -103,9 +103,9 @@
mObservers.get(uri).accept("setting changed");
}
- private boolean getBoolean(String settingName) {
+ private boolean getBoolean(String settingName, boolean defaultValue) {
final int setting = Settings.System.getIntForUser(mContext.getContentResolver(),
- settingName, 0, UserHandle.USER_CURRENT);
+ settingName, defaultValue ? 1 : 0, UserHandle.USER_CURRENT);
return setting != 0;
}
@@ -127,20 +127,21 @@
private void updateTouchpadNaturalScrollingEnabled() {
mNative.setTouchpadNaturalScrollingEnabled(
- getBoolean(Settings.System.TOUCHPAD_NATURAL_SCROLLING));
+ getBoolean(Settings.System.TOUCHPAD_NATURAL_SCROLLING, true));
}
private void updateTouchpadTapToClickEnabled() {
- mNative.setTouchpadTapToClickEnabled(getBoolean(Settings.System.TOUCHPAD_TAP_TO_CLICK));
+ mNative.setTouchpadTapToClickEnabled(
+ getBoolean(Settings.System.TOUCHPAD_TAP_TO_CLICK, true));
}
private void updateTouchpadRightClickZoneEnabled() {
mNative.setTouchpadRightClickZoneEnabled(
- getBoolean(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE));
+ getBoolean(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, false));
}
private void updateShowTouches() {
- mNative.setShowTouches(getBoolean(Settings.System.SHOW_TOUCHES));
+ mNative.setShowTouches(getBoolean(Settings.System.SHOW_TOUCHES, false));
}
private void updateAccessibilityLargePointer() {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0c99e86..b4fc195 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -30,7 +30,6 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_SYSTEM;
-import static android.provider.DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
@@ -1729,8 +1728,7 @@
if (newCredential.isPattern()) {
setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
}
- if (DeviceConfig.getBoolean(NAMESPACE_AUTO_PIN_CONFIRMATION,
- "enable_auto_pin_confirmation", /* defaultValue= */ false)) {
+ if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()) {
if (newCredential.isPin()) {
setLong(LockPatternUtils.PIN_LENGTH, newCredential.size(), userHandle);
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c5bcddc..6b9be25 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1116,12 +1116,16 @@
// Flag for bubble
ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions);
- if (options != null && options.isApplyActivityFlagsForBubbles()) {
- // Flag for bubble to make behaviour match documentLaunchMode=always.
- intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
- intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ if (options != null) {
+ if (options.isApplyActivityFlagsForBubbles()) {
+ // Flag for bubble to make behaviour match documentLaunchMode=always.
+ intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+ intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
+ if (options.isApplyMultipleTaskFlagForShortcut()) {
+ intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
}
-
intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intents[0].setSourceBounds(sourceBounds);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 5521384..ec052ec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -21,7 +21,6 @@
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
import android.os.Bundle;
import android.os.IBinder;
-import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowInsetsController.Behavior;
@@ -162,11 +161,10 @@
LetterboxDetails[] letterboxDetails);
/** @see com.android.internal.statusbar.IStatusBar#showTransient */
- void showTransient(int displayId, @InternalInsetsType int[] types,
- boolean isGestureOnSystemBar);
+ void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar);
/** @see com.android.internal.statusbar.IStatusBar#abortTransient */
- void abortTransient(int displayId, @InternalInsetsType int[] types);
+ void abortTransient(int displayId, @InsetsType int types);
/**
* @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 83f4805..4489ba9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -79,12 +79,10 @@
import android.service.quicksettings.TileService;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsController.Appearance;
@@ -645,7 +643,7 @@
}
@Override
- public void showTransient(int displayId, @InternalInsetsType int[] types,
+ public void showTransient(int displayId, @InsetsType int types,
boolean isGestureOnSystemBar) {
getUiState(displayId).showTransient(types);
if (mBar != null) {
@@ -656,7 +654,7 @@
}
@Override
- public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+ public void abortTransient(int displayId, @InsetsType int types) {
getUiState(displayId).clearTransient(types);
if (mBar != null) {
try {
@@ -1258,7 +1256,7 @@
private static class UiState {
private @Appearance int mAppearance = 0;
private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
- private final ArraySet<Integer> mTransientBarTypes = new ArraySet<>();
+ private @InsetsType int mTransientBarTypes;
private boolean mNavbarColorManagedByIme = false;
private @Behavior int mBehavior;
private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
@@ -1285,16 +1283,12 @@
mLetterboxDetails = letterboxDetails;
}
- private void showTransient(@InternalInsetsType int[] types) {
- for (int type : types) {
- mTransientBarTypes.add(type);
- }
+ private void showTransient(@InsetsType int types) {
+ mTransientBarTypes |= types;
}
- private void clearTransient(@InternalInsetsType int[] types) {
- for (int type : types) {
- mTransientBarTypes.remove(type);
- }
+ private void clearTransient(@InsetsType int types) {
+ mTransientBarTypes &= ~types;
}
private int getDisabled1() {
@@ -1410,16 +1404,12 @@
// TODO(b/118592525): Currently, status bar only works on the default display.
// Make it aware of multi-display if needed.
final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
- final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
- for (int i = 0; i < transientBarTypes.length; i++) {
- transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
- }
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes,
- state.mPackageName, transientBarTypes, state.mLetterboxDetails);
+ state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d93a62d..9b643c5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -47,8 +47,6 @@
import static android.view.Display.STATE_UNKNOWN;
import static android.view.Display.isSuspendedState;
import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
-import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
@@ -57,6 +55,7 @@
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsets.Type.systemGestures;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
@@ -174,6 +173,7 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
+import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
@@ -221,7 +221,6 @@
import android.view.InputDevice;
import android.view.InsetsSource;
import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
import android.view.MagnificationSpec;
import android.view.PrivacyIndicatorBounds;
import android.view.RemoteAnimationDefinition;
@@ -248,7 +247,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
-import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -466,6 +464,8 @@
private boolean mSystemGestureExclusionWasRestricted = false;
private final Region mSystemGestureExclusionUnrestricted = new Region();
private int mSystemGestureExclusionLimit;
+ private final Rect mSystemGestureFrameLeft = new Rect();
+ private final Rect mSystemGestureFrameRight = new Rect();
private Set<Rect> mRestrictedKeepClearAreas = new ArraySet<>();
private Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>();
@@ -1519,31 +1519,6 @@
return mDisplayRotation;
}
- void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
- @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider) {
- setInsetProvider(type, win, frameProvider, null /* overrideFrameProviders */);
- }
-
- /**
- * Marks a window as providing insets for the rest of the windows in the system.
- *
- * @param type The type of inset this window provides.
- * @param win The window.
- * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
- * the window should be taken. Only for non-WindowState providers, nav bar
- * and status bar.
- * @param overrideFrameProviders Functions to compute the frame when dispatching insets to the
- * given window types, or {@code null} if the normal frame should
- * be taken.
- */
- void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
- @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider,
- @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
- overrideFrameProviders) {
- mInsetsStateController.getSourceProvider(type).setWindowContainer(win, frameProvider,
- overrideFrameProviders);
- }
-
InsetsStateController getInsetsStateController() {
return mInsetsStateController;
}
@@ -4048,7 +4023,7 @@
final int imePid = mInputMethodWindow.mSession.mPid;
mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer);
}
- mInsetsStateController.getSourceProvider(ID_IME).setWindowContainer(win,
+ mInsetsStateController.getImeSourceProvider().setWindowContainer(win,
mDisplayPolicy.getImeSourceFrameProvider(), null);
computeImeTarget(true /* updateImeTarget */);
updateImeControlTarget();
@@ -5719,10 +5694,12 @@
final Region unhandled = Region.obtain();
unhandled.set(0, 0, mDisplayFrames.mWidth, mDisplayFrames.mHeight);
- final Rect leftEdge = mInsetsStateController.getSourceProvider(ITYPE_LEFT_GESTURES)
- .getSource().getFrame();
- final Rect rightEdge = mInsetsStateController.getSourceProvider(ITYPE_RIGHT_GESTURES)
- .getSource().getFrame();
+ final InsetsState state = mInsetsStateController.getRawInsetsState();
+ final Rect df = state.getDisplayFrame();
+ final Insets gestureInsets = state.calculateInsets(df, systemGestures(),
+ false /* ignoreVisibility */);
+ mSystemGestureFrameLeft.set(df.left, df.top, gestureInsets.left, df.bottom);
+ mSystemGestureFrameRight.set(gestureInsets.right, df.top, df.right, df.bottom);
final Region touchableRegion = Region.obtain();
final Region local = Region.obtain();
@@ -5766,25 +5743,25 @@
if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) {
// Processes the region along the left edge.
- remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
- remainingLeftRight[0], w, EXCLUSION_LEFT);
+ remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion,
+ mSystemGestureFrameLeft, remainingLeftRight[0], w, EXCLUSION_LEFT);
// Processes the region along the right edge.
- remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
- remainingLeftRight[1], w, EXCLUSION_RIGHT);
+ remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion,
+ mSystemGestureFrameRight, remainingLeftRight[1], w, EXCLUSION_RIGHT);
// Adds the middle (unrestricted area)
final Region middle = Region.obtain(local);
- middle.op(leftEdge, Op.DIFFERENCE);
- middle.op(rightEdge, Op.DIFFERENCE);
+ middle.op(mSystemGestureFrameLeft, Op.DIFFERENCE);
+ middle.op(mSystemGestureFrameRight, Op.DIFFERENCE);
outExclusion.op(middle, Op.UNION);
middle.recycle();
} else {
boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */);
if (loggable) {
- addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
+ addToGlobalAndConsumeLimit(local, outExclusion, mSystemGestureFrameLeft,
Integer.MAX_VALUE, w, EXCLUSION_LEFT);
- addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
+ addToGlobalAndConsumeLimit(local, outExclusion, mSystemGestureFrameRight,
Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
}
outExclusion.op(local, Op.UNION);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index e87680a..3c4d706 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -171,9 +171,8 @@
/** Use the transit animation in style resource (see {@link #selectAnimation}). */
static final int ANIMATION_STYLEABLE = 0;
- private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR,
- ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR};
- private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR};
+ private static final int SHOW_TYPES_FOR_SWIPE = Type.statusBars() | Type.navigationBars();
+ private static final int SHOW_TYPES_FOR_PANIC = Type.navigationBars();
private final WindowManagerService mService;
private final Context mContext;
@@ -251,7 +250,7 @@
private boolean mIsFreeformWindowOverlappingWithNavBar;
- private boolean mLastImmersiveMode;
+ private boolean mIsImmersiveMode;
// The windows we were told about in focusChanged.
private WindowState mFocusedWindow;
@@ -1077,8 +1076,16 @@
} else {
overrideProviders = null;
}
- mDisplayContent.setInsetProvider(provider.type, win, frameProvider,
- overrideProviders);
+ // TODO (b/234093736): Let InsetsFrameProvider have the following fields:
+ // - IBinder owner.
+ // - int index.
+ // - @InsetsType int type.
+ // So we can create the id by using InsetsSource#createId.
+ // And we won't need toPublicType anymore.
+ final int id = provider.type;
+ final @InsetsType int type = InsetsState.toPublicType(id);
+ mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(id, type)
+ .setWindowContainer(win, frameProvider, overrideProviders);
mInsetsSourceWindowsExceptIme.add(win);
}
}
@@ -1171,10 +1178,17 @@
mLastFocusedWindow = null;
}
- final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
- for (int index = sources.size() - 1; index >= 0; index--) {
- final @InternalInsetsType int type = sources.keyAt(index);
- mDisplayContent.setInsetProvider(type, null /* win */, null /* frameProvider */);
+ if (win.hasInsetsSourceProvider()) {
+ final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
+ final InsetsStateController controller = mDisplayContent.getInsetsStateController();
+ for (int index = providers.size() - 1; index >= 0; index--) {
+ final InsetsSourceProvider provider = providers.valueAt(index);
+ provider.setWindowContainer(
+ null /* windowContainer */,
+ null /* frameProvider */,
+ null /* overrideFrameProviders */);
+ controller.removeSourceProvider(provider.getSource().getId());
+ }
}
mInsetsSourceWindowsExceptIme.remove(win);
}
@@ -1243,7 +1257,6 @@
* some temporal states, but doesn't change the window frames used to show on screen.
*/
void simulateLayoutDisplay(DisplayFrames displayFrames) {
- final InsetsStateController controller = mDisplayContent.getInsetsStateController();
sTmpClientFrames.attachedFrame = null;
for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) {
final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i);
@@ -1252,11 +1265,10 @@
displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
UNSPECIFIED_LENGTH, win.getRequestedVisibleTypes(), win.mGlobalScale,
sTmpClientFrames);
- final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
+ final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
final InsetsState state = displayFrames.mInsetsState;
- for (int index = sources.size() - 1; index >= 0; index--) {
- final int type = sources.keyAt(index);
- state.addSource(controller.getSourceProvider(type).createSimulatedSource(
+ for (int index = providers.size() - 1; index >= 0; index--) {
+ state.addSource(providers.valueAt(index).createSimulatedSource(
displayFrames, sTmpClientFrames.frame));
}
}
@@ -1359,30 +1371,33 @@
mIsFreeformWindowOverlappingWithNavBar = true;
}
- final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
- final Rect bounds = win.getBounds();
- for (int index = sources.size() - 1; index >= 0; index--) {
- final InsetsSource source = sources.valueAt(index);
- if ((source.getType()
- & (Type.systemGestures() | Type.mandatorySystemGestures())) == 0) {
- continue;
- }
- if (mLeftGestureHost != null && mTopGestureHost != null
- && mRightGestureHost != null && mBottomGestureHost != null) {
- continue;
- }
- final Insets insets = source.calculateInsets(bounds, false /* ignoreVisibility */);
- if (mLeftGestureHost == null && insets.left > 0) {
- mLeftGestureHost = win;
- }
- if (mTopGestureHost == null && insets.top > 0) {
- mTopGestureHost = win;
- }
- if (mRightGestureHost == null && insets.right > 0) {
- mRightGestureHost = win;
- }
- if (mBottomGestureHost == null && insets.bottom > 0) {
- mBottomGestureHost = win;
+ if (win.hasInsetsSourceProvider()) {
+ final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
+ final Rect bounds = win.getBounds();
+ for (int index = providers.size() - 1; index >= 0; index--) {
+ final InsetsSourceProvider provider = providers.valueAt(index);
+ final InsetsSource source = provider.getSource();
+ if ((source.getType()
+ & (Type.systemGestures() | Type.mandatorySystemGestures())) == 0) {
+ continue;
+ }
+ if (mLeftGestureHost != null && mTopGestureHost != null
+ && mRightGestureHost != null && mBottomGestureHost != null) {
+ continue;
+ }
+ final Insets insets = source.calculateInsets(bounds, false /* ignoreVisibility */);
+ if (mLeftGestureHost == null && insets.left > 0) {
+ mLeftGestureHost = win;
+ }
+ if (mTopGestureHost == null && insets.top > 0) {
+ mTopGestureHost = win;
+ }
+ if (mRightGestureHost == null && insets.right > 0) {
+ mRightGestureHost = win;
+ }
+ if (mBottomGestureHost == null && insets.bottom > 0) {
+ mBottomGestureHost = win;
+ }
}
}
@@ -2171,14 +2186,27 @@
appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
freeformRootTaskVisible);
+ // Show immersive mode confirmation if needed.
+ final boolean wasImmersiveMode = mIsImmersiveMode;
+ final boolean isImmersiveMode = isImmersiveMode(win);
+ if (wasImmersiveMode != isImmersiveMode) {
+ mIsImmersiveMode = isImmersiveMode;
+ // The immersive confirmation window should be attached to the immersive window root.
+ final RootDisplayArea root = win.getRootDisplayArea();
+ final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId;
+ mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, isImmersiveMode,
+ mService.mPolicy.isUserSetupComplete(),
+ isNavBarEmpty(disableFlags));
+ }
+
+ // Show transient bars for panic if needed.
final boolean requestHideNavBar = !win.isRequestedVisible(Type.navigationBars());
final long now = SystemClock.uptimeMillis();
final boolean pendingPanic = mPendingPanicGestureUptime != 0
&& now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
final DisplayPolicy defaultDisplayPolicy =
mService.getDefaultDisplayContentLocked().getDisplayPolicy();
- if (pendingPanic && requestHideNavBar && win != mNotificationShade
- && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
+ if (pendingPanic && requestHideNavBar && isImmersiveMode
// TODO (b/111955725): Show keyguard presentation on all external displays
&& defaultDisplayPolicy.isKeyguardDrawComplete()) {
// The user performed the panic gesture recently, we're about to hide the bars,
@@ -2190,19 +2218,6 @@
}
}
- // update navigation bar
- boolean oldImmersiveMode = mLastImmersiveMode;
- boolean newImmersiveMode = isImmersiveMode(win);
- if (oldImmersiveMode != newImmersiveMode) {
- mLastImmersiveMode = newImmersiveMode;
- // The immersive confirmation window should be attached to the immersive window root.
- final RootDisplayArea root = win.getRootDisplayArea();
- final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId;
- mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, newImmersiveMode,
- mService.mPolicy.isUserSetupComplete(),
- isNavBarEmpty(disableFlags));
- }
-
return appearance;
}
@@ -2324,18 +2339,10 @@
if (win == null) {
return false;
}
- return getNavigationBar() != null
- && canHideNavigationBar()
- && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
- && win != getNotificationShade()
- && !win.isActivityTypeDream();
- }
-
- /**
- * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
- */
- private boolean canHideNavigationBar() {
- return hasNavigationBar();
+ if (win == getNotificationShade() || win.isActivityTypeDream()) {
+ return false;
+ }
+ return getInsetsPolicy().hasHiddenSources(Type.navigationBars());
}
private static boolean isNavBarEmpty(int systemUiFlags) {
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index bd82113..97dd291 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -26,8 +26,6 @@
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -41,8 +39,6 @@
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.res.Resources;
-import android.util.ArrayMap;
-import android.util.IntArray;
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
import android.view.InsetsAnimationControlImpl;
@@ -52,7 +48,6 @@
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
import android.view.InternalInsetsAnimationController;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
@@ -81,7 +76,6 @@
private final InsetsStateController mStateController;
private final DisplayContent mDisplayContent;
private final DisplayPolicy mPolicy;
- private final IntArray mShowingTransientTypes = new IntArray();
/** For resetting visibilities of insets sources. */
private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() {
@@ -95,7 +89,7 @@
return;
}
for (InsetsSourceControl control : controls) {
- if (mShowingTransientTypes.indexOf(control.getId()) != -1) {
+ if (isTransient(control.getType())) {
// The visibilities of transient bars will be handled with animations.
continue;
}
@@ -117,13 +111,16 @@
};
private WindowState mFocusedWin;
- private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
- private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
+ private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
+ private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
+ private @InsetsType int mShowingTransientTypes;
private boolean mAnimatingShown;
+
/**
* Let remote insets controller control system bars regardless of other settings.
*/
private boolean mRemoteInsetsControllerControlsSystemBars;
+
private final boolean mHideNavBarForKeyboard;
private final float[] mTmpFloat9 = new float[9];
@@ -178,37 +175,46 @@
mNavBar.updateVisibility(navControlTarget, Type.navigationBars());
}
- boolean isHidden(@InternalInsetsType int type) {
- final WindowContainerInsetsSourceProvider provider = mStateController
- .peekSourceProvider(type);
- return provider != null && provider.hasWindowContainer()
- && !provider.getSource().isVisible();
+ boolean hasHiddenSources(@InsetsType int types) {
+ final InsetsState state = mStateController.getRawInsetsState();
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if ((source.getType() & types) == 0) {
+ continue;
+ }
+ if (!source.getFrame().isEmpty() && !source.isVisible()) {
+ return true;
+ }
+ }
+ return false;
}
- void showTransient(@InternalInsetsType int[] types, boolean isGestureOnSystemBar) {
- boolean changed = false;
- for (int i = types.length - 1; i >= 0; i--) {
- final @InternalInsetsType int type = types[i];
- if (!isHidden(type)) {
+ void showTransient(@InsetsType int types, boolean isGestureOnSystemBar) {
+ @InsetsType int showingTransientTypes = mShowingTransientTypes;
+ final InsetsState rawState = mStateController.getRawInsetsState();
+ for (int i = rawState.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = rawState.sourceAt(i);
+ if (source.isVisible()) {
continue;
}
- if (mShowingTransientTypes.indexOf(type) != -1) {
+ final @InsetsType int type = source.getType();
+ if ((source.getType() & types) == 0) {
continue;
}
- mShowingTransientTypes.add(type);
- changed = true;
+ showingTransientTypes |= type;
}
- if (changed) {
+ if (mShowingTransientTypes != showingTransientTypes) {
+ mShowingTransientTypes = showingTransientTypes;
StatusBarManagerInternal statusBarManagerInternal =
mPolicy.getStatusBarManagerInternal();
if (statusBarManagerInternal != null) {
statusBarManagerInternal.showTransient(mDisplayContent.getDisplayId(),
- mShowingTransientTypes.toArray(), isGestureOnSystemBar);
+ showingTransientTypes, isGestureOnSystemBar);
}
updateBarControlTarget(mFocusedWin);
dispatchTransientSystemBarsVisibilityChanged(
mFocusedWin,
- isTransient(ITYPE_STATUS_BAR) || isTransient(ITYPE_NAVIGATION_BAR),
+ (showingTransientTypes & (Type.statusBars() | Type.navigationBars())) != 0,
isGestureOnSystemBar);
// The leashes can be created while updating bar control target. The surface transaction
@@ -224,7 +230,7 @@
}
void hideTransient() {
- if (mShowingTransientTypes.size() == 0) {
+ if (mShowingTransientTypes == 0) {
return;
}
@@ -235,20 +241,25 @@
startAnimation(false /* show */, () -> {
synchronized (mDisplayContent.mWmService.mGlobalLock) {
- for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+ final SparseArray<WindowContainerInsetsSourceProvider> providers =
+ mStateController.getSourceProviders();
+ for (int i = providers.size() - 1; i >= 0; i--) {
+ final WindowContainerInsetsSourceProvider provider = providers.valueAt(i);
+ if (!isTransient(provider.getSource().getType())) {
+ continue;
+ }
// We are about to clear mShowingTransientTypes, we don't want the transient bar
// can cause insets on the client. Restore the client visibility.
- final @InternalInsetsType int type = mShowingTransientTypes.get(i);
- mStateController.getSourceProvider(type).setClientVisible(false);
+ provider.setClientVisible(false);
}
- mShowingTransientTypes.clear();
+ mShowingTransientTypes = 0;
updateBarControlTarget(mFocusedWin);
}
});
}
- boolean isTransient(@InternalInsetsType int type) {
- return mShowingTransientTypes.indexOf(type) != -1;
+ boolean isTransient(@InsetsType int type) {
+ return (mShowingTransientTypes & type) != 0;
}
/**
@@ -280,9 +291,9 @@
? token.getFixedRotationTransformInsetsState()
: mStateController.getRawInsetsState();
outInsetsState.set(srcState, true /* copySources */);
- for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- final InsetsSource source = outInsetsState.peekSource(mShowingTransientTypes.get(i));
- if (source != null) {
+ for (int i = outInsetsState.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = outInsetsState.sourceAt(i);
+ if (isTransient(source.getType())) {
source.setVisible(false);
}
}
@@ -333,8 +344,8 @@
}
}
- final ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController
- .getSourceProviders();
+ final SparseArray<WindowContainerInsetsSourceProvider> providers =
+ mStateController.getSourceProviders();
final int windowType = attrs.type;
for (int i = providers.size() - 1; i >= 0; i--) {
final WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i);
@@ -365,18 +376,17 @@
private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) {
InsetsState state = originalState;
- for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- final @InternalInsetsType int type = mShowingTransientTypes.get(i);
- final InsetsSource originalSource = state.peekSource(type);
- if (originalSource != null && originalSource.isVisible()) {
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if (isTransient(source.getType()) && source.isVisible()) {
if (state == originalState) {
// The source will be modified, create a non-deep copy to store the new one.
state = new InsetsState(originalState);
}
// Replace the source with a copy in invisible state.
- final InsetsSource source = new InsetsSource(originalSource);
- source.setVisible(false);
- state.addSource(source);
+ final InsetsSource outSource = new InsetsSource(source);
+ outSource.setVisible(false);
+ state.addSource(outSource);
}
}
return state;
@@ -385,18 +395,23 @@
private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
boolean copyState) {
if (w.mIsImWindow) {
+ InsetsState state = originalState;
// If navigation bar is not hidden by IME, IME should always receive visible
// navigation bar insets.
final boolean navVisible = !mHideNavBarForKeyboard;
- final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
- if (originalNavSource != null && originalNavSource.isVisible() != navVisible) {
- final InsetsState state = copyState ? new InsetsState(originalState)
- : originalState;
- final InsetsSource navSource = new InsetsSource(originalNavSource);
+ for (int i = originalState.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = originalState.sourceAt(i);
+ if (source.getType() != Type.navigationBars() || source.isVisible() == navVisible) {
+ continue;
+ }
+ if (state == originalState && copyState) {
+ state = new InsetsState(originalState);
+ }
+ final InsetsSource navSource = new InsetsSource(source);
navSource.setVisible(navVisible);
state.addSource(navSource);
- return state;
}
+ return state;
} else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
// During switching tasks with gestural navigation, before the next IME input target
// starts the input, we should adjust and freeze the last IME visibility of the window
@@ -447,23 +462,22 @@
* @param caller who changed the insets state.
*/
private void checkAbortTransient(InsetsControlTarget caller) {
- if (mShowingTransientTypes.size() != 0) {
- final IntArray abortTypes = new IntArray();
- final boolean imeRequestedVisible = caller.isRequestedVisible(Type.ime());
- for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
- final @InternalInsetsType int type = mShowingTransientTypes.get(i);
- if ((mStateController.isFakeTarget(type, caller)
- && caller.isRequestedVisible(InsetsState.toPublicType(type)))
- || (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) {
- mShowingTransientTypes.remove(i);
- abortTypes.add(type);
- }
- }
- StatusBarManagerInternal statusBarManagerInternal =
- mPolicy.getStatusBarManagerInternal();
- if (abortTypes.size() > 0 && statusBarManagerInternal != null) {
- statusBarManagerInternal.abortTransient(
- mDisplayContent.getDisplayId(), abortTypes.toArray());
+ if (mShowingTransientTypes == 0) {
+ return;
+ }
+ final boolean isImeVisible = mStateController.getImeSourceProvider().isClientVisible();
+ final @InsetsType int fakeControllingTypes =
+ mStateController.getFakeControllingTypes(caller);
+ final @InsetsType int abortTypes =
+ (fakeControllingTypes & caller.getRequestedVisibleTypes())
+ | (isImeVisible ? Type.navigationBars() : 0);
+ mShowingTransientTypes &= ~abortTypes;
+ if (abortTypes != 0) {
+ mDisplayContent.setLayoutNeeded();
+ mDisplayContent.mWmService.requestTraversal();
+ final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal();
+ if (statusBarManager != null) {
+ statusBarManager.abortTransient(mDisplayContent.getDisplayId(), abortTypes);
}
}
}
@@ -473,12 +487,16 @@
* updateBarControlTarget(mFocusedWin) after this invocation.
*/
private void abortTransient() {
- StatusBarManagerInternal statusBarManagerInternal = mPolicy.getStatusBarManagerInternal();
- if (statusBarManagerInternal != null) {
- statusBarManagerInternal.abortTransient(
- mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray());
+ if (mShowingTransientTypes == 0) {
+ return;
}
- mShowingTransientTypes.clear();
+ final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal();
+ if (statusBarManager != null) {
+ statusBarManager.abortTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes);
+ }
+ mShowingTransientTypes = 0;
+ mDisplayContent.setLayoutNeeded();
+ mDisplayContent.mWmService.requestTraversal();
dispatchTransientSystemBarsVisibilityChanged(
mFocusedWin,
@@ -488,7 +506,7 @@
private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin,
boolean fake) {
- if (!fake && isShowingTransientTypes(Type.statusBars())) {
+ if (!fake && isTransient(Type.statusBars())) {
return mDummyControlTarget;
}
final WindowState notificationShade = mPolicy.getNotificationShade();
@@ -541,7 +559,7 @@
// configured to be hidden by the IME.
return null;
}
- if (!fake && isShowingTransientTypes(Type.navigationBars())) {
+ if (!fake && isTransient(Type.navigationBars())) {
return mDummyControlTarget;
}
if (focusedWin == mPolicy.getNotificationShade()) {
@@ -577,16 +595,6 @@
return focusedWin;
}
- private boolean isShowingTransientTypes(@InsetsType int types) {
- final IntArray showingTransientTypes = mShowingTransientTypes;
- for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
- if ((InsetsState.toPublicType(showingTransientTypes.get(i)) & types) != 0) {
- return true;
- }
- }
- return false;
- }
-
/**
* Determines whether the remote insets controller should take control of system bars for all
* windows.
@@ -622,21 +630,17 @@
@VisibleForTesting
void startAnimation(boolean show, Runnable callback) {
- int typesReady = 0;
- final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
- final IntArray showingTransientTypes = mShowingTransientTypes;
- for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
- final int sourceId = showingTransientTypes.get(i);
- final WindowContainerInsetsSourceProvider provider =
- mStateController.getSourceProvider(sourceId);
- final InsetsSourceControl control = provider.getControl(mDummyControlTarget);
- if (control == null || control.getLeash() == null) {
- continue;
+ @InsetsType int typesReady = 0;
+ final SparseArray<InsetsSourceControl> controlsReady = new SparseArray<>();
+ final InsetsSourceControl[] controls =
+ mStateController.getControlsForDispatch(mDummyControlTarget);
+ for (InsetsSourceControl control : controls) {
+ if (isTransient(control.getType()) && control.getLeash() != null) {
+ typesReady |= control.getType();
+ controlsReady.put(control.getId(), new InsetsSourceControl(control));
}
- typesReady |= control.getType();
- controls.put(sourceId, new InsetsSourceControl(control));
}
- controlAnimationUnchecked(typesReady, controls, show, callback);
+ controlAnimationUnchecked(typesReady, controlsReady, show, callback);
}
private void controlAnimationUnchecked(int typesReady,
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index f5af292..2b7a451 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -164,7 +164,7 @@
// TODO: Ideally, we should wait for the animation to finish so previous window can
// animate-out as new one animates-in.
mWindowContainer.cancelAnimation();
- mWindowContainer.getProvidedInsetsSources().remove(mSource.getId());
+ mWindowContainer.getInsetsSourceProviders().remove(mSource.getId());
mSeamlessRotating = false;
}
ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s",
@@ -180,7 +180,7 @@
mSource.setInsetsRoundedCornerFrame(false);
mSourceFrame.setEmpty();
} else {
- mWindowContainer.getProvidedInsetsSources().put(mSource.getId(), mSource);
+ mWindowContainer.getInsetsSourceProviders().put(mSource.getId(), this);
if (mControllable) {
mWindowContainer.setControllableInsetProvider(this);
if (mPendingControlTarget != null) {
@@ -192,13 +192,6 @@
}
/**
- * @return Whether there is a window container which backs this source.
- */
- boolean hasWindowContainer() {
- return mWindowContainer != null;
- }
-
- /**
* The source frame can affect the layout of other windows, so this should be called once the
* window container gets laid out.
*/
@@ -363,9 +356,9 @@
}
/**
- * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget)
+ * @see InsetsStateController#onControlTargetChanged
*/
- void updateControlForFakeTarget(@Nullable InsetsControlTarget fakeTarget) {
+ void updateFakeControlTarget(@Nullable InsetsControlTarget fakeTarget) {
if (fakeTarget == mFakeControlTarget) {
return;
}
@@ -570,6 +563,10 @@
return mControlTarget;
}
+ InsetsControlTarget getFakeControlTarget() {
+ return mFakeControlTarget;
+ }
+
boolean isClientVisible() {
return mClientVisible;
}
@@ -609,15 +606,15 @@
}
if (mControlTarget != null) {
pw.print(prefix + "mControlTarget=");
- pw.println(mControlTarget.getWindow());
+ pw.println(mControlTarget);
}
if (mPendingControlTarget != null) {
pw.print(prefix + "mPendingControlTarget=");
- pw.println(mPendingControlTarget.getWindow());
+ pw.println(mPendingControlTarget);
}
if (mFakeControlTarget != null) {
pw.print(prefix + "mFakeControlTarget=");
- pw.println(mFakeControlTarget.getWindow());
+ pw.println(mFakeControlTarget);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index a3f62b2..0e1e63e 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -18,10 +18,6 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
@@ -38,10 +34,11 @@
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets;
+import android.view.WindowInsets.Type.InsetsType;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -49,7 +46,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Manages global window inset state in the system represented by {@link InsetsState}.
@@ -60,14 +56,11 @@
private final InsetsState mState = new InsetsState();
private final DisplayContent mDisplayContent;
- private final ArrayMap<Integer, WindowContainerInsetsSourceProvider> mProviders =
- new ArrayMap<>();
- private final ArrayMap<InsetsControlTarget, ArrayList<Integer>> mControlTargetTypeMap =
- new ArrayMap<>();
- private final SparseArray<InsetsControlTarget> mTypeControlTargetMap = new SparseArray<>();
-
- /** @see #onControlFakeTargetChanged */
- private final SparseArray<InsetsControlTarget> mTypeFakeControlTargetMap = new SparseArray<>();
+ private final SparseArray<WindowContainerInsetsSourceProvider> mProviders = new SparseArray<>();
+ private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
+ mControlTargetProvidersMap = new ArrayMap<>();
+ private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>();
+ private final SparseArray<InsetsControlTarget> mIdFakeControlTargetMap = new SparseArray<>();
private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();
@@ -92,15 +85,8 @@
}
};
- private final Function<Integer, WindowContainerInsetsSourceProvider> mSourceProviderFunc;
-
InsetsStateController(DisplayContent displayContent) {
mDisplayContent = displayContent;
- mSourceProviderFunc = id -> (id == ID_IME)
- ? new ImeInsetsSourceProvider(mState.getOrCreateSource(
- id, ime()), this, mDisplayContent)
- : new WindowContainerInsetsSourceProvider(mState.getOrCreateSource(
- id, InsetsState.toPublicType(id)), this, mDisplayContent);
}
InsetsState getRawInsetsState() {
@@ -108,39 +94,55 @@
}
@Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) {
- ArrayList<Integer> controlled = mControlTargetTypeMap.get(target);
+ final ArrayList<InsetsSourceProvider> controlled = mControlTargetProvidersMap.get(target);
if (controlled == null) {
return null;
}
final int size = controlled.size();
final InsetsSourceControl[] result = new InsetsSourceControl[size];
for (int i = 0; i < size; i++) {
- result[i] = mProviders.get(controlled.get(i)).getControl(target);
+ result[i] = controlled.get(i).getControl(target);
}
return result;
}
- ArrayMap<Integer, WindowContainerInsetsSourceProvider> getSourceProviders() {
+ SparseArray<WindowContainerInsetsSourceProvider> getSourceProviders() {
return mProviders;
}
/**
* @return The provider of a specific source ID.
*/
- WindowContainerInsetsSourceProvider getSourceProvider(int id) {
- return mProviders.computeIfAbsent(id, mSourceProviderFunc);
+ WindowContainerInsetsSourceProvider getOrCreateSourceProvider(int id, @InsetsType int type) {
+ WindowContainerInsetsSourceProvider provider = mProviders.get(id);
+ if (provider != null) {
+ return provider;
+ }
+ final InsetsSource source = mState.getOrCreateSource(id, type);
+ provider = id == ID_IME
+ ? new ImeInsetsSourceProvider(source, this, mDisplayContent)
+ : new WindowContainerInsetsSourceProvider(source, this, mDisplayContent);
+ mProviders.put(id, provider);
+ return provider;
}
ImeInsetsSourceProvider getImeSourceProvider() {
- return (ImeInsetsSourceProvider) getSourceProvider(ID_IME);
+ return (ImeInsetsSourceProvider) getOrCreateSourceProvider(ID_IME, ime());
+ }
+
+ void removeSourceProvider(int id) {
+ if (id != ID_IME) {
+ mState.removeSource(id);
+ mProviders.remove(id);
+ }
}
/**
- * @return The provider of a specific type or null if we don't have it.
+ * @return The provider of a source ID or null if we don't have it.
*/
@Nullable
- WindowContainerInsetsSourceProvider peekSourceProvider(@InternalInsetsType int type) {
- return mProviders.get(type);
+ WindowContainerInsetsSourceProvider peekSourceProvider(int id) {
+ return mProviders.get(id);
}
/**
@@ -208,8 +210,16 @@
}
}
- boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) {
- return mTypeFakeControlTargetMap.get(type) == target;
+ @InsetsType int getFakeControllingTypes(InsetsControlTarget target) {
+ @InsetsType int types = 0;
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ final InsetsSourceProvider provider = mProviders.valueAt(i);
+ final InsetsControlTarget fakeControlTarget = provider.getFakeControlTarget();
+ if (target == fakeControlTarget) {
+ types |= provider.getSource().getType();
+ }
+ }
+ return types;
}
void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) {
@@ -217,7 +227,7 @@
// Make sure that we always have a control target for the IME, even if the IME target is
// null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible.
InsetsControlTarget target = imeTarget != null ? imeTarget : mEmptyImeControlTarget;
- onControlChanged(ID_IME, target);
+ onControlTargetChanged(getImeSourceProvider(), target, false /* fake */);
ProtoLog.d(WM_DEBUG_IME, "onImeControlTargetChanged %s",
target != null ? target.getWindow() : "null");
notifyPendingInsetsControlChanged();
@@ -235,101 +245,88 @@
@Nullable InsetsControlTarget fakeStatusControlling,
@Nullable InsetsControlTarget navControlling,
@Nullable InsetsControlTarget fakeNavControlling) {
- onControlChanged(ITYPE_STATUS_BAR, statusControlling);
- onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
- onControlChanged(ITYPE_CLIMATE_BAR, statusControlling);
- onControlChanged(ITYPE_EXTRA_NAVIGATION_BAR, navControlling);
- onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
- onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
- onControlFakeTargetChanged(ITYPE_CLIMATE_BAR, fakeStatusControlling);
- onControlFakeTargetChanged(ITYPE_EXTRA_NAVIGATION_BAR, fakeNavControlling);
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ final InsetsSourceProvider provider = mProviders.valueAt(i);
+ final @InsetsType int type = provider.getSource().getType();
+ if (type == WindowInsets.Type.statusBars()) {
+ onControlTargetChanged(provider, statusControlling, false /* fake */);
+ onControlTargetChanged(provider, fakeStatusControlling, true /* fake */);
+ } else if (type == WindowInsets.Type.navigationBars()) {
+ onControlTargetChanged(provider, navControlling, false /* fake */);
+ onControlTargetChanged(provider, fakeNavControlling, true /* fake */);
+ }
+ }
notifyPendingInsetsControlChanged();
}
void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget,
InsetsSourceProvider provider) {
- removeFromControlMaps(previousControlTarget, provider.getSource().getId(),
- false /* fake */);
+ removeFromControlMaps(previousControlTarget, provider, false /* fake */);
}
- private void onControlChanged(@InternalInsetsType int type,
- @Nullable InsetsControlTarget target) {
- final InsetsControlTarget previous = mTypeControlTargetMap.get(type);
- if (target == previous) {
- return;
- }
- final WindowContainerInsetsSourceProvider provider = mProviders.get(type);
- if (provider == null) {
+ private void onControlTargetChanged(InsetsSourceProvider provider,
+ @Nullable InsetsControlTarget target, boolean fake) {
+ final InsetsControlTarget lastTarget = fake
+ ? mIdFakeControlTargetMap.get(provider.getSource().getId())
+ : mIdControlTargetMap.get(provider.getSource().getId());
+ if (target == lastTarget) {
return;
}
if (!provider.isControllable()) {
return;
}
- provider.updateControlForTarget(target, false /* force */);
- target = provider.getControlTarget();
- if (previous != null) {
- removeFromControlMaps(previous, type, false /* fake */);
- mPendingControlChanged.add(previous);
+ if (fake) {
+ // The fake target updated here will be used to pretend to the app that it's still under
+ // control of the bars while it's not really, but we still need to find out the apps
+ // intentions around showing/hiding. For example, when the transient bars are showing,
+ // and the fake target requests to show system bars, the transient state will be
+ // aborted.
+ provider.updateFakeControlTarget(target);
+ } else {
+ provider.updateControlForTarget(target, false /* force */);
+
+ // Get control target again in case the provider didn't accept the one we passed to it.
+ target = provider.getControlTarget();
+ if (target == lastTarget) {
+ return;
+ }
+ }
+ if (lastTarget != null) {
+ removeFromControlMaps(lastTarget, provider, fake);
+ mPendingControlChanged.add(lastTarget);
}
if (target != null) {
- addToControlMaps(target, type, false /* fake */);
+ addToControlMaps(target, provider, fake);
mPendingControlChanged.add(target);
}
}
- /**
- * The fake target saved here will be used to pretend to the app that it's still under control
- * of the bars while it's not really, but we still need to find out the apps intentions around
- * showing/hiding. For example, when the transient bars are showing, and the fake target
- * requests to show system bars, the transient state will be aborted.
- */
- void onControlFakeTargetChanged(@InternalInsetsType int type,
- @Nullable InsetsControlTarget fakeTarget) {
- final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type);
- if (fakeTarget == previous) {
- return;
- }
- final WindowContainerInsetsSourceProvider provider = mProviders.get(type);
- if (provider == null) {
- return;
- }
- provider.updateControlForFakeTarget(fakeTarget);
- if (previous != null) {
- removeFromControlMaps(previous, type, true /* fake */);
- mPendingControlChanged.add(previous);
- }
- if (fakeTarget != null) {
- addToControlMaps(fakeTarget, type, true /* fake */);
- mPendingControlChanged.add(fakeTarget);
- }
- }
-
private void removeFromControlMaps(@NonNull InsetsControlTarget target,
- @InternalInsetsType int type, boolean fake) {
- final ArrayList<Integer> array = mControlTargetTypeMap.get(target);
+ InsetsSourceProvider provider, boolean fake) {
+ final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.get(target);
if (array == null) {
return;
}
- array.remove((Integer) type);
+ array.remove(provider);
if (array.isEmpty()) {
- mControlTargetTypeMap.remove(target);
+ mControlTargetProvidersMap.remove(target);
}
if (fake) {
- mTypeFakeControlTargetMap.remove(type);
+ mIdFakeControlTargetMap.remove(provider.getSource().getId());
} else {
- mTypeControlTargetMap.remove(type);
+ mIdControlTargetMap.remove(provider.getSource().getId());
}
}
private void addToControlMaps(@NonNull InsetsControlTarget target,
- @InternalInsetsType int type, boolean fake) {
- final ArrayList<Integer> array = mControlTargetTypeMap.computeIfAbsent(target,
- key -> new ArrayList<>());
- array.add(type);
+ InsetsSourceProvider provider, boolean fake) {
+ final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.computeIfAbsent(
+ target, key -> new ArrayList<>());
+ array.add(provider);
if (fake) {
- mTypeFakeControlTargetMap.put(type, target);
+ mIdFakeControlTargetMap.put(provider.getSource().getId(), target);
} else {
- mTypeControlTargetMap.put(type, target);
+ mIdControlTargetMap.put(provider.getSource().getId(), target);
}
}
@@ -351,7 +348,7 @@
for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
controlTarget.notifyInsetsControlChanged();
- if (mControlTargetTypeMap.containsKey(controlTarget)) {
+ if (mControlTargetProvidersMap.containsKey(controlTarget)) {
// We only collect targets who get controls, not lose controls.
newControlTargets.add(controlTarget);
}
@@ -377,10 +374,25 @@
prefix = prefix + " ";
mState.dump(prefix, pw);
pw.println(prefix + "Control map:");
- for (int i = mTypeControlTargetMap.size() - 1; i >= 0; i--) {
+ for (int i = mControlTargetProvidersMap.size() - 1; i >= 0; i--) {
+ final InsetsControlTarget controlTarget = mControlTargetProvidersMap.keyAt(i);
pw.print(prefix + " ");
- pw.println(InsetsState.typeToString(mTypeControlTargetMap.keyAt(i)) + " -> "
- + mTypeControlTargetMap.valueAt(i));
+ pw.print(controlTarget);
+ pw.println(":");
+ final ArrayList<InsetsSourceProvider> providers = mControlTargetProvidersMap.valueAt(i);
+ for (int j = providers.size() - 1; j >= 0; j--) {
+ final InsetsSourceProvider provider = providers.get(j);
+ if (provider != null) {
+ pw.print(prefix + " ");
+ if (controlTarget == provider.getFakeControlTarget()) {
+ pw.print("(fake) ");
+ }
+ pw.println(provider.getControl(controlTarget));
+ }
+ }
+ }
+ if (mControlTargetProvidersMap.isEmpty()) {
+ pw.print(prefix + " none");
}
pw.println(prefix + "InsetsSourceProviders:");
for (int i = mProviders.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ee11f68..1e53cc3 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -149,7 +149,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
-import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
@@ -171,6 +170,7 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
+import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.RemoteAnimationAdapter;
import android.view.Surface;
@@ -2833,14 +2833,13 @@
void adjustAnimationBoundsForTransition(Rect animationBounds) {
TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
if (spec != null) {
- for (@InsetsState.InternalInsetsType int insetType : spec.animationBoundInsets) {
- WindowContainerInsetsSourceProvider insetProvider = getDisplayContent()
- .getInsetsStateController()
- .getSourceProvider(insetType);
-
- Insets insets = insetProvider.getSource().calculateVisibleInsets(
- animationBounds);
- animationBounds.inset(insets);
+ final InsetsState state =
+ getDisplayContent().getInsetsStateController().getRawInsetsState();
+ for (int id : spec.animationBoundInsets) {
+ final InsetsSource source = state.peekSource(id);
+ if (source != null) {
+ animationBounds.inset(source.calculateVisibleInsets(animationBounds));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index b06bdb1..7173980 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -170,9 +170,9 @@
protected InsetsSourceProvider mControllableInsetProvider;
/**
- * The insets sources provided by this windowContainer.
+ * The {@link InsetsSourceProvider}s provided by this window container.
*/
- protected SparseArray<InsetsSource> mProvidedInsetsSources = null;
+ protected SparseArray<InsetsSourceProvider> mInsetsSourceProviders = null;
// List of children for this window container. List is in z-order as the children appear on
// screen with the top-most window container at the tail of the list.
@@ -366,7 +366,7 @@
* {@link WindowState#mMergedLocalInsetsSources} by visiting the entire hierarchy.
*
* {@link WindowState#mAboveInsetsState} is updated by visiting all the windows in z-order
- * top-to-bottom manner and considering the {@link WindowContainer#mProvidedInsetsSources}
+ * top-to-bottom manner and considering the {@link WindowContainer#mInsetsSourceProviders}
* provided by the {@link WindowState}s at the top.
* {@link WindowState#updateAboveInsetsState(InsetsState, SparseArray, ArraySet)} visits the
* IME container in the correct order to make sure the IME insets are passed correctly to the
@@ -1035,11 +1035,21 @@
}
}
- public SparseArray<InsetsSource> getProvidedInsetsSources() {
- if (mProvidedInsetsSources == null) {
- mProvidedInsetsSources = new SparseArray<>();
+ /**
+ * Returns {@code true} if this node provides insets.
+ */
+ public boolean hasInsetsSourceProvider() {
+ return mInsetsSourceProviders != null;
+ }
+
+ /**
+ * Returns {@link InsetsSourceProvider}s provided by this node.
+ */
+ public SparseArray<InsetsSourceProvider> getInsetsSourceProviders() {
+ if (mInsetsSourceProviders == null) {
+ mInsetsSourceProviders = new SparseArray<>();
}
- return mProvidedInsetsSources;
+ return mInsetsSourceProviders;
}
public DisplayContent getDisplayContent() {
@@ -4102,13 +4112,13 @@
}
}
- private void hideInsetSourceViewOverflows(Set<Integer> insetTypes) {
- final ArrayList<SurfaceControl> surfaceControls =
- new ArrayList<>(insetTypes.size());
-
- for (int insetType : insetTypes) {
- WindowContainerInsetsSourceProvider insetProvider = getDisplayContent()
- .getInsetsStateController().getSourceProvider(insetType);
+ private void hideInsetSourceViewOverflows(Set<Integer> sourceIds) {
+ final InsetsStateController controller = getDisplayContent().getInsetsStateController();
+ for (int id : sourceIds) {
+ final InsetsSourceProvider insetProvider = controller.peekSourceProvider(id);
+ if (insetProvider == null) {
+ return;
+ }
// Will apply it immediately to current leash and to all future inset animations
// until we disable it.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7b880fe..e8aa38e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1392,15 +1392,18 @@
}
void updateSourceFrame(Rect winFrame) {
+ if (!hasInsetsSourceProvider()) {
+ // This window doesn't provide any insets.
+ return;
+ }
if (mGivenInsetsPending) {
// The given insets are pending, and they are not reliable for now. The source frame
// should be updated after the new given insets are sent to window manager.
return;
}
- final SparseArray<InsetsSource> providedSources = getProvidedInsetsSources();
- final InsetsStateController controller = getDisplayContent().getInsetsStateController();
- for (int i = providedSources.size() - 1; i >= 0; i--) {
- controller.getSourceProvider(providedSources.keyAt(i)).updateSourceFrame(winFrame);
+ final SparseArray<InsetsSourceProvider> providers = getInsetsSourceProviders();
+ for (int i = providers.size() - 1; i >= 0; i--) {
+ providers.valueAt(i).updateSourceFrame(winFrame);
}
}
@@ -1879,11 +1882,11 @@
}
boolean providesNonDecorInsets() {
- if (mProvidedInsetsSources == null) {
+ if (mInsetsSourceProviders == null) {
return false;
}
- for (int i = mProvidedInsetsSources.size() - 1; i >= 0; i--) {
- final InsetsSource source = mProvidedInsetsSources.valueAt(i);
+ for (int i = mInsetsSourceProviders.size() - 1; i >= 0; i--) {
+ final InsetsSource source = mInsetsSourceProviders.valueAt(i).getSource();
if (source.getType() == WindowInsets.Type.navigationBars()) {
return true;
}
@@ -4840,10 +4843,10 @@
insetsChangedWindows.add(w);
}
- final SparseArray<InsetsSource> providedSources = w.mProvidedInsetsSources;
- if (providedSources != null) {
- for (int i = providedSources.size() - 1; i >= 0; i--) {
- aboveInsetsState.addSource(providedSources.valueAt(i));
+ final SparseArray<InsetsSourceProvider> providers = w.mInsetsSourceProviders;
+ if (providers != null) {
+ for (int i = providers.size() - 1; i >= 0; i--) {
+ aboveInsetsState.addSource(providers.valueAt(i).getSource());
}
}
}, true /* traverseTopToBottom */);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 99f7905..e605a31 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -35,6 +35,7 @@
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
+import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
@@ -364,6 +365,16 @@
showHideOverlay(c -> c.onLockoutPermanent());
}
+ @Test
+ public void testPowerPressForwardsErrorMessage() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient();
+
+ client.onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR,
+ BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED);
+
+ verify(mClientMonitorCallbackConverter).onError(anyInt(), anyInt(),
+ eq(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED), eq(0));
+ }
private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
throws RemoteException {
final FingerprintAuthenticationClient client = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 26524d7..a40d3fe 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -16,8 +16,6 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
-import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED;
-
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -29,6 +27,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.biometrics.fingerprint.PointerContext;
@@ -276,11 +275,12 @@
@Test
public void testPowerPressForwardsAcquireMessage() throws RemoteException {
final FingerprintEnrollClient client = createClient();
- client.start(mCallback);
- client.onPowerPressed();
+
+ client.onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR,
+ BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED);
verify(mClientMonitorCallbackConverter).onAcquired(anyInt(),
- eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt());
+ eq(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED), eq(0));
}
private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 56d59b4..e5fe32a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3177,7 +3177,7 @@
public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- mDisplayContent.getInsetsStateController().getSourceProvider(ID_IME).setWindowContainer(
+ mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
mImeWindow, null, null);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
@@ -3222,7 +3222,7 @@
final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
- mDisplayContent.getInsetsStateController().getSourceProvider(ID_IME).setWindowContainer(
+ mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
mImeWindow, null, null);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
@@ -3288,7 +3288,7 @@
makeWindowVisibleAndDrawn(app1, app2);
final InsetsStateController controller = mDisplayContent.getInsetsStateController();
- controller.getSourceProvider(ID_IME).setWindowContainer(
+ controller.getImeSourceProvider().setWindowContainer(
ime, null, null);
ime.getControllableInsetProvider().setServerVisible(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 45cf530..6656f4c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -163,19 +163,20 @@
InsetsStateController controller = mDisplayContent.getInsetsStateController();
controller.onPostLayout();
- InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR);
+ InsetsSourceProvider statusBarProvider = controller.peekSourceProvider(ITYPE_STATUS_BAR);
assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame());
assertEquals(Insets.of(0, 100, 0, 0),
statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
false /* ignoreVisibility */));
- InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES);
+ InsetsSourceProvider topGesturesProvider = controller.peekSourceProvider(
+ ITYPE_TOP_GESTURES);
assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame());
assertEquals(Insets.of(0, 100, 0, 0),
topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
false /* ignoreVisibility */));
- InsetsSourceProvider navigationBarProvider = controller.getSourceProvider(
+ InsetsSourceProvider navigationBarProvider = controller.peekSourceProvider(
ITYPE_NAVIGATION_BAR);
assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame());
}
@@ -194,7 +195,7 @@
mDisplayContent.getInsetsStateController().onPostLayout();
InsetsSourceProvider provider =
- mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR);
+ mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_STATUS_BAR);
// In the new flexible insets setup, the insets frame should always respect the window
// layout result.
assertEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index dba2995..1a126cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -280,8 +280,7 @@
assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
.isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
- policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
- true /* isGestureOnSystemBar */);
+ policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */);
waitUntilWindowAnimatorIdle();
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -308,11 +307,11 @@
spyOn(policy);
doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(mAppWindow);
- policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+ policy.showTransient(navigationBars() | statusBars(),
true /* isGestureOnSystemBar */);
waitUntilWindowAnimatorIdle();
- assertTrue(policy.isTransient(ITYPE_STATUS_BAR));
- assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+ assertTrue(policy.isTransient(statusBars()));
+ assertFalse(policy.isTransient(navigationBars()));
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -344,7 +343,7 @@
spyOn(policy);
doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(mAppWindow);
- policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+ policy.showTransient(navigationBars() | statusBars(),
true /* isGestureOnSystemBar */);
waitUntilWindowAnimatorIdle();
InsetsSourceControl[] controls =
@@ -393,13 +392,13 @@
spyOn(policy);
doNothing().when(policy).startAnimation(anyBoolean(), any());
policy.updateBarControlTarget(app);
- policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+ policy.showTransient(navigationBars() | statusBars(),
true /* isGestureOnSystemBar */);
final InsetsSourceControl[] controls =
mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
policy.updateBarControlTarget(app2);
- assertFalse(policy.isTransient(ITYPE_STATUS_BAR));
- assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+ assertFalse(policy.isTransient(statusBars()));
+ assertFalse(policy.isTransient(navigationBars()));
}
private WindowState addNavigationBar() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 88ecd3f..74fde65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -20,11 +20,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -49,6 +46,7 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
+import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -64,6 +62,15 @@
@RunWith(WindowTestRunner.class)
public class InsetsStateControllerTest extends WindowTestsBase {
+ private static final int ID_STATUS_BAR =
+ InsetsSource.createId(null /* owner */, 0 /* index */, statusBars());
+ private static final int ID_NAVIGATION_BAR =
+ InsetsSource.createId(null /* owner */, 0 /* index */, navigationBars());
+ private static final int ID_CLIMATE_BAR =
+ InsetsSource.createId(null /* owner */, 1 /* index */, statusBars());
+ private static final int ID_EXTRA_NAVIGATION_BAR =
+ InsetsSource.createId(null /* owner */, 1 /* index */, navigationBars());
+
@Test
public void testStripForDispatch_navBar() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
@@ -73,14 +80,15 @@
// IME cannot be the IME target.
ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
- getController().getSourceProvider(ID_IME).setWindowContainer(ime, null, null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(ime, null, null);
assertNull(navBar.getInsetsState().peekSource(ID_IME));
- assertNull(navBar.getInsetsState().peekSource(ITYPE_STATUS_BAR));
+ assertNull(navBar.getInsetsState().peekSource(ID_STATUS_BAR));
}
@Test
@@ -89,14 +97,14 @@
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
app.setWindowingMode(WINDOWING_MODE_PINNED);
- assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
- assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
assertNull(app.getInsetsState().peekSource(ID_IME));
}
@@ -106,14 +114,14 @@
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
app.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
- assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
}
@Test
@@ -122,21 +130,22 @@
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
app.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
app.setAlwaysOnTop(true);
- assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
- assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
}
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testStripForDispatch_independentSources() {
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
@@ -151,7 +160,8 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testStripForDispatch_belowIme() {
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mAboveInsetsState.getOrCreateSource(ID_IME, ime())
@@ -165,7 +175,8 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testStripForDispatch_aboveIme() {
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
@@ -184,7 +195,8 @@
// Make IME and stay visible during the test.
mImeWindow.setHasSurface(true);
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
getController().onImeControlTargetChanged(
mDisplayContent.getImeInputTarget().getWindowState());
mDisplayContent.getImeInputTarget().getWindowState().setRequestedVisibleTypes(ime(), ime());
@@ -228,7 +240,8 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testStripForDispatch_childWindow_altFocusable() {
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
@@ -248,7 +261,8 @@
@SetupWindows(addWindows = W_INPUT_METHOD)
@Test
public void testStripForDispatch_childWindow_splitScreen() {
- getController().getSourceProvider(ID_IME).setWindowContainer(mImeWindow, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
@@ -274,20 +288,21 @@
ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
WindowContainerInsetsSourceProvider statusBarProvider =
- getController().getSourceProvider(ITYPE_STATUS_BAR);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars());
final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverrideProviders =
new SparseArray<>();
imeOverrideProviders.put(TYPE_INPUT_METHOD, ((displayFrames, windowState, rect) ->
rect.set(0, 1, 2, 3)));
statusBarProvider.setWindowContainer(statusBar, null, imeOverrideProviders);
- getController().getSourceProvider(ID_IME).setWindowContainer(ime, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(ime, null, null);
statusBar.setControllableInsetProvider(statusBarProvider);
statusBar.updateSourceFrame(statusBar.getFrame());
statusBarProvider.onPostLayout();
final InsetsState state = ime.getInsetsState();
- assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_STATUS_BAR).getFrame());
+ assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ID_STATUS_BAR).getFrame());
}
@Test
@@ -297,15 +312,14 @@
final WindowState climateBar = createWindow(null, TYPE_APPLICATION, "climateBar");
final WindowState extraNavBar = createWindow(null, TYPE_APPLICATION, "extraNavBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
- getController().getSourceProvider(ITYPE_CLIMATE_BAR).setWindowContainer(climateBar, null,
- null);
- getController().getSourceProvider(ITYPE_EXTRA_NAVIGATION_BAR).setWindowContainer(
- extraNavBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
+ getController().getOrCreateSourceProvider(ID_CLIMATE_BAR, statusBars())
+ .setWindowContainer(climateBar, null, null);
+ getController().getOrCreateSourceProvider(ID_EXTRA_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(extraNavBar, null, null);
getController().onBarControlTargetChanged(app, null, app, null);
InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
assertEquals(4, controls.length);
@@ -315,8 +329,8 @@
public void testControlRevoked() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
getController().onBarControlTargetChanged(app, null, null, null);
assertNotNull(getController().getControlsForDispatch(app));
getController().onBarControlTargetChanged(null, null, null, null);
@@ -327,8 +341,8 @@
public void testControlRevoked_animation() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
getController().onBarControlTargetChanged(app, null, null, null);
assertNotNull(getController().getControlsForDispatch(app));
statusBar.cancelAnimation();
@@ -340,22 +354,22 @@
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowContainerInsetsSourceProvider provider = getController()
- .getSourceProvider(ITYPE_STATUS_BAR);
+ .getOrCreateSourceProvider(ID_STATUS_BAR, statusBars());
provider.setWindowContainer(statusBar, null, null);
final InsetsState rotatedState = new InsetsState(app.getInsetsState(),
true /* copySources */);
- rotatedState.getOrCreateSource(ITYPE_STATUS_BAR, statusBars());
+ rotatedState.getOrCreateSource(ID_STATUS_BAR, statusBars());
spyOn(app.mToken);
doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
- assertTrue(rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+ assertTrue(rotatedState.isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
provider.getSource().setVisible(false);
- mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR },
+ mDisplayContent.getInsetsPolicy().showTransient(statusBars(),
true /* isGestureOnSystemBar */);
- assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
- assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+ assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars()));
+ assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
}
@Test
@@ -364,18 +378,18 @@
final WindowState statusBar = createTestWindow("statusBar");
final WindowState navBar = createTestWindow("navBar");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
- assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(statusBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(navBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
getController().updateAboveInsetsState(true /* notifyInsetsChange */);
- assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNotNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(statusBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(navBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
verify(app, atLeastOnce()).notifyInsetsChanged();
}
@@ -386,18 +400,18 @@
final WindowState statusBar = createTestWindow("statusBar");
final WindowState navBar = createTestWindow("navBar");
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
- assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(app.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
getController().updateAboveInsetsState(true /* notifyInsetsChange */);
- assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+ assertNotNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNotNull(app.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
verify(app, atLeastOnce()).notifyInsetsChanged();
}
@@ -409,19 +423,21 @@
final WindowState statusBar = createTestWindow("statusBar");
final WindowState navBar = createTestWindow("navBar");
- getController().getSourceProvider(ID_IME).setWindowContainer(ime, null, null);
+ final InsetsSourceProvider imeSourceProvider =
+ getController().getOrCreateSourceProvider(ID_IME, ime());
+ imeSourceProvider.setWindowContainer(ime, null, null);
waitUntilHandlersIdle();
clearInvocations(mDisplayContent);
- getController().getSourceProvider(ID_IME).setClientVisible(true);
+ imeSourceProvider.setClientVisible(true);
waitUntilHandlersIdle();
// The visibility change should trigger a traversal to notify the change.
verify(mDisplayContent).notifyInsetsChanged(any());
- getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
- null);
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+ .setWindowContainer(statusBar, null, null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
getController().updateAboveInsetsState(false /* notifyInsetsChange */);
@@ -429,8 +445,8 @@
assertNull(app.mAboveInsetsState.peekSource(ID_IME));
assertNull(statusBar.mAboveInsetsState.peekSource(ID_IME));
assertNull(navBar.mAboveInsetsState.peekSource(ID_IME));
- assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+ assertNotNull(ime.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNotNull(ime.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
ime.getParent().positionChildAt(POSITION_TOP, ime, true /* includingParents */);
getController().updateAboveInsetsState(true /* notifyInsetsChange */);
@@ -439,8 +455,8 @@
assertNotNull(app.mAboveInsetsState.peekSource(ID_IME));
assertNotNull(statusBar.mAboveInsetsState.peekSource(ID_IME));
assertNotNull(navBar.mAboveInsetsState.peekSource(ID_IME));
- assertNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
- assertNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(ime.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+ assertNull(ime.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
verify(ime, atLeastOnce()).notifyInsetsChanged();
verify(app, atLeastOnce()).notifyInsetsChanged();
@@ -454,7 +470,8 @@
final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, imeToken, "ime");
final WindowState app = createTestWindow("app");
- getController().getSourceProvider(ID_IME).setWindowContainer(ime, null, null);
+ getController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(ime, null, null);
ime.getControllableInsetProvider().setServerVisible(true);
app.mActivityRecord.setVisibility(true);
@@ -489,12 +506,12 @@
@Test
public void testDispatchGlobalInsets() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
- getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
- null);
+ getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+ .setWindowContainer(navBar, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
app.mAttrs.receiveInsetsIgnoringZOrder = true;
- assertNotNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+ assertNotNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
}
@SetupWindows(addWindows = W_INPUT_METHOD)
@@ -504,7 +521,8 @@
final WindowState app2 = createTestWindow("app2");
makeWindowVisible(mImeWindow);
- final InsetsSourceProvider imeInsetsProvider = getController().getSourceProvider(ID_IME);
+ final InsetsSourceProvider imeInsetsProvider =
+ getController().getOrCreateSourceProvider(ID_IME, ime());
imeInsetsProvider.setWindowContainer(mImeWindow, null, null);
imeInsetsProvider.updateSourceFrame(mImeWindow.getFrame());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
index 1e5ec4c..7d13de8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
@@ -170,10 +170,10 @@
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
statusBar.getFrame().set(0, 0, 500, 100);
mProvider.setWindowContainer(statusBar, null, null);
- mProvider.updateControlForFakeTarget(target);
+ mProvider.updateFakeControlTarget(target);
assertNotNull(mProvider.getControl(target));
assertNull(mProvider.getControl(target).getLeash());
- mProvider.updateControlForFakeTarget(null);
+ mProvider.updateFakeControlTarget(null);
assertNull(mProvider.getControl(target));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index c44869b..17b44ee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -437,13 +437,15 @@
final WindowState app = mAppWindow;
statusBar.mHasSurface = true;
assertTrue(statusBar.isVisible());
- mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
+ mDisplayContent.getInsetsStateController()
+ .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
.setWindowContainer(statusBar, null /* frameProvider */,
null /* imeFrameProvider */);
mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
app.setRequestedVisibleTypes(0, statusBars());
- mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
+ mDisplayContent.getInsetsStateController()
+ .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
.updateClientVisibility(app);
waitUntilHandlersIdle();
assertFalse(statusBar.isVisible());
@@ -1169,8 +1171,8 @@
mNotificationShadeWindow.setHasSurface(true);
mNotificationShadeWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
assertTrue(mNotificationShadeWindow.canBeImeTarget());
- mDisplayContent.getInsetsStateController().getSourceProvider(ID_IME).setWindowContainer(
- mImeWindow, null, null);
+ mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(ID_IME, ime())
+ .setWindowContainer(mImeWindow, null, null);
mDisplayContent.computeImeTarget(true);
assertEquals(mNotificationShadeWindow, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index bd63560..714eb4b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -39,6 +39,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets;
import android.window.WindowContext;
import androidx.test.filters.SmallTest;
@@ -262,8 +263,9 @@
@Test
public void testSetInsetsFrozen_notAffectImeWindowState() {
// Pre-condition: make the IME window be controlled by IME insets provider.
- mDisplayContent.getInsetsStateController().getSourceProvider(ID_IME).setWindowContainer(
- mDisplayContent.mInputMethodWindow, null, null);
+ mDisplayContent.getInsetsStateController()
+ .getOrCreateSourceProvider(ID_IME, WindowInsets.Type.ime())
+ .setWindowContainer(mDisplayContent.mInputMethodWindow, null, null);
// Simulate an app window to be the IME layering target, assume the app window has no
// frozen insets state by default.
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7c86a75a..20564d6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -951,6 +951,23 @@
public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
/**
+ * Intent action to trigger "switch to managed profile" dialog for call in SystemUI
+ *
+ * @hide
+ */
+ public static final String ACTION_SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG =
+ "android.telecom.action.SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG";
+
+ /**
+ * Extra specifying the managed profile user id.
+ * This is used with {@link TelecomManager#ACTION_SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG}
+ *
+ * @hide
+ */
+ public static final String EXTRA_MANAGED_PROFILE_USER_ID =
+ "android.telecom.extra.MANAGED_PROFILE_USER_ID";
+
+ /**
* Indicating the call is initiated via emergency dialer's shortcut button.
*
* @hide