Merge "Restore some greylist entries." into qt-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index 74725bc..1dc6faa 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2294,6 +2294,7 @@
field public static final String NAMESPACE_PRIVACY = "privacy";
field public static final String NAMESPACE_ROLLBACK = "rollback";
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
+ field public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
}
public static interface DeviceConfig.OnPropertiesChangedListener {
@@ -2310,6 +2311,10 @@
method @Nullable public String getString(@NonNull String, @Nullable String);
}
+ public static interface DeviceConfig.WindowManager {
+ field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+ }
+
public final class MediaStore {
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 10f25ea..c30a6f4 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -581,6 +581,7 @@
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName;
Landroid/service/euicc/IEuiccService$Stub;-><init>()V
+Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
Landroid/service/notification/INotificationListener$Stub;-><init>()V
Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 769fd48..360be35 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1017,6 +1017,7 @@
}
}
+ @UnsupportedAppUsage
@Override
public boolean setInstantAppCookie(@NonNull byte[] cookie) {
try {
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 60fb6fb..a812c32 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,6 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -83,6 +84,7 @@
*
* @hide
*/
+ @UnsupportedAppUsage
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
"android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
@@ -303,6 +305,7 @@
* @return false on immediate error, true otherwise
* @hide
*/
+ @UnsupportedAppUsage
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
final IBluetoothHearingAid service = getService();
@@ -331,6 +334,7 @@
* is not active, it will be null on that position. Returns empty list on error.
* @hide
*/
+ @UnsupportedAppUsage
@RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 1838bab..f39fc66 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.os.Parcel;
import android.os.Parcelable;
@@ -169,6 +170,7 @@
* The state of this OverlayInfo as defined by the STATE_* constants in this class.
* @hide
*/
+ @UnsupportedAppUsage
public final @State int state;
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 89be000..b377678 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -8396,6 +8396,7 @@
PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
Collections.emptySet(), state);
pi.applicationInfo.sourceDir = apexFile.getPath();
+ pi.applicationInfo.publicSourceDir = apexFile.getPath();
if (apexInfo.isFactory) {
pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
} else {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 04e8cf4..5ac13d8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -925,14 +925,14 @@
* case, when the application configures a RAW stream, the camera device will make sure
* the active physical camera will remain active to ensure consistent RAW output
* behavior, and not switch to other physical cameras.</p>
- * <p>To maintain backward compatibility, the capture request and result metadata tags
- * required for basic camera functionalities will be solely based on the
- * logical camera capabiltity. Other request and result metadata tags, on the other
- * hand, will be based on current active physical camera. For example, the physical
- * cameras' sensor sensitivity and lens capability could be different from each other.
- * So when the application manually controls sensor exposure time/gain, or does manual
- * focus control, it must checks the current active physical camera's exposure, gain,
- * and focus distance range.</p>
+ * <p>The capture request and result metadata tags required for backward compatible camera
+ * functionalities will be solely based on the logical camera capabiltity. On the other
+ * hand, the use of manual capture controls (sensor or post-processing) with a
+ * logical camera may result in unexpected behavior when the HAL decides to switch
+ * between physical cameras with different characteristics under the hood. For example,
+ * when the application manually sets exposure time and sensitivity while zooming in,
+ * the brightness of the camera images may suddenly change because HAL switches from one
+ * physical camera to the other.</p>
*
* @see CameraCharacteristics#LENS_DISTORTION
* @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index b121234..d70ba99 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -68,6 +68,7 @@
public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
/** @hide An undefined user id */
+ @UnsupportedAppUsage
public static final @UserIdInt int USER_NULL = -10000;
/**
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 3ab5c51..5b2e3a2 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -808,6 +808,9 @@
@Override
public void run() {
+ if (mBackupReader.getStatus() != AsyncTask.Status.PENDING) {
+ return;
+ }
mBackupReader.execute();
ParcelFileDescriptor remotePipe = mBackupReader.getRemotePipe();
@@ -919,6 +922,9 @@
@Override
public void run(@NonNull IPermissionController service) {
+ if (mBackupSender.getStatus() != AsyncTask.Status.PENDING) {
+ return;
+ }
mBackupSender.execute(mBackup);
ParcelFileDescriptor remotePipe = mBackupSender.getRemotePipe();
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 19dbc6a..920eb4b 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -285,6 +285,15 @@
public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
/**
+ * Namespace for window manager related features. The names to access the properties in this
+ * namespace should be defined in {@link WindowManager}.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
+
+ /**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
*
* @hide
@@ -301,6 +310,23 @@
@TestApi
public static final String NAMESPACE_PRIVACY = "privacy";
+ /**
+ * Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
+ * @hide
+ */
+ @TestApi
+ public interface WindowManager {
+
+ /**
+ * Key for accessing the system gesture exclusion limit (an integer in dp).
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ @TestApi
+ String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+ }
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertyChangedListener, Pair<String, Executor>> sSingleListeners =
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 882e6fd..2e9d881 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -184,7 +184,7 @@
boolean mIsTouchExplorationEnabled;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768939)
+ @UnsupportedAppUsage(trackingBug = 123768939L)
boolean mIsHighTextContrastEnabled;
AccessibilityPolicy mAccessibilityPolicy;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 564d972..86cec5e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -206,13 +206,13 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public ApplicationInfo mApplication;
/**
* The resource ID of the layout file. (Added to the parcel)
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private final int mLayoutId;
/**
@@ -224,13 +224,13 @@
* An array of actions to perform on the view tree once it has been
* inflated
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private ArrayList<Action> mActions;
/**
* Maps bitmaps to unique indicies to avoid Bitmap duplication.
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private BitmapCache mBitmapCache;
/**
@@ -252,7 +252,7 @@
* RemoteViews.
*/
private RemoteViews mLandscape = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private RemoteViews mPortrait = null;
@ApplyFlags
@@ -430,7 +430,7 @@
// Do nothing
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int mergeBehavior() {
return MERGE_REPLACE;
}
@@ -466,7 +466,7 @@
// Nothing to visit by default
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
int viewId;
}
@@ -499,7 +499,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void mergeRemoteViews(RemoteViews newRv) {
if (newRv == null) return;
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
@@ -690,7 +690,7 @@
return SET_PENDING_INTENT_TEMPLATE_TAG;
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
PendingIntent pendingIntentTemplate;
}
@@ -1138,7 +1138,7 @@
private static class BitmapCache {
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
ArrayList<Bitmap> mBitmaps;
int mBitmapMemory = -1;
@@ -1190,9 +1190,9 @@
private class BitmapReflectionAction extends Action {
int bitmapId;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
Bitmap bitmap;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
String methodName;
BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) {
@@ -1258,10 +1258,10 @@
static final int COLOR_STATE_LIST = 15;
static final int ICON = 16;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
String methodName;
int type;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
Object value;
ReflectionAction(int viewId, String methodName, int type, Object value) {
@@ -1554,7 +1554,7 @@
* ViewGroup methods that are related to adding Views.
*/
private class ViewGroupActionAdd extends Action {
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
private RemoteViews mNestedViews;
private int mIndex;
@@ -2469,7 +2469,7 @@
* Returns an estimate of the bitmap heap memory usage for this RemoteViews.
*/
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int estimateMemoryUsage() {
return mBitmapCache.getBitmapMemory();
}
@@ -2517,7 +2517,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void addView(int viewId, RemoteViews nestedView, int index) {
addAction(new ViewGroupActionAdd(viewId, nestedView, index));
}
@@ -2994,7 +2994,8 @@
* @hide
* @deprecated this appears to have no users outside of UnsupportedAppUsage?
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
+ @Deprecated
public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) {
addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount));
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7cc8128..f905ea2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -29,7 +29,6 @@
import android.app.VoiceInteractor.PickOptionRequest;
import android.app.VoiceInteractor.PickOptionRequest.Option;
import android.app.VoiceInteractor.Prompt;
-import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -111,7 +110,6 @@
protected AbsListView mAdapterView;
private Button mAlwaysButton;
private Button mOnceButton;
- private Button mSettingsButton;
protected View mProfileView;
private int mIconDpi;
private int mLastSelected = AbsListView.INVALID_POSITION;
@@ -146,6 +144,10 @@
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
+ private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
+ private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+ private static final String OPEN_LINKS_COMPONENT_KEY = "app_link_state";
+
private final PackageMonitor mPackageMonitor = createPackageMonitor();
/**
@@ -196,9 +198,13 @@
// titles for layout that deals with http(s) intents
public static final int BROWSABLE_TITLE_RES =
- com.android.internal.R.string.whichGiveAccessToApplication;
- public static final int BROWSABLE_NAMED_TITLE_RES =
- com.android.internal.R.string.whichGiveAccessToApplicationNamed;
+ com.android.internal.R.string.whichOpenLinksWith;
+ public static final int BROWSABLE_HOST_TITLE_RES =
+ com.android.internal.R.string.whichOpenHostLinksWith;
+ public static final int BROWSABLE_HOST_APP_TITLE_RES =
+ com.android.internal.R.string.whichOpenHostLinksWithApp;
+ public static final int BROWSABLE_APP_TITLE_RES =
+ com.android.internal.R.string.whichOpenLinksWithApp;
public final String action;
public final int titleRes;
@@ -322,9 +328,7 @@
? false
: isHttpSchemeAndViewAction(getTargetIntent());
- // We don't want to support Always Use if browsable layout is being used,
- // as to mitigate Intent Capturing vulnerability
- mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;
+ mSupportsAlwaysUseOption = supportsAlwaysUseOption;
if (configureContentView(mIntents, initialIntents, rList)) {
return;
@@ -554,10 +558,21 @@
} else if (isHttpSchemeAndViewAction(intent)) {
// If the Intent's scheme is http(s) then we need to warn the user that
// they're giving access for the activity to open URLs from this specific host
- return named
- ? getString(ActionTitle.BROWSABLE_NAMED_TITLE_RES, intent.getData().getHost(),
- mAdapter.getFilteredItem().getDisplayLabel())
- : getString(ActionTitle.BROWSABLE_TITLE_RES, intent.getData().getHost());
+ String dialogTitle = null;
+ if (named && !mUseLayoutForBrowsables) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_APP_TITLE_RES,
+ mAdapter.getFilteredItem().getDisplayLabel());
+ } else if (named && mUseLayoutForBrowsables) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_HOST_APP_TITLE_RES,
+ intent.getData().getHost(),
+ mAdapter.getFilteredItem().getDisplayLabel());
+ } else if (mAdapter.areAllTargetsBrowsers()) {
+ dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES);
+ } else {
+ dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES,
+ intent.getData().getHost());
+ }
+ return dialogTitle;
} else {
return named
? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
@@ -856,6 +871,13 @@
} else {
enabled = true;
}
+ if (mUseLayoutForBrowsables && !ri.handleAllWebDataURI) {
+ mAlwaysButton.setText(getResources()
+ .getString(R.string.activity_resolver_set_always));
+ } else {
+ mAlwaysButton.setText(getResources()
+ .getString(R.string.activity_resolver_use_always));
+ }
}
mAlwaysButton.setEnabled(enabled);
}
@@ -866,26 +888,29 @@
? mAdapter.getFilteredPosition()
: mAdapterView.getCheckedItemPosition();
boolean hasIndexBeenFiltered = !mAdapter.hasFilteredItem();
- if (id == R.id.button_app_settings) {
- showSettingsForSelected(which, hasIndexBeenFiltered);
+ ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+ if (!ri.handleAllWebDataURI && id == R.id.button_always) {
+ showSettingsForSelected(ri);
} else {
startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
}
}
- private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
- ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+ private void showSettingsForSelected(ResolveInfo ri) {
Intent intent = new Intent();
- // For browsers, we open the Default Browser page
+
+ final String packageName = ri.activityInfo.packageName;
+ Bundle showFragmentArgs = new Bundle();
+ showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY);
+ showFragmentArgs.putString("package", packageName);
+
// For regular apps, we open the Open by Default page
- if (ri.handleAllWebDataURI) {
- intent.setAction(Intent.ACTION_MANAGE_DEFAULT_APP)
- .putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_BROWSER);
- } else {
- intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
- .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- }
+ intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
+ .setData(Uri.fromParts("package", packageName, null))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+ .putExtra(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY)
+ .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
+
startActivity(intent);
}
@@ -1332,41 +1357,15 @@
R.dimen.resolver_button_bar_spacing) + inset);
mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
- mSettingsButton = (Button) buttonLayout.findViewById(R.id.button_app_settings);
mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
- if (mUseLayoutForBrowsables) {
- resetSettingsOrOnceButtonBar();
- } else {
- resetAlwaysOrOnceButtonBar();
- }
+ resetAlwaysOrOnceButtonBar();
} else {
Log.e(TAG, "Layout unexpectedly does not have a button bar");
}
}
- private void resetSettingsOrOnceButtonBar() {
- //unsetting always button
- mAlwaysButton.setVisibility(View.GONE);
-
- // When the items load in, if an item was already selected,
- // enable the buttons
- if (mAdapterView != null
- && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
- mSettingsButton.setEnabled(true);
- mOnceButton.setEnabled(true);
- }
- }
-
private void resetAlwaysOrOnceButtonBar() {
- // This check needs to be made because layout with default
- // doesn't have a settings button
- if (mSettingsButton != null) {
- //unsetting always button
- mSettingsButton.setVisibility(View.GONE);
- mSettingsButton = null;
- }
-
if (useLayoutWithDefault()
&& mAdapter.getFilteredPosition() != ListView.INVALID_POSITION) {
setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
@@ -1626,6 +1625,7 @@
private DisplayResolveInfo mOtherProfile;
private ResolverListController mResolverListController;
private int mPlaceholderCount;
+ private boolean mAllTargetsAreBrowsers = false;
protected final LayoutInflater mInflater;
@@ -1701,6 +1701,14 @@
}
/**
+ * @return true if all items in the display list are defined as browsers by
+ * ResolveInfo.handleAllWebDataURI
+ */
+ public boolean areAllTargetsBrowsers() {
+ return mAllTargetsAreBrowsers;
+ }
+
+ /**
* Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
* to complete.
*
@@ -1712,6 +1720,7 @@
mOtherProfile = null;
mLastChosen = null;
mLastChosenPosition = -1;
+ mAllTargetsAreBrowsers = false;
mDisplayList.clear();
if (mBaseResolveList != null) {
currentResolveList = mUnfilteredResolveList = new ArrayList<>();
@@ -1812,6 +1821,8 @@
private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
int N;
if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
+ mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
+
// First put the initial items at the top.
if (mInitialIntents != null) {
for (int i = 0; i < mInitialIntents.length; i++) {
@@ -1841,6 +1852,8 @@
ri.noResourceId = true;
ri.icon = 0;
}
+ mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
addResolveInfo(new DisplayResolveInfo(ii, ri,
ri.loadLabel(getPackageManager()), null, ii));
}
@@ -1850,6 +1863,8 @@
for (ResolvedComponentInfo rci : sortedComponents) {
final ResolveInfo ri = rci.getResolveInfoAt(0);
if (ri != null) {
+ mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
ResolveInfoPresentationGetter pg = makePresentationGetter(ri);
addResolveInfoWithAlternates(rci, pg.getSubLabel(), pg.getLabel());
}
@@ -2152,14 +2167,8 @@
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (!useLayoutWithDefault()
&& (!hasValidSelection || mLastSelected != checkedPos)
- && (mAlwaysButton != null || mSettingsButton != null)) {
- if (mSettingsButton != null) {
- // this implies that the layout for browsables is being used
- mSettingsButton.setEnabled(true);
- } else {
- // this implies that mAlwaysButton != null
- setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
- }
+ && mAlwaysButton != null) {
+ setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
mAdapterView.smoothScrollToPosition(checkedPos);
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 64291de..d00108e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -16,8 +16,6 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuPresenter.Callback;
-
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,14 +24,14 @@
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.Build;
-import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow.OnDismissListener;
+import com.android.internal.view.menu.MenuPresenter.Callback;
+
/**
* Presents a menu as a small, simple popup anchored to another view.
*/
@@ -114,7 +112,7 @@
* @param forceShowIcon {@code true} to force icons to be shown, or
* {@code false} for icons to be optionally shown
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public void setForceShowIcon(boolean forceShowIcon) {
mForceShowIcon = forceShowIcon;
if (mPopup != null) {
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index aeaccfd..1dd4207 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -129,18 +129,6 @@
android:enabled="false"
android:text="@string/activity_resolver_use_always"
android:onClick="onButtonClick" />
-
- <Button
- android:id="@+id/button_app_settings"
- android:layout_width="wrap_content"
- android:layout_gravity="end"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?attr/buttonBarPositiveButtonStyle"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:text="@string/activity_resolver_app_settings"
- android:onClick="onButtonClick" />
</LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a8f1c64..152b131 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3074,12 +3074,20 @@
<string name="whichViewApplicationNamed">Open with %1$s</string>
<!-- Label for a link to a intent resolver dialog to view something -->
<string name="whichViewApplicationLabel">Open</string>
- <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
+ <!-- Title of intent resolver dialog when selecting a browser/application that opens specific URIs
[CHAR LIMIT=128]. -->
- <string name="whichGiveAccessToApplication">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+ <string name="whichOpenHostLinksWith">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+ <!-- Title of intent resolver dialog when selecting a browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenLinksWith">Open links with</string>
+ <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenLinksWithApp">Open links with <xliff:g id="application" example="Chrome">%1$s</xliff:g></string>
+ <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+ [CHAR LIMIT=128]. -->
+ <string name="whichOpenHostLinksWithApp">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Chrome">%2$s</xliff:g></string>
<!-- Title of intent resolver dialog when selecting a viewer application that opens URI
and a previously used application is known [CHAR LIMIT=128]. -->
- <string name="whichGiveAccessToApplicationNamed">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Gmail">%2$s</xliff:g></string>
<!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=18] -->
<string name="whichGiveAccessToApplicationLabel">Give access</string>
<!-- Title of intent resolver dialog when selecting an editor application to run. -->
@@ -4212,6 +4220,10 @@
<string name="activity_resolver_use_always">Always</string>
<!-- Title for a button to choose the currently selected activity
+ as the default in the activity resolver. [CHAR LIMIT=50] -->
+ <string name="activity_resolver_set_always">Set to always open</string>
+
+ <!-- Title for a button to choose the currently selected activity
from the activity resolver to use just this once. [CHAR LIMIT=25] -->
<string name="activity_resolver_use_once">Just once</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b38c12e..4504aa9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2238,7 +2238,6 @@
<java-symbol type="id" name="resolver_list" />
<java-symbol type="id" name="button_once" />
<java-symbol type="id" name="button_always" />
- <java-symbol type="id" name="button_app_settings" />
<java-symbol type="integer" name="config_globalActionsKeyTimeout" />
<java-symbol type="integer" name="config_screenshotChordKeyTimeout" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -2623,14 +2622,17 @@
<java-symbol type="bool" name="config_use_voip_mode_for_ims" />
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
- <java-symbol type="string" name="activity_resolver_app_settings" />
+ <java-symbol type="string" name="activity_resolver_set_always" />
+ <java-symbol type="string" name="activity_resolver_use_always" />
<java-symbol type="string" name="whichApplicationNamed" />
<java-symbol type="string" name="whichApplicationLabel" />
<java-symbol type="string" name="whichViewApplication" />
<java-symbol type="string" name="whichViewApplicationNamed" />
<java-symbol type="string" name="whichViewApplicationLabel" />
- <java-symbol type="string" name="whichGiveAccessToApplication" />
- <java-symbol type="string" name="whichGiveAccessToApplicationNamed" />
+ <java-symbol type="string" name="whichOpenHostLinksWith" />
+ <java-symbol type="string" name="whichOpenHostLinksWithApp" />
+ <java-symbol type="string" name="whichOpenLinksWith" />
+ <java-symbol type="string" name="whichOpenLinksWithApp" />
<java-symbol type="string" name="whichGiveAccessToApplicationLabel" />
<java-symbol type="string" name="whichEditApplication" />
<java-symbol type="string" name="whichEditApplicationNamed" />
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 9cf342c..35fbfe1 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -150,9 +150,11 @@
/**
* Whether history is enabled.
+ *
+ * <p>The feature is permanently disabled in Android Q
*/
@GuardedBy("mInMemoryLock")
- private int mMode = AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE;
+ private final int mMode = AppOpsManager.HISTORICAL_MODE_DISABLED;
/**
* This granularity has been chosen to allow clean delineation for intervals
@@ -451,6 +453,7 @@
void setHistoryParameters(@HistoricalMode int mode,
long baseSnapshotInterval, long intervalCompressionMultiplier) {
+ /*
synchronized (mOnDiskLock) {
synchronized (mInMemoryLock) {
// NOTE: We allow this call if persistence is not initialized as
@@ -479,6 +482,7 @@
}
}
}
+ */
}
void offsetHistory(long offsetMillis) {
diff --git a/services/core/java/com/android/server/pm/ShareTargetInfo.java b/services/core/java/com/android/server/pm/ShareTargetInfo.java
index 9e8b73e..fdfee77 100644
--- a/services/core/java/com/android/server/pm/ShareTargetInfo.java
+++ b/services/core/java/com/android/server/pm/ShareTargetInfo.java
@@ -15,12 +15,36 @@
*/
package com.android.server.pm;
+import android.annotation.NonNull;
import android.text.TextUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
/**
* Represents a Share Target definition, read from the application's manifest (shortcuts.xml)
*/
class ShareTargetInfo {
+
+ private static final String TAG_SHARE_TARGET = "share-target";
+ private static final String ATTR_TARGET_CLASS = "targetClass";
+
+ private static final String TAG_DATA = "data";
+ private static final String ATTR_SCHEME = "scheme";
+ private static final String ATTR_HOST = "host";
+ private static final String ATTR_PORT = "port";
+ private static final String ATTR_PATH = "path";
+ private static final String ATTR_PATH_PATTERN = "pathPattern";
+ private static final String ATTR_PATH_PREFIX = "pathPrefix";
+ private static final String ATTR_MIME_TYPE = "mimeType";
+
+ private static final String TAG_CATEGORY = "category";
+ private static final String ATTR_NAME = "name";
+
static class TargetData {
final String mScheme;
final String mHost;
@@ -98,4 +122,72 @@
return strBuilder.toString();
}
+
+ void saveToXml(@NonNull XmlSerializer out) throws IOException {
+ out.startTag(null, TAG_SHARE_TARGET);
+
+ ShortcutService.writeAttr(out, ATTR_TARGET_CLASS, mTargetClass);
+
+ for (int i = 0; i < mTargetData.length; i++) {
+ out.startTag(null, TAG_DATA);
+ ShortcutService.writeAttr(out, ATTR_SCHEME, mTargetData[i].mScheme);
+ ShortcutService.writeAttr(out, ATTR_HOST, mTargetData[i].mHost);
+ ShortcutService.writeAttr(out, ATTR_PORT, mTargetData[i].mPort);
+ ShortcutService.writeAttr(out, ATTR_PATH, mTargetData[i].mPath);
+ ShortcutService.writeAttr(out, ATTR_PATH_PATTERN, mTargetData[i].mPathPattern);
+ ShortcutService.writeAttr(out, ATTR_PATH_PREFIX, mTargetData[i].mPathPrefix);
+ ShortcutService.writeAttr(out, ATTR_MIME_TYPE, mTargetData[i].mMimeType);
+ out.endTag(null, TAG_DATA);
+ }
+
+ for (int i = 0; i < mCategories.length; i++) {
+ out.startTag(null, TAG_CATEGORY);
+ ShortcutService.writeAttr(out, ATTR_NAME, mCategories[i]);
+ out.endTag(null, TAG_CATEGORY);
+ }
+
+ out.endTag(null, TAG_SHARE_TARGET);
+ }
+
+ static ShareTargetInfo loadFromXml(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ final String targetClass = ShortcutService.parseStringAttribute(parser, ATTR_TARGET_CLASS);
+ final ArrayList<ShareTargetInfo.TargetData> targetData = new ArrayList<>();
+ final ArrayList<String> categories = new ArrayList<>();
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG) {
+ switch (parser.getName()) {
+ case TAG_DATA:
+ targetData.add(parseTargetData(parser));
+ break;
+ case TAG_CATEGORY:
+ categories.add(ShortcutService.parseStringAttribute(parser, ATTR_NAME));
+ break;
+ }
+ } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_SHARE_TARGET)) {
+ break;
+ }
+ }
+ if (targetData.isEmpty() || targetClass == null || categories.isEmpty()) {
+ return null;
+ }
+ return new ShareTargetInfo(
+ targetData.toArray(new ShareTargetInfo.TargetData[targetData.size()]),
+ targetClass, categories.toArray(new String[categories.size()]));
+ }
+
+ private static ShareTargetInfo.TargetData parseTargetData(XmlPullParser parser) {
+ final String scheme = ShortcutService.parseStringAttribute(parser, ATTR_SCHEME);
+ final String host = ShortcutService.parseStringAttribute(parser, ATTR_HOST);
+ final String port = ShortcutService.parseStringAttribute(parser, ATTR_PORT);
+ final String path = ShortcutService.parseStringAttribute(parser, ATTR_PATH);
+ final String pathPattern = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PATTERN);
+ final String pathPrefix = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PREFIX);
+ final String mimeType = ShortcutService.parseStringAttribute(parser, ATTR_MIME_TYPE);
+
+ return new ShareTargetInfo.TargetData(scheme, host, port, path, pathPattern, pathPrefix,
+ mimeType);
+ }
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d6e87aa..06c71ba 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -73,6 +73,7 @@
private static final String TAG_INTENT = "intent";
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
+ private static final String TAG_SHARE_TARGET = "share-target";
private static final String TAG_CATEGORIES = "categories";
private static final String TAG_PERSON = "person";
@@ -1453,8 +1454,9 @@
public void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
throws IOException, XmlPullParserException {
final int size = mShortcuts.size();
+ final int shareTargetSize = mShareTargets.size();
- if (size == 0 && mApiCallCount == 0) {
+ if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
return; // nothing to write.
}
@@ -1470,6 +1472,12 @@
getPackageInfo().isBackupAllowed());
}
+ if (!forBackup) {
+ for (int j = 0; j < shareTargetSize; j++) {
+ mShareTargets.get(j).saveToXml(out);
+ }
+ }
+
out.endTag(null, TAG_ROOT);
}
@@ -1627,6 +1635,9 @@
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
continue;
+ case TAG_SHARE_TARGET:
+ ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ continue;
}
}
ShortcutService.warnForInvalidTag(depth, tag);
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 8b332d2..55f062b 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -1032,11 +1032,13 @@
// must always grant permissions on behalf of someone explicit.
final int callingAppId = UserHandle.getAppId(callingUid);
if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
- if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
+ if ("com.android.settings.files".equals(grantUri.uri.getAuthority())
+ || "com.android.settings.module_licenses".equals(grantUri.uri.getAuthority())) {
// Exempted authority for
// 1. cropping user photos and sharing a generated license html
// file in Settings app
// 2. sharing a generated license html file in TvSettings app
+ // 3. Sharing module license files from Settings app
} else {
Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
+ " grant to " + grantUri + "; use startActivityAsCaller() instead");
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 9e8876a..30e866b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1387,13 +1387,12 @@
}
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
- + taskIntent.getComponent().flattenToShortString()
+ + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
+ "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
- if (taskIntent != null && taskIntent.getComponent() != null &&
- taskIntent.getComponent().compareTo(cls) == 0 &&
- Objects.equals(documentData, taskDocumentData)) {
+ if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
+ && Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG_TASKS,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 142c3b3..e2421d6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4781,18 +4781,12 @@
private void applyUpdateVrModeLocked(ActivityRecord r) {
// VR apps are expected to run in a main display. If an app is turning on VR for
- // itself, but lives in a dynamic stack, then make sure that it is moved to the main
- // fullscreen stack before enabling VR Mode.
- // TODO: The goal of this code is to keep the VR app on the main display. When the
- // stack implementation changes in the future, keep in mind that the use of the fullscreen
- // stack is a means to move the activity to the main display and a moveActivityToDisplay()
- // option would be a better choice here.
+ // itself, but isn't on the main display, then move it there before enabling VR Mode.
if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
- Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
- + " to main stack for VR");
- final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
- WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
- moveTaskToStack(r.getTaskRecord().taskId, stack.mStackId, true /* toTop */);
+ Slog.i(TAG, "Moving " + r.shortComponentName + " from display " + r.getDisplayId()
+ + " to main display for VR");
+ mRootActivityContainer.moveStackToDisplay(
+ r.getStackId(), DEFAULT_DISPLAY, true /* toTop */);
}
mH.post(() -> {
if (!mVrController.onVrModeChanged(r)) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4a9a3f7..03cae42 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1322,7 +1322,15 @@
if (prevDc == null || prevDc == mDisplayContent) {
return;
}
- if (prevDc.mChangingApps.contains(this)) {
+
+ if (prevDc.mOpeningApps.remove(this)) {
+ // Transfer opening transition to new display.
+ mDisplayContent.mOpeningApps.add(this);
+ mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+ mDisplayContent.executeAppTransition();
+ }
+
+ if (prevDc.mChangingApps.remove(this)) {
// This gets called *after* the AppWindowToken has been reparented to the new display.
// That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
// so this token is now "frozen" while waiting for the animation to start on prevDc
@@ -1331,6 +1339,8 @@
// so we need to cancel the change transition here.
clearChangeLeash(getPendingTransaction(), true /* cancel */);
}
+ prevDc.mClosingApps.remove(this);
+
if (prevDc.mFocusedApp == this) {
prevDc.setFocusedApp(null);
final TaskStack stack = dc.getTopStack();
@@ -3216,16 +3226,6 @@
true /* topToBottom */);
}
- void removeFromPendingTransition() {
- if (isWaitingForTransitionStart() && mDisplayContent != null) {
- mDisplayContent.mOpeningApps.remove(this);
- if (mDisplayContent.mChangingApps.remove(this)) {
- clearChangeLeash(getPendingTransaction(), true /* cancel */);
- }
- mDisplayContent.mClosingApps.remove(this);
- }
- }
-
private void updateColorTransform() {
if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
getPendingTransaction().setColorTransform(mSurfaceControl,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c3a769b..1659131 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -30,16 +30,21 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_LEFT_GESTURES;
+import static android.view.InsetsState.TYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -135,6 +140,7 @@
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
import android.animation.AnimationHandler;
@@ -324,6 +330,7 @@
private final RemoteCallbackList<ISystemGestureExclusionListener>
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
private final Region mSystemGestureExclusion = new Region();
+ private int mSystemGestureExclusionLimit;
/**
* For default display it contains real metrics, empty for others.
@@ -894,6 +901,8 @@
mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
+ mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
@@ -1549,8 +1558,8 @@
longSize = height;
}
- final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
- final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+ final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
+ final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
@@ -2200,6 +2209,18 @@
onDisplayChanged(this);
}
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ updateSystemGestureExclusionLimit();
+ }
+
+ void updateSystemGestureExclusionLimit() {
+ mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+ * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
+ updateSystemGestureExclusion();
+ }
+
void initializeDisplayBaseInfo() {
final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
if (displayManagerInternal != null) {
@@ -2377,9 +2398,6 @@
+ " to its current displayId=" + mDisplayId);
}
- // Clean up all pending transitions when stack reparent to another display.
- stack.forAllAppWindows(AppWindowToken::removeFromPendingTransition);
-
prevDc.mTaskStackContainers.removeChild(stack);
mTaskStackContainers.addStackToDisplay(stack, onTop);
}
@@ -5110,24 +5128,35 @@
@VisibleForTesting
Region calculateSystemGestureExclusion() {
+ final Region unhandled = Region.obtain();
+ unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
+
+ final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES)
+ .getSource().getFrame();
+ final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
+ .getSource().getFrame();
+
final Region global = Region.obtain();
final Region touchableRegion = Region.obtain();
final Region local = Region.obtain();
+ final int[] remainingLeftRight =
+ {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
// Traverse all windows bottom up to assemble the gesture exclusion rects.
// For each window, we only take the rects that fall within its touchable region.
forAllWindows(w -> {
if (w.cantReceiveTouchInput() || !w.isVisible()
- || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
+ || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
+ || unhandled.isEmpty()) {
return;
}
final boolean modal =
(w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
- // Only keep the exclusion zones from the windows behind where the current window
- // isn't touchable.
+ // Get the touchable region of the window, and intersect with where the screen is still
+ // touchable, i.e. touchable regions on top are not covering it yet.
w.getTouchableRegion(touchableRegion);
- global.op(touchableRegion, Op.DIFFERENCE);
+ touchableRegion.op(unhandled, Op.INTERSECT);
rectListToRegion(w.getSystemGestureExclusion(), local);
@@ -5139,13 +5168,78 @@
// A window can only exclude system gestures where it is actually touchable
local.op(touchableRegion, Op.INTERSECT);
- global.op(local, Op.UNION);
- }, false /* topToBottom */);
+ // Apply restriction if necessary.
+ if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
+
+ // Processes the region along the left edge.
+ remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
+ remainingLeftRight[0]);
+
+ // Processes the region along the right edge.
+ remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
+ remainingLeftRight[1]);
+
+ // Adds the middle (unrestricted area)
+ final Region middle = Region.obtain(local);
+ middle.op(leftEdge, Op.DIFFERENCE);
+ middle.op(rightEdge, Op.DIFFERENCE);
+ global.op(middle, Op.UNION);
+ middle.recycle();
+ } else {
+ global.op(local, Op.UNION);
+ }
+ unhandled.op(touchableRegion, Op.DIFFERENCE);
+ }, true /* topToBottom */);
local.recycle();
touchableRegion.recycle();
+ unhandled.recycle();
return global;
}
+ /**
+ * @return Whether gesture exclusion area should be restricted from the window depending on the
+ * current SystemUI visibility flags.
+ */
+ private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
+ final int type = win.mAttrs.type;
+ final int stickyHideNavFlags =
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ final boolean stickyHideNav =
+ (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
+ return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR
+ && win.getActivityType() != ACTIVITY_TYPE_HOME;
+ }
+
+ /**
+ * Adds a local gesture exclusion area to the global area while applying a limit per edge.
+ *
+ * @param local The gesture exclusion area to add.
+ * @param global The destination.
+ * @param edge Only processes the part in that region.
+ * @param limit How much limit in pixels we have.
+ * @return How much of the limit are remaining.
+ */
+ private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
+ int limit) {
+ final Region r = Region.obtain(local);
+ r.op(edge, Op.INTERSECT);
+
+ final int[] remaining = {limit};
+ forEachRect(r, rect -> {
+ if (remaining[0] <= 0) {
+ return;
+ }
+ final int height = rect.height();
+ if (height > remaining[0]) {
+ rect.bottom = rect.top + remaining[0];
+ }
+ remaining[0] -= height;
+ global.op(rect, Op.UNION);
+ });
+ r.recycle();
+ return remaining[0];
+ }
+
void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
mSystemGestureExclusionListeners.register(listener);
final boolean changed;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 28bb3d8..2db0131 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,6 +32,7 @@
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -154,6 +155,7 @@
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
@@ -175,6 +177,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -380,6 +383,8 @@
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
+ private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
+
final WindowTracing mWindowTracing;
final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -838,6 +843,8 @@
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
boolean mWindowsChanged = false;
+ int mSystemGestureExclusionLimitDp;
+
public interface WindowChangeListener {
public void windowsChanged();
public void focusChanged();
@@ -1132,6 +1139,21 @@
this, mInputManager, mActivityTaskManager, mH.getLooper());
mDragDropController = new DragDropController(this, mH.getLooper());
+ mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ new HandlerExecutor(mH), properties -> {
+ synchronized (mGlobalLock) {
+ final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+ properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ if (mSystemGestureExclusionLimitDp != exclusionLimitDp) {
+ mSystemGestureExclusionLimitDp = exclusionLimitDp;
+ mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
+ }
+ }
+ });
+
LocalServices.addService(WindowManagerInternal.class, new LocalService());
}
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index 1458440..8cd6f88 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -18,8 +18,10 @@
import android.graphics.Rect;
import android.graphics.Region;
+import android.graphics.RegionIterator;
import java.util.List;
+import java.util.function.Consumer;
/**
* Utility methods to handle Regions.
@@ -42,4 +44,18 @@
outRegion.union(rects.get(i));
}
}
+
+ /**
+ * Applies actions on each rect contained within a {@code Region}.
+ *
+ * @param region the given region.
+ * @param rectConsumer the action holder.
+ */
+ public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
+ final RegionIterator it = new RegionIterator(region);
+ final Rect rect = new Rect();
+ while (it.next(rect)) {
+ rectConsumer.accept(rect);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 552058f..7166145 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -46,6 +46,7 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -242,6 +243,7 @@
assertThat(getLoggedOps()).isNull();
}
+ @Ignore("Historical appops are disabled in Android Q")
@Test
public void testPackageRemovedHistoricalOps() throws InterruptedException {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 7e6b7da..6c917b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -97,16 +97,25 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.SparseArray;
+import android.util.Xml;
import com.android.frameworks.servicestests.R;
+import com.android.internal.util.FastXmlSerializer;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import com.android.server.pm.ShortcutUser.PackageWithUser;
import org.mockito.ArgumentCaptor;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -8089,4 +8098,70 @@
}
}
}
+
+ public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
+ List<ShareTargetInfo> expectedValues = new ArrayList<>();
+ expectedValues.add(new ShareTargetInfo(
+ new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
+ "http", "www.google.com", "1234", "somePath", "somePathPattern",
+ "somePathPrefix", "text/plain")}, "com.test.directshare.TestActivity1",
+ new String[]{"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"}));
+ expectedValues.add(new ShareTargetInfo(new ShareTargetInfo.TargetData[]{
+ new ShareTargetInfo.TargetData(null, null, null, null, null, null, "video/mp4"),
+ new ShareTargetInfo.TargetData("content", null, null, null, null, null, "video/*")},
+ "com.test.directshare.TestActivity5",
+ new String[]{"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}));
+
+ // Write ShareTargets to Xml
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ final XmlSerializer outXml = new FastXmlSerializer();
+ outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
+ outXml.startDocument(null, true);
+ for (int i = 0; i < expectedValues.size(); i++) {
+ expectedValues.get(i).saveToXml(outXml);
+ }
+ outXml.endDocument();
+ outXml.flush();
+
+ // Read ShareTargets from Xml
+ ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new InputStreamReader(inStream));
+ List<ShareTargetInfo> shareTargets = new ArrayList<>();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (type == XmlPullParser.START_TAG && parser.getName().equals("share-target")) {
+ shareTargets.add(ShareTargetInfo.loadFromXml(parser));
+ }
+ }
+
+ // Assert two lists are equal
+ assertNotNull(shareTargets);
+ assertEquals(expectedValues.size(), shareTargets.size());
+
+ for (int i = 0; i < expectedValues.size(); i++) {
+ ShareTargetInfo expected = expectedValues.get(i);
+ ShareTargetInfo actual = shareTargets.get(i);
+
+ assertEquals(expected.mTargetData.length, actual.mTargetData.length);
+ for (int j = 0; j < expected.mTargetData.length; j++) {
+ assertEquals(expected.mTargetData[j].mScheme, actual.mTargetData[j].mScheme);
+ assertEquals(expected.mTargetData[j].mHost, actual.mTargetData[j].mHost);
+ assertEquals(expected.mTargetData[j].mPort, actual.mTargetData[j].mPort);
+ assertEquals(expected.mTargetData[j].mPath, actual.mTargetData[j].mPath);
+ assertEquals(expected.mTargetData[j].mPathPrefix,
+ actual.mTargetData[j].mPathPrefix);
+ assertEquals(expected.mTargetData[j].mPathPattern,
+ actual.mTargetData[j].mPathPattern);
+ assertEquals(expected.mTargetData[j].mMimeType, actual.mTargetData[j].mMimeType);
+ }
+
+ assertEquals(expected.mTargetClass, actual.mTargetClass);
+
+ assertEquals(expected.mCategories.length, actual.mCategories.length);
+ for (int j = 0; j < expected.mCategories.length; j++) {
+ assertEquals(expected.mCategories[j], actual.mCategories[j]);
+ }
+ }
+ }
}
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 5136705..2ce33fc 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -36,6 +36,7 @@
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 757267e5..bde0ef6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -262,6 +262,35 @@
}
@Test
+ public void testFindTaskAlias() {
+ final String targetActivity = "target.activity";
+ final String aliasActivity = "alias.activity";
+ final ComponentName target = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+ targetActivity);
+ final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+ aliasActivity);
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+ task.origActivity = alias;
+ task.realActivity = target;
+ new ActivityBuilder(mService).setComponent(target).setTask(task).setTargetActivity(
+ targetActivity).build();
+
+ // Using target activity to find task.
+ final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
+ target).setTargetActivity(targetActivity).build();
+ RootActivityContainer.FindTaskResult result = new RootActivityContainer.FindTaskResult();
+ mStack.findTaskLocked(r1, result);
+ assertThat(result.mRecord).isNotNull();
+
+ // Using alias activity to find task.
+ final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
+ alias).setTargetActivity(targetActivity).build();
+ result = new RootActivityContainer.FindTaskResult();
+ mStack.findTaskLocked(r2, result);
+ assertThat(result.mRecord).isNotNull();
+ }
+
+ @Test
public void testMoveStackToBackIncludingParent() {
final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,