summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java2
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/app/ActivityManager.java2
-rw-r--r--core/java/android/app/ActivityManagerInternal.java11
-rw-r--r--core/java/android/app/ActivityThread.java6
-rw-r--r--core/java/android/app/ActivityView.java11
-rw-r--r--core/java/android/app/ITaskStackListener.aidl8
-rw-r--r--core/java/android/app/Notification.java33
-rw-r--r--core/java/android/app/StatusBarManager.java64
-rw-r--r--core/java/android/app/TaskStackListener.java4
-rw-r--r--core/java/android/hardware/Sensor.java4
-rw-r--r--core/java/android/hardware/biometrics/BiometricManager.java29
-rw-r--r--core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl2
-rw-r--r--core/java/android/hardware/biometrics/IBiometricService.aidl5
-rw-r--r--core/java/android/hardware/display/AmbientDisplayConfiguration.java13
-rw-r--r--core/java/android/hardware/face/FaceManager.java18
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl11
-rw-r--r--core/java/android/net/NetworkTemplate.java37
-rw-r--r--core/java/android/os/IVibratorService.aidl5
-rw-r--r--core/java/android/os/RecoverySystem.java129
-rw-r--r--core/java/android/os/SharedMemory.java22
-rw-r--r--core/java/android/os/SystemVibrator.java6
-rw-r--r--core/java/android/provider/ContactsContract.java88
-rw-r--r--core/java/android/provider/DeviceConfig.java23
-rw-r--r--core/java/android/provider/Settings.java114
-rw-r--r--core/java/android/util/FeatureFlagUtils.java1
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java28
-rw-r--r--core/java/android/view/Choreographer.java3
-rw-r--r--core/java/android/view/DisplayEventReceiver.java24
-rw-r--r--core/java/android/view/IRecentsAnimationController.aidl44
-rw-r--r--core/java/android/view/IRecentsAnimationRunner.aidl2
-rw-r--r--core/java/android/view/ISystemGestureExclusionListener.aidl11
-rw-r--r--core/java/android/view/IWindow.aidl7
-rw-r--r--core/java/android/view/RemoteAnimationAdapter.java13
-rw-r--r--core/java/android/view/RemoteAnimationDefinition.java4
-rw-r--r--core/java/android/view/Surface.java29
-rw-r--r--core/java/android/view/SurfaceControl.java3
-rw-r--r--core/java/android/view/View.java578
-rw-r--r--core/java/android/view/ViewGroup.java60
-rw-r--r--core/java/android/view/ViewRootImpl.java189
-rw-r--r--core/java/android/view/WindowInsets.java9
-rw-r--r--core/java/android/view/WindowManager.java16
-rw-r--r--core/java/android/view/WindowManagerPolicyConstants.java3
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java20
-rw-r--r--core/java/android/webkit/PermissionRequest.java2
-rw-r--r--core/java/android/webkit/WebChromeClient.java20
-rw-r--r--core/java/android/webkit/WebSettings.java4
-rw-r--r--core/java/android/webkit/WebView.java13
-rw-r--r--core/java/android/widget/AbsSeekBar.java21
-rw-r--r--core/java/android/widget/AdapterView.java3
-rw-r--r--core/java/android/widget/ArrayAdapter.java2
-rw-r--r--core/java/android/widget/RelativeLayout.java8
-rw-r--r--core/java/android/widget/TabWidget.java2
-rw-r--r--core/java/android/widget/TextView.java39
54 files changed, 1567 insertions, 242 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index cebe6e1211e0..90b80e73c323 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -309,7 +309,7 @@ public abstract class AccessibilityService extends Service {
* Name under which an AccessibilityService component publishes information
* about itself. This meta-data must reference an XML resource containing an
* <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
- * tag. This is a a sample XML file configuring an accessibility service:
+ * tag. This is a sample XML file configuring an accessibility service:
* <pre> &lt;accessibility-service
* android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
* android:packageNames="foo.bar, foo.baz"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dc52c52cca1f..f5b0b592e6a7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1547,7 +1547,9 @@ public class Activity extends ContextThemeWrapper
* had previously been frozen by {@link #onSaveInstanceState}.
*
* <p>This method is called between {@link #onStart} and
- * {@link #onPostCreate}.
+ * {@link #onPostCreate}. This method is called only when recreating
+ * an activity; the method isn't invoked if {@link #onStart} is called for
+ * any other reason.</p>
*
* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
*
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 17368b789645..91b98c71a613 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -925,7 +925,7 @@ public class ActivityManager {
* (which tends to consume a lot more RAM).
* @hide
*/
- @UnsupportedAppUsage
+ @TestApi
static public boolean isHighEndGfx() {
return !isLowRamDeviceStatic()
&& !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 8508c2c95666..1725db046a95 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -120,17 +120,6 @@ public abstract class ActivityManagerInternal {
public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);
/**
- * Sets if the given pid is currently running a remote animation, which is taken a signal for
- * determining oom adjustment and scheduling behavior.
- *
- * @param pid The pid we are setting overlay UI for.
- * @param runningRemoteAnimation True if the process is running a remote animation, false
- * otherwise.
- * @see RemoteAnimationAdapter
- */
- public abstract void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation);
-
- /**
* Called after the network policy rules are updated by
* {@link com.android.server.net.NetworkPolicyManagerService} for a specific {@param uid} and
* {@param procStateSeq}.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d780b09bc7f1..1b515737c479 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1005,8 +1005,7 @@ public final class ActivityThread extends ClientTransactionHandler {
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
- ContentCaptureOptions contentCaptureOptions,
- long[] disabledCompatChanges) {
+ ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
@@ -1052,6 +1051,8 @@ public final class ActivityThread extends ClientTransactionHandler {
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
+ data.autofillOptions = autofillOptions;
+ data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
sendMessage(H.BIND_APPLICATION, data);
}
@@ -6133,7 +6134,6 @@ public final class ActivityThread extends ClientTransactionHandler {
if (data.trackAllocation) {
DdmVmInternal.enableRecentAllocations(true);
}
-
// Note when this process has started.
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 4771f9f6ad04..3bf659b663b0 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -120,6 +120,7 @@ public class ActivityView extends ViewGroup {
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
+ mSurfaceView.setAlpha(0f);
mSurfaceCallback = new SurfaceCallback();
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
addView(mSurfaceView);
@@ -347,6 +348,16 @@ public class ActivityView extends ViewGroup {
}
@Override
+ public void setAlpha(float alpha) {
+ mSurfaceView.setAlpha(alpha);
+ }
+
+ @Override
+ public float getAlpha() {
+ return mSurfaceView.getAlpha();
+ }
+
+ @Override
public boolean gatherTransparentRegion(Region region) {
// The tap exclude region may be affected by any view on top of it, so we detect the
// possible change by monitoring this function.
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 0df3bbe42c7e..650147b45bd2 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -170,6 +170,14 @@ oneway interface ITaskStackListener {
*/
void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo);
+ /*
+ * Called when contents are drawn for the first time on a display which can only contain one
+ * task.
+ *
+ * @param displayId the id of the display on which contents are drawn.
+ */
+ void onSingleTaskDisplayDrawn(int displayId);
+
/**
* Called when a task is reparented to a stack on a different display.
*
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 789351e0d157..ceadd8510e44 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3386,11 +3386,7 @@ public class Notification implements Parcelable
*/
private int mCachedContrastColor = COLOR_INVALID;
private int mCachedContrastColorIsFor = COLOR_INVALID;
- /**
- * Caches a ambient version of {@link #mCachedAmbientColorIsFor}.
- */
- private int mCachedAmbientColor = COLOR_INVALID;
- private int mCachedAmbientColorIsFor = COLOR_INVALID;
+
/**
* A neutral color color that can be used for icons.
*/
@@ -5441,26 +5437,14 @@ public class Notification implements Parcelable
/**
* Construct a RemoteViews for the display in public contexts like on the lockscreen.
*
+ * @param isLowPriority is this notification low priority
* @hide
*/
@UnsupportedAppUsage
- public RemoteViews makePublicContentView() {
- return makePublicView(false /* ambient */);
- }
-
- /**
- * Construct a RemoteViews for the display in public contexts like on the lockscreen.
- *
- * @hide
- */
- public RemoteViews makePublicAmbientNotification() {
- return makePublicView(true /* ambient */);
- }
-
- private RemoteViews makePublicView(boolean ambient) {
+ public RemoteViews makePublicContentView(boolean isLowPriority) {
if (mN.publicVersion != null) {
final Builder builder = recoverBuilder(mContext, mN.publicVersion);
- return ambient ? builder.makeAmbientNotification() : builder.createContentView();
+ return builder.createContentView();
}
Bundle savedBundle = mN.extras;
Style style = mStyle;
@@ -5484,7 +5468,11 @@ public class Notification implements Parcelable
}
mN.extras = publicExtras;
RemoteViews view;
- view = makeNotificationHeader();
+ StandardTemplateParams params = mParams.reset().fillTextsFrom(this);
+ if (isLowPriority) {
+ params.forceDefaultColor();
+ }
+ view = makeNotificationHeader(params);
view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true);
mN.extras = savedBundle;
mN.mLargeIcon = largeIcon;
@@ -8118,8 +8106,7 @@ public class Notification implements Parcelable
*/
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
- RemoteViews expanded = makeMediaBigContentView();
- return expanded != null ? expanded : makeMediaContentView();
+ return makeMediaContentView();
}
/** @hide */
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index d9e8763d7f7b..28413be29a1d 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -433,6 +433,9 @@ public class StatusBarManager {
private boolean mNotificationPeeking;
private boolean mRecents;
private boolean mSearch;
+ private boolean mSystemIcons;
+ private boolean mClock;
+ private boolean mNotificationIcons;
/** @hide */
public DisableInfo(int flags1, int flags2) {
@@ -441,6 +444,9 @@ public class StatusBarManager {
mNotificationPeeking = (flags1 & DISABLE_NOTIFICATION_ALERTS) != 0;
mRecents = (flags1 & DISABLE_RECENT) != 0;
mSearch = (flags1 & DISABLE_SEARCH) != 0;
+ mSystemIcons = (flags1 & DISABLE_SYSTEM_INFO) != 0;
+ mClock = (flags1 & DISABLE_CLOCK) != 0;
+ mNotificationIcons = (flags1 & DISABLE_NOTIFICATION_ICONS) != 0;
}
/** @hide */
@@ -527,6 +533,48 @@ public class StatusBarManager {
}
/**
+ * @return {@code true} if system icons are disabled
+ *
+ * @hide
+ */
+ public boolean areSystemIconsDisabled() {
+ return mSystemIcons;
+ }
+
+ /** * @hide */
+ public void setSystemIconsDisabled(boolean disabled) {
+ mSystemIcons = disabled;
+ }
+
+ /**
+ * @return {@code true} if the clock icon is disabled
+ *
+ * @hide
+ */
+ public boolean isClockDisabled() {
+ return mClock;
+ }
+
+ /** * @hide */
+ public void setClockDisabled(boolean disabled) {
+ mClock = disabled;
+ }
+
+ /**
+ * @return {@code true} if notification icons are disabled
+ *
+ * @hide
+ */
+ public boolean areNotificationIconsDisabled() {
+ return mNotificationIcons;
+ }
+
+ /** * @hide */
+ public void setNotificationIconsDisabled(boolean disabled) {
+ mNotificationIcons = disabled;
+ }
+
+ /**
* @return {@code true} if no components are disabled (default state)
*
* @hide
@@ -535,7 +583,7 @@ public class StatusBarManager {
@TestApi
public boolean areAllComponentsEnabled() {
return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents
- && !mSearch;
+ && !mSearch && !mSystemIcons && !mClock && !mNotificationIcons;
}
/** @hide */
@@ -545,6 +593,9 @@ public class StatusBarManager {
mNotificationPeeking = false;
mRecents = false;
mSearch = false;
+ mSystemIcons = false;
+ mClock = false;
+ mNotificationIcons = false;
}
/**
@@ -554,7 +605,7 @@ public class StatusBarManager {
*/
public boolean areAllComponentsDisabled() {
return mStatusBarExpansion && mNavigateHome && mNotificationPeeking
- && mRecents && mSearch;
+ && mRecents && mSearch && mSystemIcons && mClock && mNotificationIcons;
}
/** @hide */
@@ -564,6 +615,9 @@ public class StatusBarManager {
mNotificationPeeking = true;
mRecents = true;
mSearch = true;
+ mSystemIcons = true;
+ mClock = true;
+ mNotificationIcons = true;
}
@NonNull
@@ -577,6 +631,9 @@ public class StatusBarManager {
.append(mNotificationPeeking ? "disabled" : "enabled");
sb.append(" mRecents=").append(mRecents ? "disabled" : "enabled");
sb.append(" mSearch=").append(mSearch ? "disabled" : "enabled");
+ sb.append(" mSystemIcons=").append(mSystemIcons ? "disabled" : "enabled");
+ sb.append(" mClock=").append(mClock ? "disabled" : "enabled");
+ sb.append(" mNotificationIcons=").append(mNotificationIcons ? "disabled" : "enabled");
return sb.toString();
@@ -597,6 +654,9 @@ public class StatusBarManager {
if (mNotificationPeeking) disable1 |= DISABLE_NOTIFICATION_ALERTS;
if (mRecents) disable1 |= DISABLE_RECENT;
if (mSearch) disable1 |= DISABLE_SEARCH;
+ if (mSystemIcons) disable1 |= DISABLE_SYSTEM_INFO;
+ if (mClock) disable1 |= DISABLE_CLOCK;
+ if (mNotificationIcons) disable1 |= DISABLE_NOTIFICATION_ICONS;
return new Pair<Integer, Integer>(disable1, disable2);
}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 73fc7a3db6c7..b63feb590ad1 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -176,6 +176,10 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
+ public void onSingleTaskDisplayDrawn(int displayId) throws RemoteException {
+ }
+
+ @Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) throws RemoteException {
}
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 099ae291c8f4..e78fb7f00797 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -339,6 +339,8 @@ public final class Sensor {
* for {@link #TYPE_STEP_COUNTER} instead. It is defined as a
* {@link Sensor#REPORTING_MODE_SPECIAL_TRIGGER} sensor.
* <p>
+ * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
+ * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_STEP_DETECTOR = 18;
@@ -384,8 +386,6 @@ public final class Sensor {
* gyroscope. This sensor uses lower power than the other rotation vectors, because it doesn't
* use the gyroscope. However, it is more noisy and will work best outdoors.
* <p>
- * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
- * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 6c497d47c645..d8110f33d723 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -104,9 +104,17 @@ public class BiometricManager {
*/
@RequiresPermission(USE_BIOMETRIC)
public @BiometricError int canAuthenticate() {
+ return canAuthenticate(mContext.getUserId());
+ }
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public @BiometricError int canAuthenticate(int userId) {
if (mService != null) {
try {
- return mService.canAuthenticate(mContext.getOpPackageName());
+ return mService.canAuthenticate(mContext.getOpPackageName(), userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -121,6 +129,25 @@ public class BiometricManager {
}
/**
+ * @hide
+ * @param userId
+ * @return
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public boolean hasEnrolledBiometrics(int userId) {
+ if (mService != null) {
+ try {
+ return mService.hasEnrolledBiometrics(userId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Remote exception in hasEnrolledBiometrics(): " + e);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Listens for changes to biometric eligibility on keyguard from user settings.
* @param callback
* @hide
diff --git a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
index d22e7e295b77..62d727c080e3 100644
--- a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
@@ -22,5 +22,5 @@ import android.hardware.biometrics.BiometricSourceType;
* @hide
*/
oneway interface IBiometricEnabledOnKeyguardCallback {
- void onChanged(in BiometricSourceType type, boolean enabled);
+ void onChanged(in BiometricSourceType type, boolean enabled, int userId);
} \ No newline at end of file
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index 90d4921c3c18..f0a0b2f0235f 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -40,7 +40,10 @@ interface IBiometricService {
void cancelAuthentication(IBinder token, String opPackageName);
// Checks if biometrics can be used.
- int canAuthenticate(String opPackageName);
+ int canAuthenticate(String opPackageName, int userId);
+
+ // Checks if any biometrics are enrolled.
+ boolean hasEnrolledBiometrics(int userId);
// Register callback for when keyguard biometric eligibility changes.
void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback);
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index c45b8ed52187..3e995b624112 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -48,7 +48,8 @@ public class AmbientDisplayConfiguration {
return pulseOnNotificationEnabled(user)
|| pulseOnLongPressEnabled(user)
|| alwaysOnEnabled(user)
- || wakeScreenGestureEnabled(user)
+ || wakeLockScreenGestureEnabled(user)
+ || wakeDisplayGestureEnabled(user)
|| pickupGestureEnabled(user)
|| tapGestureEnabled(user)
|| doubleTapGestureEnabled(user);
@@ -105,8 +106,14 @@ public class AmbientDisplayConfiguration {
}
/** {@hide} */
- public boolean wakeScreenGestureEnabled(int user) {
- return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+ public boolean wakeLockScreenGestureEnabled(int user) {
+ return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
+ && wakeScreenGestureAvailable();
+ }
+
+ /** {@hide} */
+ public boolean wakeDisplayGestureEnabled(int user) {
+ return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, user)
&& wakeScreenGestureAvailable();
}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 8596af107ac1..12b285a0f0ab 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -262,7 +262,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void enroll(byte[] token, CancellationSignal cancel,
+ public void enroll(int userId, byte[] token, CancellationSignal cancel,
EnrollmentCallback callback, int[] disabledFeatures) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
@@ -281,7 +281,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enroll");
- mService.enroll(mToken, token, mServiceReceiver,
+ mService.enroll(userId, mToken, token, mServiceReceiver,
mContext.getOpPackageName(), disabledFeatures);
} catch (RemoteException e) {
Log.w(TAG, "Remote exception in enroll: ", e);
@@ -339,12 +339,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void setFeature(int feature, boolean enabled, byte[] token,
+ public void setFeature(int userId, int feature, boolean enabled, byte[] token,
SetFeatureCallback callback) {
if (mService != null) {
try {
mSetFeatureCallback = callback;
- mService.setFeature(feature, enabled, token, mServiceReceiver);
+ mService.setFeature(userId, feature, enabled, token, mServiceReceiver,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -355,11 +356,11 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
- public void getFeature(int feature, GetFeatureCallback callback) {
+ public void getFeature(int userId, int feature, GetFeatureCallback callback) {
if (mService != null) {
try {
mGetFeatureCallback = callback;
- mService.getFeature(feature, mServiceReceiver);
+ mService.getFeature(userId, feature, mServiceReceiver, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -414,7 +415,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
try {
mRemovalCallback = callback;
mRemovalFace = face;
- mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver);
+ mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "Remote exception in remove: ", e);
if (callback != null) {
@@ -637,7 +639,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
}
Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode);
- return null;
+ return "";
}
/**
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 601be7595581..b6a0afbf716c 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -50,14 +50,15 @@ interface IFaceService {
int callingUid, int callingPid, int callingUserId, boolean fromClient);
// Start face enrollment
- void enroll(IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
+ void enroll(int userId, IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
String opPackageName, in int [] disabledFeatures);
// Cancel enrollment in progress
void cancelEnrollment(IBinder token);
// Any errors resulting from this call will be returned to the listener
- void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver);
+ void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver,
+ String opPackageName);
// Rename the face specified by faceId to the given name
void rename(int faceId, String name);
@@ -98,10 +99,10 @@ interface IFaceService {
// Enumerate all faces
void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
- void setFeature(int feature, boolean enabled, in byte [] token,
- IFaceServiceReceiver receiver);
+ void setFeature(int userId, int feature, boolean enabled, in byte [] token,
+ IFaceServiceReceiver receiver, String opPackageName);
- void getFeature(int feature, IFaceServiceReceiver receiver);
+ void getFeature(int userId, int feature, IFaceServiceReceiver receiver, String opPackageName);
void userActivity();
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index ae421a4991a4..87c7118c0ed8 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -48,6 +48,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -481,17 +482,39 @@ public class NetworkTemplate implements Parcelable {
* For example, given an incoming template matching B, and the currently
* active merge set [A,B], we'd return a new template that primarily matches
* A, but also matches B.
+ * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
*/
@UnsupportedAppUsage
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
- if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
- // Requested template subscriber is part of the merge group; return
- // a template that matches all merged subscribers.
- return new NetworkTemplate(template.mMatchRule, merged[0], merged,
- template.mNetworkId);
- } else {
- return template;
+ return normalize(template, Arrays.<String[]>asList(merged));
+ }
+
+ /**
+ * Examine the given template and normalize if it refers to a "merged"
+ * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ *
+ * There can be multiple merged subscriberIds for multi-SIM devices.
+ *
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that primarily matches
+ * A, but also matches B.
+ */
+ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
+ if (!template.isMatchRuleMobile()) return template;
+
+ for (String[] merged : mergedList) {
+ if (ArrayUtils.contains(merged, template.mSubscriberId)) {
+ // Requested template subscriber is part of the merge group; return
+ // a template that matches all merged subscribers.
+ return new NetworkTemplate(template.mMatchRule, merged[0], merged,
+ template.mNetworkId);
+ }
}
+
+ return template;
}
@UnsupportedAppUsage
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index e8b3ca6cb7ae..1456ff7e6c5e 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -16,6 +16,7 @@
package android.os;
+import android.media.AudioAttributes;
import android.os.VibrationEffect;
/** {@hide} */
@@ -23,8 +24,8 @@ interface IVibratorService
{
boolean hasVibrator();
boolean hasAmplitudeControl();
- void vibrate(int uid, String opPkg, in VibrationEffect effect, int usageHint, String reason,
- IBinder token);
+ void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
+ String reason, IBinder token);
void cancelVibrate(IBinder token);
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 53298d8d8aed..48fc2a6bf449 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -31,6 +31,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -56,10 +58,12 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
@@ -87,11 +91,14 @@ public class RecoverySystem {
private static final long PUBLISH_PROGRESS_INTERVAL_MS = 500;
private static final long DEFAULT_EUICC_FACTORY_RESET_TIMEOUT_MILLIS = 30000L; // 30 s
-
private static final long MIN_EUICC_FACTORY_RESET_TIMEOUT_MILLIS = 5000L; // 5 s
-
private static final long MAX_EUICC_FACTORY_RESET_TIMEOUT_MILLIS = 60000L; // 60 s
+ private static final long DEFAULT_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS =
+ 45000L; // 45 s
+ private static final long MIN_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS = 15000L; // 15 s
+ private static final long MAX_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS = 90000L; // 90 s
+
/** Used to communicate with recovery. See bootable/recovery/recovery.cpp. */
private static final File RECOVERY_DIR = new File("/cache/recovery");
private static final File LOG_FILE = new File(RECOVERY_DIR, "log");
@@ -99,9 +106,14 @@ public class RecoverySystem {
private static final String LAST_PREFIX = "last_";
private static final String ACTION_EUICC_FACTORY_RESET =
"com.android.internal.action.EUICC_FACTORY_RESET";
+ private static final String ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS =
+ "com.android.internal.action.EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS";
- /** used in {@link #wipeEuiccData} as package name of callback intent */
- private static final String PACKAGE_NAME_WIPING_EUICC_DATA_CALLBACK = "android";
+ /**
+ * Used in {@link #wipeEuiccData} & {@link #removeEuiccInvisibleSubs} as package name of
+ * callback intent.
+ */
+ private static final String PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK = "android";
/**
* The recovery image uses this file to identify the location (i.e. blocks)
@@ -754,8 +766,11 @@ public class RecoverySystem {
// Block until the ordered broadcast has completed.
condition.block();
+ EuiccManager euiccManager = context.getSystemService(EuiccManager.class);
if (wipeEuicc) {
- wipeEuiccData(context, PACKAGE_NAME_WIPING_EUICC_DATA_CALLBACK);
+ wipeEuiccData(context, PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK);
+ } else {
+ removeEuiccInvisibleSubs(context, euiccManager);
}
String shutdownArg = null;
@@ -851,6 +866,110 @@ public class RecoverySystem {
return false;
}
+ private static void removeEuiccInvisibleSubs(
+ Context context, EuiccManager euiccManager) {
+ ContentResolver cr = context.getContentResolver();
+ if (Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) == 0) {
+ // If the eUICC isn't provisioned, there's no need to remove euicc invisible profiles,
+ // as there's nothing to be removed.
+ Log.i(TAG, "Skip removing eUICC invisible profiles as it is not provisioned.");
+ return;
+ } else if (euiccManager == null || !euiccManager.isEnabled()) {
+ Log.i(TAG, "Skip removing eUICC invisible profiles as eUICC manager is not available.");
+ return;
+ }
+ SubscriptionManager subscriptionManager =
+ context.getSystemService(SubscriptionManager.class);
+ List<SubscriptionInfo> availableSubs =
+ subscriptionManager.getAvailableSubscriptionInfoList();
+ if (availableSubs == null || availableSubs.isEmpty()) {
+ Log.i(TAG, "Skip removing eUICC invisible profiles as no available profiles found.");
+ return;
+ }
+ List<SubscriptionInfo> invisibleSubs = new ArrayList<>();
+ for (SubscriptionInfo sub : availableSubs) {
+ if (sub.isEmbedded() && !subscriptionManager.isSubscriptionVisible(sub)) {
+ invisibleSubs.add(sub);
+ }
+ }
+ removeEuiccInvisibleSubs(context, invisibleSubs, euiccManager);
+ }
+
+ private static boolean removeEuiccInvisibleSubs(
+ Context context, List<SubscriptionInfo> subscriptionInfos, EuiccManager euiccManager) {
+ if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
+ Log.i(TAG, "There are no eUICC invisible profiles needed to be removed.");
+ return true;
+ }
+ CountDownLatch removeSubsLatch = new CountDownLatch(subscriptionInfos.size());
+ final AtomicInteger removedSubsCount = new AtomicInteger(0);
+
+ BroadcastReceiver removeEuiccSubsReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS.equals(intent.getAction())) {
+ if (getResultCode() != EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK) {
+ int detailedCode = intent.getIntExtra(
+ EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0);
+ Log.e(TAG, "Error removing euicc opportunistic profile, Detailed code = "
+ + detailedCode);
+ } else {
+ Log.e(TAG, "Successfully remove euicc opportunistic profile.");
+ removedSubsCount.incrementAndGet();
+ }
+ removeSubsLatch.countDown();
+ }
+ }
+ };
+
+ Intent intent = new Intent(ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS);
+ intent.setPackage(PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK);
+ PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS);
+ HandlerThread euiccHandlerThread =
+ new HandlerThread("euiccRemovingSubsReceiverThread");
+ euiccHandlerThread.start();
+ Handler euiccHandler = new Handler(euiccHandlerThread.getLooper());
+ context.getApplicationContext()
+ .registerReceiver(
+ removeEuiccSubsReceiver, intentFilter, null, euiccHandler);
+ for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
+ Log.i(
+ TAG,
+ "Remove invisible subscription " + subscriptionInfo.getSubscriptionId()
+ + " from card " + subscriptionInfo.getCardId());
+ euiccManager.createForCardId(subscriptionInfo.getCardId())
+ .deleteSubscription(subscriptionInfo.getSubscriptionId(), callbackIntent);
+ }
+ try {
+ long waitingTimeMillis = Settings.Global.getLong(
+ context.getContentResolver(),
+ Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
+ DEFAULT_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS);
+ if (waitingTimeMillis < MIN_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS) {
+ waitingTimeMillis = MIN_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS;
+ } else if (waitingTimeMillis > MAX_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS) {
+ waitingTimeMillis = MAX_EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS;
+ }
+ if (!removeSubsLatch.await(waitingTimeMillis, TimeUnit.MILLISECONDS)) {
+ Log.e(TAG, "Timeout removing invisible euicc profiles.");
+ return false;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Log.e(TAG, "Removing invisible euicc profiles interrupted", e);
+ return false;
+ } finally {
+ context.getApplicationContext().unregisterReceiver(removeEuiccSubsReceiver);
+ if (euiccHandlerThread != null) {
+ euiccHandlerThread.quit();
+ }
+ }
+ return removedSubsCount.get() == subscriptionInfos.size();
+ }
+
/** {@hide} */
public static void rebootPromptAndWipeUserData(Context context, String reason)
throws IOException {
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 7df4b5d8f63b..57a88012a31a 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -25,8 +25,6 @@ import android.system.OsConstants;
import dalvik.system.VMRuntime;
-import libcore.io.IoUtils;
-
import java.io.Closeable;
import java.io.FileDescriptor;
import java.nio.ByteBuffer;
@@ -64,7 +62,7 @@ public final class SharedMemory implements Parcelable, Closeable {
mMemoryRegistration = new MemoryRegistration(mSize);
mCleaner = Cleaner.create(mFileDescriptor,
- new Closer(mFileDescriptor.getInt$(), mMemoryRegistration));
+ new Closer(mFileDescriptor, mMemoryRegistration));
}
/**
@@ -261,9 +259,6 @@ public final class SharedMemory implements Parcelable, Closeable {
mCleaner.clean();
mCleaner = null;
}
-
- // Cleaner.clean doesn't clear the value of the file descriptor.
- mFileDescriptor.setInt$(-1);
}
@Override
@@ -295,24 +290,19 @@ public final class SharedMemory implements Parcelable, Closeable {
* Cleaner that closes the FD
*/
private static final class Closer implements Runnable {
- // This is a copy of the FileDescriptor we're attached to, in order to avoid a reference
- // cycle.
private FileDescriptor mFd;
private MemoryRegistration mMemoryReference;
- private Closer(int fd, MemoryRegistration memoryReference) {
- mFd = new FileDescriptor();
- mFd.setInt$(fd);
- IoUtils.setFdOwner(mFd, this);
-
+ private Closer(FileDescriptor fd, MemoryRegistration memoryReference) {
+ mFd = fd;
mMemoryReference = memoryReference;
}
@Override
public void run() {
- IoUtils.closeQuietly(mFd);
- mFd = null;
-
+ try {
+ Os.close(mFd);
+ } catch (ErrnoException e) { /* swallow error */ }
mMemoryReference.release();
mMemoryReference = null;
}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 4af514abfd69..a5188e7cd58d 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -77,16 +77,12 @@ public class SystemVibrator extends Vibrator {
return;
}
try {
- mService.vibrate(uid, opPkg, effect, usageForAttributes(attributes), reason, mToken);
+ mService.vibrate(uid, opPkg, effect, attributes, reason, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
}
- private static int usageForAttributes(AudioAttributes attributes) {
- return attributes != null ? attributes.getUsage() : AudioAttributes.USAGE_UNKNOWN;
- }
-
@Override
public void cancel() {
if (mService == null) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 81e1eb99336b..af3a16c987e6 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -870,8 +870,8 @@ public final class ContactsContract {
protected interface ContactOptionsColumns {
/**
* The number of times a contact has been contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -885,8 +885,8 @@ public final class ContactsContract {
/**
* The last time a contact was contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -1691,10 +1691,10 @@ public final class ContactsContract {
* TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED
* field is populated with the current system time.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this method is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*
* @param resolver the ContentResolver to use
* @param contactId the person who was contacted
@@ -1730,8 +1730,8 @@ public final class ContactsContract {
* Frequent contacts are no longer included in the result as of
* Android version {@link android.os.Build.VERSION_CODES#Q}.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1745,8 +1745,8 @@ public final class ContactsContract {
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This URI always returns an empty cursor.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1760,8 +1760,8 @@ public final class ContactsContract {
* various parts of the contact name. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -4292,10 +4292,10 @@ public final class ContactsContract {
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String LAST_TIME_USED = "last_time_used";
@@ -4306,10 +4306,10 @@ public final class ContactsContract {
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String TIMES_USED = "times_used";
@@ -5259,8 +5259,8 @@ public final class ContactsContract {
/**
* The content:// style URI for this table.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -5277,8 +5277,8 @@ public final class ContactsContract {
/**
* <p>URI used for the "enterprise caller-id".</p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -6079,8 +6079,8 @@ public final class ContactsContract {
* to display names as well as phone numbers. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field deosn't sort results based on contacts
+ * frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6092,8 +6092,9 @@ public final class ContactsContract {
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6360,8 +6361,9 @@ public final class ContactsContract {
* as an additional path segment after this URI.
* </p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*
@@ -6383,8 +6385,9 @@ public final class ContactsContract {
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7602,8 +7605,8 @@ public final class ContactsContract {
* <p>Similar to {@link Phone#CONTENT_FILTER_URI}, but allows users to filter callable
* data.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field no longer sorts results based on
+ * contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7615,8 +7618,9 @@ public final class ContactsContract {
* callable data. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*/
@@ -7646,8 +7650,9 @@ public final class ContactsContract {
* <p>The content:// style URI for these data items, which allows for a query parameter
* to be appended onto the end to filter for data items matching the query.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -8298,15 +8303,14 @@ public final class ContactsContract {
}
/**
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this class is obsolete. For
- * more information, see the
- * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
- * </p>
* <p>
* API allowing applications to send usage information for each {@link Data} row to the
* Contacts Provider. Applications can also clear all usage information.
* </p>
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
+ * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
+ * page.</p>
* <p>
* With the feedback, Contacts Provider may return more contextually appropriate results for
* Data listing, typically supplied with
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index e30ba38c127f..ea50ae810535 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -336,6 +336,29 @@ public final class DeviceConfig {
@TestApi
String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
"system_gestures_excluded_by_pre_q_sticky_immersive";
+
+ /**
+ * The minimum duration between gesture exclusion logging for a given window in
+ * milliseconds.
+ *
+ * Events that happen in-between will be silently dropped.
+ *
+ * A non-positive value disables logging.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
+ "system_gesture_exclusion_log_debounce_millis";
+
+ /**
+ * Key for controlling which packages are explicitly blocked from running at refresh rates
+ * higher than 60hz.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
}
private static final Object sLock = new Object();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 383d8dbce791..f92be195229e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -88,6 +88,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.MemoryIntArray;
+import android.view.Display;
import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.annotations.GuardedBy;
@@ -4073,7 +4074,7 @@ public final class Settings {
* preference, this rotation value will be used. Must be one of the
* {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
*
- * @see android.view.Display#getRotation
+ * @see Display#getRotation
*/
public static final String USER_ROTATION = "user_rotation";
@@ -6321,13 +6322,15 @@ public final class Settings {
"lock_screen_allow_remote_input";
/**
- * Indicates which clock face to show on lock screen and AOD.
+ * Indicates which clock face to show on lock screen and AOD formatted as a serialized
+ * {@link org.json.JSONObject} with the format:
+ * {"clock": id, "_applied_timestamp": timestamp}
* @hide
*/
public static final String LOCK_SCREEN_CUSTOM_CLOCK_FACE = "lock_screen_custom_clock_face";
private static final Validator LOCK_SCREEN_CUSTOM_CLOCK_FACE_VALIDATOR =
- ANY_STRING_VALIDATOR;
+ SettingsValidators.JSON_OBJECT_VALIDATOR;
/**
* Indicates which clock face to show on lock screen and AOD while docked.
@@ -7731,12 +7734,21 @@ public final class Settings {
private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
- * Gesture that wakes up the display, showing the ambient version of the status bar.
+ * Gesture that wakes up the display, showing some version of the lock screen.
+ * @hide
+ */
+ public static final String DOZE_WAKE_LOCK_SCREEN_GESTURE = "doze_wake_screen_gesture";
+
+ private static final Validator DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
+ * Gesture that wakes up the display, toggling between {@link Display.STATE_OFF} and
+ * {@link Display.STATE_DOZE}.
* @hide
*/
- public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+ public static final String DOZE_WAKE_DISPLAY_GESTURE = "doze_wake_display_gesture";
- private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+ private static final Validator DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
/**
* Gesture that skips media.
@@ -7752,10 +7764,30 @@ public final class Settings {
*/
public static final String SKIP_GESTURE_COUNT = "skip_gesture_count";
+ /**
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SKIP_TOUCH_COUNT = "skip_touch_count";
+
private static final Validator SKIP_GESTURE_COUNT_VALIDATOR =
NON_NEGATIVE_INTEGER_VALIDATOR;
/**
+ * Direction to advance media for skip gesture
+ * @hide
+ */
+ public static final String SKIP_DIRECTION = "skip_gesture_direction";
+
+ /**
+ * Only used if FeatureFlag "settings_skip_direction_mutable" is enabled.
+ * If feature flag is disabled, should assume SKIP_DIRECTION = 0.
+ * 0 / false = right to left to advance to next
+ * 1 / true = left to right to advance to next
+ */
+ private static final Validator SKIP_DIRECTION_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
* Gesture that silences sound (alarms, notification, calls).
* @hide
*/
@@ -7782,11 +7814,22 @@ public final class Settings {
public static final String SILENCE_CALL_GESTURE_COUNT = "silence_call_gesture_count";
/**
- * Count of successful silence notification gestures.
+ * Count of non-gesture interaction.
* @hide
*/
- public static final String SILENCE_NOTIFICATION_GESTURE_COUNT =
- "silence_notification_gesture_count";
+ public static final String SILENCE_ALARMS_TOUCH_COUNT = "silence_alarms_touch_count";
+
+ /**
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SILENCE_TIMER_TOUCH_COUNT = "silence_timer_touch_count";
+
+ /**
+ * Count of non-gesture interaction.
+ * @hide
+ */
+ public static final String SILENCE_CALL_TOUCH_COUNT = "silence_call_touch_count";
private static final Validator SILENCE_GESTURE_COUNT_VALIDATOR =
NON_NEGATIVE_INTEGER_VALIDATOR;
@@ -8250,6 +8293,16 @@ public final class Settings {
BOOLEAN_VALIDATOR;
/**
+ * Whether or not media is shown automatically when bypassing as a heads up.
+ * @hide
+ */
+ public static final String SHOW_MEDIA_WHEN_BYPASSING =
+ "show_media_when_bypassing";
+
+ private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Whether or not face unlock requires attention. This is a cached value, the source of
* truth is obtained through the HAL.
* @hide
@@ -8289,16 +8342,6 @@ public final class Settings {
BOOLEAN_VALIDATOR;
/**
- * Whether or not the face unlock education screen has been shown to the user.
- * @hide
- */
- public static final String FACE_UNLOCK_EDUCATION_INFO_DISPLAYED =
- "face_unlock_education_info_displayed";
-
- private static final Validator FACE_UNLOCK_EDUCATION_INFO_DISPLAYED_VALIDATOR =
- BOOLEAN_VALIDATOR;
-
- /**
* Whether or not debugging is enabled.
* @hide
*/
@@ -8948,10 +8991,12 @@ public final class Settings {
DOZE_PICK_UP_GESTURE,
DOZE_DOUBLE_TAP_GESTURE,
DOZE_TAP_SCREEN_GESTURE,
- DOZE_WAKE_SCREEN_GESTURE,
+ DOZE_WAKE_LOCK_SCREEN_GESTURE,
+ DOZE_WAKE_DISPLAY_GESTURE,
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
+ SHOW_MEDIA_WHEN_BYPASSING,
FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
@@ -8992,15 +9037,19 @@ public final class Settings {
UI_NIGHT_MODE,
LOCK_SCREEN_WHEN_TRUST_LOST,
SKIP_GESTURE,
+ SKIP_DIRECTION,
SILENCE_GESTURE,
THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
NAVIGATION_MODE,
AWARE_ENABLED,
SKIP_GESTURE_COUNT,
+ SKIP_TOUCH_COUNT,
SILENCE_ALARMS_GESTURE_COUNT,
- SILENCE_NOTIFICATION_GESTURE_COUNT,
SILENCE_CALL_GESTURE_COUNT,
SILENCE_TIMER_GESTURE_COUNT,
+ SILENCE_ALARMS_TOUCH_COUNT,
+ SILENCE_CALL_TOUCH_COUNT,
+ SILENCE_TIMER_TOUCH_COUNT,
DARK_MODE_DIALOG_SEEN,
GLOBAL_ACTIONS_PANEL_ENABLED,
AWARE_LOCK_ENABLED
@@ -9119,18 +9168,18 @@ public final class Settings {
VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR);
- VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
+ VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR);
+ VALIDATORS.put(DOZE_WAKE_DISPLAY_GESTURE, DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR);
VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
+ VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
- VALIDATORS.put(FACE_UNLOCK_EDUCATION_INFO_DISPLAYED,
- FACE_UNLOCK_EDUCATION_INFO_DISPLAYED_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
@@ -9178,16 +9227,21 @@ public final class Settings {
VALIDATORS.put(LOCK_SCREEN_CUSTOM_CLOCK_FACE, LOCK_SCREEN_CUSTOM_CLOCK_FACE_VALIDATOR);
VALIDATORS.put(LOCK_SCREEN_WHEN_TRUST_LOST, LOCK_SCREEN_WHEN_TRUST_LOST_VALIDATOR);
VALIDATORS.put(SKIP_GESTURE, SKIP_GESTURE_VALIDATOR);
+ VALIDATORS.put(SKIP_DIRECTION, SKIP_DIRECTION_VALIDATOR);
+ VALIDATORS.put(SKIP_DIRECTION, SKIP_DIRECTION_VALIDATOR);
VALIDATORS.put(SILENCE_GESTURE, SILENCE_GESTURE_VALIDATOR);
VALIDATORS.put(THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
THEME_CUSTOMIZATION_OVERLAY_PACKAGES_VALIDATOR);
VALIDATORS.put(NAVIGATION_MODE, NAVIGATION_MODE_VALIDATOR);
VALIDATORS.put(AWARE_ENABLED, AWARE_ENABLED_VALIDATOR);
VALIDATORS.put(SKIP_GESTURE_COUNT, SKIP_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SKIP_TOUCH_COUNT, SKIP_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_ALARMS_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
- VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_ALARMS_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_TIMER_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
+ VALIDATORS.put(SILENCE_CALL_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR);
@@ -13549,6 +13603,16 @@ public final class Settings {
"location_settings_link_to_permissions_enabled";
/**
+ * Flag to set the waiting time for removing invisible euicc profiles inside System >
+ * Settings.
+ * Type: long
+ *
+ * @hide
+ */
+ public static final String EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS =
+ "euicc_removing_invisible_profiles_timeout_millis";
+
+ /**
* Flag to set the waiting time for euicc factory reset inside System > Settings
* Type: long
*
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 324e02ceb1d5..0e0c676c2782 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -57,6 +57,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
+ DEFAULT_FLAGS.put("settings_skip_direction_mutable", "true");
}
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index bbd44c8b85af..4b929683fd6d 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -830,6 +830,32 @@ public final class AccessibilityInteractionController {
return false;
}
+ private void adjustBoundsInScreenIfNeeded(List<AccessibilityNodeInfo> infos) {
+ if (infos == null || shouldBypassAdjustBoundsInScreen()) {
+ return;
+ }
+ final int infoCount = infos.size();
+ for (int i = 0; i < infoCount; i++) {
+ final AccessibilityNodeInfo info = infos.get(i);
+ adjustBoundsInScreenIfNeeded(info);
+ }
+ }
+
+ private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) {
+ if (info == null || shouldBypassAdjustBoundsInScreen()) {
+ return;
+ }
+ final Rect boundsInScreen = mTempRect;
+ info.getBoundsInScreen(boundsInScreen);
+ boundsInScreen.offset(mViewRootImpl.mAttachInfo.mLocationInParentDisplay.x,
+ mViewRootImpl.mAttachInfo.mLocationInParentDisplay.y);
+ info.setBoundsInScreen(boundsInScreen);
+ }
+
+ private boolean shouldBypassAdjustBoundsInScreen() {
+ return mViewRootImpl.mAttachInfo.mLocationInParentDisplay.equals(0, 0);
+ }
+
private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
MagnificationSpec spec) {
if (info == null) {
@@ -921,6 +947,7 @@ public final class AccessibilityInteractionController {
MagnificationSpec spec, Region interactiveRegion) {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ adjustBoundsInScreenIfNeeded(infos);
applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
@@ -939,6 +966,7 @@ public final class AccessibilityInteractionController {
MagnificationSpec spec, Region interactiveRegion) {
try {
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ adjustBoundsInScreenIfNeeded(info);
applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
callback.setFindAccessibilityNodeInfoResult(info, interactionId);
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index c64386e8db79..e95b5caa4fa0 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.DisplayEventReceiver.CONFIG_CHANGED_EVENT_SUPPRESS;
import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
@@ -910,7 +911,7 @@ public final class Choreographer {
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
- super(looper, vsyncSource);
+ super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
}
// TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 60daddd663d5..91acc4638c26 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -53,6 +53,20 @@ public abstract class DisplayEventReceiver {
*/
public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;
+ /**
+ * Specifies to suppress config changed events from being generated from Surface Flinger.
+ * <p>
+ * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
+ */
+ public static final int CONFIG_CHANGED_EVENT_SUPPRESS = 0;
+
+ /**
+ * Specifies to generate config changed events from Surface Flinger.
+ * <p>
+ * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
+ */
+ public static final int CONFIG_CHANGED_EVENT_DISPATCH = 1;
+
private static final String TAG = "DisplayEventReceiver";
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -65,7 +79,7 @@ public abstract class DisplayEventReceiver {
private MessageQueue mMessageQueue;
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
- MessageQueue messageQueue, int vsyncSource);
+ MessageQueue messageQueue, int vsyncSource, int configChanged);
private static native void nativeDispose(long receiverPtr);
@FastNative
private static native void nativeScheduleVsync(long receiverPtr);
@@ -77,7 +91,7 @@ public abstract class DisplayEventReceiver {
*/
@UnsupportedAppUsage
public DisplayEventReceiver(Looper looper) {
- this(looper, VSYNC_SOURCE_APP);
+ this(looper, VSYNC_SOURCE_APP, CONFIG_CHANGED_EVENT_SUPPRESS);
}
/**
@@ -85,15 +99,17 @@ public abstract class DisplayEventReceiver {
*
* @param looper The looper to use when invoking callbacks.
* @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
+ * @param configChanged Whether to dispatch config changed events. Must be one of the
+ * CONFIG_CHANGED_EVENT_* values.
*/
- public DisplayEventReceiver(Looper looper, int vsyncSource) {
+ public DisplayEventReceiver(Looper looper, int vsyncSource, int configChanged) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
- vsyncSource);
+ vsyncSource, configChanged);
mCloseGuard.open("dispose");
}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 956161acd762..955be8d40c47 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -77,6 +77,21 @@ interface IRecentsAnimationController {
void hideCurrentInputMethod();
/**
+ * This call is deprecated, use #setDeferCancelUntilNextTransition() instead
+ * TODO(138144750): Remove this method once there are no callers
+ * @deprecated
+ */
+ void setCancelWithDeferredScreenshot(boolean screenshot);
+
+ /**
+ * Clean up the screenshot of previous task which was created during recents animation that
+ * was cancelled by a stack order change.
+ *
+ * @see {@link IRecentsAnimationRunner#onAnimationCanceled}
+ */
+ void cleanupScreenshot();
+
+ /**
* Set a state for controller whether would like to cancel recents animations with deferred
* task screenshot presentation.
*
@@ -86,22 +101,23 @@ interface IRecentsAnimationController {
* screenshot, so that Launcher can still control the leash lifecycle & make the next app
* transition animate smoothly without flickering.
*
- * @param screenshot When set {@code true}, means recents animation will be canceled when the
- * next app launch. System will take previous task's screenshot when the next
- * app transition starting, and skip previous task's animation.
- * Set {@code false} means will not take screenshot & skip animation
- * for previous task.
+ * @param defer When set {@code true}, means that the recents animation will defer canceling the
+ * animation when a stack order change is triggered until the subsequent app
+ * transition start and skip previous task's animation.
+ * When set to {@code false}, means that the recents animation will be canceled
+ * immediately when the stack order changes.
+ * @param screenshot When set {@code true}, means that the system will take previous task's
+ * screenshot and replace the contents of the leash with it when the next app
+ * transition starting. The runner must call #cleanupScreenshot() to end the
+ * recents animation.
+ * When set to {@code false}, means that the system will simply wait for the
+ * next app transition start to immediately cancel the recents animation. This
+ * can be useful when you want an immediate transition into a state where the
+ * task is shown in the home/recents activity (without waiting for a
+ * screenshot).
*
* @see #cleanupScreenshot()
* @see IRecentsAnimationRunner#onCancelled
*/
- void setCancelWithDeferredScreenshot(boolean screenshot);
-
- /**
- * Clean up the screenshot of previous task which was created during recents animation that
- * was cancelled by a stack order change.
- *
- * @see {@link IRecentsAnimationRunner#onAnimationCanceled}
- */
- void cleanupScreenshot();
+ void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot);
}
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index 9c652a8d990b..6cda60c80b7d 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -36,7 +36,7 @@ oneway interface IRecentsAnimationRunner {
* @param deferredWithScreenshot If set to {@code true}, the contents of the task will be
* replaced with a screenshot, such that the runner's leash is
* still active. As soon as the runner doesn't need the leash
- * anymore, it can call
+ * anymore, it must call
* {@link IRecentsAnimationController#cleanupScreenshot).
*
* @see {@link RecentsAnimationController#cleanupScreenshot}
diff --git a/core/java/android/view/ISystemGestureExclusionListener.aidl b/core/java/android/view/ISystemGestureExclusionListener.aidl
index a032625547d2..9c2f9a6a192c 100644
--- a/core/java/android/view/ISystemGestureExclusionListener.aidl
+++ b/core/java/android/view/ISystemGestureExclusionListener.aidl
@@ -28,7 +28,14 @@ oneway interface ISystemGestureExclusionListener {
* Called when the system gesture exclusion for the given display changed.
* @param displayId the display whose system gesture exclusion changed
* @param systemGestureExclusion a {@code Region} where the app would like priority over the
- * system gestures, in display coordinates.
+ * system gestures, in display coordinates. Certain restrictions
+ * might be applied such that apps don't get all the exclusions
+ * they request.
+ * @param systemGestureExclusionUnrestricted a {@code Region} where the app would like priority
+ * over the system gestures, in display coordinates, without
+ * any restrictions applied. Null if no restrictions have been
+ * applied.
*/
- void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion);
+ void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion,
+ in Region systemGestureExclusionUnrestricted);
} \ No newline at end of file
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 699e795be980..f34f9e6d5ce8 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -17,6 +17,7 @@
package android.view;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -57,6 +58,12 @@ oneway interface IWindow {
in DisplayCutout.ParcelableWrapper displayCutout);
/**
+ * Called when the window location in parent display has changed. The offset will only be a
+ * nonzero value if the window is on an embedded display that is re-parented to another window.
+ */
+ void locationInParentDisplayChanged(in Point offset);
+
+ /**
* Called when the window insets configuration has changed.
*/
void insetsChanged(in InsetsState insetsState);
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index bc2fe545a8ac..c686440171a2 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -55,6 +55,7 @@ public class RemoteAnimationAdapter implements Parcelable {
/** @see #getCallingPid */
private int mCallingPid;
+ private int mCallingUid;
/**
* @param runner The interface that gets notified when we actually need to start the animation.
@@ -103,10 +104,11 @@ public class RemoteAnimationAdapter implements Parcelable {
}
/**
- * To be called by system_server to keep track which pid is running this animation.
+ * To be called by system_server to keep track which pid and uid is running this animation.
*/
- public void setCallingPid(int pid) {
+ public void setCallingPidUid(int pid, int uid) {
mCallingPid = pid;
+ mCallingUid = uid;
}
/**
@@ -116,6 +118,13 @@ public class RemoteAnimationAdapter implements Parcelable {
return mCallingPid;
}
+ /**
+ * @return The uid of the process running the animation.
+ */
+ public int getCallingUid() {
+ return mCallingUid;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index 884cae440bed..da599efb6eee 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -118,9 +118,9 @@ public class RemoteAnimationDefinition implements Parcelable {
* To be called by system_server to keep track which pid is running the remote animations inside
* this definition.
*/
- public void setCallingPid(int pid) {
+ public void setCallingPidUid(int pid, int uid) {
for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
- mTransitionAnimationMap.valueAt(i).adapter.setCallingPid(pid);
+ mTransitionAnimationMap.valueAt(i).adapter.setCallingPidUid(pid, uid);
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index cb64ab1fd921..17f07b5a2ad4 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.RecordingCanvas;
@@ -80,7 +81,8 @@ public class Surface implements Parcelable {
private static native long nativeGetNextFrameNumber(long nativeObject);
private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
private static native int nativeForceScopedDisconnect(long nativeObject);
- private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
+ private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject,
+ GraphicBuffer buffer, int colorSpaceId);
private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
@@ -699,21 +701,38 @@ public class Surface implements Parcelable {
}
/**
- * Transfer ownership of buffer and present it on the Surface.
+ * Transfer ownership of buffer with a color space and present it on the Surface.
+ * The supported color spaces are SRGB and Display P3, other color spaces will be
+ * treated as SRGB.
* @hide
*/
- public void attachAndQueueBuffer(GraphicBuffer buffer) {
+ public void attachAndQueueBufferWithColorSpace(GraphicBuffer buffer, ColorSpace colorSpace) {
synchronized (mLock) {
checkNotReleasedLocked();
- int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
+ if (colorSpace == null) {
+ colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+ }
+ int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer,
+ colorSpace.getId());
if (err != 0) {
throw new RuntimeException(
- "Failed to attach and queue buffer to Surface (bad object?)");
+ "Failed to attach and queue buffer to Surface (bad object?), "
+ + "native error: " + err);
}
}
}
/**
+ * Deprecated, use attachAndQueueBufferWithColorSpace instead.
+ * Transfer ownership of buffer and present it on the Surface.
+ * The color space of the buffer is treated as SRGB.
+ * @hide
+ */
+ public void attachAndQueueBuffer(GraphicBuffer buffer) {
+ attachAndQueueBufferWithColorSpace(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
+ }
+
+ /**
* Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
* @hide
*/
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 63e14853b51d..3c045f4fdb88 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1866,7 +1866,8 @@ public final class SurfaceControl implements Parcelable {
final ScreenshotGraphicBuffer buffer = screenshotToBuffer(display, sourceCrop, width,
height, useIdentityTransform, rotation);
try {
- consumer.attachAndQueueBuffer(buffer.getGraphicBuffer());
+ consumer.attachAndQueueBufferWithColorSpace(buffer.getGraphicBuffer(),
+ buffer.getColorSpace());
} catch (RuntimeException e) {
Log.w(TAG, "Failed to take screenshot - " + e.getMessage());
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1275e46ed421..4e86e60fdd62 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1390,6 +1390,74 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
+ /** @hide */
+ @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
+ IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
+ IMPORTANT_FOR_CONTENT_CAPTURE_YES,
+ IMPORTANT_FOR_CONTENT_CAPTURE_NO,
+ IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+ IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentCaptureImportance {}
+
+ /**
+ * Automatically determine whether a view is important for content capture.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
+
+ /**
+ * The view is important for content capture, and its children (if any) will be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
+
+ /**
+ * The view is not important for content capture, but its children (if any) will be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
+
+ /**
+ * The view is important for content capture, but its children (if any) will not be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+ /**
+ * The view is not important for content capture, and its children (if any) will not be
+ * traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+
/**
* This view is enabled. Interpretation varies by subclass.
* Use with ENABLED_MASK when calling setFlags.
@@ -3362,6 +3430,55 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/* End of masks for mPrivateFlags3 */
+ /*
+ * Masks for mPrivateFlags4, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
+ * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
+ * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
+ * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
+ * |-------|-------|-------|-------|
+ */
+
+ /**
+ * Mask for obtaining the bits which specify how to determine
+ * whether a view is important for autofill.
+ *
+ * <p>NOTE: the important for content capture values were the first flags added and are set in
+ * the rightmost position, so we don't need to shift them
+ */
+ private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
+ IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
+ | IMPORTANT_FOR_CONTENT_CAPTURE_NO
+ | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
+
+ /*
+ * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
+ * should be called.
+ *
+ * The idea is to call notifyAppeared() after the view is layout and visible, then call
+ * notifyDisappeared() when it's gone (without known when it was removed from the parent).
+ */
+ private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
+ private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
+
+ /*
+ * Flags used to cache the value returned by isImportantForContentCapture while the view
+ * hierarchy is being traversed.
+ */
+ private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
+ private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
+
+ private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
+ PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
+ | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
+
+ /* End of masks for mPrivateFlags4 */
+
/** @hide */
protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
/** @hide */
@@ -3985,6 +4102,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
int mPrivateFlags3;
+ private int mPrivateFlags4;
+
/**
* This view's request for the visibility of the status bar.
* @hide
@@ -8442,6 +8561,65 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
}
+ /**
+ * Populates a {@link ViewStructure} for content capture.
+ *
+ * <p>This method is called after a view is that is eligible for content capture
+ * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
+ * the user, and the activity rendering the view is enabled for content capture) is laid out and
+ * is visible.
+ *
+ * <p>The populated structure is then passed to the service through
+ * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
+ *
+ * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
+ * the node representing this view and return right away, then asynchronously report (not
+ * necessarily in the UI thread) when the children nodes appear, disappear or have their text
+ * changed by calling
+ * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
+ * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
+ * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
+ * respectively. The structure for the a child must be created using
+ * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
+ * {@code autofillId} for a child can be obtained either through
+ * {@code childStructure.getAutofillId()} or
+ * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
+ *
+ * <p>When the virtual view hierarchy represents a web page, you should also:
+ *
+ * <ul>
+ * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
+ * capture events should be generate for that URL.
+ * <li>Create a new {@link ContentCaptureSession} child for every HTML element that
+ * renders a new URL (like an {@code IFRAME}) and use that session to notify events from
+ * that subtree.
+ * </ul>
+ *
+ * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+ * <ul>
+ * <li>{@link ViewStructure#setChildCount(int)}
+ * <li>{@link ViewStructure#addChildCount(int)}
+ * <li>{@link ViewStructure#getChildCount()}
+ * <li>{@link ViewStructure#newChild(int)}
+ * <li>{@link ViewStructure#asyncNewChild(int)}
+ * <li>{@link ViewStructure#asyncCommit()}
+ * <li>{@link ViewStructure#setWebDomain(String)}
+ * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+ * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+ * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+ * <li>{@link ViewStructure#setAlpha(float)}
+ * <li>{@link ViewStructure#setElevation(float)}
+ * <li>{@link ViewStructure#setTransformation(Matrix)}
+ *
+ * </ul>
+ *
+ * @hide
+ */
+ @TestApi
+ public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+ onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
+ }
+
/** @hide */
protected void onProvideStructure(@NonNull ViewStructure structure,
@ViewStructureType int viewFor, int flags) {
@@ -9080,6 +9258,280 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Gets the mode for determining whether this view is important for content capture.
+ *
+ * <p>See {@link #setImportantForContentCapture(int)} and
+ * {@link #isImportantForContentCapture()} for more info about this mode.
+ *
+ * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
+ * {@link #setImportantForContentCapture(int)}.
+ *
+ * @attr ref android.R.styleable#View_importantForContentCapture
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(mapping = {
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+ to = "yesExcludeDescendants"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+ to = "noExcludeDescendants")})
+// @InspectableProperty(enumMapping = {
+// @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
+// @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
+// @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
+// @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+// name = "yesExcludeDescendants"),
+// @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+// name = "noExcludeDescendants"),
+// })
+ @TestApi
+ public @ContentCaptureImportance int getImportantForContentCapture() {
+ // NOTE: the important for content capture values were the first flags added and are set in
+ // the rightmost position, so we don't need to shift them
+ return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+ }
+
+ /**
+ * Sets the mode for determining whether this view is considered important for content capture.
+ *
+ * <p>The platform determines the importance for autofill automatically but you
+ * can use this method to customize the behavior. Typically, a view that provides text should
+ * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
+ *
+ * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
+ * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
+ * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
+ * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
+ *
+ * @attr ref android.R.styleable#View_importantForContentCapture
+ *
+ * @hide
+ */
+ @TestApi
+ public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
+ // Reset first
+ mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+ // Then set again
+ // NOTE: the important for content capture values were the first flags added and are set in
+ // the rightmost position, so we don't need to shift them
+ mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
+ }
+
+ /**
+ * Hints the Android System whether this view is considered important for content capture, based
+ * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
+ * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
+ *
+ * <p>See {@link ContentCaptureManager} for more info about content capture.
+ *
+ * @return whether the view is considered important for content capture.
+ *
+ * @see #setImportantForContentCapture(int)
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ *
+ * @hide
+ */
+ @TestApi
+ public final boolean isImportantForContentCapture() {
+ boolean isImportant;
+ if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
+ isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
+ return isImportant;
+ }
+
+ isImportant = calculateIsImportantForContentCapture();
+
+ mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
+ if (isImportant) {
+ mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
+ }
+ mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
+ return isImportant;
+ }
+
+ /**
+ * Calculates whether the flag is important for content capture so it can be used by
+ * {@link #isImportantForContentCapture()} while the tree is traversed.
+ */
+ private boolean calculateIsImportantForContentCapture() {
+ // Check parent mode to ensure we're important
+ ViewParent parent = mParent;
+ while (parent instanceof View) {
+ final int parentImportance = ((View) parent).getImportantForContentCapture();
+ if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for "
+ + "content capture because parent " + parent + "'s importance is "
+ + parentImportance);
+ }
+ return false;
+ }
+ parent = parent.getParent();
+ }
+
+ final int importance = getImportantForContentCapture();
+
+ // First, check the explicit states.
+ if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
+ return true;
+ }
+ if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for content "
+ + "capture because its importance is " + importance);
+ }
+ return false;
+ }
+
+ // Then use some heuristics to handle AUTO.
+ if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
+ + " on view " + this);
+ return false;
+ }
+
+ // View group is important if at least one children also is
+ if (this instanceof ViewGroup) {
+ final ViewGroup group = (ViewGroup) this;
+ for (int i = 0; i < group.getChildCount(); i++) {
+ final View child = group.getChildAt(i);
+ if (child.isImportantForContentCapture()) {
+ return true;
+ }
+ }
+ }
+
+ // If the app developer explicitly set hints or autofill hintsfor it, it's important.
+ if (getAutofillHints() != null) {
+ return true;
+ }
+
+ // Otherwise, assume it's not important...
+ return false;
+ }
+
+ /**
+ * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
+ * added, based on whether it's laid out and visible, and without knowing if the parent removed
+ * it from the view hierarchy.
+ *
+ * <p>This method is called from many places (visibility changed, view laid out, view attached
+ * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
+ * described below:
+ *
+ * <ol>
+ * <li>It should only be called when content capture is enabled for the view.
+ * <li>It must call viewAppeared() before viewDisappeared()
+ * <li>viewAppearead() can only be called when the view is visible and laidout
+ * <li>It should not call the same event twice.
+ * </ol>
+ */
+ private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
+ AttachInfo ai = mAttachInfo;
+ // Skip it while the view is being laided out for the first time
+ if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
+
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW,
+ "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
+ }
+ try {
+ notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+
+ private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
+ AttachInfo ai = mAttachInfo;
+
+ // First check if context has client, so it saves a service lookup when it doesn't
+ if (mContext.getContentCaptureOptions() == null) return;
+
+ // Then check if it's enabled in the context...
+ final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
+ : mContext.getSystemService(ContentCaptureManager.class);
+ if (ccm == null || !ccm.isContentCaptureEnabled()) return;
+
+ // ... and finally at the view level
+ // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
+ if (!isImportantForContentCapture()) return;
+
+ ContentCaptureSession session = getContentCaptureSession();
+ if (session == null) return;
+
+ if (appeared) {
+ if (!isLaidOut() || getVisibility() != VISIBLE
+ || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
+ + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
+ + ", visible=" + (getVisibility() == VISIBLE)
+ + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
+ & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
+ + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
+ & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
+ }
+ return;
+ }
+ setNotifiedContentCaptureAppeared();
+
+ if (ai != null) {
+ ai.delayNotifyContentCaptureEvent(session, this, appeared);
+ } else {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
+ }
+ }
+ } else {
+ if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
+ || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
+ + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
+ + ", visible=" + (getVisibility() == VISIBLE)
+ + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
+ & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
+ + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
+ & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
+ }
+ return;
+ }
+ mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
+ mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
+
+ if (ai != null) {
+ ai.delayNotifyContentCaptureEvent(session, this, appeared);
+ } else {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
+ }
+ }
+ }
+ }
+
+ private void setNotifiedContentCaptureAppeared() {
+ mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
+ mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
+ }
+
+ /** @hide */
+ protected boolean getNotifiedContentCaptureAppeared() {
+ return (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0;
+ }
+
+
+ /**
* Sets the (optional) {@link ContentCaptureSession} associated with this view.
*
* <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
@@ -9332,6 +9784,68 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Dispatches the initial content capture events for a view structure.
+ *
+ * @hide
+ */
+ public void dispatchInitialProvideContentCaptureStructure() {
+ AttachInfo ai = mAttachInfo;
+ if (ai == null) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG,
+ "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
+ return;
+ }
+ ContentCaptureManager ccm = ai.mContentCaptureManager;
+ if (ccm == null) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
+ + "no ContentCaptureManager for " + this);
+ return;
+ }
+
+ // We must set it before checkign if the view itself is important, because it might
+ // initially not be (for example, if it's empty), although that might change later (for
+ // example, if important views are added)
+ ai.mReadyForContentCaptureUpdates = true;
+
+ if (!isImportantForContentCapture()) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
+ Log.d(CONTENT_CAPTURE_LOG_TAG,
+ "dispatchProvideContentCaptureStructure(): decorView is not important");
+ }
+ return;
+ }
+
+ ai.mContentCaptureManager = ccm;
+
+ ContentCaptureSession session = getContentCaptureSession();
+ if (session == null) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
+ Log.d(CONTENT_CAPTURE_LOG_TAG,
+ "dispatchProvideContentCaptureStructure(): no session for " + this);
+ }
+ return;
+ }
+
+ session.internalNotifyViewTreeEvent(/* started= */ true);
+ try {
+ dispatchProvideContentCaptureStructure();
+ } finally {
+ session.internalNotifyViewTreeEvent(/* started= */ false);
+ }
+ }
+
+ /** @hide */
+ void dispatchProvideContentCaptureStructure() {
+ ContentCaptureSession session = getContentCaptureSession();
+ if (session != null) {
+ ViewStructure structure = session.newViewStructure(this);
+ onProvideContentCaptureStructure(structure, /* flags= */ 0);
+ setNotifiedContentCaptureAppeared();
+ session.notifyViewAppeared(structure);
+ }
+ }
+
+ /**
* @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
*
* Note: Called from the default {@link AccessibilityDelegate}.
@@ -10571,6 +11085,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* <p>Do not modify the provided list after this method is called.</p>
*
+ * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
+ * exclusions it takes into account. The limit does not apply while the navigation
+ * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
+ * {@link android.inputmethodservice.InputMethodService input method} and
+ * {@link Intent#CATEGORY_HOME home activity}.
+ * </p>
+ *
* @param rects A list of precision gesture regions that this view needs to function correctly
*/
public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
@@ -13281,6 +13802,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void dispatchStartTemporaryDetach() {
mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
notifyEnterOrExitForAutoFillIfNeeded(false);
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
onStartTemporaryDetach();
}
@@ -13307,6 +13829,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
notifyEnterOrExitForAutoFillIfNeeded(true);
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
/**
@@ -13898,6 +14421,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
: AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
}
}
+
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
}
/**
@@ -17593,6 +18118,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
// Reset content capture caches
+ mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
mCachedContentCaptureSession = null;
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
@@ -19602,6 +20128,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
needGlobalAttributesUpdate(false);
notifyEnterOrExitForAutoFillIfNeeded(true);
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -19651,6 +20178,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
notifyEnterOrExitForAutoFillIfNeeded(false);
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
}
/**
@@ -21985,6 +22513,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
notifyEnterOrExitForAutoFillIfNeeded(true);
}
+
+ notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
private boolean hasParentWantsFocus() {
@@ -28050,6 +28580,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean mHandlingPointerEvent;
/**
+ * The offset of this view's window when it's on an embedded display that is re-parented
+ * to another window.
+ */
+ final Point mLocationInParentDisplay = new Point();
+
+ /**
* Global to the view hierarchy used as a temporary for dealing with
* x/y points in the transparent region computations.
*/
@@ -28196,6 +28732,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
View mTooltipHost;
/**
+ * The initial structure has been reported so the view is ready to report updates.
+ */
+ boolean mReadyForContentCaptureUpdates;
+
+ /**
+ * Map(keyed by session) of content capture events that need to be notified after the view
+ * hierarchy is traversed: value is either the view itself for appearead events, or its
+ * autofill id for disappeared.
+ */
+ SparseArray<ArrayList<Object>> mContentCaptureEvents;
+
+ /**
+ * Cached reference to the {@link ContentCaptureManager}.
+ */
+ ContentCaptureManager mContentCaptureManager;
+
+ /**
* Creates a new set of attachment information with the specified
* events handler and thread.
*
@@ -28213,6 +28766,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mRootCallbacks = effectPlayer;
mTreeObserver = new ViewTreeObserver(context);
}
+
+ private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
+ @NonNull View view, boolean appeared) {
+ if (mContentCaptureEvents == null) {
+ // Most of the time there will be just one session, so intial capacity is 1
+ mContentCaptureEvents = new SparseArray<>(1);
+ }
+ int sessionId = session.getId();
+ // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
+ ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
+ if (events == null) {
+ events = new ArrayList<>();
+ mContentCaptureEvents.put(sessionId, events);
+ }
+ events.add(appeared ? view : view.getAutofillId());
+ }
+
+ @Nullable
+ ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
+ if (mContentCaptureManager != null) {
+ return mContentCaptureManager;
+ }
+ mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
+ return mContentCaptureManager;
+ }
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d362024ed525..937bd1b34e61 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3606,7 +3606,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return;
}
- final ChildListForAutofill children = getChildrenForAutofill(flags);
+ final ChildListForAutoFillOrContentCapture children = getChildrenForAutofill(flags);
final int childrenCount = children.size();
structure.setChildCount(childrenCount);
for (int i = 0; i < childrenCount; i++) {
@@ -3617,14 +3617,30 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
children.recycle();
}
+ /** @hide */
+ @Override
+ public void dispatchProvideContentCaptureStructure() {
+ super.dispatchProvideContentCaptureStructure();
+
+ if (!isLaidOut()) return;
+
+ final ChildListForAutoFillOrContentCapture children = getChildrenForContentCapture();
+ final int childrenCount = children.size();
+ for (int i = 0; i < childrenCount; i++) {
+ final View child = children.get(i);
+ child.dispatchProvideContentCaptureStructure();
+ }
+ children.recycle();
+ }
+
/**
* Gets the children for autofill. Children for autofill are the first
* level descendants that are important for autofill. The returned
* child list object is pooled and the caller must recycle it once done.
* @hide */
- private @NonNull ChildListForAutofill getChildrenForAutofill(
+ private @NonNull ChildListForAutoFillOrContentCapture getChildrenForAutofill(
@AutofillFlags int flags) {
- final ChildListForAutofill children = ChildListForAutofill
+ final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
.obtain();
populateChildrenForAutofill(children, flags);
return children;
@@ -3652,6 +3668,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ private @NonNull ChildListForAutoFillOrContentCapture getChildrenForContentCapture() {
+ final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
+ .obtain();
+ populateChildrenForContentCapture(children);
+ return children;
+ }
+
+ /** @hide */
+ private void populateChildrenForContentCapture(ArrayList<View> list) {
+ final int childrenCount = mChildrenCount;
+ if (childrenCount <= 0) {
+ return;
+ }
+ final ArrayList<View> preorderedList = buildOrderedChildList();
+ final boolean customOrder = preorderedList == null
+ && isChildrenDrawingOrderEnabled();
+ for (int i = 0; i < childrenCount; i++) {
+ final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+ final View child = (preorderedList == null)
+ ? mChildren[childIndex] : preorderedList.get(childIndex);
+ if (child.isImportantForContentCapture()) {
+ list.add(child);
+ } else if (child instanceof ViewGroup) {
+ ((ViewGroup) child).populateChildrenForContentCapture(list);
+ }
+ }
+ }
+
private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children,
int childIndex) {
final View child;
@@ -8634,16 +8678,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* Pooled class that to hold the children for autifill.
*/
- private static class ChildListForAutofill extends ArrayList<View> {
+ private static class ChildListForAutoFillOrContentCapture extends ArrayList<View> {
private static final int MAX_POOL_SIZE = 32;
- private static final Pools.SimplePool<ChildListForAutofill> sPool =
+ private static final Pools.SimplePool<ChildListForAutoFillOrContentCapture> sPool =
new Pools.SimplePool<>(MAX_POOL_SIZE);
- public static ChildListForAutofill obtain() {
- ChildListForAutofill list = sPool.acquire();
+ public static ChildListForAutoFillOrContentCapture obtain() {
+ ChildListForAutoFillOrContentCapture list = sPool.acquire();
if (list == null) {
- list = new ChildListForAutofill();
+ list = new ChildListForAutoFillOrContentCapture();
}
return list;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index aceb276e9fc0..440df89f814f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -105,7 +105,11 @@ import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
+import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
+import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureSession;
+import android.view.contentcapture.MainContentCaptureSession;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -220,6 +224,21 @@ public final class ViewRootImpl implements ViewParent,
*/
static final int MAX_TRACKBALL_DELAY = 250;
+ /**
+ * Initial value for {@link #mContentCaptureEnabled}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_NOT_CHECKED = 0;
+
+ /**
+ * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code true}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_TRUE = 1;
+
+ /**
+ * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code false}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
+
@UnsupportedAppUsage
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
@@ -410,6 +429,10 @@ public final class ViewRootImpl implements ViewParent,
boolean mLayoutRequested;
boolean mFirst;
+ @Nullable
+ int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
+ boolean mPerformContentCapture;
+
boolean mReportNextDraw;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -607,6 +630,7 @@ public final class ViewRootImpl implements ViewParent,
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
+ mPerformContentCapture = true; // also true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
@@ -2765,9 +2789,55 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ if (mAttachInfo.mContentCaptureEvents != null) {
+ notifyContentCatpureEvents();
+ }
+
mIsInTraversal = false;
}
+ private void notifyContentCatpureEvents() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
+ try {
+ MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
+ .getMainContentCaptureSession();
+ for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
+ int sessionId = mAttachInfo.mContentCaptureEvents.keyAt(i);
+ mainSession.notifyViewTreeEvent(sessionId, /* started= */ true);
+ ArrayList<Object> events = mAttachInfo.mContentCaptureEvents
+ .valueAt(i);
+ for_each_event: for (int j = 0; j < events.size(); j++) {
+ Object event = events.get(j);
+ if (event instanceof AutofillId) {
+ mainSession.notifyViewDisappeared(sessionId, (AutofillId) event);
+ } else if (event instanceof View) {
+ View view = (View) event;
+ ContentCaptureSession session = view.getContentCaptureSession();
+ if (session == null) {
+ Log.w(mTag, "no content capture session on view: " + view);
+ continue for_each_event;
+ }
+ int actualId = session.getId();
+ if (actualId != sessionId) {
+ Log.w(mTag, "content capture session mismatch for view (" + view
+ + "): was " + sessionId + " before, it's " + actualId + " now");
+ continue for_each_event;
+ }
+ ViewStructure structure = session.newViewStructure(view);
+ view.onProvideContentCaptureStructure(structure, /* flags= */ 0);
+ session.notifyViewAppeared(structure);
+ } else {
+ Log.w(mTag, "invalid content capture event: " + event);
+ }
+ }
+ mainSession.notifyViewTreeEvent(sessionId, /* started= */ false);
+ }
+ mAttachInfo.mContentCaptureEvents = null;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+
private void notifySurfaceDestroyed() {
mSurfaceHolder.ungetCallbacks();
SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
@@ -2902,6 +2972,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
+
+ // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
+ // is lost, so we don't need to to force a flush - there might be other events such as
+ // text changes, but these should be flushed independently.
+ if (hasWindowFocus) {
+ handleContentCaptureFlush();
+ }
}
private void fireAccessibilityFocusEventIfHasFocusedNode() {
@@ -3468,6 +3545,86 @@ public final class ViewRootImpl implements ViewParent,
pendingDrawFinished();
}
}
+ if (mPerformContentCapture) {
+ performContentCaptureInitialReport();
+ }
+ }
+
+ /**
+ * Checks (and caches) if content capture is enabled for this context.
+ */
+ private boolean isContentCaptureEnabled() {
+ switch (mContentCaptureEnabled) {
+ case CONTENT_CAPTURE_ENABLED_TRUE:
+ return true;
+ case CONTENT_CAPTURE_ENABLED_FALSE:
+ return false;
+ case CONTENT_CAPTURE_ENABLED_NOT_CHECKED:
+ final boolean reallyEnabled = isContentCaptureReallyEnabled();
+ mContentCaptureEnabled = reallyEnabled ? CONTENT_CAPTURE_ENABLED_TRUE
+ : CONTENT_CAPTURE_ENABLED_FALSE;
+ return reallyEnabled;
+ default:
+ Log.w(TAG, "isContentCaptureEnabled(): invalid state " + mContentCaptureEnabled);
+ return false;
+ }
+
+ }
+
+ /**
+ * Checks (without caching) if content capture is enabled for this context.
+ */
+ private boolean isContentCaptureReallyEnabled() {
+ // First check if context supports it, so it saves a service lookup when it doesn't
+ if (mContext.getContentCaptureOptions() == null) return false;
+
+ final ContentCaptureManager ccm = mAttachInfo.getContentCaptureManager(mContext);
+ // Then check if it's enabled in the contex itself.
+ if (ccm == null || !ccm.isContentCaptureEnabled()) return false;
+
+ return true;
+ }
+
+ private void performContentCaptureInitialReport() {
+ mPerformContentCapture = false; // One-time offer!
+ final View rootView = mView;
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
+ }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
+ + getClass().getSimpleName());
+ }
+ try {
+ if (!isContentCaptureEnabled()) return;
+
+ // Content capture is a go!
+ rootView.dispatchInitialProvideContentCaptureStructure();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+
+ private void handleContentCaptureFlush() {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(mTag, "handleContentCaptureFlush()");
+ }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
+ + getClass().getSimpleName());
+ }
+ try {
+ if (!isContentCaptureEnabled()) return;
+
+ final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
+ if (ccm == null) {
+ Log.w(TAG, "No ContentCapture on AttachInfo");
+ return;
+ }
+ ccm.flush(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
}
private boolean draw(boolean fullRedrawNeeded) {
@@ -3834,6 +3991,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ void updateLocationInParentDisplay(int x, int y) {
+ if (mAttachInfo != null
+ && !mAttachInfo.mLocationInParentDisplay.equals(x, y)) {
+ mAttachInfo.mLocationInParentDisplay.set(x, y);
+ }
+ }
+
/**
* Set the root-level system gesture exclusion rects. These are added to those provided by
* the root's view hierarchy.
@@ -4338,6 +4502,7 @@ public final class ViewRootImpl implements ViewParent,
private static final int MSG_INSETS_CHANGED = 30;
private static final int MSG_INSETS_CONTROL_CHANGED = 31;
private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
+ private static final int MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED = 33;
final class ViewRootHandler extends Handler {
@Override
@@ -4399,6 +4564,8 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_INSETS_CONTROL_CHANGED";
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED:
return "MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED";
+ case MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED:
+ return "MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED";
}
return super.getMessageName(message);
}
@@ -4634,6 +4801,9 @@ public final class ViewRootImpl implements ViewParent,
case MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED: {
systemGestureExclusionChanged();
} break;
+ case MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED: {
+ updateLocationInParentDisplay(msg.arg1, msg.arg2);
+ } break;
}
}
}
@@ -7840,6 +8010,17 @@ public final class ViewRootImpl implements ViewParent,
mHandler.sendMessage(msg);
}
+ /**
+ * Dispatch the offset changed.
+ *
+ * @param offset the offset of this view in the parent window.
+ */
+ public void dispatchLocationInParentDisplayChanged(Point offset) {
+ Message msg =
+ mHandler.obtainMessage(MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED, offset.x, offset.y);
+ mHandler.sendMessage(msg);
+ }
+
public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
synchronized (this) {
mWindowFocusChanged = true;
@@ -8367,6 +8548,14 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
+ public void locationInParentDisplayChanged(Point offset) {
+ final ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchLocationInParentDisplayChanged(offset);
+ }
+ }
+
+ @Override
public void insetsChanged(InsetsState insetsState) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 9340b71a5280..bcc6a552f569 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -35,6 +35,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.SparseArray;
@@ -644,6 +645,14 @@ public final class WindowInsets {
* {@link View#setSystemGestureExclusionRects} outside of the
* {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
*
+ * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
+ * exclusions it takes into account. The limit does not apply while the navigation
+ * bar is {@link View#SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
+ * {@link android.inputmethodservice.InputMethodService input method} and
+ * {@link Intent#CATEGORY_HOME home activity}.
+ * </p>
+ *
+ *
* <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
* as long as they are outside the {@link #getTappableElementInsets() system window insets}.
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index a25f2eede905..2e5a7501f898 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -261,6 +261,13 @@ public interface WindowManager extends ViewManager {
int TRANSIT_TASK_CHANGE_WINDOWING_MODE = 27;
/**
+ * A display which can only contain one task is being shown because the first activity is
+ * started or it's being turned on.
+ * @hide
+ */
+ int TRANSIT_SHOW_SINGLE_TASK_DISPLAY = 28;
+
+ /**
* @hide
*/
@IntDef(prefix = { "TRANSIT_" }, value = {
@@ -287,7 +294,8 @@ public interface WindowManager extends ViewManager {
TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
TRANSIT_CRASHING_ACTIVITY_CLOSE,
- TRANSIT_TASK_CHANGE_WINDOWING_MODE
+ TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+ TRANSIT_SHOW_SINGLE_TASK_DISPLAY
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionType {}
@@ -311,6 +319,12 @@ public interface WindowManager extends ViewManager {
int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER = 0x4;
/**
+ * Transition flag: Keyguard is going away with subtle animation.
+ * @hide
+ */
+ int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION = 0x8;
+
+ /**
* @hide
*/
@IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 46a59f09eca7..a22f5a576ab6 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -38,10 +38,11 @@ public interface WindowManagerPolicyConstants {
int FLAG_INTERACTIVE = 0x20000000;
int FLAG_PASS_TO_USER = 0x40000000;
- // Flags for IActivityManager.keyguardGoingAway()
+ // Flags for IActivityTaskManager.keyguardGoingAway()
int KEYGUARD_GOING_AWAY_FLAG_TO_SHADE = 1 << 0;
int KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS = 1 << 1;
int KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER = 1 << 2;
+ int KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS = 1 << 3;
// Flags used for indicating whether the internal and/or external input devices
// of some type are available.
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index c5a5f7360321..1e7440bd5a43 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -428,14 +428,16 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
final int flushFrequencyMs;
- if (reason == FLUSH_REASON_IDLE_TIMEOUT) {
- flushFrequencyMs = mManager.mOptions.idleFlushingFrequencyMs;
- } else if (reason == FLUSH_REASON_TEXT_CHANGE_TIMEOUT) {
+ if (reason == FLUSH_REASON_TEXT_CHANGE_TIMEOUT) {
flushFrequencyMs = mManager.mOptions.textChangeFlushingFrequencyMs;
} else {
- Log.e(TAG, "handleScheduleFlush(" + getDebugState(reason) + "): not called with a "
- + "timeout reason.");
- return;
+ if (reason != FLUSH_REASON_IDLE_TIMEOUT) {
+ if (sDebug) {
+ Log.d(TAG, "handleScheduleFlush(" + getDebugState(reason) + "): not a timeout "
+ + "reason because mDirectServiceInterface is not ready yet");
+ }
+ }
+ flushFrequencyMs = mManager.mOptions.idleFlushingFrequencyMs;
}
mNextFlush = System.currentTimeMillis() + flushFrequencyMs;
@@ -478,6 +480,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
return;
}
+ mNextFlushForTextChanged = false;
+
final int numberEvents = mEvents.size();
final String reasonString = getFlushReasonAsString(reason);
if (sDebug) {
@@ -493,10 +497,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
try {
mHandler.removeMessages(MSG_FLUSH);
- if (reason == FLUSH_REASON_TEXT_CHANGE_TIMEOUT) {
- mNextFlushForTextChanged = false;
- }
-
final ParceledListSlice<ContentCaptureEvent> events = clearEvents();
mDirectServiceInterface.sendEvents(events, reason, mManager.mOptions);
} catch (RemoteException e) {
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 18ec334d0283..ac145b1d81a5 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -32,7 +32,7 @@ import android.net.Uri;
* avoid unintentionally granting requests for new permissions, you should pass the
* specific permissions you intend to grant to {@link #grant(String[]) grant()},
* and avoid writing code like this example:
- * <pre>
+ * <pre class="prettyprint">
* permissionRequest.grant(permissionRequest.getResources()) // This is wrong!!!
* </pre>
* See the WebView's release notes for information about new protected resources.
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 95fe963d7891..4db630808ef1 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -519,15 +519,17 @@ public class WebChromeClient {
* may not be supported and applications wishing to support these sources
* or more advanced file operations should build their own Intent.
*
- * <pre>
- * How to use:
- * 1. Build an intent using {@link #createIntent}
- * 2. Fire the intent using {@link android.app.Activity#startActivityForResult}.
- * 3. Check for ActivityNotFoundException and take a user friendly action if thrown.
- * 4. Listen the result using {@link android.app.Activity#onActivityResult}
- * 5. Parse the result using {@link #parseResult} only if media capture was not requested.
- * 6. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser}
- * </pre>
+ * <p>How to use:
+ * <ol>
+ * <li>Build an intent using {@link #createIntent}</li>
+ * <li>Fire the intent using {@link android.app.Activity#startActivityForResult}.</li>
+ * <li>Check for ActivityNotFoundException and take a user friendly action if thrown.</li>
+ * <li>Listen the result using {@link android.app.Activity#onActivityResult}</li>
+ * <li>Parse the result using {@link #parseResult} only if media capture was not
+ * requested.</li>
+ * <li>Send the result using filePathCallback of {@link
+ * WebChromeClient#onShowFileChooser}</li>
+ * </ol>
*
* @return an Intent that supports basic file chooser sources.
*/
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index a46580dcc539..18d4d691f726 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -464,7 +464,9 @@ public abstract class WebSettings {
* Note that the feature will continue to be supported on older versions of
* Android as before.
*
- * This function does not have any effect.
+ * @deprecated In Android O and afterwards, this function does not have
+ * any effect, the form data will be saved to platform's autofill service
+ * if applicable.
*/
@Deprecated
public abstract void setSaveFormData(boolean save);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 14be73dec41c..95fca00f2346 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -413,6 +413,9 @@ public class WebView extends AbsoluteLayout
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
+ if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+ }
if (context == null) {
throw new IllegalArgumentException("Invalid context argument");
@@ -759,7 +762,7 @@ public class WebView extends AbsoluteLayout
* encoded. If the data is base64 encoded, the value of the encoding
* parameter must be {@code "base64"}. HTML can be encoded with {@link
* android.util.Base64#encodeToString(byte[],int)} like so:
- * <pre>
+ * <pre class="prettyprint">
* String unencodedHtml =
* "&lt;html&gt;&lt;body&gt;'%28' is the code for '('&lt;/body&gt;&lt;/html&gt;";
* String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING);
@@ -1851,7 +1854,7 @@ public class WebView extends AbsoluteLayout
* important security note below for implications.
* <p> Note that injected objects will not appear in JavaScript until the page is next
* (re)loaded. JavaScript should be enabled before injecting the object. For example:
- * <pre>
+ * <pre class="prettyprint">
* class JsObject {
* {@literal @}JavascriptInterface
* public String toString() { return "injectedObject"; }
@@ -2803,6 +2806,12 @@ public class WebView extends AbsoluteLayout
mProvider.getViewDelegate().onProvideAutofillVirtualStructure(structure, flags);
}
+ /** @hide */
+ @Override
+ public void onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+ mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
+ }
+
@Override
public void autofill(SparseArray<AutofillValue>values) {
mProvider.getViewDelegate().autofill(values);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index c3e08fcf87d1..bbcba2e12a2c 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -91,6 +91,7 @@ public abstract class AbsSeekBar extends ProgressBar {
@UnsupportedAppUsage
private float mDisabledAlpha;
+ private int mThumbExclusionMaxSize;
private int mScaledTouchSlop;
private float mTouchDownX;
@UnsupportedAppUsage
@@ -171,6 +172,8 @@ public abstract class AbsSeekBar extends ProgressBar {
applyTickMarkTint();
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mThumbExclusionMaxSize = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.seekbar_thumb_exclusion_max_size);
}
/**
@@ -763,12 +766,30 @@ public abstract class AbsSeekBar extends ProgressBar {
}
mGestureExclusionRects.clear();
thumb.copyBounds(mThumbRect);
+ mThumbRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
+ growRectTo(mThumbRect, Math.min(getHeight(), mThumbExclusionMaxSize));
mGestureExclusionRects.add(mThumbRect);
mGestureExclusionRects.addAll(mUserGestureExclusionRects);
super.setSystemGestureExclusionRects(mGestureExclusionRects);
}
/**
+ * Grows {@code r} from its center such that each dimension is at least {@code minimumSize}.
+ */
+ private void growRectTo(Rect r, int minimumSize) {
+ int dy = (minimumSize - r.height()) / 2;
+ if (dy > 0) {
+ r.top -= dy;
+ r.bottom += dy;
+ }
+ int dx = (minimumSize - r.width()) / 2;
+ if (dx > 0) {
+ r.left -= dx;
+ r.right += dx;
+ }
+ }
+
+ /**
* @hide
*/
@Override
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c3bb9a0201d0..c55f7d654548 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1318,7 +1318,8 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
@ViewStructureType int viewFor, int flags) {
super.onProvideStructure(structure, viewFor, flags);
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
final Adapter adapter = getAdapter();
if (adapter == null) return;
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index c3c2c0db9a77..2bf1ba5cf017 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -50,7 +50,7 @@ import java.util.List;
* override {@link #getView(int, View, ViewGroup)}
* and inflate a view resource.
* For a code example, see
- * the <a href="https://developer.android.com/samples/CustomChoiceList/index.html">
+ * the <a href="https://github.com/googlesamples/android-CustomChoiceList/#readme">
* CustomChoiceList</a> sample.
* </p>
* <p>
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index d985528c38fb..6b324a541c42 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1202,13 +1202,13 @@ public class RelativeLayout extends ViewGroup {
* determine where to position the view on the screen. If the view is not contained
* within a relative layout, these attributes are ignored.
*
- * See the <a href="/guide/topics/ui/layout/relative.html">
- * Relative Layout</a> guide for example code demonstrating how to use relative layout’s
+ * See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative
+ * Layout</a> guide for example code demonstrating how to use relative layout's
* layout parameters in a layout XML.
*
* To learn more about layout parameters and how they differ from typical view attributes,
- * see the <a href="/guide/topics/ui/declaring-layout.html#attributes">
- * Layouts guide</a>.
+ * see the <a href="{@docRoot}guide/topics/ui/declaring-layout.html#attributes">Layouts
+ * guide</a>.
*
*
* @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 49a0f39b3bad..4c67b080252a 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -433,7 +433,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
* to the next tabbed view, in this example).
* <p>
* To move both the focus AND the selected tab at once, please use
- * {@link #setCurrentTab}. Normally, the view logic takes care of
+ * {@link #focusCurrentTab}. Normally, the view logic takes care of
* adjusting the focus, so unless you're circumventing the UI,
* you'll probably just focus your interest here.
*
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 62598fce5947..0918c5fdefa8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -162,6 +162,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureSession;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -977,6 +979,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
+ if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+ }
setTextInternal("");
@@ -10558,7 +10563,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * Notify managers (such as {@link AutofillManager}) that are interested in text changes.
+ * Notify managers (such as {@link AutofillManager} and {@link ContentCaptureManager}) that are
+ * interested on text changes.
*/
private void notifyListeningManagersAfterTextChanged() {
@@ -10574,6 +10580,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
afm.notifyValueChanged(TextView.this);
}
}
+
+ // TODO(b/121045053): should use a flag / boolean to keep status of SHOWN / HIDDEN instead
+ // of using isLaidout(), so it's not called in cases where it's laid out but a
+ // notifyAppeared was not sent.
+
+ // ContentCapture
+ if (isLaidOut() && isImportantForContentCapture() && getNotifiedContentCaptureAppeared()) {
+ final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
+ if (cm != null && cm.isContentCaptureEnabled()) {
+ final ContentCaptureSession session = getContentCaptureSession();
+ if (session != null) {
+ // TODO(b/111276913): pass flags when edited by user / add CTS test
+ session.notifyViewTextChanged(getAutofillId(), getText());
+ }
+ }
+ }
}
private boolean isAutofillable() {
@@ -11417,7 +11439,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
}
@@ -11433,8 +11456,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
if (mLayout == null) {
+ if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ Log.w(LOG_TAG, "onProvideContentCaptureStructure(): calling assumeLayout()");
+ }
assumeLayout();
}
Layout layout = mLayout;
@@ -11522,7 +11549,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
+ if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
// Extract style information that applies to the TextView as a whole.
int style = 0;
int typefaceStyle = getTypefaceStyle();
@@ -11550,7 +11578,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
}
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
structure.setMinTextEms(getMinEms());
structure.setMaxTextEms(getMaxEms());
int maxLength = -1;