Merge "Ambient wallpaper API feedback"
diff --git a/api/current.txt b/api/current.txt
index 7c32ef0..1b5b3ee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -480,6 +480,10 @@
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
+ field public static final int dataRetentionTime = 16844189; // 0x101059d
+ field public static final int dataSentOffDevice = 16844186; // 0x101059a
+ field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b
+ field public static final int dataUsedForMonetization = 16844188; // 0x101059c
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -1495,6 +1499,7 @@
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int usageInfoRequired = 16844185; // 0x1010599
field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useAppZygote = 16844184; // 0x1010598
field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -3802,6 +3807,7 @@
method public void overridePendingTransition(int, int);
method public void postponeEnterTransition();
method public void recreate();
+ method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
method public void registerForContextMenu(android.view.View);
method public boolean releaseInstance();
method public final deprecated void removeDialog(int);
@@ -3879,6 +3885,7 @@
method public deprecated void stopManagingCursor(android.database.Cursor);
method public void takeKeyEvents(boolean);
method public void triggerSearch(java.lang.String, android.os.Bundle);
+ method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
method public void unregisterForContextMenu(android.view.View);
field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
field public static final int DEFAULT_KEYS_DISABLE = 0; // 0x0
@@ -11169,8 +11176,8 @@
field public android.content.pm.ProviderInfo[] providers;
field public android.content.pm.ActivityInfo[] receivers;
field public android.content.pm.FeatureInfo[] reqFeatures;
- field public java.lang.String[] requestedPermissions;
- field public int[] requestedPermissionsFlags;
+ field public deprecated java.lang.String[] requestedPermissions;
+ field public deprecated int[] requestedPermissionsFlags;
field public android.content.pm.ServiceInfo[] services;
field public java.lang.String sharedUserId;
field public int sharedUserLabel;
@@ -11178,6 +11185,7 @@
field public android.content.pm.SigningInfo signingInfo;
field public java.lang.String[] splitNames;
field public int[] splitRevisionCodes;
+ field public android.content.pm.UsesPermissionInfo[] usesPermissions;
field public deprecated int versionCode;
field public java.lang.String versionName;
}
@@ -11653,6 +11661,7 @@
field public java.lang.String group;
field public java.lang.CharSequence nonLocalizedDescription;
field public deprecated int protectionLevel;
+ field public boolean usageInfoRequired;
}
public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
@@ -11832,6 +11841,28 @@
field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR;
}
+ public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDataRetention();
+ method public int getDataRetentionWeeks();
+ method public int getDataSentOffDevice();
+ method public int getDataSharedWithThirdParty();
+ method public int getDataUsedForMonetization();
+ method public int getFlags();
+ method public java.lang.String getPermission();
+ field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR;
+ field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+ field public static final int RETENTION_NOT_RETAINED = 1; // 0x1
+ field public static final int RETENTION_SPECIFIED = 4; // 0x4
+ field public static final int RETENTION_UNDEFINED = 0; // 0x0
+ field public static final int RETENTION_UNLIMITED = 3; // 0x3
+ field public static final int RETENTION_USER_SELECTED = 2; // 0x2
+ field public static final int USAGE_NO = 3; // 0x3
+ field public static final int USAGE_UNDEFINED = 0; // 0x0
+ field public static final int USAGE_USER_TRIGGERED = 2; // 0x2
+ field public static final int USAGE_YES = 1; // 0x1
+ }
+
public final class VersionedPackage implements android.os.Parcelable {
ctor public VersionedPackage(java.lang.String, int);
ctor public VersionedPackage(java.lang.String, long);
@@ -13941,6 +13972,7 @@
}
public final class Insets {
+ method public static android.graphics.Insets add(android.graphics.Insets, android.graphics.Insets);
method public static android.graphics.Insets of(int, int, int, int);
method public static android.graphics.Insets of(android.graphics.Rect);
field public static final android.graphics.Insets NONE;
@@ -14693,6 +14725,7 @@
method public float getTranslationX();
method public float getTranslationY();
method public float getTranslationZ();
+ method public long getUniqueId();
method public int getWidth();
method public boolean hasDisplayList();
method public boolean hasIdentityMatrix();
@@ -15046,6 +15079,7 @@
method public void invalidateSelf();
method public boolean isAutoMirrored();
method public boolean isFilterBitmap();
+ method public boolean isProjected();
method public boolean isStateful();
method public final boolean isVisible();
method public void jumpToCurrentState();
diff --git a/api/system-current.txt b/api/system-current.txt
index b43f6c6..b4c7336 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3685,6 +3685,10 @@
public class WifiManager {
method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+ method public void connect(int, android.net.wifi.WifiManager.ActionListener);
+ method public void disable(int, android.net.wifi.WifiManager.ActionListener);
+ method public void disableEphemeralNetwork(java.lang.String);
+ method public void forget(int, android.net.wifi.WifiManager.ActionListener);
method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
method public java.util.List<android.net.wifi.hotspot2.OsuProvider> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
@@ -3696,6 +3700,7 @@
method public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
+ method public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method public boolean startScan(android.os.WorkSource);
method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
diff --git a/api/test-current.txt b/api/test-current.txt
index 8c710c1..c0f7ab6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -61,6 +61,7 @@
}
public class ActivityTaskManager {
+ method public void clearLaunchParamsForPackages(java.util.List<java.lang.String>);
method public java.lang.String listAllStacks();
method public void moveTaskToStack(int, int, boolean);
method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0277b7e..25bd033 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1461,7 +1461,6 @@
Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
Landroid/view/IWindowManager;->showStrictModeViolation(Z)V
Landroid/view/IWindowManager;->thawRotation()V
-Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowSession;
Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V
Landroid/view/IWindowSession;->getInTouchMode()Z
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 5940c45..3095925 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -4117,6 +4117,10 @@
com.android.internal.util.VirtualRefBasePtr
com.android.internal.util.XmlUtils
com.android.internal.util.XmlUtils$WriteMapCallback
+com.android.internal.util.function.NonaConsumer
+com.android.internal.util.function.NonaFunction
+com.android.internal.util.function.OctConsumer
+com.android.internal.util.function.OctFunction
com.android.internal.util.function.HeptConsumer
com.android.internal.util.function.HeptFunction
com.android.internal.util.function.HexConsumer
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 83fab7e..05bb9a1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -827,6 +827,8 @@
/** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */
@Nullable private IntelligenceManager mIntelligenceManager;
+ private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
+ new ArrayList<Application.ActivityLifecycleCallbacks>();
static final class NonConfigurationInstances {
Object activity;
@@ -1065,6 +1067,288 @@
}
/**
+ * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
+ * lifecycle callbacks for only this Activity.
+ * <p>
+ * In relation to any
+ * {@link Application#registerActivityLifecycleCallbacks Application registered callbacks},
+ * the callbacks registered here will always occur nested within those callbacks. This means:
+ * <ul>
+ * <li>Pre events will first be sent to Application registered callbacks, then to callbacks
+ * registered here.</li>
+ * <li>{@link Application.ActivityLifecycleCallbacks#onActivityCreated(Activity, Bundle)},
+ * {@link Application.ActivityLifecycleCallbacks#onActivityStarted(Activity)}, and
+ * {@link Application.ActivityLifecycleCallbacks#onActivityResumed(Activity)} will
+ * be sent first to Application registered callbacks, then to callbacks registered here.
+ * For all other events, callbacks registered here will be sent first.</li>
+ * <li>Post events will first be sent to callbacks registered here, then to
+ * Application registered callbacks.</li>
+ * </ul>
+ * <p>
+ * If multiple callbacks are registered here, they receive events in a first in (up through
+ * {@link Application.ActivityLifecycleCallbacks#onActivityPostResumed}, last out
+ * ordering.
+ * <p>
+ * It is strongly recommended to register this in the constructor of your Activity to ensure
+ * you get all available callbacks. As this callback is associated with only this Activity,
+ * it is not usually necessary to {@link #unregisterActivityLifecycleCallbacks unregister} it
+ * unless you specifically do not want to receive further lifecycle callbacks.
+ *
+ * @param callback The callback instance to register
+ */
+ public void registerActivityLifecycleCallbacks(
+ @NonNull Application.ActivityLifecycleCallbacks callback) {
+ synchronized (mActivityLifecycleCallbacks) {
+ mActivityLifecycleCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Unregister an {@link Application.ActivityLifecycleCallbacks} previously registered
+ * with {@link #registerActivityLifecycleCallbacks}. It will not receive any further
+ * callbacks.
+ *
+ * @param callback The callback instance to unregister
+ * @see #registerActivityLifecycleCallbacks
+ */
+ public void unregisterActivityLifecycleCallbacks(
+ @NonNull Application.ActivityLifecycleCallbacks callback) {
+ synchronized (mActivityLifecycleCallbacks) {
+ mActivityLifecycleCallbacks.remove(callback);
+ }
+ }
+
+ private void dispatchActivityPreCreated(@Nullable Bundle savedInstanceState) {
+ getApplication().dispatchActivityPreCreated(this, savedInstanceState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(this,
+ savedInstanceState);
+ }
+ }
+ }
+
+ private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) {
+ getApplication().dispatchActivityCreated(this, savedInstanceState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(this,
+ savedInstanceState);
+ }
+ }
+ }
+
+ private void dispatchActivityPostCreated(@Nullable Bundle savedInstanceState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(this,
+ savedInstanceState);
+ }
+ }
+ getApplication().dispatchActivityPostCreated(this, savedInstanceState);
+ }
+
+ private void dispatchActivityPreStarted() {
+ getApplication().dispatchActivityPreStarted(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(this);
+ }
+ }
+ }
+
+ private void dispatchActivityStarted() {
+ getApplication().dispatchActivityStarted(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPostStarted() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostStarted(this);
+ }
+ }
+ getApplication().dispatchActivityPostStarted(this);
+ }
+
+ private void dispatchActivityPreResumed() {
+ getApplication().dispatchActivityPreResumed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityResumed() {
+ getApplication().dispatchActivityResumed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityResumed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPostResumed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(this);
+ }
+ }
+ getApplication().dispatchActivityPostResumed(this);
+ }
+
+ private void dispatchActivityPrePaused() {
+ getApplication().dispatchActivityPrePaused(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPaused() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPaused(this);
+ }
+ }
+ getApplication().dispatchActivityPaused(this);
+ }
+
+ private void dispatchActivityPostPaused() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(this);
+ }
+ }
+ getApplication().dispatchActivityPostPaused(this);
+ }
+
+ private void dispatchActivityPreStopped() {
+ getApplication().dispatchActivityPreStopped(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(this);
+ }
+ }
+ }
+
+ private void dispatchActivityStopped() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStopped(this);
+ }
+ }
+ getApplication().dispatchActivityStopped(this);
+ }
+
+ private void dispatchActivityPostStopped() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostStopped(this);
+ }
+ }
+ getApplication().dispatchActivityPostStopped(this);
+ }
+
+ private void dispatchActivityPreSaveInstanceState(@NonNull Bundle outState) {
+ getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPreSaveInstanceState(this, outState);
+ }
+ }
+ }
+
+ private void dispatchActivitySaveInstanceState(@NonNull Bundle outState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivitySaveInstanceState(this, outState);
+ }
+ }
+ getApplication().dispatchActivitySaveInstanceState(this, outState);
+ }
+
+ private void dispatchActivityPostSaveInstanceState(@NonNull Bundle outState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostSaveInstanceState(this, outState);
+ }
+ }
+ getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ }
+
+ private void dispatchActivityPreDestroyed() {
+ getApplication().dispatchActivityPreDestroyed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPreDestroyed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityDestroyed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityDestroyed(this);
+ }
+ }
+ getApplication().dispatchActivityDestroyed(this);
+ }
+
+ private void dispatchActivityPostDestroyed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostDestroyed(this);
+ }
+ }
+ getApplication().dispatchActivityPostDestroyed(this);
+ }
+
+ private Object[] collectActivityLifecycleCallbacks() {
+ Object[] callbacks = null;
+ synchronized (mActivityLifecycleCallbacks) {
+ if (mActivityLifecycleCallbacks.size() > 0) {
+ callbacks = mActivityLifecycleCallbacks.toArray();
+ }
+ }
+ return callbacks;
+ }
+
+ /**
* Called when the activity is starting. This is where most initialization
* should go: calling {@link #setContentView(int)} to inflate the
* activity's UI, using {@link #findViewById} to programmatically interact
@@ -1119,7 +1403,7 @@
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
- getApplication().dispatchActivityCreated(this, savedInstanceState);
+ dispatchActivityCreated(savedInstanceState);
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
@@ -1355,7 +1639,7 @@
mFragments.doLoaderStart();
- getApplication().dispatchActivityStarted(this);
+ dispatchActivityStarted();
if (mAutoFillResetNeeded) {
getAutofillManager().onVisibleForAutofill();
@@ -1426,7 +1710,7 @@
@CallSuper
protected void onResume() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
- getApplication().dispatchActivityResumed(this);
+ dispatchActivityResumed();
mActivityTransitionState.onResume(this, isTopOfTask());
enableAutofillCompatibilityIfNeeded();
if (mAutoFillResetNeeded) {
@@ -1642,13 +1926,13 @@
* @param outState The bundle to save the state to.
*/
final void performSaveInstanceState(@NonNull Bundle outState) {
- getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ dispatchActivityPreSaveInstanceState(outState);
onSaveInstanceState(outState);
saveManagedDialogs(outState);
mActivityTransitionState.saveState(outState);
storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
- getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ dispatchActivityPostSaveInstanceState(outState);
}
/**
@@ -1662,13 +1946,13 @@
*/
final void performSaveInstanceState(@NonNull Bundle outState,
@NonNull PersistableBundle outPersistentState) {
- getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ dispatchActivityPreSaveInstanceState(outState);
onSaveInstanceState(outState, outPersistentState);
saveManagedDialogs(outState);
storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
", " + outPersistentState);
- getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ dispatchActivityPostSaveInstanceState(outState);
}
/**
@@ -1731,7 +2015,7 @@
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
- getApplication().dispatchActivitySaveInstanceState(this, outState);
+ dispatchActivitySaveInstanceState(outState);
}
/**
@@ -1831,7 +2115,7 @@
@CallSuper
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
- getApplication().dispatchActivityPaused(this);
+ dispatchActivityPaused();
if (mAutoFillResetNeeded) {
if (!mAutoFillIgnoreFirstResumePause) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill notifyViewExited " + this);
@@ -2015,7 +2299,7 @@
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
mActivityTransitionState.onStop();
- getApplication().dispatchActivityStopped(this);
+ dispatchActivityStopped();
mTranslucentCallback = null;
mCalled = true;
@@ -2104,7 +2388,7 @@
mActionBar.onDestroy();
}
- getApplication().dispatchActivityDestroyed(this);
+ dispatchActivityDestroyed();
notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
@@ -7284,7 +7568,7 @@
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
- getApplication().dispatchActivityPreCreated(this, icicle);
+ dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
restoreHasCurrentPermissionRequest(icicle);
if (persistentState != null) {
@@ -7299,7 +7583,7 @@
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
- getApplication().dispatchActivityPostCreated(this, icicle);
+ dispatchActivityPostCreated(icicle);
}
final void performNewIntent(@NonNull Intent intent) {
@@ -7308,7 +7592,7 @@
}
final void performStart(String reason) {
- getApplication().dispatchActivityPreStarted(this);
+ dispatchActivityPreStarted();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
mFragments.noteStateNotSaved();
mCalled = false;
@@ -7351,7 +7635,7 @@
}
mActivityTransitionState.enterReady(this);
- getApplication().dispatchActivityPostStarted(this);
+ dispatchActivityPostStarted();
}
/**
@@ -7406,7 +7690,7 @@
}
final void performResume(boolean followedByPause, String reason) {
- getApplication().dispatchActivityPreResumed(this);
+ dispatchActivityPreResumed();
performRestart(true /* start */, reason);
mFragments.execPendingActions();
@@ -7456,11 +7740,11 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onPostResume()");
}
- getApplication().dispatchActivityPostResumed(this);
+ dispatchActivityPostResumed();
}
final void performPause() {
- getApplication().dispatchActivityPrePaused(this);
+ dispatchActivityPrePaused();
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
@@ -7473,7 +7757,7 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
- getApplication().dispatchActivityPostPaused(this);
+ dispatchActivityPostPaused();
}
final void performUserLeaving() {
@@ -7489,7 +7773,7 @@
mCanEnterPictureInPicture = false;
if (!mStopped) {
- getApplication().dispatchActivityPreStopped(this);
+ dispatchActivityPreStopped();
if (mWindow != null) {
mWindow.closeAllPanels();
}
@@ -7524,13 +7808,13 @@
}
mStopped = true;
- getApplication().dispatchActivityPostStopped(this);
+ dispatchActivityPostStopped();
}
mResumed = false;
}
final void performDestroy() {
- getApplication().dispatchActivityPreDestroyed(this);
+ dispatchActivityPreDestroyed();
mDestroyed = true;
mWindow.destroy();
mFragments.dispatchDestroy();
@@ -7540,7 +7824,7 @@
if (mVoiceInteractor != null) {
mVoiceInteractor.detachActivity();
}
- getApplication().dispatchActivityPostDestroyed(this);
+ dispatchActivityPostDestroyed();
}
final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 56ccf6f..6fdf7c8 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -433,4 +433,18 @@
}
return sb.toString();
}
+
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ try {
+ getService().clearLaunchParamsForPackages(packageNames);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 09b77d5..777a494 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -445,4 +445,9 @@
void setPackageScreenCompatMode(in String packageName, int mode);
boolean getPackageAskScreenCompat(in String packageName);
void setPackageAskScreenCompat(in String packageName, boolean ask);
+
+ /**
+ * Clears launch params for given packages.
+ */
+ void clearLaunchParamsForPackages(in List<String> packageNames);
}
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 1c9a43a..673d85f 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,7 +1,6 @@
-artikz@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index ecdd810..099d15a 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -22,6 +22,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Overall information about the contents of a package. This corresponds
* to all of the information collected from AndroidManifest.xml.
@@ -204,7 +207,10 @@
* {@link PackageManager#GET_PERMISSIONS} was set. This list includes
* all permissions requested, even those that were not granted or known
* by the system at install time.
+ *
+ * @deprecated Use {@link #usesPermissions}
*/
+ @Deprecated
public String[] requestedPermissions;
/**
@@ -214,10 +220,23 @@
* {@link PackageManager#GET_PERMISSIONS} was set. Each value matches
* the corresponding entry in {@link #requestedPermissions}, and will have
* the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
+ *
+ * @deprecated Use {@link #usesPermissions}
*/
+ @Deprecated
public int[] requestedPermissionsFlags;
/**
+ * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
+ * <uses-permission>} tags included under <manifest>,
+ * or null if there were none. This is only filled in if the flag
+ * {@link PackageManager#GET_PERMISSIONS} was set. This list includes
+ * all permissions requested, even those that were not granted or known
+ * by the system at install time.
+ */
+ public UsesPermissionInfo[] usesPermissions;
+
+ /**
* Flag for {@link #requestedPermissionsFlags}: the requested permission
* is required for the application to run; the user can not optionally
* disable it. Currently all permissions are required.
@@ -456,6 +475,7 @@
dest.writeTypedArray(permissions, parcelableFlags);
dest.writeStringArray(requestedPermissions);
dest.writeIntArray(requestedPermissionsFlags);
+ dest.writeTypedArray(usesPermissions, parcelableFlags);
dest.writeTypedArray(signatures, parcelableFlags);
dest.writeTypedArray(configPreferences, parcelableFlags);
dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -520,6 +540,7 @@
permissions = source.createTypedArray(PermissionInfo.CREATOR);
requestedPermissions = source.createStringArray();
requestedPermissionsFlags = source.createIntArray();
+ usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR);
signatures = source.createTypedArray(Signature.CREATOR);
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d00c9a0..49189e5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -785,18 +785,23 @@
pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
}
}
- N = p.requestedPermissions.size();
+ N = p.usesPermissionInfos.size();
if (N > 0) {
pi.requestedPermissions = new String[N];
pi.requestedPermissionsFlags = new int[N];
+ pi.usesPermissions = new UsesPermissionInfo[N];
for (int i=0; i<N; i++) {
- final String perm = p.requestedPermissions.get(i);
+ UsesPermissionInfo info = p.usesPermissionInfos.get(i);
+ final String perm = info.getPermission();
pi.requestedPermissions[i] = perm;
+ int permissionFlags = 0;
// The notion of required permissions is deprecated but for compatibility.
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+ permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
if (grantedPermissions != null && grantedPermissions.contains(perm)) {
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+ permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
}
+ pi.requestedPermissionsFlags[i] = permissionFlags;
+ pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags);
}
}
}
@@ -2114,12 +2119,12 @@
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION)) {
- if (!parseUsesPermission(pkg, res, parser)) {
+ if (!parseUsesPermission(pkg, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
- if (!parseUsesPermission(pkg, res, parser)) {
+ if (!parseUsesPermission(pkg, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_USES_CONFIGURATION)) {
@@ -2442,7 +2447,7 @@
newPermsMsg.append(' ');
}
newPermsMsg.append(npi.name);
- pkg.requestedPermissions.add(npi.name);
+ addRequestedPermission(pkg, npi.name);
pkg.implicitPermissions.add(npi.name);
}
}
@@ -2463,7 +2468,7 @@
for (int in = 0; in < newPerms.size(); in++) {
final String perm = newPerms.get(in);
if (!pkg.requestedPermissions.contains(perm)) {
- pkg.requestedPermissions.add(perm);
+ addRequestedPermission(pkg, perm);
pkg.implicitPermissions.add(perm);
}
}
@@ -2543,13 +2548,13 @@
}
} else {
if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO);
}
if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO);
}
if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES);
}
}
@@ -2589,6 +2594,14 @@
}
/**
+ * Helper method for adding a requested permission to a package outside of a uses-permission.
+ */
+ private void addRequestedPermission(Package pkg, String permission) {
+ pkg.requestedPermissions.add(permission);
+ pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission));
+ }
+
+ /**
* Computes the targetSdkVersion to use at runtime. If the package is not
* compatible with this platform, populates {@code outError[0]} with an
* error message.
@@ -2845,8 +2858,8 @@
return certSha256Digests;
}
- private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
- throws XmlPullParserException, IOException {
+ private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
+ String[] outError) throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesPermission);
@@ -2870,6 +2883,44 @@
final String requiredNotfeature = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
+ int dataSentOffDevice = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0);
+
+ int dataSharedWithThirdParty = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0);
+
+ int dataUsedForMonetization = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0);
+
+ int retentionWeeks = -1;
+ int retention;
+
+ String rawRetention = sa.getString(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime);
+
+ if (rawRetention == null) {
+ retention = UsesPermissionInfo.RETENTION_UNDEFINED;
+ } else if ("notRetained".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_NOT_RETAINED;
+ } else if ("userSelected".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_USER_SELECTED;
+ } else if ("unlimited".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_UNLIMITED;
+ } else {
+ // A number of weeks was specified
+ retention = UsesPermissionInfo.RETENTION_SPECIFIED;
+ retentionWeeks = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime,
+ -1);
+
+ if (retentionWeeks < 0) {
+ outError[0] = "Bad value provided for dataRetentionTime.";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ XmlUtils.skipCurrentTag(parser);
+ sa.recycle();
+ return false;
+ }
+ }
sa.recycle();
XmlUtils.skipCurrentTag(parser);
@@ -2902,6 +2953,10 @@
+ parser.getPositionDescription());
}
+ UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice,
+ dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks);
+ pkg.usesPermissionInfos.add(info);
+
return true;
}
@@ -3236,6 +3291,10 @@
perm.info.flags = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
+ perm.info.usageInfoRequired = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0)
+ != 0;
+
sa.recycle();
if (perm.info.protectionLevel == -1) {
@@ -6370,6 +6429,9 @@
@UnsupportedAppUsage
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
+ public final ArrayList<UsesPermissionInfo> usesPermissionInfos =
+ new ArrayList<>();
+
/** Permissions requested but not in the manifest. */
public final ArrayList<String> implicitPermissions = new ArrayList<>();
@@ -6900,6 +6962,7 @@
dest.readStringList(requestedPermissions);
internStringArrayList(requestedPermissions);
+ dest.readParcelableList(usesPermissionInfos, boot);
dest.readStringList(implicitPermissions);
internStringArrayList(implicitPermissions);
protectedBroadcasts = dest.createStringArrayList();
@@ -7066,6 +7129,7 @@
dest.writeParcelableList(instrumentation, flags);
dest.writeStringList(requestedPermissions);
+ dest.writeParcelableList(usesPermissionInfos, flags);
dest.writeStringList(implicitPermissions);
dest.writeStringList(protectedBroadcasts);
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 60c06a1..7523949 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -20,6 +20,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -308,6 +309,12 @@
*/
public CharSequence nonLocalizedDescription;
+ /**
+ * If {@code true} an application targeting {@link Build.VERSION_CODES.Q} <em>must</em>
+ * include permission data usage information in order to be able to be granted this permission.
+ */
+ public boolean usageInfoRequired;
+
/** @hide */
public static int fixProtectionLevel(int level) {
if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -394,6 +401,7 @@
descriptionRes = orig.descriptionRes;
requestRes = orig.requestRes;
nonLocalizedDescription = orig.nonLocalizedDescription;
+ usageInfoRequired = orig.usageInfoRequired;
}
/**
@@ -458,6 +466,7 @@
dest.writeInt(descriptionRes);
dest.writeInt(requestRes);
TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
+ dest.writeInt(usageInfoRequired ? 1 : 0);
}
/** @hide */
@@ -498,5 +507,6 @@
descriptionRes = source.readInt();
requestRes = source.readInt();
nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ usageInfoRequired = source.readInt() != 0;
}
}
diff --git a/core/java/android/content/pm/UsesPermissionInfo.java b/core/java/android/content/pm/UsesPermissionInfo.java
new file mode 100644
index 0000000..997552b
--- /dev/null
+++ b/core/java/android/content/pm/UsesPermissionInfo.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2018 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.content.pm;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.RetentionPolicy;
+/**
+ * Information you can retrive about a particular application requested permission. This
+ * corresponds to information collected from the AndroidManifest.xml's <uses-permission>
+ * tags.
+ */
+public final class UsesPermissionInfo extends PackageItemInfo implements Parcelable {
+
+ /**
+ * Flag for {@link #flags}: the requested permission is currently granted to the application.
+ */
+ public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 1 << 1;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_REQUESTED_PERMISSION_GRANTED})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Flags {}
+
+ /** An unset value for {@link #getDataSentOffDevice()},
+ * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+ */
+ public static final int USAGE_UNDEFINED = 0;
+
+ /**
+ * A yes value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+ * and {@link #getDataUsedForMonetization()} corresponding to the <code>yes</code> value of
+ * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+ * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_YES = 1;
+
+ /**
+ * A user triggered only value for {@link #getDataSentOffDevice()},
+ * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+ * corresponding to the <code>userTriggered</code> value of
+ * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+ * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_USER_TRIGGERED = 2;
+
+ /**
+ * A no value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+ * and {@link #getDataUsedForMonetization()} corresponding to the <code>no</code> value of
+ * {@link android.R.attrs#dataSentOffDevice}, {@link android.R.attrs#dataSharedWithThirdParty},
+ * and {@link android.R.attrs#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_NO = 3;
+
+ /** @hide */
+ @IntDef(prefix = {"USAGE_"}, value = {
+ USAGE_UNDEFINED,
+ USAGE_YES,
+ USAGE_USER_TRIGGERED,
+ USAGE_NO})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Usage {}
+
+ /**
+ * An unset value for {@link #getDataRetention}.
+ */
+ public static final int RETENTION_UNDEFINED = 0;
+
+ /**
+ * A data not retained value for {@link #getDataRetention()} corresponding to the
+ * <code>notRetained</code> value of {@link android.R.attrs#dataRetentionTime}.
+ */
+ public static final int RETENTION_NOT_RETAINED = 1;
+
+ /**
+ * A user selected value for {@link #getDataRetention()} corresponding to the
+ * <code>userSelected</code> value of {@link android.R.attrs#dataRetentionTime}.
+ */
+ public static final int RETENTION_USER_SELECTED = 2;
+
+ /**
+ * An unlimited value for {@link #getDataRetention()} corresponding to the
+ * <code>unlimited</code> value of {@link android.R.attrs#dataRetentionTime}.
+ */
+ public static final int RETENTION_UNLIMITED = 3;
+
+ /**
+ * A specified value for {@link #getDataRetention()} corresponding to providing the number of
+ * weeks data is retained in {@link android.R.attrs#dataRetentionTime}. The number of weeks
+ * is available in {@link #getDataRetentionWeeks()}.
+ */
+ public static final int RETENTION_SPECIFIED = 4;
+
+ /** @hide */
+ @IntDef(prefix = {"RETENTION_"}, value = {
+ RETENTION_UNDEFINED,
+ RETENTION_NOT_RETAINED,
+ RETENTION_USER_SELECTED,
+ RETENTION_UNLIMITED,
+ RETENTION_SPECIFIED})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Retention {}
+
+ private final String mPermission;
+ private final @Flags int mFlags;
+ private final @Usage int mDataSentOffDevice;
+ private final @Usage int mDataSharedWithThirdParty;
+ private final @Usage int mDataUsedForMonetization;
+ private final @Retention int mDataRetention;
+ private final int mDataRetentionWeeks;
+
+ /** @hide */
+ public UsesPermissionInfo(String permission) {
+ mPermission = permission;
+ mDataSentOffDevice = USAGE_UNDEFINED;
+ mDataSharedWithThirdParty = USAGE_UNDEFINED;
+ mDataUsedForMonetization = USAGE_UNDEFINED;
+ mDataRetention = RETENTION_UNDEFINED;
+ mDataRetentionWeeks = -1;
+ mFlags = 0;
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(String permission,
+ @Usage int dataSentOffDevice, @Usage int dataSharedWithThirdParty,
+ @Usage int dataUsedForMonetization, @Retention int dataRetention,
+ int dataRetentionWeeks) {
+ mPermission = permission;
+ mDataSentOffDevice = dataSentOffDevice;
+ mDataSharedWithThirdParty = dataSharedWithThirdParty;
+ mDataUsedForMonetization = dataUsedForMonetization;
+ mDataRetention = dataRetention;
+ mDataRetentionWeeks = dataRetentionWeeks;
+ mFlags = 0;
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(UsesPermissionInfo orig) {
+ this(orig, orig.mFlags);
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(UsesPermissionInfo orig, int flags) {
+ super(orig);
+ mPermission = orig.mPermission;
+ mFlags = flags;
+ mDataSentOffDevice = orig.mDataSentOffDevice;
+ mDataSharedWithThirdParty = orig.mDataSharedWithThirdParty;
+ mDataUsedForMonetization = orig.mDataUsedForMonetization;
+ mDataRetention = orig.mDataRetention;
+ mDataRetentionWeeks = orig.mDataRetentionWeeks;
+ }
+
+ /**
+ * The name of the requested permission.
+ */
+ public String getPermission() {
+ return mPermission;
+ }
+
+ public @Flags int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * If the application sends the data guarded by this permission off the device.
+ *
+ * See {@link android.R.attrs#dataSentOffDevice}
+ */
+ public @Usage int getDataSentOffDevice() {
+ return mDataSentOffDevice;
+ }
+
+ /**
+ * If the application or its services shares the data guarded by this permission with third
+ * parties.
+ *
+ * See {@link android.R.attrs#dataSharedWithThirdParty}
+ */
+ public @Usage int getDataSharedWithThirdParty() {
+ return mDataSharedWithThirdParty;
+ }
+
+ /**
+ * If the application or its services use the data guarded by this permission for monetization
+ * purposes.
+ *
+ * See {@link android.R.attrs#dataUsedForMonetization}
+ */
+ public @Usage int getDataUsedForMonetization() {
+ return mDataUsedForMonetization;
+ }
+
+ /**
+ * How long the application or its services store the data guarded by this permission.
+ * If set to {@link #RETENTION_SPECIFIED} {@link #getDataRetentionWeeks()} will contain the
+ * number of weeks the data is stored.
+ *
+ * See {@link android.R.attrs#dataRetentionTime}
+ */
+ public @Retention int getDataRetention() {
+ return mDataRetention;
+ }
+
+ /**
+ * If {@link #getDataRetention()} is {@link #RETENTION_SPECIFIED} the number of weeks the
+ * application or its services store data guarded by this permission.
+ *
+ * @throws IllegalStateException if {@link #getDataRetention} is not
+ * {@link #RETENTION_SPECIFIED}.
+ */
+ public int getDataRetentionWeeks() {
+ if (mDataRetention != RETENTION_SPECIFIED) {
+ throw new IllegalStateException("Data retention weeks not specified");
+ }
+ return mDataRetentionWeeks;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mPermission);
+ dest.writeInt(mFlags);
+ dest.writeInt(mDataSentOffDevice);
+ dest.writeInt(mDataSharedWithThirdParty);
+ dest.writeInt(mDataUsedForMonetization);
+ dest.writeInt(mDataRetention);
+ dest.writeInt(mDataRetentionWeeks);
+ }
+
+ private UsesPermissionInfo(Parcel source) {
+ super(source);
+ mPermission = source.readString();
+ mFlags = source.readInt();
+ mDataSentOffDevice = source.readInt();
+ mDataSharedWithThirdParty = source.readInt();
+ mDataUsedForMonetization = source.readInt();
+ mDataRetention = source.readInt();
+ mDataRetentionWeeks = source.readInt();
+ }
+
+ public static final Creator<UsesPermissionInfo> CREATOR =
+ new Creator<UsesPermissionInfo>() {
+ @Override
+ public UsesPermissionInfo createFromParcel(Parcel source) {
+ return new UsesPermissionInfo(source);
+ }
+ @Override
+ public UsesPermissionInfo[] newArray(int size) {
+ return new UsesPermissionInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 979bcae..a095b0d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -57,6 +57,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -185,6 +186,7 @@
final DisplayCutout.ParcelableWrapper mDisplayCutout =
new DisplayCutout.ParcelableWrapper();
DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT;
+ final InsetsState mInsetsState = new InsetsState();
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
final WindowManager.LayoutParams mLayout
@@ -808,9 +810,11 @@
mLayout.windowAnimations =
com.android.internal.R.style.Animation_Wallpaper;
mInputChannel = new InputChannel();
+
if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets,
- mOutsets, mDisplayCutout, mInputChannel) < 0) {
+ mOutsets, mDisplayCutout, mInputChannel,
+ mInsetsState) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
@@ -836,7 +840,8 @@
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, -1, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface);
+ mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface,
+ mInsetsState);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 4b8b7f3..af41b69 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -24,6 +24,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.DisplayCutout;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
import android.util.MergedConfiguration;
@@ -53,6 +54,12 @@
in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
in DisplayCutout.ParcelableWrapper displayCutout);
+
+ /**
+ * Called when the window insets configuration has changed.
+ */
+ void insetsChanged(in InsetsState insetsState);
+
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index bedfa9f..9762586 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -28,6 +28,7 @@
import android.view.IWindowId;
import android.view.MotionEvent;
import android.view.WindowManager;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -40,10 +41,11 @@
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outFrame,
out Rect outContentInsets, out Rect outStableInsets, out Rect outOutsets,
- out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel);
+ out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
+ out InsetsState insetsState);
int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
- out Rect outStableInsets);
+ out Rect outStableInsets, out InsetsState insetsState);
void remove(IWindow window);
/**
@@ -86,6 +88,7 @@
* config for window, if it is now becoming visible and the merged configuration has changed
* since it was last displayed.
* @param outSurface Object in which is placed the new display surface.
+ * @param insetsState The current insets state in the system.
*
* @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
* {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -96,7 +99,8 @@
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
out Rect outOutsets, out Rect outBackdropFrame,
out DisplayCutout.ParcelableWrapper displayCutout,
- out MergedConfiguration outMergedConfiguration, out Surface outSurface);
+ out MergedConfiguration outMergedConfiguration, out Surface outSurface,
+ out InsetsState insetsState);
/*
* Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
new file mode 100644
index 0000000..7841d04
--- /dev/null
+++ b/core/java/android/view/InsetsController.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import android.graphics.Rect;
+
+import java.io.PrintWriter;
+
+/**
+ * Implements {@link WindowInsetsController} on the client.
+ */
+class InsetsController {
+
+ private final InsetsState mState = new InsetsState();
+ private final Rect mFrame = new Rect();
+
+ void onFrameChanged(Rect frame) {
+ mFrame.set(frame);
+ }
+
+ public InsetsState getState() {
+ return mState;
+ }
+
+ public void setState(InsetsState state) {
+ mState.set(state);
+ }
+
+ /**
+ * @see InsetsState#calculateInsets
+ */
+ WindowInsets calculateInsets(boolean isScreenRound,
+ boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+ return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout);
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix); pw.println("InsetsController:");
+ mState.dump(prefix + " ", pw);
+ }
+}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
new file mode 100644
index 0000000..0cb8ad7
--- /dev/null
+++ b/core/java/android/view/InsetsSource.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InsetsState.InternalInsetType;
+
+import java.io.PrintWriter;
+
+/**
+ * Represents the state of a single window generating insets for clients.
+ * @hide
+ */
+public class InsetsSource implements Parcelable {
+
+ private final @InternalInsetType int mType;
+
+ /** Frame of the source in screen coordinate space */
+ private final Rect mFrame;
+ private boolean mVisible;
+
+ private final Rect mTmpFrame = new Rect();
+
+ public InsetsSource(@InternalInsetType int type) {
+ mType = type;
+ mFrame = new Rect();
+ }
+
+ public InsetsSource(InsetsSource other) {
+ mType = other.mType;
+ mFrame = new Rect(other.mFrame);
+ mVisible = other.mVisible;
+ }
+
+ public void setFrame(Rect frame) {
+ mFrame.set(frame);
+ }
+
+ public void setVisible(boolean visible) {
+ mVisible = visible;
+ }
+
+ public @InternalInsetType int getType() {
+ return mType;
+ }
+
+ public Rect getFrame() {
+ return mFrame;
+ }
+
+ /**
+ * Calculates the insets this source will cause to a client window.
+ *
+ * @param relativeFrame The frame to calculate the insets relative to.
+ * @param ignoreVisibility If true, always reports back insets even if source isn't visible.
+ * @return The resulting insets.
+ */
+ public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) {
+ if (!ignoreVisibility && !mVisible) {
+ return Insets.NONE;
+ }
+ if (!mTmpFrame.setIntersect(mFrame, relativeFrame)) {
+ return Insets.NONE;
+ }
+
+ // Intersecting at top/bottom
+ if (mTmpFrame.width() == relativeFrame.width()) {
+ if (mTmpFrame.top == relativeFrame.top) {
+ return Insets.of(0, mTmpFrame.height(), 0, 0);
+ } else {
+ return Insets.of(0, 0, 0, mTmpFrame.height());
+ }
+ }
+ // Intersecting at left/right
+ else if (mTmpFrame.height() == relativeFrame.height()) {
+ if (mTmpFrame.left == relativeFrame.left) {
+ return Insets.of(mTmpFrame.width(), 0, 0, 0);
+ } else {
+ return Insets.of(0, 0, mTmpFrame.width(), 0);
+ }
+ } else {
+ return Insets.NONE;
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix);
+ pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType));
+ pw.print(" frame="); pw.print(mFrame.toShortString());
+ pw.print(" visible="); pw.print(mVisible);
+ pw.println();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InsetsSource that = (InsetsSource) o;
+
+ if (mType != that.mType) return false;
+ if (mVisible != that.mVisible) return false;
+ return mFrame.equals(that.mFrame);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mType;
+ result = 31 * result + mFrame.hashCode();
+ result = 31 * result + (mVisible ? 1 : 0);
+ return result;
+ }
+
+ public InsetsSource(Parcel in) {
+ mType = in.readInt();
+ mFrame = in.readParcelable(null /* loader */);
+ mVisible = in.readBoolean();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeParcelable(mFrame, 0 /* flags*/);
+ dest.writeBoolean(mVisible);
+ }
+
+ public static final Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {
+
+ public InsetsSource createFromParcel(Parcel in) {
+ return new InsetsSource(in);
+ }
+
+ public InsetsSource[] newArray(int size) {
+ return new InsetsSource[size];
+ }
+ };
+}
diff --git a/core/java/android/view/InsetsState.aidl b/core/java/android/view/InsetsState.aidl
new file mode 100644
index 0000000..d02ddd1
--- /dev/null
+++ b/core/java/android/view/InsetsState.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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.view;
+
+parcelable InsetsState;
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
new file mode 100644
index 0000000..9895adc
--- /dev/null
+++ b/core/java/android/view/InsetsState.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import android.annotation.IntDef;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Holder for state of system windows that cause window insets for all other windows in the system.
+ * @hide
+ */
+public class InsetsState implements Parcelable {
+
+ /**
+ * Internal representation of inset source types. This is different from the public API in
+ * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
+ * at the same time.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE", value = {
+ TYPE_TOP_BAR,
+ TYPE_SIDE_BAR_1,
+ TYPE_SIDE_BAR_2,
+ TYPE_SIDE_BAR_3,
+ TYPE_IME
+ })
+ public @interface InternalInsetType {}
+
+ static final int FIRST_TYPE = 0;
+
+ /** Top bar. Can be status bar or caption in freeform windowing mode. */
+ public static final int TYPE_TOP_BAR = FIRST_TYPE;
+
+ /**
+ * Up to 3 side bars that appear on left/right/bottom. On phones there is only one side bar
+ * (the navigation bar, see {@link #TYPE_NAVIGATION_BAR}), but other form factors might have
+ * multiple, like Android Auto.
+ */
+ public static final int TYPE_SIDE_BAR_1 = 1;
+ public static final int TYPE_SIDE_BAR_2 = 2;
+ public static final int TYPE_SIDE_BAR_3 = 3;
+
+ /** Input method window. */
+ public static final int TYPE_IME = 4;
+ static final int LAST_TYPE = TYPE_IME;
+
+ // Derived types
+
+ /** First side bar is navigation bar. */
+ public static final int TYPE_NAVIGATION_BAR = TYPE_SIDE_BAR_1;
+
+ /** A shelf is the same as the navigation bar. */
+ public static final int TYPE_SHELF = TYPE_NAVIGATION_BAR;
+
+ private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+
+ public InsetsState() {
+ }
+
+ /**
+ * Calculates {@link WindowInsets} based on the current source configuration.
+ *
+ * @param frame The frame to calculate the insets relative to.
+ * @return The calculated insets.
+ */
+ public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
+ boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+ Insets systemInsets = Insets.NONE;
+ Insets maxInsets = Insets.NONE;
+ final Rect relativeFrame = new Rect(frame);
+ final Rect relativeFrameMax = new Rect(frame);
+ for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
+ InsetsSource source = mSources.get(type);
+ if (source == null) {
+ continue;
+ }
+ systemInsets = processSource(source, systemInsets, relativeFrame,
+ false /* ignoreVisibility */);
+
+ // IME won't be reported in max insets as the size depends on the EditorInfo of the IME
+ // target.
+ if (source.getType() != TYPE_IME) {
+ maxInsets = processSource(source, maxInsets, relativeFrameMax,
+ true /* ignoreVisibility */);
+ }
+ }
+ return new WindowInsets(new Rect(systemInsets), null, new Rect(maxInsets), isScreenRound,
+ alwaysConsumeNavBar, cutout);
+ }
+
+ private Insets processSource(InsetsSource source, Insets insets, Rect relativeFrame,
+ boolean ignoreVisibility) {
+ Insets currentInsets = source.calculateInsets(relativeFrame, ignoreVisibility);
+ insets = Insets.add(currentInsets, insets);
+ relativeFrame.inset(insets);
+ return insets;
+ }
+
+ public InsetsSource getSource(@InternalInsetType int type) {
+ return mSources.computeIfAbsent(type, InsetsSource::new);
+ }
+
+ /**
+ * Modifies the state of this class to exclude a certain type to make it ready for dispatching
+ * to the client.
+ *
+ * @param type The {@link InternalInsetType} of the source to remove
+ */
+ public void removeSource(int type) {
+ mSources.remove(type);
+ }
+
+ public void set(InsetsState other) {
+ set(other, false /* copySources */);
+ }
+
+ public void set(InsetsState other, boolean copySources) {
+ mSources.clear();
+ if (copySources) {
+ for (int i = 0; i < other.mSources.size(); i++) {
+ InsetsSource source = other.mSources.valueAt(i);
+ mSources.put(source.getType(), new InsetsSource(source));
+ }
+ } else {
+ mSources.putAll(other.mSources);
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "InsetsState");
+ for (int i = mSources.size() - 1; i >= 0; i--) {
+ mSources.valueAt(i).dump(prefix + " ", pw);
+ }
+ }
+
+ static String typeToString(int type) {
+ switch (type) {
+ case TYPE_TOP_BAR:
+ return "TYPE_TOP_BAR";
+ case TYPE_SIDE_BAR_1:
+ return "TYPE_SIDE_BAR_1";
+ case TYPE_SIDE_BAR_2:
+ return "TYPE_SIDE_BAR_2";
+ case TYPE_SIDE_BAR_3:
+ return "TYPE_SIDE_BAR_3";
+ case TYPE_IME:
+ return "TYPE_IME";
+ default:
+ return "TYPE_UNKNOWN";
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+
+ InsetsState state = (InsetsState) o;
+
+ if (mSources.size() != state.mSources.size()) {
+ return false;
+ }
+ for (int i = mSources.size() - 1; i >= 0; i--) {
+ InsetsSource source = mSources.valueAt(i);
+ InsetsSource otherSource = state.mSources.get(source.getType());
+ if (otherSource == null) {
+ return false;
+ }
+ if (!otherSource.equals(source)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mSources.hashCode();
+ }
+
+ public InsetsState(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSources.size());
+ for (int i = 0; i < mSources.size(); i++) {
+ dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+ }
+ }
+
+ public static final Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
+
+ public InsetsState createFromParcel(Parcel in) {
+ return new InsetsState(in);
+ }
+
+ public InsetsState[] newArray(int size) {
+ return new InsetsState[size];
+ }
+ };
+
+ public void readFromParcel(Parcel in) {
+ mSources.clear();
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ final InsetsSource source = in.readParcelable(null /* loader */);
+ mSources.put(source.getType(), source);
+ }
+ }
+}
+
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8e9f2d7..d9d52c0 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -161,6 +161,19 @@
private static final boolean MT_RENDERER_AVAILABLE = true;
/**
+ * If set to true, the view system will switch from using rectangles retrieved from window to
+ * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets
+ * directly from the full configuration, enabling richer information about the insets state, as
+ * well as new APIs to control it frame-by-frame, and synchronize animations with it.
+ * <p>
+ * Only switch this to true once the new insets system is productionized and the old APIs are
+ * fully migrated over.
+ */
+ private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets";
+ private static final boolean USE_NEW_INSETS =
+ SystemProperties.getBoolean(USE_NEW_INSETS_PROPERTY, false);
+
+ /**
* Set this system property to true to force the view hierarchy to render
* at 60 Hz. This can be used to measure the potential framerate.
*/
@@ -432,6 +445,8 @@
boolean mAdded;
boolean mAddedTouchMode;
+ final Rect mTmpFrame = new Rect();
+
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -444,6 +459,7 @@
final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
boolean mPendingAlwaysConsumeNavBar;
+ private InsetsState mPendingInsets;
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -531,6 +547,8 @@
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
new InputEventConsistencyVerifier(this, 0) : null;
+ private final InsetsController mInsetsController = new InsetsController();
+
static final class SystemUiVisibilityInfo {
int seq;
int globalVisibility;
@@ -797,9 +815,11 @@
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
+ getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
- mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
+ mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
+ mInsetsController.getState());
+ setFrame(mTmpFrame);
} catch (RemoteException e) {
mAdded = false;
mView = null;
@@ -826,6 +846,7 @@
mAttachInfo.mAlwaysConsumeNavBar =
(res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
+ mPendingInsets = mInsetsController.getState();
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
@@ -1771,7 +1792,8 @@
Rect stableInsets = mDispatchStableInsets;
DisplayCutout displayCutout = mDispatchDisplayCutout;
// For dispatch we preserve old logic, but for direct requests from Views we allow to
- // immediately use pending insets.
+ // immediately use pending insets. This is such that getRootWindowInsets returns the
+ // result from the layout hint before we ran a traversal shortly after adding a window.
if (!forceConstruct
&& (!mPendingContentInsets.equals(contentInsets) ||
!mPendingStableInsets.equals(stableInsets) ||
@@ -1788,10 +1810,16 @@
}
contentInsets = ensureInsetsNonNegative(contentInsets, "content");
stableInsets = ensureInsetsNonNegative(stableInsets, "stable");
- mLastWindowInsets = new WindowInsets(contentInsets,
- null /* windowDecorInsets */, stableInsets,
- mContext.getResources().getConfiguration().isScreenRound(),
- mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ if (USE_NEW_INSETS) {
+ mLastWindowInsets = mInsetsController.calculateInsets(
+ mContext.getResources().getConfiguration().isScreenRound(),
+ mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ } else {
+ mLastWindowInsets = new WindowInsets(contentInsets,
+ null /* windowDecorInsets */, stableInsets,
+ mContext.getResources().getConfiguration().isScreenRound(),
+ mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ }
}
return mLastWindowInsets;
}
@@ -1991,6 +2019,9 @@
if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
insetsChanged = true;
}
+ if (!mPendingInsets.equals(mInsetsController.getState())) {
+ insetsChanged = true;
+ }
if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
windowSizeMayChange = true;
@@ -2184,6 +2215,8 @@
mAttachInfo.mStableInsets);
final boolean cutoutChanged = !mPendingDisplayCutout.equals(
mAttachInfo.mDisplayCutout);
+ final boolean insetsStateChanged = !mPendingInsets.equals(
+ mInsetsController.getState());
final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
final boolean surfaceSizeChanged = (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
@@ -2221,6 +2254,10 @@
mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
contentInsetsChanged = true;
}
+ if (insetsStateChanged) {
+ mInsetsController.setState(mPendingInsets);
+ contentInsetsChanged = true;
+ }
if (contentInsetsChanged || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
|| mLastOverscanRequested != mAttachInfo.mOverscanRequested
@@ -2666,7 +2703,6 @@
}
private void maybeHandleWindowMove(Rect frame) {
-
// TODO: Well, we are checking whether the frame has changed similarly
// to how this is done for the insets. This is however incorrect since
// the insets and the frame are translated. For example, the old frame
@@ -4171,6 +4207,7 @@
private final static int MSG_UPDATE_POINTER_ICON = 27;
private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
private final static int MSG_DRAW_FINISHED = 29;
+ private final static int MSG_INSETS_CHANGED = 30;
final class ViewRootHandler extends Handler {
@Override
@@ -4226,6 +4263,8 @@
return "MSG_POINTER_CAPTURE_CHANGED";
case MSG_DRAW_FINISHED:
return "MSG_DRAW_FINISHED";
+ case MSG_INSETS_CHANGED:
+ return "MSG_INSETS_CHANGED";
}
return super.getMessageName(message);
}
@@ -4306,7 +4345,7 @@
|| !mPendingVisibleInsets.equals(args.arg3)
|| !mPendingOutsets.equals(args.arg7);
- mWinFrame.set((Rect) args.arg1);
+ setFrame((Rect) args.arg1);
mPendingOverscanInsets.set((Rect) args.arg5);
mPendingContentInsets.set((Rect) args.arg2);
mPendingStableInsets.set((Rect) args.arg6);
@@ -4329,16 +4368,25 @@
requestLayout();
}
break;
+ case MSG_INSETS_CHANGED:
+ mPendingInsets = (InsetsState) msg.obj;
+
+ // TODO: Full traversal not needed here
+ if (USE_NEW_INSETS) {
+ requestLayout();
+ }
+ break;
case MSG_WINDOW_MOVED:
if (mAdded) {
final int w = mWinFrame.width();
final int h = mWinFrame.height();
final int l = msg.arg1;
final int t = msg.arg2;
- mWinFrame.left = l;
- mWinFrame.right = l + w;
- mWinFrame.top = t;
- mWinFrame.bottom = t + h;
+ mTmpFrame.left = l;
+ mTmpFrame.right = l + w;
+ mTmpFrame.top = t;
+ mTmpFrame.bottom = t + h;
+ setFrame(mTmpFrame);
mPendingBackDropFrame.set(mWinFrame);
maybeHandleWindowMove(mWinFrame);
@@ -6724,9 +6772,9 @@
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
- mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
+ mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
- mPendingMergedConfiguration, mSurface);
+ mPendingMergedConfiguration, mSurface, mPendingInsets);
mPendingAlwaysConsumeNavBar =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6736,15 +6784,22 @@
}
if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+ mTranslator.translateRectInScreenToAppWinFrame(mTmpFrame);
mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
}
+ setFrame(mTmpFrame);
+
return relayoutResult;
}
+ private void setFrame(Rect frame) {
+ mWinFrame.set(frame);
+ mInsetsController.onFrameChanged(frame);
+ }
+
/**
* {@inheritDoc}
*/
@@ -6847,6 +6902,8 @@
mChoreographer.dump(prefix, writer);
+ mInsetsController.dump(prefix, writer);
+
writer.print(prefix); writer.println("View Hierarchy:");
dumpViewHierarchy(innerPrefix, writer, mView);
}
@@ -7055,6 +7112,10 @@
mHandler.sendMessage(msg);
}
+ private void dispatchInsetsChanged(InsetsState insetsState) {
+ mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
+ }
+
public void dispatchMoved(int newX, int newY) {
if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
if (mTranslator != null) {
@@ -8118,6 +8179,14 @@
}
@Override
+ public void insetsChanged(InsetsState insetsState) {
+ final ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchInsetsChanged(insetsState);
+ }
+ }
+
+ @Override
public void moved(int newX, int newY) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index b9d53c1..d78bfac 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -120,6 +120,8 @@
arg5 = null;
arg6 = null;
arg7 = null;
+ arg8 = null;
+ arg9 = null;
argi1 = 0;
argi2 = 0;
argi3 = 0;
diff --git a/core/java/com/android/internal/util/function/NonaConsumer.java b/core/java/com/android/internal/util/function/NonaConsumer.java
new file mode 100644
index 0000000..3e7ce2b
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 9-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface NonaConsumer<A, B, C, D, E, F, G, H, I> {
+ void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaFunction.java b/core/java/com/android/internal/util/function/NonaFunction.java
new file mode 100644
index 0000000..560b4f1
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Function;
+
+/**
+ * A 9-argument {@link Function}
+ *
+ * @hide
+ */
+public interface NonaFunction<A, B, C, D, E, F, G, H, I, R> {
+ R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaPredicate.java b/core/java/com/android/internal/util/function/NonaPredicate.java
new file mode 100644
index 0000000..c1e6f37
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 9-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface NonaPredicate<A, B, C, D, E, F, G, H, I> {
+ boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/OctConsumer.java b/core/java/com/android/internal/util/function/OctConsumer.java
new file mode 100644
index 0000000..83ee305
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 8-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface OctConsumer<A, B, C, D, E, F, G, H> {
+ void accept(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/OctFunction.java b/core/java/com/android/internal/util/function/OctFunction.java
new file mode 100644
index 0000000..cb16624
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Function;
+
+/**
+ * A 8-argument {@link Function}
+ *
+ * @hide
+ */
+public interface OctFunction<A, B, C, D, E, F, G, H, R> {
+ R apply(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/OctPredicate.java b/core/java/com/android/internal/util/function/OctPredicate.java
new file mode 100644
index 0000000..7f36d6a
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 8-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface OctPredicate<A, B, C, D, E, F, G, H> {
+ boolean test(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index 4ffe441..d74e715 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -22,6 +22,10 @@
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
@@ -39,61 +43,62 @@
*
* @hide
*/
-abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements
PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
+ OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>,
PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
- HeptConsumer<A, B, C, D, E, F, G>,
- PooledPredicate<A>, BiPredicate<A, B>,
+ HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
+ NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>,
PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
- abstract R invoke(A a, B b, C c, D d, E e, F f, G g);
+ abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i);
@Override
public R apply(A o, B o2) {
- return invoke(o, o2, null, null, null, null, null);
+ return invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public R apply(A o) {
- return invoke(o, null, null, null, null, null, null);
+ return invoke(o, null, null, null, null, null, null, null, null);
}
- public abstract <V> OmniFunction<A, B, C, D, E, F, G, V> andThen(
+ public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, V> andThen(
Function<? super R, ? extends V> after);
- public abstract OmniFunction<A, B, C, D, E, F, G, R> negate();
+ public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> negate();
@Override
public void accept(A o, B o2) {
- invoke(o, o2, null, null, null, null, null);
+ invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public void accept(A o) {
- invoke(o, null, null, null, null, null, null);
+ invoke(o, null, null, null, null, null, null, null, null);
}
@Override
public void run() {
- invoke(null, null, null, null, null, null, null);
+ invoke(null, null, null, null, null, null, null, null, null);
}
@Override
public R get() {
- return invoke(null, null, null, null, null, null, null);
+ return invoke(null, null, null, null, null, null, null, null, null);
}
@Override
public boolean test(A o, B o2) {
- return (Boolean) invoke(o, o2, null, null, null, null, null);
+ return (Boolean) invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public boolean test(A o) {
- return (Boolean) invoke(o, null, null, null, null, null, null);
+ return (Boolean) invoke(o, null, null, null, null, null, null, null, null);
}
@Override
@@ -108,52 +113,72 @@
@Override
public R apply(A a, B b, C c) {
- return invoke(a, b, c, null, null, null, null);
+ return invoke(a, b, c, null, null, null, null, null, null);
}
@Override
public void accept(A a, B b, C c) {
- invoke(a, b, c, null, null, null, null);
+ invoke(a, b, c, null, null, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d) {
- return invoke(a, b, c, d, null, null, null);
+ return invoke(a, b, c, d, null, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e) {
- return invoke(a, b, c, d, e, null, null);
+ return invoke(a, b, c, d, e, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e, F f) {
- return invoke(a, b, c, d, e, f, null);
+ return invoke(a, b, c, d, e, f, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e, F f, G g) {
- return invoke(a, b, c, d, e, f, g);
+ return invoke(a, b, c, d, e, f, g, null, null);
+ }
+
+ @Override
+ public R apply(A a, B b, C c, D d, E e, F f, G g, H h) {
+ return invoke(a, b, c, d, e, f, g, h, null);
+ }
+
+ @Override
+ public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+ return invoke(a, b, c, d, e, f, g, h, i);
}
@Override
public void accept(A a, B b, C c, D d) {
- invoke(a, b, c, d, null, null, null);
+ invoke(a, b, c, d, null, null, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e) {
- invoke(a, b, c, d, e, null, null);
+ invoke(a, b, c, d, e, null, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e, F f) {
- invoke(a, b, c, d, e, f, null);
+ invoke(a, b, c, d, e, f, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e, F f, G g) {
- invoke(a, b, c, d, e, f, g);
+ invoke(a, b, c, d, e, f, g, null, null);
+ }
+
+ @Override
+ public void accept(A a, B b, C c, D d, E e, F f, G g, H h) {
+ invoke(a, b, c, d, e, f, g, h, null);
+ }
+
+ @Override
+ public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+ invoke(a, b, c, d, e, f, g, h, i);
}
@Override
@@ -167,5 +192,5 @@
}
@Override
- public abstract OmniFunction<A, B, C, D, E, F, G, R> recycleOnUse();
+ public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse();
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index af3c752..c00932e 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -25,6 +25,10 @@
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
@@ -176,7 +180,8 @@
Consumer<? super A> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -192,7 +197,8 @@
Predicate<? super A> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -208,7 +214,8 @@
Function<? super A, ? extends R> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -238,7 +245,8 @@
A arg1) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -257,7 +265,8 @@
BiConsumer<? super A, ? super B> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -274,7 +283,8 @@
BiPredicate<? super A, ? super B> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -291,7 +301,8 @@
BiFunction<? super A, ? super B, ? extends R> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -308,7 +319,8 @@
BiConsumer<? super A, ? super B> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -325,7 +337,8 @@
BiPredicate<? super A, ? super B> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -342,7 +355,8 @@
BiFunction<? super A, ? super B, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -359,7 +373,8 @@
BiConsumer<? super A, ? super B> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -376,7 +391,8 @@
BiPredicate<? super A, ? super B> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -393,7 +409,8 @@
BiFunction<? super A, ? super B, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -424,7 +441,8 @@
A arg1, B arg2) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -444,7 +462,8 @@
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -462,7 +481,8 @@
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -480,7 +500,8 @@
TriConsumer<? super A, ? super B, ? super C> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -498,7 +519,8 @@
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -516,7 +538,8 @@
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -534,7 +557,8 @@
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -552,7 +576,8 @@
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -570,7 +595,8 @@
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -602,7 +628,8 @@
A arg1, B arg2, C arg3) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -623,7 +650,8 @@
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -642,7 +670,8 @@
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -661,7 +690,8 @@
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -680,7 +710,8 @@
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -699,7 +730,8 @@
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -718,7 +750,8 @@
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -737,7 +770,8 @@
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -756,7 +790,8 @@
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -775,7 +810,8 @@
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -794,7 +830,8 @@
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -827,7 +864,8 @@
A arg1, B arg2, C arg3, D arg4) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -849,7 +887,8 @@
QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
A arg1, B arg2, C arg3, D arg4, E arg5) {
return acquire(PooledLambdaImpl.sPool,
- function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
}
/**
@@ -869,7 +908,8 @@
QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
function, A arg1, B arg2, C arg3, D arg4, E arg5) {
return acquire(PooledLambdaImpl.sPool,
- function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
}
/**
@@ -904,7 +944,8 @@
A arg1, B arg2, C arg3, D arg4, E arg5) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -927,7 +968,8 @@
HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
return acquire(PooledLambdaImpl.sPool,
- function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
}
/**
@@ -948,7 +990,8 @@
HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
return acquire(PooledLambdaImpl.sPool,
- function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
}
/**
@@ -984,7 +1027,8 @@
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -1008,7 +1052,8 @@
HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
return acquire(PooledLambdaImpl.sPool,
- function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
}
/**
@@ -1031,7 +1076,8 @@
? super G, ? extends R> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
return acquire(PooledLambdaImpl.sPool,
- function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
}
/**
@@ -1068,7 +1114,195 @@
? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
+ return Message.obtain().setCallback(callback.recycleOnUse());
+ }
+ }
+
+ /**
+ * {@link PooledRunnable} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link PooledRunnable}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+ */
+ static <A, B, C, D, E, F, G, H> PooledRunnable obtainRunnable(
+ OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+ ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+ H arg8) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ }
+
+ /**
+ * {@link PooledSupplier} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link PooledSupplier}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+ */
+ static <A, B, C, D, E, F, G, H, R> PooledSupplier<R> obtainSupplier(
+ OctFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? extends R> function,
+ A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ }
+
+ /**
+ * Factory of {@link Message}s that contain an
+ * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+ * {@link Message#getCallback internal callback}.
+ *
+ * The callback is equivalent to one obtainable via
+ * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+ *
+ * Note that using this method with {@link android.os.Handler#handleMessage}
+ * is more efficient than the alternative of {@link android.os.Handler#post}
+ * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+ * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+ *
+ * You may optionally set a {@link Message#what} for the message if you want to be
+ * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+ * there's no need to do so
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+ * arg7, arg8) } when handled
+ */
+ static <A, B, C, D, E, F, G, H> Message obtainMessage(
+ OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+ ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+ H arg8) {
+ synchronized (Message.sPoolSync) {
+ PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+ function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ return Message.obtain().setCallback(callback.recycleOnUse());
+ }
+ }
+
+ /**
+ * {@link PooledRunnable} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link PooledRunnable}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+ */
+ static <A, B, C, D, E, F, G, H, I> PooledRunnable obtainRunnable(
+ NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+ E arg5, F arg6, G arg7, H arg8, I arg9) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
+ }
+
+ /**
+ * {@link PooledSupplier} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link PooledSupplier}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+ */
+ static <A, B, C, D, E, F, G, H, I, R> PooledSupplier<R> obtainSupplier(
+ NonaFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I, ? extends R> function,
+ A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
+ }
+
+ /**
+ * Factory of {@link Message}s that contain an
+ * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+ * {@link Message#getCallback internal callback}.
+ *
+ * The callback is equivalent to one obtainable via
+ * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+ *
+ * Note that using this method with {@link android.os.Handler#handleMessage}
+ * is more efficient than the alternative of {@link android.os.Handler#post}
+ * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+ * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+ *
+ * You may optionally set a {@link Message#what} for the message if you want to be
+ * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+ * there's no need to do so
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+ * arg7, arg8, arg9) } when handled
+ */
+ static <A, B, C, D, E, F, G, H, I> Message obtainMessage(
+ NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+ E arg5, F arg6, G arg7, H arg8, I arg9) {
+ synchronized (Message.sPoolSync) {
+ PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+ function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index eea1e5f..6be626a 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -30,6 +30,12 @@
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.HexPredicate;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.NonaPredicate;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.OctPredicate;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuadPredicate;
@@ -54,12 +60,12 @@
* @hide
*/
final class PooledLambdaImpl<R> extends OmniFunction<Object,
- Object, Object, Object, Object, Object, Object, R> {
+ Object, Object, Object, Object, Object, Object, Object, Object, R> {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "PooledLambdaImpl";
- private static final int MAX_ARGS = 7;
+ private static final int MAX_ARGS = 9;
private static final int MAX_POOL_SIZE = 50;
@@ -125,7 +131,7 @@
/**
* Bit schema:
- * AAAAAAABCDEEEEEEFFFFFF
+ * AAAAAAAAABCDEEEEEEFFFFFF
*
* Where:
* A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -161,17 +167,19 @@
}
@Override
- R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
+ R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) {
checkNotRecycled();
if (DEBUG) {
Log.i(LOG_TAG, this + ".invoke("
+ commaSeparateFirstN(
- new Object[] { a1, a2, a3, a4, a5, a6, a7 },
+ new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9 },
LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
+ ")");
}
- final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3)
- && fillInArg(a4) && fillInArg(a5) && fillInArg(a6) && fillInArg(a7);
+ final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
+ && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
+ && fillInArg(a9);
int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
if (argCount != LambdaType.MASK_ARG_COUNT) {
for (int i = 0; i < argCount; i++) {
@@ -335,7 +343,7 @@
popArg(2), popArg(3), popArg(4), popArg(5));
}
}
- }
+ } break;
case 7: {
switch (returnType) {
@@ -356,7 +364,49 @@
popArg(5), popArg(6));
}
}
- }
+ } break;
+
+ case 8: {
+ switch (returnType) {
+ case LambdaType.ReturnType.VOID: {
+ ((OctConsumer) mFunc).accept(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7));
+ return null;
+ }
+ case LambdaType.ReturnType.BOOLEAN: {
+ return (R) (Object) ((OctPredicate) mFunc).test(popArg(0),
+ popArg(1), popArg(2), popArg(3),
+ popArg(4), popArg(5), popArg(6), popArg(7));
+ }
+ case LambdaType.ReturnType.OBJECT: {
+ return (R) ((OctFunction) mFunc).apply(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7));
+ }
+ }
+ } break;
+
+ case 9: {
+ switch (returnType) {
+ case LambdaType.ReturnType.VOID: {
+ ((NonaConsumer) mFunc).accept(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4), popArg(5),
+ popArg(6), popArg(7), popArg(8));
+ return null;
+ }
+ case LambdaType.ReturnType.BOOLEAN: {
+ return (R) (Object) ((NonaPredicate) mFunc).test(popArg(0),
+ popArg(1), popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7), popArg(8));
+ }
+ case LambdaType.ReturnType.OBJECT: {
+ return (R) ((NonaFunction) mFunc).apply(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4), popArg(5),
+ popArg(6), popArg(7), popArg(8));
+ }
+ }
+ } break;
}
throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
}
@@ -419,8 +469,8 @@
* Internal non-typesafe factory method for {@link PooledLambdaImpl}
*/
static <E extends PooledLambda> E acquire(Pool pool, Object func,
- int fNumArgs, int numPlaceholders, int fReturnType,
- Object a, Object b, Object c, Object d, Object e, Object f, Object g) {
+ int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
+ Object d, Object e, Object f, Object g, Object h, Object i) {
PooledLambdaImpl r = acquire(pool);
if (DEBUG) {
Log.i(LOG_TAG,
@@ -436,6 +486,8 @@
+ ", e = " + e
+ ", f = " + f
+ ", g = " + g
+ + ", h = " + h
+ + ", i = " + i
+ ")");
}
r.mFunc = func;
@@ -449,6 +501,8 @@
setIfInBounds(r.mArgs, 4, e);
setIfInBounds(r.mArgs, 5, f);
setIfInBounds(r.mArgs, 6, g);
+ setIfInBounds(r.mArgs, 7, h);
+ setIfInBounds(r.mArgs, 8, i);
return (E) r;
}
@@ -474,13 +528,14 @@
}
@Override
- public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> negate() {
+ public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ R> negate() {
throw new UnsupportedOperationException();
}
@Override
- public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, V> andThen(
- Function<? super R, ? extends V> after) {
+ public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ V> andThen(Function<? super R, ? extends V> after) {
throw new UnsupportedOperationException();
}
@@ -500,7 +555,8 @@
}
@Override
- public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
+ public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ R> recycleOnUse() {
if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
mFlags |= FLAG_RECYCLE_ON_USE;
return this;
@@ -584,6 +640,8 @@
case 5: return "Quint";
case 6: return "Hex";
case 7: return "Hept";
+ case 8: return "Oct";
+ case 9: return "Nona";
default: throw new IllegalArgumentException("" + argCount);
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 137ca7f..36fe4fc 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -27,6 +27,7 @@
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.PointerIcon;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
@@ -53,6 +54,10 @@
}
@Override
+ public void insetsChanged(InsetsState insetsState) {
+ }
+
+ @Override
public void moved(int newX, int newY) {
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index e89b593..752624b 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -468,6 +468,10 @@
return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
}
+static jlong android_view_RenderNode_getUniqueId(jlong renderNodePtr) {
+ return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
+}
+
// ----------------------------------------------------------------------------
// RenderProperties - Animations
// ----------------------------------------------------------------------------
@@ -694,6 +698,7 @@
{ "nGetHeight", "(J)I", (void*) android_view_RenderNode_getHeight },
{ "nSetAllowForceDark", "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark },
{ "nGetAllowForceDark", "(J)Z", (void*) android_view_RenderNode_getAllowForceDark },
+ { "nGetUniqueId", "(J)J", (void*) android_view_RenderNode_getUniqueId },
};
int register_android_view_RenderNode(JNIEnv* env) {
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 18d1d5d..d5eaa00 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1601,6 +1601,10 @@
<attr name="request" />
<attr name="protectionLevel" />
<attr name="permissionFlags" />
+ <!-- If {@code true} applications that target Q <em>must</em> specify the permission usage
+ attributes in their {@code uses-permission} elements or the permission will not be
+ granted. -->
+ <attr name="usageInfoRequired" format="boolean" />
</declare-styleable>
<!-- The <code>permission-group</code> tag declares a logical grouping of
@@ -1700,6 +1704,81 @@
requested. If it does support the feature, it will be as if the manifest didn't
request it at all. -->
<attr name="requiredNotFeature" format="string" />
+
+ <!-- Specify if the app uploads data, or derived data, guarded by this permission.
+
+ If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataSentOffDevice">
+ <!-- The application may send data, or derived data, guarded by this permission off of the
+ device. -->
+ <enum name="yes" value="1" />
+ <!-- The application may send data, or derived data, guarded by this permission off of the
+ device, however it will only do so when explicitly triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application does not send data, or derived data, guarded by this permission off
+ of the device. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify if the application or its related off-device services provide data,
+ or derived data, guarded by this permission to third parties outside of the developer's
+ organization that do not qualify as data processors.
+
+ If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataSharedWithThirdParty">
+ <!-- The application or its services may provide data, or derived data, guarded by this
+ permission to third party organizations. -->
+ <enum name="yes" value="1" />
+ <!-- The application or its services may provide data, or derived data, guarded by this
+ permission to third party organizations, however it will only do so when explicitly
+ triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application or its services does not provide data, or derived data, guarded by
+ this permission to third party organizations. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify if the application or its related off-device services use data,
+ or derived data, guarded by this permission for monetization purposes.
+
+ For example, if the data is sold to another party or used for targeting advertisements
+ this must be set to {@code yes}.
+
+ If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataUsedForMonetization">
+ <!-- The application or its services may use data, or derived data, guarded by this
+ permission for monetization purposes. -->
+ <enum name="yes" value="1" />
+ <!-- The application or its services may use data, or derived data, guarded by this
+ permission for monetization purposes, however it will only do so when explicity
+ triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application or its services does not use data, or derived data, guarded by
+ this permission for monetization purposes. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify how long the application or its related off-device services store
+ data, or derived data, guarded by this permission.
+
+ This can be one of "notRetained", "userSelected", "unlimited", or a number
+ representing the number of weeks the data is retained.
+
+ If the permission is defined with {@link AndroidManifestPermission#usageRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataRetentionTime" format="string" />
+
</declare-styleable>
<!-- The <code>uses-configuration</code> tag specifies
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 73e0f85..feefcad 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2923,6 +2923,11 @@
<public name="importantForContentCapture" />
<public name="supportsMultipleDisplays" />
<public name="useAppZygote" />
+ <public name="usageInfoRequired" />
+ <public name="dataSentOffDevice" />
+ <public name="dataSharedWithThirdParty" />
+ <public name="dataUsedForMonetization" />
+ <public name="dataRetentionTime" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
new file mode 100644
index 0000000..ed472d2
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static junit.framework.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsSourceTest {
+
+ private InsetsSource mSource = new InsetsSource(TYPE_NAVIGATION_BAR);
+
+ @Before
+ public void setUp() {
+ mSource.setVisible(true);
+ }
+
+ @Test
+ public void testCalculateInsetsTop() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsBottom() {
+ mSource.setFrame(new Rect(0, 400, 500, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 100), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsLeft() {
+ mSource.setFrame(new Rect(0, 0, 100, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(100, 0, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsRight() {
+ mSource.setFrame(new Rect(400, 0, 500, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 100, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_overextend() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_invisible() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ mSource.setVisible(false);
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_ignoreVisibility() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ mSource.setVisible(false);
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ true /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ // Parcel and equals already tested via InsetsStateTest
+}
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
new file mode 100644
index 0000000..6bb9539
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsStateTest {
+
+ private InsetsState mState = new InsetsState();
+ private InsetsState mState2 = new InsetsState();
+
+ @Test
+ public void testCalculateInsets() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(new Rect(0, 100, 0, 100), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testCalculateInsets_imeAndNav() {
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(100, insets.getStableInsetBottom());
+ assertEquals(new Rect(0, 0, 0, 200), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testCalculateInsets_navRightStatusTop() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(new Rect(0, 100, 20, 0), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testStripForDispatch() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState.removeSource(TYPE_IME);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(0, insets.getSystemWindowInsetBottom());
+ }
+
+ @Test
+ public void testEquals_differentRect() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_differentSource() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_sameButDifferentInsertOrder() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ assertEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_visibility() {
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ Parcel p = Parcel.obtain();
+ mState.writeToParcel(p, 0 /* flags */);
+ mState2.readFromParcel(p);
+ p.recycle();
+ assertEquals(mState, mState2);
+ }
+}
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index de110c8..d9da27c 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -82,6 +82,17 @@
}
/**
+ * Add two Insets.
+ *
+ * @param a The first Insets to add.
+ * @param b The second Insets to add.
+ * @return a + b, i. e. all insets on every side are added together.
+ */
+ public static @NonNull Insets add(@NonNull Insets a, @NonNull Insets b) {
+ return Insets.of(a.left + b.left, a.top + b.top, a.right + b.right, a.bottom + b.bottom);
+ }
+
+ /**
* Two Insets instances are equal iff they belong to the same class and their fields are
* pairwise equal.
*
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index c4dc0ad..40a32f3 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -106,6 +106,20 @@
}
/**
+ * @hide
+ */
+ public Rect(@Nullable Insets r) {
+ if (r == null) {
+ left = top = right = bottom = 0;
+ } else {
+ left = r.left;
+ top = r.top;
+ right = r.right;
+ bottom = r.bottom;
+ }
+ }
+
+ /**
* Returns a copy of {@code r} if {@code r} is not {@code null}, or {@code null} otherwise.
*
* @hide
@@ -418,6 +432,18 @@
}
/**
+ * Insets the rectangle on all sides specified by the dimensions of {@code insets}.
+ * @hide
+ * @param insets The insets to inset the rect by.
+ */
+ public void inset(Insets insets) {
+ left += insets.left;
+ top += insets.top;
+ right -= insets.right;
+ bottom -= insets.bottom;
+ }
+
+ /**
* Insets the rectangle on all sides specified by the insets.
* @hide
* @param left The amount to add from the rectangle's left
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 45d7a21..d6f08b9 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -1173,6 +1173,22 @@
return nGetAllowForceDark(mNativeRenderNode);
}
+ /**
+ * Returns the unique ID that identifies this RenderNode. This ID is unique for the
+ * lifetime of the process. IDs are reset on process death, and are unique only within
+ * the process.
+ *
+ * This ID is intended to be used with debugging tools to associate a particular
+ * RenderNode across different debug dumping & inspection tools. For example
+ * a View layout inspector should include the unique ID for any RenderNodes that it owns
+ * to associate the drawing content with the layout content.
+ *
+ * @return the unique ID for this RenderNode
+ */
+ public long getUniqueId() {
+ return nGetUniqueId(mNativeRenderNode);
+ }
+
///////////////////////////////////////////////////////////////////////////
// Animations
///////////////////////////////////////////////////////////////////////////
@@ -1479,4 +1495,7 @@
@CriticalNative
private static native boolean nGetAllowForceDark(long renderNode);
+
+ @CriticalNative
+ private static native long nGetUniqueId(long renderNode);
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index caf610b..5bd59d4 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -713,11 +713,12 @@
}
/**
- * Whether this drawable requests projection.
+ * Whether this drawable requests projection. Indicates that the
+ * {@link android.graphics.RenderNode} this Drawable will draw into should be drawn immediately
+ * after the closest ancestor RenderNode containing a projection receiver.
*
- * @hide magic!
+ * @see android.graphics.RenderNode#setProjectBackwards(boolean)
*/
- @UnsupportedAppUsage
public boolean isProjected() {
return false;
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d2a8f02..4a63910 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -29,6 +29,7 @@
#include <SkPathOps.h>
#include <algorithm>
+#include <atomic>
#include <sstream>
#include <string>
@@ -47,8 +48,14 @@
TreeInfo* mTreeInfo;
};
+static int64_t generateId() {
+ static std::atomic<int64_t> sNextId{1};
+ return sNextId++;
+}
+
RenderNode::RenderNode()
- : mDirtyPropertyFields(0)
+ : mUniqueId(generateId())
+ , mDirtyPropertyFields(0)
, mNeedsDisplayListSync(false)
, mDisplayList(nullptr)
, mStagingDisplayList(nullptr)
@@ -444,5 +451,38 @@
return &mClippedOutlineCache.clippedOutline;
}
+using StringBuffer = FatVector<char, 128>;
+
+template <typename... T>
+static void format(StringBuffer& buffer, const std::string_view& format, T... args) {
+ buffer.resize(buffer.capacity());
+ while (1) {
+ int needed = snprintf(buffer.data(), buffer.size(),
+ format.data(), std::forward<T>(args)...);
+ if (needed < 0) {
+ buffer[0] = '\0';
+ buffer.resize(1);
+ return;
+ }
+ if (needed < buffer.size()) {
+ buffer.resize(needed + 1);
+ return;
+ }
+ buffer.resize(buffer.size() * 2);
+ }
+}
+
+void RenderNode::markDrawStart(SkCanvas& canvas) {
+ StringBuffer buffer;
+ format(buffer, "RenderNode(id=%d, name='%s')", uniqueId(), getName());
+ canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
+void RenderNode::markDrawEnd(SkCanvas& canvas) {
+ StringBuffer buffer;
+ format(buffer, "/RenderNode(id=%d, name='%s')", uniqueId(), getName());
+ canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index be0b46b..6060123 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -213,6 +213,11 @@
UsageHint usageHint() const { return mUsageHint; }
+ int64_t uniqueId() const { return mUniqueId; }
+
+ void markDrawStart(SkCanvas& canvas);
+ void markDrawEnd(SkCanvas& canvas);
+
private:
void computeOrderingImpl(RenderNodeOp* opState,
std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
@@ -233,6 +238,7 @@
void incParentRefCount() { mParentCount++; }
void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
+ const int64_t mUniqueId;
String8 mName;
sp<VirtualLightRefBase> mUserContext;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index ea14d11..d80cb6d 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -115,12 +115,26 @@
}
}
+class MarkDraw {
+public:
+ explicit MarkDraw(SkCanvas& canvas, RenderNode& node) : mCanvas(canvas), mNode(node) {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+ mNode.markDrawStart(mCanvas);
+ }
+ }
+ ~MarkDraw() {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+ mNode.markDrawEnd(mCanvas);
+ }
+ }
+private:
+ SkCanvas& mCanvas;
+ RenderNode& mNode;
+};
+
void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
RenderNode* renderNode = mRenderNode.get();
- if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
- SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
- canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
- }
+ MarkDraw _marker{*canvas, *renderNode};
// We only respect the nothingToDraw check when we are composing a layer. This
// ensures that we paint the layer even if it is not currently visible in the
diff --git a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
index 0678263..789d185 100644
--- a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
+++ b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
@@ -72,7 +72,6 @@
</LinearLayout>
<LinearLayout
- android:id="@+id/entity_header_links"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
@@ -85,6 +84,7 @@
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="0dp"
+ android:visibility="gone"
android:minWidth="24dp"
android:src="@null"
android:tint="?android:attr/colorAccent"/>
@@ -95,6 +95,7 @@
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="0dp"
+ android:visibility="gone"
android:minWidth="24dp"
android:src="@null"
android:tint="?android:attr/colorAccent"/>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 8b434a5..496aa0e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -323,7 +323,9 @@
post(new Runnable() {
@Override
public void run() {
- handleShowingDetail(detail, x, y, false /* toggleQs */);
+ if (isAttachedToWindow()) {
+ handleShowingDetail(detail, x, y, false /* toggleQs */);
+ }
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 0638998..3a96595d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -198,7 +198,8 @@
mIcon.setIcon(state, allowAnimations);
setContentDescription(state.contentDescription);
- mAccessibilityClass = state.expandedAccessibilityClassName;
+ mAccessibilityClass =
+ state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName;
if (state instanceof QSTile.BooleanState) {
boolean newState = ((BooleanState) state).value;
if (mTileState != newState) {
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 645723e..d1dbbff 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,5 @@
anniemeng@google.com
-artikz@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 7750c37..9ed978f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -554,7 +554,7 @@
final Handler mHandler;
@VisibleForTesting
- public final Handler mUidEventHandler;
+ final Handler mUidEventHandler;
private final ServiceThread mUidEventThread;
@@ -1465,7 +1465,7 @@
}
@VisibleForTesting
- public void updateNetworks() throws InterruptedException {
+ void updateNetworks() throws InterruptedException {
updateNetworksInternal();
final CountDownLatch latch = new CountDownLatch(1);
mHandler.post(() -> {
@@ -1510,7 +1510,7 @@
* @return cycleDay to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
+ int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
int fallbackCycleDay) {
if (config == null) {
return fallbackCycleDay;
@@ -1542,7 +1542,7 @@
* @return warningBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackWarningBytes) {
if (config == null) {
return fallbackWarningBytes;
@@ -1575,7 +1575,7 @@
* @return limitBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackLimitBytes) {
if (config == null) {
return fallbackLimitBytes;
@@ -2039,7 +2039,7 @@
}
@VisibleForTesting
- public NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
+ NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final RecurrenceRule cycleRule = NetworkPolicy
.buildRule(ZonedDateTime.now().getDayOfMonth(), ZoneId.systemDefault());
@@ -3489,7 +3489,7 @@
}
@VisibleForTesting
- public boolean isUidForeground(int uid) {
+ boolean isUidForeground(int uid) {
synchronized (mUidRulesFirstLock) {
return isUidStateForeground(
mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
@@ -3931,7 +3931,7 @@
* power saving restrictions may still apply.
*/
@VisibleForTesting
- public void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+ void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
synchronized (mUidRulesFirstLock) {
if (mAppIdleTempWhitelistAppIds.get(uid) == shouldWhitelist) {
// No change.
@@ -3956,7 +3956,7 @@
/** Return the list of UIDs currently in the app idle whitelist. */
@VisibleForTesting
- public int[] getAppIdleWhitelist() {
+ int[] getAppIdleWhitelist() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
synchronized (mUidRulesFirstLock) {
@@ -3971,7 +3971,7 @@
/** Returns if the UID is currently considered idle. */
@VisibleForTesting
- public boolean isUidIdle(int uid) {
+ boolean isUidIdle(int uid) {
synchronized (mUidRulesFirstLock) {
if (mAppIdleTempWhitelistAppIds.get(uid)) {
// UID is temporarily whitelisted.
@@ -4844,13 +4844,13 @@
}
@VisibleForTesting
- public void addIdleHandler(IdleHandler handler) {
+ void addIdleHandler(IdleHandler handler) {
mHandler.getLooper().getQueue().addIdleHandler(handler);
}
@GuardedBy("mUidRulesFirstLock")
@VisibleForTesting
- public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
+ void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
mRestrictBackgroundPowerState = result;
boolean restrictBackground = result.batterySaverEnabled;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f279af0..94d276c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -309,6 +309,7 @@
newConfig = mConfig.copy();
ZenRule rule = new ZenRule();
populateZenRule(automaticZenRule, rule, true);
+ newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, rule.component, true)) {
return rule.id;
} else {
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index e194d15..2d583ca3 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -105,6 +105,8 @@
*/
private boolean perUser;
+ boolean usageInfoRequired;
+
public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) {
name = _name;
sourcePackageName = _sourcePackageName;
@@ -351,6 +353,7 @@
}
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
+ bp.usageInfoRequired = p.info.usageInfoRequired;
}
if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
Log.d(TAG, " Permissions: " + r);
@@ -430,6 +433,7 @@
permissionInfo.packageName = sourcePackageName;
permissionInfo.nonLocalizedLabel = name;
permissionInfo.protectionLevel = protectionLevel;
+ permissionInfo.usageInfoRequired = usageInfoRequired;
return permissionInfo;
}
@@ -458,6 +462,7 @@
bp.protectionLevel = readInt(parser, null, "protection",
PermissionInfo.PROTECTION_NORMAL);
bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
+ bp.usageInfoRequired = readInt(parser, null, "usageInfoRequired", 0) != 0;
if (dynamic) {
final PermissionInfo pi = new PermissionInfo();
pi.packageName = sourcePackage.intern();
@@ -465,6 +470,7 @@
pi.icon = readInt(parser, null, "icon", 0);
pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
pi.protectionLevel = bp.protectionLevel;
+ pi.usageInfoRequired = bp.usageInfoRequired;
bp.pendingPermissionInfo = pi;
}
out.put(bp.name, bp);
@@ -497,6 +503,7 @@
if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
serializer.attribute(null, "protection", Integer.toString(protectionLevel));
}
+ serializer.attribute(null, "usageInfoRequired", usageInfoRequired ? "1" : "0");
if (type == BasePermission.TYPE_DYNAMIC) {
final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo;
if (pi != null) {
@@ -533,6 +540,7 @@
if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
// We'll take care of setting this one.
if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
+ if (pi1.usageInfoRequired != pi2.usageInfoRequired) return false;
// These are not currently stored in settings.
//if (!compareStrings(pi1.group, pi2.group)) return false;
//if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
@@ -580,6 +588,8 @@
pw.print(" enforced=");
pw.println(readEnforced);
}
+ pw.print(" usageInfoRequired=");
+ pw.println(usageInfoRequired);
return true;
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 4124210..b390eeb 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -30,6 +30,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
@@ -42,6 +44,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -334,5 +337,13 @@
return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false, true, name, null);
}
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new RoleManagerShellCommand(this)).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
new file mode 100644
index 0000000..e1977ef
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.server.role;
+
+import android.app.role.IRoleManager;
+import android.app.role.IRoleManagerCallback;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+class RoleManagerShellCommand extends ShellCommand {
+ private final IRoleManager mRoleManager;
+
+ RoleManagerShellCommand(IRoleManager roleManager) {
+ mRoleManager = roleManager;
+ }
+
+ private class Callback extends IRoleManagerCallback.Stub {
+ private final CompletableFuture<Void> mResult = new CompletableFuture<>();
+
+ public int waitForResult() {
+ try {
+ mResult.get(5, TimeUnit.SECONDS);
+ return 0;
+ } catch (Exception e) {
+ getErrPrintWriter().println("Error: " + e.toString());
+ return -1;
+ }
+ }
+
+ @Override
+ public void onSuccess() {
+ mResult.complete(null);
+ }
+
+ @Override
+ public void onFailure() {
+ mResult.completeExceptionally(new RuntimeException("Failed"));
+ }
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ PrintWriter pw = getOutPrintWriter();
+ try {
+ switch (cmd) {
+ case "add-role-holder":
+ return runAddRoleHolder();
+ case "remove-role-holder":
+ return runRemoveRoleHolder();
+ case "clear-role-holders":
+ return runClearRoleHolders();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int getUserIdMaybe() {
+ int userId = UserHandle.USER_SYSTEM;
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+ return userId;
+ }
+
+ private int runAddRoleHolder() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+ String packageName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.addRoleHolderAsUser(roleName, packageName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ private int runRemoveRoleHolder() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+ String packageName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.removeRoleHolderAsUser(roleName, packageName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ private int runClearRoleHolders() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.clearRoleHoldersAsUser(roleName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Role manager (role) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println();
+ pw.println(" add-role-holder [--user USER_ID] ROLE PACKAGE");
+ pw.println(" remove-role-holder [--user USER_ID] ROLE PACKAGE");
+ pw.println(" clear-role-holders [--user USER_ID] ROLE");
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 33584d4..84750b3 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -181,6 +181,11 @@
mWindowContainerController.onDisplayChanged();
}
+ @Override
+ public void onInitializeOverrideConfiguration(Configuration config) {
+ getOverrideConfiguration().updateFrom(config);
+ }
+
void addChild(ActivityStack stack, int position) {
if (position == POSITION_BOTTOM) {
position = 0;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8f99dae..11e998c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4511,6 +4511,21 @@
return mKeyguardController.isKeyguardLocked();
}
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @Override
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "clearLaunchParamsForPackages");
+ synchronized (mGlobalLock) {
+ for (int i = 0; i < packageNames.size(); ++i) {
+ mStackSupervisor.mLaunchParamsPersister.removeRecordForPackage(packageNames.get(i));
+ }
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a834ef1..c0e9836 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -34,6 +34,7 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.InsetsState.TYPE_IME;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -123,6 +124,7 @@
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -150,6 +152,7 @@
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InsetsState.InternalInsetType;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -161,6 +164,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
+import com.android.internal.util.function.TriConsumer;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.DisplayRotationUtil;
import com.android.server.wm.utils.RotationCache;
@@ -506,6 +510,8 @@
private final PointerEventDispatcher mPointerEventDispatcher;
+ private final InsetsStateController mInsetsStateController;
+
// Last systemUiVisibility we received from status bar.
private int mLastStatusBarVisibility = 0;
// Last systemUiVisibility we dispatched to windows.
@@ -902,6 +908,7 @@
mService.mAnimator.addDisplayLocked(mDisplayId);
mInputMonitor = new InputMonitor(service, mDisplayId);
+ mInsetsStateController = new InsetsStateController(this);
}
boolean isReady() {
@@ -1038,6 +1045,23 @@
return mDisplayRotation;
}
+ /**
+ * 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.
+ */
+ void setInsetProvider(@InternalInsetType int type, WindowState win,
+ @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+ mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
+ }
+
+ InsetsStateController getInsetsStateController() {
+ return mInsetsStateController;
+ }
+
@VisibleForTesting
void setDisplayRotation(DisplayRotation displayRotation) {
mDisplayRotation = displayRotation;
@@ -2712,6 +2736,8 @@
mDisplayRotation.dump(prefix, pw);
pw.println();
mInputMonitor.dump(pw, " ");
+ pw.println();
+ mInsetsStateController.dump(prefix, pw);
}
@Override
@@ -2994,6 +3020,8 @@
mInputMethodWindow.getDisplayId());
}
computeImeTarget(true /* updateImeTarget */);
+ mInsetsStateController.getSourceProvider(TYPE_IME).setWindow(win,
+ null /* frameProvider */);
}
/**
@@ -3449,6 +3477,7 @@
pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
"after finishPostLayoutPolicyLw", pendingLayoutChanges);
+ mInsetsStateController.onPostLayout();
} while (pendingLayoutChanges != 0);
mTmpApplySurfaceChangesTransactionState.reset();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index c16f95e..0e5947a 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -128,6 +129,7 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
@@ -804,6 +806,11 @@
if (mDisplayContent.isDefaultDisplay) {
mService.mPolicy.setKeyguardCandidateLw(win);
}
+ mDisplayContent.setInsetProvider(TYPE_TOP_BAR, win,
+ (displayFrames, windowState, rect) -> {
+ rect.top = 0;
+ rect.bottom = getStatusBarHeight(displayFrames);
+ });
break;
case TYPE_NAVIGATION_BAR:
mContext.enforceCallingOrSelfPermission(
@@ -818,6 +825,8 @@
mNavigationBarController.setWindow(win);
mNavigationBarController.setOnBarVisibilityChangedListener(
mNavBarVisibilityListener, true);
+ mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR,
+ win, null /* frameProvider */);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
case TYPE_NAVIGATION_BAR_PANEL:
@@ -845,9 +854,11 @@
if (mDisplayContent.isDefaultDisplay) {
mService.mPolicy.setKeyguardCandidateLw(null);
}
+ mDisplayContent.setInsetProvider(TYPE_TOP_BAR, null, null);
} else if (mNavigationBar == win) {
mNavigationBar = null;
mNavigationBarController.setWindow(null);
+ mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR, null, null);
}
if (mLastFocusedWindow == win) {
mLastFocusedWindow = null;
@@ -855,6 +866,11 @@
mScreenDecorWindows.remove(win);
}
+ private int getStatusBarHeight(DisplayFrames displayFrames) {
+ return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
+ displayFrames.mDisplayCutoutSafe.top);
+ }
+
/**
* Control the animation to run when a window's state changes. Return a
* non-0 number to force the animation to a specific resource ID, or 0
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f1d1e49..7aabc15 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,6 +31,7 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -57,6 +59,7 @@
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
private final DisplayPolicy mDisplayPolicy;
+ private final DisplayWindowSettings mDisplayWindowSettings;
private final Context mContext;
private final Object mLock;
@@ -71,10 +74,6 @@
private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver;
- // Default display does not rotate, apps that require non-default orientation will have to
- // have the orientation emulated.
- private boolean mForceDefaultOrientation;
-
private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@VisibleForTesting
@@ -93,6 +92,13 @@
private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
private int mUserRotation = Surface.ROTATION_0;
+ /**
+ * A flag to indicate if the display rotation should be fixed to user specified rotation
+ * regardless of all other states (including app requrested orientation). {@code true} the
+ * display rotation should be fixed to user specified rotation, {@code false} otherwise.
+ */
+ private boolean mFixedToUserRotation;
+
private int mDemoHdmiRotation;
private int mDemoRotation;
private boolean mDemoHdmiRotationLock;
@@ -100,15 +106,17 @@
DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
this(service, displayContent, displayContent.getDisplayPolicy(),
- service.mContext, service.getWindowManagerLock());
+ service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock());
}
@VisibleForTesting
DisplayRotation(WindowManagerService service, DisplayContent displayContent,
- DisplayPolicy displayPolicy, Context context, Object lock) {
+ DisplayPolicy displayPolicy, DisplayWindowSettings displayWindowSettings,
+ Context context, Object lock) {
mService = service;
mDisplayContent = displayContent;
mDisplayPolicy = displayPolicy;
+ mDisplayWindowSettings = displayWindowSettings;
mContext = context;
mLock = lock;
isDefaultDisplay = displayContent.isDefaultDisplay;
@@ -204,12 +212,19 @@
// so if the orientation is forced, we need to respect that no matter what.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
- mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ final boolean forceDefaultOrientationInRes =
+ res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
+ final boolean forceDefaultOrienation =
+ ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv)
+ && forceDefaultOrientationInRes
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ && !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ // Configuration says we force to use the default orientation. We can fall back to fix
+ // rotation to only user rotation. As long as OEM doesn't change user rotation then the
+ // rotation of this display is effectively stuck at 0 deg.
+ setFixedToUserRotation(forceDefaultOrienation);
}
void setRotation(int rotation) {
@@ -227,7 +242,14 @@
}
}
- void restoreUserRotation(int userRotationMode, int userRotation) {
+ void restoreSettings(int userRotationMode, int userRotation,
+ boolean fixedToUserRotation) {
+ mFixedToUserRotation = fixedToUserRotation;
+
+ // We will retrieve user rotation and user rotation mode from settings for default display.
+ if (isDefaultDisplay) {
+ return;
+ }
if (userRotationMode != WindowManagerPolicy.USER_ROTATION_FREE
&& userRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
Slog.w(TAG, "Trying to restore an invalid user rotation mode " + userRotationMode
@@ -243,6 +265,18 @@
mUserRotation = userRotation;
}
+ void setFixedToUserRotation(boolean fixedToUserRotation) {
+ if (mFixedToUserRotation == fixedToUserRotation) {
+ return;
+ }
+
+ mFixedToUserRotation = fixedToUserRotation;
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
+ fixedToUserRotation);
+ mService.updateRotation(true /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ }
+
private void setUserRotation(int userRotationMode, int userRotation) {
if (isDefaultDisplay) {
// We'll be notified via settings listener, so we don't need to update internal values.
@@ -265,7 +299,7 @@
mUserRotation = userRotation;
changed = true;
}
- mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+ mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
mService.updateRotation(true /* alwaysSendConfiguration */,
@@ -291,9 +325,8 @@
Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
}
- /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
- boolean isDefaultOrientationForced() {
- return mForceDefaultOrientation;
+ boolean isFixedToUserRotation() {
+ return mFixedToUserRotation;
}
public int getLandscapeRotation() {
@@ -399,6 +432,12 @@
* screen is switched off.
*/
private boolean needSensorRunning() {
+ if (mFixedToUserRotation) {
+ // We are sure we only respect user rotation settings, so we are sure we will not
+ // support sensor rotation.
+ return false;
+ }
+
if (mSupportAutoRotation) {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -459,8 +498,8 @@
);
}
- if (mForceDefaultOrientation) {
- return Surface.ROTATION_0;
+ if (mFixedToUserRotation) {
+ return mUserRotation;
}
int sensorRotation = mOrientationListener != null
@@ -701,8 +740,8 @@
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mForceDefaultOrientation) {
- return false; // Rotation is forced to default orientation.
+ if (mFixedToUserRotation) {
+ return false; // Rotation is forced to user settings.
}
final int lidState = mDisplayPolicy.getLidState();
@@ -861,6 +900,7 @@
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+ pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
}
private class OrientationListener extends WindowOrientationListener {
@@ -945,4 +985,10 @@
}
}
}
+
+ @VisibleForTesting
+ interface ContentObserverRegister {
+ void registerContentObserver(Uri uri, boolean notifyForDescendants,
+ ContentObserver observer, @UserIdInt int userHandle);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f7dfd3f..45d77de 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -80,6 +80,7 @@
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
+ private boolean mFixedToUserRotation;
private Entry(String name) {
mName = name;
@@ -97,7 +98,8 @@
&& mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
- && !mShouldShowIme;
+ && !mShouldShowIme
+ && !mFixedToUserRotation;
}
}
@@ -186,6 +188,13 @@
writeSettingsIfNeeded(entry, displayInfo);
}
+ void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final Entry entry = getOrCreateEntry(displayInfo);
+ entry.mFixedToUserRotation = fixedToUserRotation;
+ writeSettingsIfNeeded(entry, displayInfo);
+ }
+
private int getWindowingModeLocked(Entry entry, int displayId) {
int windowingMode = entry != null ? entry.mWindowingMode
: WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -331,7 +340,8 @@
displayInfo.overscanRight = entry.mOverscanRight;
displayInfo.overscanBottom = entry.mOverscanBottom;
- dc.getDisplayRotation().restoreUserRotation(entry.mUserRotationMode, entry.mUserRotation);
+ dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
+ entry.mUserRotation, entry.mFixedToUserRotation);
if (entry.mForcedDensity != 0) {
dc.mBaseDisplayDensity = entry.mForcedDensity;
@@ -458,6 +468,8 @@
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
+ entry.mFixedToUserRotation = getBooleanAttribute(parser,
+ "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -541,6 +553,10 @@
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
+ if (entry.mFixedToUserRotation) {
+ out.attribute(null, "fixedToUserRotation",
+ Boolean.toString(entry.mFixedToUserRotation));
+ }
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
new file mode 100644
index 0000000..e96f0b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.view.InsetsSource;
+
+import com.android.internal.util.function.TriConsumer;
+import com.android.server.policy.WindowManagerPolicy;
+
+/**
+ * Controller for a specific inset source on the server. It's called provider as it provides the
+ * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
+ */
+class InsetsSourceProvider {
+
+ private final Rect mTmpRect = new Rect();
+ private final @NonNull InsetsSource mSource;
+ private WindowState mWin;
+ private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
+
+ InsetsSourceProvider(InsetsSource source) {
+ mSource = source;
+ }
+
+ InsetsSource getSource() {
+ return mSource;
+ }
+
+ /**
+ * Updates the window that currently backs this source.
+ *
+ * @param win The window that links to this source.
+ * @param frameProvider Based on display frame state and the window, calculates the resulting
+ * frame that should be reported to clients.
+ */
+ void setWindow(@Nullable WindowState win,
+ @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+ if (mWin != null) {
+ mWin.setInsetProvider(null);
+ }
+ mWin = win;
+ mFrameProvider = frameProvider;
+ if (win == null) {
+ mSource.setVisible(false);
+ mSource.setFrame(new Rect());
+ } else {
+ mSource.setVisible(true);
+ mWin.setInsetProvider(this);
+ }
+ }
+
+ /**
+ * Called when a layout pass has occurred.
+ */
+ void onPostLayout() {
+ if (mWin == null) {
+ return;
+ }
+
+ mTmpRect.set(mWin.getFrameLw());
+ if (mFrameProvider != null) {
+ mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
+ } else {
+ mTmpRect.inset(mWin.mGivenContentInsets);
+ }
+ mSource.setFrame(mTmpRect);
+ mSource.setVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);
+
+ }
+}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
new file mode 100644
index 0000000..1189ee6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+
+import android.util.ArrayMap;
+import android.view.InsetsState;
+
+import java.io.PrintWriter;
+import java.util.function.Consumer;
+
+/**
+ * Manages global window inset state in the system represented by {@link InsetsState}.
+ */
+class InsetsStateController {
+
+ private final InsetsState mLastState = new InsetsState();
+ private final InsetsState mState = new InsetsState();
+ private final DisplayContent mDisplayContent;
+ private ArrayMap<Integer, InsetsSourceProvider> mControllers = new ArrayMap<>();
+
+ private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
+ if (w.isVisible()) {
+ w.notifyInsetsChanged();
+ }
+ };
+
+ InsetsStateController(DisplayContent displayContent) {
+ mDisplayContent = displayContent;
+ }
+
+ /**
+ * When dispatching window state to the client, we'll need to exclude the source that represents
+ * the window that is being dispatched.
+ *
+ * @param target The client we dispatch the state to.
+ * @return The state stripped of the necessary information.
+ */
+ InsetsState getInsetsForDispatch(WindowState target) {
+ final InsetsSourceProvider provider = target.getInsetProvider();
+ if (provider == null) {
+ return mState;
+ }
+
+ final InsetsState state = new InsetsState();
+ state.set(mState);
+ final int type = provider.getSource().getType();
+ state.removeSource(type);
+
+ // Navigation bar doesn't get influenced by anything else
+ if (type == TYPE_NAVIGATION_BAR) {
+ state.removeSource(TYPE_IME);
+ state.removeSource(TYPE_TOP_BAR);
+ }
+ return state;
+ }
+
+ /**
+ * @return The provider of a specific type.
+ */
+ InsetsSourceProvider getSourceProvider(int type) {
+ return mControllers.computeIfAbsent(type,
+ key -> new InsetsSourceProvider(mState.getSource(key)));
+ }
+
+ /**
+ * Called when a layout pass has occurred.
+ */
+ void onPostLayout() {
+ for (int i = mControllers.size() - 1; i>= 0; i--) {
+ mControllers.valueAt(i).onPostLayout();
+ }
+ if (!mLastState.equals(mState)) {
+ mLastState.set(mState, true /* copySources */);
+ notifyInsetsChanged();
+ }
+ }
+
+ private void notifyInsetsChanged() {
+ mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "WindowInsetsStateController");
+ mState.dump(prefix + " ", pw);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index da9a507..bc6a690 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -269,7 +269,7 @@
outParams.mBounds.set(persistableParams.mBounds);
}
- private void onPackageRemoved(String packageName) {
+ void removeRecordForPackage(String packageName) {
final List<File> fileToDelete = new ArrayList<>();
for (int i = 0; i < mMap.size(); ++i) {
int userId = mMap.keyAt(i);
@@ -310,7 +310,7 @@
@Override
public void onPackageRemoved(String packageName) {
- LaunchParamsPersister.this.onPackageRemoved(packageName);
+ removeRecordForPackage(packageName);
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c2bc677..80d1368 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -233,6 +233,7 @@
final DisplayContent existing = getDisplayContent(displayId);
if (existing != null) {
+ initializeDisplayOverrideConfiguration(controller, existing);
existing.setController(controller);
return existing;
}
@@ -242,6 +243,7 @@
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
+ initializeDisplayOverrideConfiguration(controller, dc);
if (mService.mDisplayManagerInternal != null) {
mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
@@ -254,6 +256,19 @@
return dc;
}
+ /**
+ * The display content may have configuration set from {@link #DisplayWindowSettings}. This
+ * callback let the owner of container know there is existing configuration to prevent the
+ * values from being replaced by the initializing {@link #ActivityDisplay}.
+ */
+ private void initializeDisplayOverrideConfiguration(DisplayWindowController controller,
+ DisplayContent displayContent) {
+ if (controller != null && controller.mListener != null) {
+ controller.mListener.onInitializeOverrideConfiguration(
+ displayContent.getOverrideConfiguration());
+ }
+ }
+
boolean isLayoutNeeded() {
final int numDisplays = mChildren.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index ee0e89b..3947bd4 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -222,7 +222,7 @@
}
public ScreenRotationAnimation(Context context, DisplayContent displayContent,
- boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
+ boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) {
mService = service;
mContext = context;
mDisplayContent = displayContent;
@@ -234,7 +234,7 @@
final int originalWidth;
final int originalHeight;
DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (forceDefaultOrientation) {
+ if (fixedToUserRotation) {
// Emulated orientation.
mForceDefaultOrientation = true;
originalWidth = displayContent.mBaseDisplayWidth;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 6838c55..37b5a7c 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -50,6 +50,7 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import android.view.InsetsState;
import android.view.WindowManager;
import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -153,17 +154,21 @@
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+ InsetsState outInsetsState) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
- outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
+ outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,
+ outInsetsState);
}
@Override
public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
+ int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
+ InsetsState outInsetsState) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
- new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */);
+ new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
+ outInsetsState);
}
@Override
@@ -182,7 +187,7 @@
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
- Surface outSurface) {
+ Surface outSurface, InsetsState outInsetsState) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -190,7 +195,7 @@
requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, cutout,
- mergedConfiguration, outSurface);
+ mergedConfiguration, outSurface, outInsetsState);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 8f02f8a..9a56606 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -66,6 +66,7 @@
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -142,6 +143,7 @@
final Rect taskBounds;
final Rect tmpContentInsets = new Rect();
final Rect tmpStableInsets = new Rect();
+ final InsetsState mTmpInsetsState = new InsetsState();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
int backgroundColor = WHITE;
int statusBarColor = 0;
@@ -202,7 +204,7 @@
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
- tmpRect, tmpCutout, null);
+ tmpRect, tmpCutout, null, mTmpInsetsState);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
return null;
@@ -218,7 +220,7 @@
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
tmpFrame, tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
- tmpCutout, tmpMergedConfiguration, surface);
+ tmpCutout, tmpMergedConfiguration, surface, mTmpInsetsState);
} catch (RemoteException e) {
// Local call.
}
diff --git a/services/core/java/com/android/server/wm/WindowContainerListener.java b/services/core/java/com/android/server/wm/WindowContainerListener.java
index 4b3cd36..3d3d2e0 100644
--- a/services/core/java/com/android/server/wm/WindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/WindowContainerListener.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import android.content.res.Configuration;
+
/**
* Interface used by the owner/creator of the container to listen to changes with the container.
* @see WindowContainerController
@@ -23,4 +25,5 @@
public interface WindowContainerListener {
void registerConfigurationChangeListener(ConfigurationContainerListener listener);
void unregisterConfigurationChangeListener(ConfigurationContainerListener listener);
+ default void onInitializeOverrideConfiguration(Configuration config) {}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5df3451..4085f3d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -218,6 +218,7 @@
import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowContentFrameStats;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.RemoveContentMode;
@@ -1111,7 +1112,8 @@
public int addWindow(Session session, IWindow client, int seq,
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+ InsetsState outInsetsState) {
int[] appOp = new int[1];
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -1459,6 +1461,7 @@
outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
}
+ outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -1856,7 +1859,7 @@
long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
- Surface outSurface) {
+ Surface outSurface, InsetsState outInsetsState) {
int result = 0;
boolean configChanged;
final boolean hasStatusBarPermission =
@@ -2157,6 +2160,7 @@
outStableInsets, outOutsets);
outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
+ outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
if (localLOGV) Slog.v(
TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth
@@ -3587,6 +3591,17 @@
}
}
+ void setRotateForApp(int displayId, boolean enabled) {
+ synchronized (mGlobalLock) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to set rotate for app for a missing display.");
+ return;
+ }
+ display.getDisplayRotation().setFixedToUserRotation(enabled);
+ }
+ }
+
@Override
public void freezeRotation(int rotation) {
freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
@@ -5393,7 +5408,7 @@
displayContent.updateDisplayInfo();
screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
+ displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
this);
mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
screenRotationAnimation);
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bf77ba8..6865ce3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -76,6 +76,8 @@
getNextArgRequired());
case "set-user-rotation":
return runSetDisplayUserRotation(pw);
+ case "set-fix-to-user-rotation":
+ return runSetFixToUserRotation(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -297,6 +299,32 @@
}
}
+ private int runSetFixToUserRotation(PrintWriter pw) {
+ int displayId = Display.DEFAULT_DISPLAY;
+ String arg = getNextArgRequired();
+ if ("-d".equals(arg)) {
+ displayId = Integer.parseInt(getNextArgRequired());
+ arg = getNextArgRequired();
+ }
+
+ final boolean enabled;
+ switch (arg) {
+ case "enabled":
+ enabled = true;
+ break;
+ case "disabled":
+ enabled = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
+ + arg);
+ return -1;
+ }
+
+ mInternal.setRotateForApp(displayId, enabled);
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -316,6 +344,8 @@
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
pw.println(" Set user rotation mode and user rotation.");
+ pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
+ pw.println(" Enable or disable rotating display for app requested orientation.");
if (!IS_USER) {
pw.println(" tracing (start | stop)");
pw.println(" Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 91c3288..cfd1f86 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -143,6 +143,7 @@
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
import android.annotation.CallSuper;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -194,6 +195,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowManagerPolicy.DisplayContentInfo;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.utils.InsetUtils;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -578,6 +580,8 @@
*/
private boolean mIsDimming = false;
+ private @Nullable InsetsSourceProvider mInsetProvider;
+
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@@ -2955,6 +2959,18 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ /**
+ * Called when the insets state changed.
+ */
+ void notifyInsetsChanged() {
+ try {
+ mClient.insetsChanged(
+ getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to deliver inset state change", e);
+ }
+ }
+
Rect getBackdropFrame(Rect frame) {
// When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
// start even if we haven't received the relayout window, so that the client requests
@@ -4776,6 +4792,14 @@
mWindowFrames.setContentChanged(false);
}
+ void setInsetProvider(InsetsSourceProvider insetProvider) {
+ mInsetProvider = insetProvider;
+ }
+
+ InsetsSourceProvider getInsetProvider() {
+ return mInsetProvider;
+ }
+
private final class MoveAnimationSpec implements AnimationSpec {
private final long mDuration;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 92efc3c..99b827c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -72,7 +72,6 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -142,9 +141,8 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
-import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.net.NetworkStatsManagerInternal;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
import com.google.common.util.concurrent.AbstractFuture;
@@ -195,15 +193,6 @@
/**
* Tests for {@link NetworkPolicyManagerService}.
- *
- * <p>Typical usage:
- *
- * <pre><code>
- m -j32 FrameworksServicesTests && adb install -r -g \
- ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
- adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
- "com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner"
- * </code></pre>
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -376,7 +365,7 @@
return null;
}
}).when(mActivityManager).registerUidObserver(any(), anyInt(),
- eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), isNull(String.class));
+ eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
mFutureIntent = newRestrictBackgroundChangedFuture();
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
@@ -425,7 +414,7 @@
// catch INetworkManagementEventObserver during systemReady()
final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
- ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
@@ -1782,7 +1771,7 @@
}
private static NetworkPolicy buildFakeMobilePolicy(int cycleDay, long warningBytes,
- long limitBytes, boolean inferred){
+ long limitBytes, boolean inferred) {
final NetworkTemplate template = buildTemplateMobileAll(FAKE_SUBSCRIBER_ID);
return new NetworkPolicy(template, cycleDay, new Time().timezone, warningBytes,
limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
@@ -1880,7 +1869,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals("notification type mismatch for '" + actualTag +"'",
+ assertEquals("notification type mismatch for '" + actualTag + "'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1914,7 +1903,8 @@
final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
final Intent intent = future.get(5, TimeUnit.SECONDS);
assertNotNull("Didn't get a " + action + "intent in 5 seconds");
- assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
+ assertEquals("Wrong package on " + action + " intent",
+ expectedPackage, intent.getPackage());
}
// TODO: replace by Truth, Hamcrest, or a similar tool.
@@ -1935,7 +1925,7 @@
}
if (errors.length() > 0) {
fail("assertContainsInAnyOrder(expected=" + Arrays.toString(expected)
- + ", actual=" + Arrays.toString(actual) +") failed: \n" + errors);
+ + ", actual=" + Arrays.toString(actual) + ") failed: \n" + errors);
}
}
@@ -1998,7 +1988,7 @@
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
- Log.d(TAG,"counting down on answer: " + invocation);
+ Log.d(TAG, "counting down on answer: " + invocation);
latch.countDown();
return null;
}
@@ -2036,8 +2026,8 @@
final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
final File netConfigFile = new File(mPolicyDir, "netpolicy.xml");
Log.d(TAG, "Creating " + netConfigFile + " from asset " + assetPath);
- try (final InputStream in = context.getResources().getAssets().open(assetPath);
- final OutputStream out = new FileOutputStream(netConfigFile)) {
+ try (InputStream in = context.getResources().getAssets().open(assetPath);
+ OutputStream out = new FileOutputStream(netConfigFile)) {
Streams.copy(in, out);
}
}
@@ -2049,9 +2039,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NetPolicyXml {
-
- public String value() default "";
-
+ String value() default "";
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index d798865..ce59e6e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -31,6 +31,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
+import android.content.pm.UsesPermissionInfo;
import android.os.Bundle;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -464,6 +465,7 @@
pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
pkg.requestedPermissions.add("foo7");
+ pkg.usesPermissionInfos.add(new UsesPermissionInfo("foo7"));
pkg.implicitPermissions.add("foo25");
pkg.protectedBroadcasts = new ArrayList<>();
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index b823e70..7f390a5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -27,7 +27,12 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.WindowConfiguration;
import android.platform.test.annotations.Presubmit;
@@ -378,6 +383,33 @@
mSecondaryDisplay.getDisplayRotation().getUserRotation());
}
+ @Test
+ public void testNotFixedToUserRotationByDefault() {
+ mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_0);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ }
+
+ @Test
+ public void testSetFixedToUserRotation() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ }
+
private static void assertOverscan(DisplayContent display, int left, int top, int right,
int bottom) {
final DisplayInfo info = display.getDisplayInfo();
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
new file mode 100644
index 0000000..241b987
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsSourceProviderTest extends WindowTestsBase {
+
+ private InsetsSourceProvider mProvider = new InsetsSourceProvider(
+ new InsetsSource(TYPE_TOP_BAR));
+
+ @Test
+ public void testPostLayout() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ topBar.mHasSurface = true;
+ mProvider.setWindow(topBar, null);
+ mProvider.onPostLayout();
+ assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
+ assertEquals(Insets.of(0, 100, 0, 0),
+ mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+ }
+
+ @Test
+ public void testPostLayout_invisible() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ mProvider.setWindow(topBar, null);
+ mProvider.onPostLayout();
+ assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+ }
+
+ @Test
+ public void testPostLayout_frameProvider() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ mProvider.setWindow(topBar,
+ (displayFrames, windowState, rect) -> {
+ rect.set(10, 10, 20, 20);
+ });
+ mProvider.onPostLayout();
+ assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
new file mode 100644
index 0000000..7505db1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsStateControllerTest extends WindowTestsBase {
+
+ @Test
+ public void testStripForDispatch_notOwn() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ topBar.setInsetProvider(
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+ assertNotNull(mDisplayContent.getInsetsStateController().getInsetsForDispatch(app)
+ .getSource(TYPE_TOP_BAR));
+ }
+
+ @Test
+ public void testStripForDispatch_own() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ topBar.setInsetProvider(
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+ assertEquals(new InsetsState(),
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(topBar));
+ }
+
+ @Test
+ public void testStripForDispatch_navBar() {
+ final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState ime = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_NAVIGATION_BAR)
+ .setWindow(navBar, null);
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_IME)
+ .setWindow(ime, null);
+ assertEquals(new InsetsState(),
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(navBar));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index 99deeb9..432af0d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -24,6 +24,7 @@
import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IWindow;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
@@ -39,6 +40,9 @@
Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException {
}
+ @Override
+ public void insetsChanged(InsetsState insetsState) throws RemoteException {
+ }
@Override
public void moved(int newX, int newY) throws RemoteException {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 38d8e39..6c7ede3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -41,6 +41,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
@@ -1097,6 +1098,25 @@
assertFalse(Objects.equals(defaultRuleName, ruleAfterUpdating.name)); // update name
}
+ @Test
+ public void testAddAutomaticZenRule() {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+
+ assertTrue(id != null);
+ ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
+ assertTrue(ruleInConfig != null);
+ assertEquals(zenRule.isEnabled(), ruleInConfig.enabled);
+ assertEquals(zenRule.isModified(), ruleInConfig.modified);
+ assertEquals(zenRule.getConditionId(), ruleInConfig.conditionId);
+ assertEquals(NotificationManager.zenModeFromInterruptionFilter(
+ zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode);
+ assertEquals(zenRule.getName(), ruleInConfig.name);
+ }
+
private void setupZenConfig() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index f128b4e2..67acec6 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -37,6 +37,8 @@
<application android:debuggable="true"
android:testOnly="true">
+ <uses-library android:name="android.test.mock" android:required="true" />
+
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityA" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityB" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
new file mode 100644
index 0000000..e988994
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2018 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.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.PowerManagerInternal;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.view.Surface;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class for {@link DisplayRotation}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayRotationTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
+public class DisplayRotationTests {
+ private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50;
+
+ private StatusBarManagerInternal mPreviousStatusBarManagerInternal;
+
+ private WindowManagerService mMockWm;
+ private DisplayContent mMockDisplayContent;
+ private DisplayPolicy mMockDisplayPolicy;
+ private Context mMockContext;
+ private Resources mMockRes;
+ private SensorManager mMockSensorManager;
+ private Sensor mFakeSensor;
+ private DisplayWindowSettings mMockDisplayWindowSettings;
+ private ContentResolver mMockResolver;
+ private FakeSettingsProvider mFakeSettingsProvider;
+ private StatusBarManagerInternal mMockStatusBarManagerInternal;
+
+ // Fields below are callbacks captured from test target.
+ private ContentObserver mShowRotationSuggestionsObserver;
+ private ContentObserver mAccelerometerRotationObserver;
+ private ContentObserver mUserRotationObserver;
+ private SensorEventListener mOrientationSensorListener;
+
+ private DisplayRotationBuilder mBuilder;
+
+ private DisplayRotation mTarget;
+
+ @Before
+ public void setUp() {
+ FakeSettingsProvider.clearSettingsProvider();
+
+ mMockWm = mock(WindowManagerService.class);
+ mMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
+
+ mPreviousStatusBarManagerInternal = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class);
+ LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
+
+ mBuilder = new DisplayRotationBuilder();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ if (mPreviousStatusBarManagerInternal != null) {
+ LocalServices.addService(StatusBarManagerInternal.class,
+ mPreviousStatusBarManagerInternal);
+ mPreviousStatusBarManagerInternal = null;
+ }
+ }
+
+ // ================================
+ // Display Settings Related Tests
+ // ================================
+ @Test
+ public void testLocksUserRotation_LockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ assertEquals(0, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ assertEquals(Surface.ROTATION_180, Settings.System.getInt(mMockResolver,
+ Settings.System.USER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(mMockDisplayContent,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_180);
+ }
+
+ @Test
+ public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ assertEquals(1, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(same(mMockDisplayContent),
+ eq(WindowManagerPolicy.USER_ROTATION_FREE), anyInt());
+ }
+
+ @Test
+ public void testPersistsFixedToUserRotation() throws Exception {
+ mBuilder.build();
+
+ mTarget.setFixedToUserRotation(true);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(false);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ }
+
+ // ========================================
+ // Tests for User Rotation based Rotation
+ // ========================================
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_NoAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_CompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsSidesays_UserRotationLocked_IncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_90);
+ assertTrue("Rotation should be sideways, but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ // =================================
+ // Tests for Sensor based Rotation
+ // =================================
+ private void verifyOrientationListenerRegistration(int numOfInvocation) {
+ final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(
+ SensorEventListener.class);
+ verify(mMockSensorManager, times(numOfInvocation)).registerListener(
+ listenerCaptor.capture(),
+ same(mFakeSensor),
+ anyInt(),
+ any());
+ if (numOfInvocation > 0) {
+ mOrientationSensorListener = listenerCaptor.getValue();
+ }
+ }
+
+ @Test
+ public void testNotEnablesSensor_AutoRotationNotSupported() throws Exception {
+ mBuilder.setSupportAutoRotation(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ScreenNotOn() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(false);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_NotAwake() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(false);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_KeyguardNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(false);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_WindowManagerNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(false);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_FixedUserRotation() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.setFixedToUserRotation(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ private void enableOrientationSensor() {
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(1);
+ }
+
+ private SensorEvent createSensorEvent(int rotation) throws Exception {
+ final Constructor<SensorEvent> constructor =
+ SensorEvent.class.getDeclaredConstructor(int.class);
+ constructor.setAccessible(true);
+ final SensorEvent event = constructor.newInstance(1);
+ event.sensor = mFakeSensor;
+ event.values[0] = rotation;
+ event.timestamp = SystemClock.elapsedRealtimeNanos();
+ return event;
+ }
+
+ @Test
+ public void testReturnsSensorRotation_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ private boolean waitForUiHandler() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ UiThread.getHandler().post(latch::countDown);
+ return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void testUpdatesRotationWhenSensorUpdates_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockWm).updateRotation(false, false);
+ }
+
+ @Test
+ public void testNotifiesChoiceWhenSensorUpdates_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);
+ }
+
+ @Test
+ public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ final int rotation = mTarget.rotationForOrientation(SCREEN_ORIENTATION_LANDSCAPE,
+ Surface.ROTATION_0);
+ assertTrue("Rotation should be sideways but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ @Test
+ public void testReturnsUserRotation_SensorEnabled_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ // =================================
+ // Tests for Policy based Rotation
+ // =================================
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsLidOpenRotation_LidOpen() throws Exception {
+ mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getLidState()).thenReturn(
+ WindowManagerPolicy.WindowManagerFuncs.LID_OPEN);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testReturnsCarDockRotation_CarDockedMode() throws Exception {
+ mBuilder.setCarDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_CAR);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsDeskDockRotation_DeskDockedMode() throws Exception {
+ mBuilder.setDeskDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ mTarget.setFixedToUserRotation(true);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90);
+ assertEquals(Surface.ROTATION_180, rotation);
+ }
+
+ @Test
+ public void testReturnsUserRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ /**
+ * Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
+ * according to given parameters.
+ */
+ private void configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv) {
+ final int width;
+ final int height;
+ switch (displayOrientation) {
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ width = 1920;
+ height = 1080;
+ break;
+ case SCREEN_ORIENTATION_PORTRAIT:
+ width = 1080;
+ height = 1920;
+ break;
+ default:
+ throw new IllegalArgumentException("displayOrientation needs to be either landscape"
+ + " or portrait, but we got "
+ + ActivityInfo.screenOrientationToString(displayOrientation));
+ }
+
+ final PackageManager mockPackageManager = mock(PackageManager.class);
+ when(mMockContext.getPackageManager()).thenReturn(mockPackageManager);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ .thenReturn(isCar);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ .thenReturn(isTv);
+
+ final int shortSizeDp = (isCar || isTv) ? 540 : 720;
+ final int longSizeDp = 960;
+ mTarget.configure(width, height, shortSizeDp, longSizeDp);
+ }
+
+ private void freezeRotation(int rotation) {
+ mTarget.freezeRotation(rotation);
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private void thawRotation() {
+ mTarget.thawRotation();
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private class DisplayRotationBuilder {
+ private boolean mIsDefaultDisplay = true;
+ private boolean mSupportAutoRotation = true;
+
+ private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+ private int mCarDockRotation;
+ private int mDeskDockRotation;
+ private int mUndockedHdmiRotation;
+
+ private DisplayRotationBuilder setIsDefaultDisplay(boolean isDefaultDisplay) {
+ mIsDefaultDisplay = isDefaultDisplay;
+ return this;
+ }
+
+ private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) {
+ mSupportAutoRotation = supportAutoRotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setLidOpenRotation(int rotation) {
+ mLidOpenRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setCarDockRotation(int rotation) {
+ mCarDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setDeskDockRotation(int rotation) {
+ mDeskDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setUndockedHdmiRotation(int rotation) {
+ mUndockedHdmiRotation = rotation;
+ return this;
+ }
+
+ private void captureObservers() {
+ ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(
+ ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.Secure.getUriFor(Settings.Secure.SHOW_ROTATION_SUGGESTIONS)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mShowRotationSuggestionsObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mAccelerometerRotationObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.USER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mUserRotationObserver = captor.getValue();
+ }
+ }
+
+ private Sensor createSensor(int type) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+
+ setSensorType(sensor, type);
+ setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+ setSensorField(sensor, "mVendor", "Mock Vendor");
+ setSensorField(sensor, "mVersion", 1);
+ setSensorField(sensor, "mHandle", -1);
+ setSensorField(sensor, "mMaxRange", 10);
+ setSensorField(sensor, "mResolution", 1);
+ setSensorField(sensor, "mPower", 1);
+ setSensorField(sensor, "mMinDelay", 1000);
+ setSensorField(sensor, "mMaxDelay", 1000000000);
+ setSensorField(sensor, "mFlags", 0);
+ setSensorField(sensor, "mId", -1);
+
+ return sensor;
+ }
+
+ private void setSensorType(Sensor sensor, int type) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ }
+
+ private void setSensorField(Sensor sensor, String fieldName, Object value)
+ throws Exception {
+ Field field = Sensor.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(sensor, value);
+ }
+
+ private int convertRotationToDegrees(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return 0;
+ case Surface.ROTATION_90:
+ return 90;
+ case Surface.ROTATION_180:
+ return 180;
+ case Surface.ROTATION_270:
+ return 270;
+ default:
+ return -1;
+ }
+ }
+
+ private void build() throws Exception {
+ mMockContext = mock(Context.class);
+
+ mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
+ mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
+
+ mMockDisplayPolicy = mock(DisplayPolicy.class);
+
+ mMockRes = mock(Resources.class);
+ when(mMockContext.getResources()).thenReturn((mMockRes));
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation))
+ .thenReturn(mSupportAutoRotation);
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation))
+ .thenReturn(convertRotationToDegrees(mLidOpenRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_carDockRotation))
+ .thenReturn(convertRotationToDegrees(mCarDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_deskDockRotation))
+ .thenReturn(convertRotationToDegrees(mDeskDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
+ .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+
+ mMockSensorManager = mock(SensorManager.class);
+ when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
+ .thenReturn(mMockSensorManager);
+ mFakeSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION);
+ when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn(
+ Collections.singletonList(mFakeSensor));
+
+ mMockResolver = mock(ContentResolver.class);
+ when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
+ mFakeSettingsProvider = new FakeSettingsProvider();
+ when(mMockResolver.acquireProvider(Settings.AUTHORITY))
+ .thenReturn(mFakeSettingsProvider.getIContentProvider());
+
+ mMockDisplayWindowSettings = mock(DisplayWindowSettings.class);
+ mTarget = new DisplayRotation(mMockWm, mMockDisplayContent, mMockDisplayPolicy,
+ mMockDisplayWindowSettings, mMockContext, new Object());
+
+ captureObservers();
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 2c3c66b..f3a125b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -272,6 +272,51 @@
}
@Test
+ public void testClearsRecordInMemory() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ mTarget.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsWriteQueueItem() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsFile() {
+ mTarget.saveTask(mTestTask);
+ mPersisterQueue.flush();
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+
+ @Test
public void testClearsRecordInMemoryOnPackageUninstalled() {
mTarget.saveTask(mTestTask);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index e56edab..3c87721 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -65,7 +65,7 @@
final DisplayRotation displayRotation = new DisplayRotation(
mock(WindowManagerService.class), displayContent, displayPolicy,
- context, new Object());
+ mock(DisplayWindowSettings.class), context, new Object());
displayRotation.mPortraitRotation = Surface.ROTATION_0;
displayRotation.mLandscapeRotation = Surface.ROTATION_90;
displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 34a8c96..45cfe1e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -569,14 +569,6 @@
public static final String IS_OPPORTUNISTIC = "is_opportunistic";
/**
- * TelephonyProvider column name for subId of parent subscription of an opportunistic
- * subscription.
- * if the parent sub id is valid, then is_opportunistic should always to true.
- * @hide
- */
- public static final String PARENT_SUB_ID = "parent_sub_id";
-
- /**
* TelephonyProvider column name for group ID. Subscriptions with same group ID
* are considered bundled together, and should behave as a single subscription at
* certain scenarios.
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
index ae3914e..d5987a5 100644
--- a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -26,6 +26,7 @@
import android.view.Display;
import android.view.DisplayCutout;
import android.view.IWindowSession;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
@@ -105,7 +106,7 @@
window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, -1, mTmpRect,
mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
new DisplayCutout.ParcelableWrapper(), new MergedConfiguration(),
- new Surface());
+ new Surface(), new InsetsState());
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -131,8 +132,9 @@
final IWindowSession session = WindowManagerGlobal.getWindowSession();
final Rect tmpRect = new Rect();
try {
- final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
- View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+ final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq,
+ layoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect,
+ new InsetsState());
} catch (RemoteException e) {
e.printStackTrace();
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 3ec8a41..364d5084 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -58,7 +58,7 @@
*/
oneway void requestActivityInfo(in ResultReceiver result);
- ParceledListSlice getConfiguredNetworks();
+ ParceledListSlice getConfiguredNetworks(String packageName);
ParceledListSlice getPrivilegedConfiguredNetworks();
@@ -90,11 +90,11 @@
List<ScanResult> getScanResults(String callingPackage);
- void disconnect(String packageName);
+ boolean disconnect(String packageName);
- void reconnect(String packageName);
+ boolean reconnect(String packageName);
- void reassociate(String packageName);
+ boolean reassociate(String packageName);
WifiInfo getConnectionInfo(String callingPackage);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7aff03c..8dd6c77 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1067,7 +1067,7 @@
public List<WifiConfiguration> getConfiguredNetworks() {
try {
ParceledListSlice<WifiConfiguration> parceledList =
- mService.getConfiguredNetworks();
+ mService.getConfiguredNetworks(mContext.getOpPackageName());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1761,8 +1761,7 @@
@Deprecated
public boolean disconnect() {
try {
- mService.disconnect(mContext.getOpPackageName());
- return true;
+ return mService.disconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1786,8 +1785,7 @@
@Deprecated
public boolean reconnect() {
try {
- mService.reconnect(mContext.getOpPackageName());
- return true;
+ return mService.reconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1811,8 +1809,7 @@
@Deprecated
public boolean reassociate() {
try {
- mService.reassociate(mContext.getOpPackageName());
- return true;
+ return mService.reassociate(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2132,14 +2129,14 @@
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
- * @return {@code false} Will always return true.
+ * @return {@code false}.
* @deprecated There is no need to call this method -
* {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
* and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
@Deprecated
public boolean saveConfiguration() {
- return true;
+ return false;
}
/**
@@ -3406,6 +3403,11 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
// Use INVALID_NETWORK_ID for arg1 when passing a config object
@@ -3426,7 +3428,12 @@
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
@@ -3452,7 +3459,12 @@
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
@@ -3471,7 +3483,12 @@
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void forget(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
@@ -3486,7 +3503,12 @@
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void disable(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
@@ -3498,6 +3520,12 @@
* @param SSID, in the format of WifiConfiguration's SSID.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void disableEphemeralNetwork(String SSID) {
if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
try {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 529548f..6622a25 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -184,6 +184,9 @@
public static final String SCAN_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
/** {@hide} */
public static final String SCAN_PARAMS_WORK_SOURCE_KEY = "WorkSource";
+ /** {@hide} */
+ public static final String REQUEST_PACKAGE_NAME_KEY = "PackageName";
+
/**
* scan configuration parameters to be sent to {@link #startBackgroundScan}
*/
@@ -798,6 +801,7 @@
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
mAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
}
@@ -812,8 +816,11 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key, scanParams);
}
+
/**
* reports currently available scan results on appropriate listeners
* @return true if all scan results were reported correctly
@@ -821,7 +828,10 @@
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public boolean getScanResults() {
validateChannel();
- Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ Message reply =
+ mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0, 0, scanParams);
return reply.what == CMD_OP_SUCCEEDED;
}
@@ -856,6 +866,7 @@
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
@@ -870,7 +881,9 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key, scanParams);
}
/**
@@ -879,7 +892,10 @@
*/
public List<ScanResult> getSingleScanResults() {
validateChannel();
- Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0, 0,
+ scanParams);
if (reply.what == WifiScanner.CMD_OP_SUCCEEDED) {
return Arrays.asList(((ParcelableScanResults) reply.obj).getResults());
}
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
index 04bc557..aa526d2 100644
--- a/wifi/java/com/android/server/wifi/AbstractWifiService.java
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -73,7 +73,7 @@
}
@Override
- public ParceledListSlice getConfiguredNetworks() {
+ public ParceledListSlice getConfiguredNetworks(String packageName) {
throw new UnsupportedOperationException();
}
@@ -188,17 +188,17 @@
}
@Override
- public void disconnect(String packageName) {
+ public boolean disconnect(String packageName) {
throw new UnsupportedOperationException();
}
@Override
- public void reconnect(String packageName) {
+ public boolean reconnect(String packageName) {
throw new UnsupportedOperationException();
}
@Override
- public void reassociate(String packageName) {
+ public boolean reassociate(String packageName) {
throw new UnsupportedOperationException();
}