Merge "Replace the native scrypt in SyntheticPasswordManager by android.security.Scrypt (try this again)"
diff --git a/Android.bp b/Android.bp
index 34162d1..2ae7d6c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -268,6 +268,8 @@
"core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
":keystore_aidl",
"core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
+ "core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl",
+ "core/java/android/service/autofill/augmented/IFillCallback.aidl",
"core/java/android/service/autofill/IAutoFillService.aidl",
"core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
"core/java/android/service/autofill/IFillCallback.aidl",
@@ -290,7 +292,7 @@
"core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
"core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
"core/java/android/service/gatekeeper/IGateKeeperService.aidl",
- "core/java/android/service/intelligence/IIntelligenceService.aidl",
+ "core/java/android/service/contentcapture/IContentCaptureService.aidl",
"core/java/android/service/notification/INotificationListener.aidl",
"core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
"core/java/android/service/notification/IConditionListener.aidl",
@@ -351,7 +353,7 @@
"core/java/android/view/autofill/IAutoFillManagerClient.aidl",
"core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl",
"core/java/android/view/autofill/IAutofillWindowPresenter.aidl",
- "core/java/android/view/intelligence/IIntelligenceManager.aidl",
+ "core/java/android/view/contentcapture/IContentCaptureManager.aidl",
"core/java/android/view/IApplicationToken.aidl",
"core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
"core/java/android/view/IDockedStackListener.aidl",
diff --git a/api/current.txt b/api/current.txt
index f7060f3..f6f5476 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11479,6 +11479,7 @@
field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ field public static final java.lang.String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
field public static final java.lang.String FEATURE_IRIS = "android.hardware.iris";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
@@ -27019,6 +27020,7 @@
public static final class MediaSessionManager.RemoteUserInfo {
ctor public MediaSessionManager.RemoteUserInfo(java.lang.String, int, int);
+ ctor public MediaSessionManager.RemoteUserInfo(java.lang.String, int, int, android.os.IBinder);
method public java.lang.String getPackageName();
method public int getPid();
method public int getUid();
@@ -34659,6 +34661,7 @@
field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
+ field public static final java.lang.String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
field public static final java.lang.String DISALLOW_CREATE_WINDOWS = "no_create_windows";
field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
field public static final java.lang.String DISALLOW_DATA_ROAMING = "no_data_roaming";
@@ -34668,7 +34671,6 @@
field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY = "no_install_unknown_sources_globally";
- field public static final java.lang.String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -37369,11 +37371,15 @@
method public static void ejectRoot(android.content.ContentResolver, android.net.Uri);
method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
method public static java.lang.String getDocumentId(android.net.Uri);
+ method public static android.os.Bundle getDocumentMetadata(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public static java.lang.String getRootId(android.net.Uri);
method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
method public static java.lang.String getTreeDocumentId(android.net.Uri);
+ method public static boolean isChildDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+ method public static boolean isRootUri(android.content.Context, android.net.Uri);
+ method public static boolean isRootsUri(android.content.Context, android.net.Uri);
method public static boolean isTreeUri(android.net.Uri);
method public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
@@ -37386,7 +37392,14 @@
field public static final java.lang.String EXTRA_LOADING = "loading";
field public static final java.lang.String EXTRA_ORIENTATION = "android.provider.extra.ORIENTATION";
field public static final java.lang.String EXTRA_PROMPT = "android.provider.extra.PROMPT";
+ field public static final java.lang.String METADATA_EXIF = "android:documentExif";
+ field public static final java.lang.String METADATA_TYPES = "android:documentMetadataTypes";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
+ field public static final java.lang.String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
+ field public static final java.lang.String QUERY_ARG_EXCLUDE_MEDIA = "android:query-arg-exclude-media";
+ field public static final java.lang.String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
+ field public static final java.lang.String QUERY_ARG_LAST_MODIFIED_AFTER = "android:query-arg-last-modified-after";
+ field public static final java.lang.String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
}
public static final class DocumentsContract.Document {
@@ -37401,8 +37414,10 @@
field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
+ field public static final int FLAG_PARTIAL = 8192; // 0x2000
field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
+ field public static final int FLAG_SUPPORTS_METADATA = 16384; // 0x4000
field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
field public static final int FLAG_SUPPORTS_REMOVE = 1024; // 0x400
field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
@@ -37433,6 +37448,7 @@
field public static final java.lang.String COLUMN_ROOT_ID = "root_id";
field public static final java.lang.String COLUMN_SUMMARY = "summary";
field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final int FLAG_EMPTY = 64; // 0x40
field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
field public static final int FLAG_SUPPORTS_EJECT = 32; // 0x20
@@ -37451,6 +37467,7 @@
method public void deleteDocument(java.lang.String) throws java.io.FileNotFoundException;
method public void ejectRoot(java.lang.String);
method public android.provider.DocumentsContract.Path findDocumentPath(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
+ method public android.os.Bundle getDocumentMetadata(java.lang.String) throws java.io.FileNotFoundException;
method public java.lang.String[] getDocumentStreamTypes(java.lang.String, java.lang.String);
method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
method public final java.lang.String getType(android.net.Uri);
@@ -37475,6 +37492,7 @@
method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+ method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String[], android.os.Bundle) throws java.io.FileNotFoundException;
method public void removeDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
method public final void revokeDocumentPermission(java.lang.String);
@@ -51850,6 +51868,21 @@
}
+package android.view.contentcapture {
+
+ public final class ContentCaptureManager {
+ method public android.content.ComponentName getServiceComponentName();
+ method public boolean isContentCaptureEnabled();
+ method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+ method public void notifyViewAppeared(android.view.ViewStructure);
+ method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+ method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
+ method public void setContentCaptureEnabled(boolean);
+ field public static final int FLAG_USER_INPUT = 1; // 0x1
+ }
+
+}
+
package android.view.inputmethod {
public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -52331,21 +52364,6 @@
}
-package android.view.intelligence {
-
- public final class ContentCaptureManager {
- method public android.content.ComponentName getServiceComponentName();
- method public boolean isContentCaptureEnabled();
- method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
- method public void notifyViewAppeared(android.view.ViewStructure);
- method public void notifyViewDisappeared(android.view.autofill.AutofillId);
- method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
- method public void setContentCaptureEnabled(boolean);
- field public static final int FLAG_USER_INPUT = 1; // 0x1
- }
-
-}
-
package android.view.textclassifier {
public final class ConversationActions implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9cf66b2..57b7eed 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21,7 +21,9 @@
field public static final java.lang.String BACKUP = "android.permission.BACKUP";
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
+ field public static final java.lang.String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -33,7 +35,6 @@
field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
- field public static final java.lang.String BIND_SMART_SUGGESTIONS_SERVICE = "android.permission.BIND_SMART_SUGGESTIONS_SERVICE";
field public static final java.lang.String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE";
field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
@@ -105,11 +106,11 @@
field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
+ field public static final java.lang.String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
field public static final java.lang.String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
- field public static final java.lang.String MANAGE_SMART_SUGGESTIONS = "android.permission.MANAGE_SMART_SUGGESTIONS";
field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
@@ -613,7 +614,12 @@
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL";
field public static final java.lang.String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL";
+ field public static final java.lang.String EXTRA_PROVISIONING_TRIGGER = "android.app.extra.PROVISIONING_TRIGGER";
field public static final java.lang.String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
+ field public static final int PROVISIONING_TRIGGER_CLOUD_ENROLLMENT = 1; // 0x1
+ field public static final int PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER = 3; // 0x3
+ field public static final int PROVISIONING_TRIGGER_QR_CODE = 2; // 0x2
+ field public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0; // 0x0
field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
@@ -4506,6 +4512,21 @@
field public static final java.lang.String STATE = "state";
}
+ public final class DocumentsContract {
+ method public static boolean isManageMode(android.net.Uri);
+ method public static android.net.Uri setManageMode(android.net.Uri);
+ field public static final java.lang.String ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
+ field public static final java.lang.String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
+ field public static final java.lang.String EXTRA_SHOW_ADVANCED = "android.provider.extra.SHOW_ADVANCED";
+ }
+
+ public static final class DocumentsContract.Root {
+ field public static final int FLAG_ADVANCED = 65536; // 0x10000
+ field public static final int FLAG_HAS_SETTINGS = 131072; // 0x20000
+ field public static final int FLAG_REMOVABLE_SD = 262144; // 0x40000
+ field public static final int FLAG_REMOVABLE_USB = 524288; // 0x80000
+ }
+
public abstract class SearchIndexableData {
ctor public SearchIndexableData();
ctor public SearchIndexableData(android.content.Context);
@@ -4858,6 +4879,69 @@
}
+package android.service.autofill.augmented {
+
+ public abstract class AugmentedAutofillService extends android.app.Service {
+ ctor public AugmentedAutofillService();
+ method public void onFillRequest(android.service.autofill.augmented.FillRequest, android.os.CancellationSignal, android.service.autofill.augmented.FillController, android.service.autofill.augmented.FillCallback);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
+ }
+
+ public final class FillCallback {
+ method public void onSuccess(android.service.autofill.augmented.FillResponse);
+ }
+
+ public final class FillController {
+ method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
+ }
+
+ public final class FillRequest {
+ method public android.content.ComponentName getActivityComponent();
+ method public android.view.autofill.AutofillId getFocusedId();
+ method public android.view.autofill.AutofillValue getFocusedValue();
+ method public android.service.autofill.augmented.PresentationParams getPresentationParams();
+ method public int getTaskId();
+ }
+
+ public final class FillResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.augmented.FillResponse> CREATOR;
+ }
+
+ public static final class FillResponse.Builder {
+ ctor public FillResponse.Builder();
+ method public android.service.autofill.augmented.FillResponse build();
+ method public android.service.autofill.augmented.FillResponse.Builder setFillWindow(android.service.autofill.augmented.FillWindow);
+ method public android.service.autofill.augmented.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
+ }
+
+ public final class FillWindow implements java.lang.AutoCloseable {
+ ctor public FillWindow();
+ method public void destroy();
+ method public boolean update(android.service.autofill.augmented.PresentationParams.Area, android.view.View, long);
+ field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
+ }
+
+ public abstract class PresentationParams {
+ method public int getFlags();
+ method public android.service.autofill.augmented.PresentationParams.Area getFullArea();
+ method public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
+ field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
+ field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
+ field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
+ field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
+ field public static final int FLAG_HOST_IME = 16; // 0x10
+ field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
+ }
+
+ public static abstract class PresentationParams.Area {
+ method public android.graphics.Rect getBounds();
+ method public android.service.autofill.augmented.PresentationParams.Area getSubArea(android.graphics.Rect);
+ }
+
+}
+
package android.service.carrier {
public abstract class ApnService extends android.app.Service {
@@ -4868,6 +4952,58 @@
}
+package android.service.contentcapture {
+
+ public final class ContentCaptureEventsRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
+ }
+
+ public abstract class ContentCaptureService extends android.app.Service {
+ ctor public ContentCaptureService();
+ method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
+ method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
+ method public void onActivitySnapshot(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.SnapshotData);
+ method public abstract void onContentCaptureEventsRequest(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.ContentCaptureEventsRequest);
+ method public void onCreateInteractionSession(android.service.contentcapture.InteractionContext, android.service.contentcapture.InteractionSessionId);
+ method public void onDestroyInteractionSession(android.service.contentcapture.InteractionSessionId);
+ method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
+ method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
+ method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
+ }
+
+ public final class InteractionContext implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.ComponentName getActivityComponent();
+ method public int getDisplayId();
+ method public int getFlags();
+ method public int getTaskId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionContext> CREATOR;
+ field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
+ field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
+ }
+
+ public final class InteractionSessionId implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionSessionId> CREATOR;
+ }
+
+ public final class SnapshotData implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.app.assist.AssistContent getAssistContent();
+ method public android.os.Bundle getAssistData();
+ method public android.app.assist.AssistStructure getAssistStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR;
+ }
+
+}
+
package android.service.euicc {
public final class EuiccProfileInfo implements android.os.Parcelable {
@@ -4988,111 +5124,6 @@
}
-package android.service.intelligence {
-
- public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method public int describeContents();
- method public java.util.List<android.view.intelligence.ContentCaptureEvent> getEvents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.ContentCaptureEventsRequest> CREATOR;
- }
-
- public final class FillCallback {
- method public void onSuccess(android.service.intelligence.FillResponse);
- }
-
- public final class FillController {
- method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
- }
-
- public final class FillRequest {
- method public android.view.autofill.AutofillValue getFocusedAutofillValue();
- method public android.view.autofill.AutofillId getFocusedId();
- method public android.service.intelligence.PresentationParams getPresentationParams();
- method public android.service.intelligence.InteractionSessionId getSessionId();
- }
-
- public final class FillResponse implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.FillResponse> CREATOR;
- }
-
- public static class FillResponse.Builder {
- ctor public FillResponse.Builder();
- method public android.service.intelligence.FillResponse build();
- method public android.service.intelligence.FillResponse.Builder setFillWindow(android.service.intelligence.FillWindow);
- method public android.service.intelligence.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
- }
-
- public final class FillWindow {
- ctor public FillWindow();
- method public void destroy();
- method public boolean update(android.service.intelligence.PresentationParams.Area, android.view.View, long);
- field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
- }
-
- public final class InteractionContext implements android.os.Parcelable {
- method public int describeContents();
- method public android.content.ComponentName getActivityComponent();
- method public int getDisplayId();
- method public int getFlags();
- method public int getTaskId();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionContext> CREATOR;
- field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
- field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
- }
-
- public final class InteractionSessionId implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionSessionId> CREATOR;
- }
-
- public abstract class PresentationParams {
- method public int getFlags();
- method public android.service.intelligence.PresentationParams.Area getFullArea();
- method public android.service.intelligence.PresentationParams.Area getSuggestionArea();
- field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
- field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
- field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
- field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
- field public static final int FLAG_HOST_IME = 16; // 0x10
- field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
- }
-
- public static abstract class PresentationParams.Area {
- method public android.graphics.Rect getBounds();
- method public android.service.intelligence.PresentationParams.Area getSubArea(android.graphics.Rect);
- }
-
- public abstract class SmartSuggestionsService extends android.app.Service {
- ctor public SmartSuggestionsService();
- method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
- method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
- method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData);
- method public abstract void onContentCaptureEventsRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.ContentCaptureEventsRequest);
- method public void onCreateInteractionSession(android.service.intelligence.InteractionContext, android.service.intelligence.InteractionSessionId);
- method public void onDestroyInteractionSession(android.service.intelligence.InteractionSessionId);
- method public void onFillRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.FillRequest, android.os.CancellationSignal, android.service.intelligence.FillController, android.service.intelligence.FillCallback);
- method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
- method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
- method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
- field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.SmartSuggestionsService";
- }
-
- public final class SnapshotData implements android.os.Parcelable {
- method public int describeContents();
- method public android.app.assist.AssistContent getAssistContent();
- method public android.os.Bundle getAssistData();
- method public android.app.assist.AssistStructure getAssistStructure();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.SnapshotData> CREATOR;
- }
-
-}
-
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
@@ -7269,7 +7300,7 @@
}
-package android.view.intelligence {
+package android.view.contentcapture {
public final class ContentCaptureEvent implements android.os.Parcelable {
method public int describeContents();
@@ -7278,13 +7309,13 @@
method public android.view.autofill.AutofillId getId();
method public java.lang.CharSequence getText();
method public int getType();
- method public android.view.intelligence.ViewNode getViewNode();
+ method public android.view.contentcapture.ViewNode getViewNode();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.intelligence.ContentCaptureEvent> CREATOR;
- field public static final int TYPE_ACTIVITY_PAUSED = 3; // 0x3
- field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
- field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
- field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
+ field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
+ field public static final deprecated int TYPE_ACTIVITY_PAUSED = 3; // 0x3
+ field public static final deprecated int TYPE_ACTIVITY_RESUMED = 2; // 0x2
+ field public static final deprecated int TYPE_ACTIVITY_STARTED = 1; // 0x1
+ field public static final deprecated int TYPE_ACTIVITY_STOPPED = 4; // 0x4
field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index b3e287b..d4fdf85 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -45,6 +45,7 @@
static struct {
jmethodID onDeviceOpen;
+ jmethodID onDeviceGetReport;
jmethodID onDeviceError;
} gDeviceCallbackClassInfo;
@@ -82,6 +83,13 @@
checkAndClearException(env, "onDeviceOpen");
}
+void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) {
+ JNIEnv* env = getJNIEnv();
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceGetReport,
+ requestId, reportId);
+ checkAndClearException(env, "onDeviceGetReport");
+}
+
JNIEnv* DeviceCallback::getJNIEnv() {
JNIEnv* env;
mJavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
@@ -103,8 +111,7 @@
return nullptr;
}
- struct uhid_event ev;
- memset(&ev, 0, sizeof(ev));
+ struct uhid_event ev = {};
ev.type = UHID_CREATE2;
strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name, sizeof(ev.u.create2.name));
memcpy(&ev.u.create2.rd_data, descriptor.data(),
@@ -152,8 +159,7 @@
} else {
LOGE("Could not remove fd, ALooper_forThread() returned NULL!");
}
- struct uhid_event ev;
- memset(&ev, 0, sizeof(ev));
+ struct uhid_event ev = {};
ev.type = UHID_DESTROY;
TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
::close(mFd);
@@ -166,8 +172,7 @@
return;
}
- struct uhid_event ev;
- memset(&ev, 0, sizeof(ev));
+ struct uhid_event ev = {};
ev.type = UHID_INPUT2;
ev.u.input2.size = report.size();
memcpy(&ev.u.input2.data, report.data(), report.size() * sizeof(ev.u.input2.data[0]));
@@ -177,6 +182,20 @@
}
}
+void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const {
+ struct uhid_event ev = {};
+ ev.type = UHID_GET_REPORT_REPLY;
+ ev.u.get_report_reply.id = id;
+ ev.u.get_report_reply.err = report.size() == 0 ? EIO : 0;
+ ev.u.get_report_reply.size = report.size();
+ memcpy(&ev.u.get_report_reply.data, report.data(),
+ report.size() * sizeof(ev.u.get_report_reply.data[0]));
+ ssize_t ret = TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
+ if (ret < 0 || ret != sizeof(ev)) {
+ LOGE("Failed to send hid event (UHID_GET_REPORT_REPLY): %s", strerror(errno));
+ }
+}
+
int Device::handleEvents(int events) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
LOGE("uhid node was closed or an error occurred. events=0x%x", events);
@@ -193,6 +212,11 @@
if (ev.type == UHID_OPEN) {
mDeviceCallback->onDeviceOpen();
+ } else if (ev.type == UHID_GET_REPORT) {
+ mDeviceCallback->onDeviceGetReport(ev.u.get_report.id, ev.u.get_report.rnum);
+ } else if (ev.type == UHID_SET_REPORT) {
+ LOGE("UHID_SET_REPORT is currently not supported");
+ return 0;
}
return 1;
@@ -201,9 +225,13 @@
} // namespace uhid
std::vector<uint8_t> getData(JNIEnv* env, jbyteArray javaArray) {
+ std::vector<uint8_t> data;
+ if (javaArray == nullptr) {
+ return data;
+ }
+
ScopedByteArrayRO scopedArray(env, javaArray);
size_t size = scopedArray.size();
- std::vector<uint8_t> data;
data.reserve(size);
for (size_t i = 0; i < size; i++) {
data.push_back(static_cast<uint8_t>(scopedArray[i]));
@@ -237,6 +265,17 @@
}
}
+static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr, jint id,
+ jbyteArray rawReport) {
+ uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
+ if (d) {
+ std::vector<uint8_t> report = getData(env, rawReport);
+ d->sendGetFeatureReportReply(id, report);
+ } else {
+ LOGE("Could not send get feature report reply, Device* is null!");
+ }
+}
+
static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
if (d) {
@@ -250,6 +289,8 @@
"Lcom/android/commands/hid/Device$DeviceCallback;)J",
reinterpret_cast<void*>(openDevice) },
{ "nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport) },
+ { "nativeSendGetFeatureReportReply", "(JI[B)V",
+ reinterpret_cast<void*>(sendGetFeatureReportReply) },
{ "nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice) },
};
@@ -261,6 +302,8 @@
}
uhid::gDeviceCallbackClassInfo.onDeviceOpen =
env->GetMethodID(clazz, "onDeviceOpen", "()V");
+ uhid::gDeviceCallbackClassInfo.onDeviceGetReport =
+ env->GetMethodID(clazz, "onDeviceGetReport", "(II)V");
uhid::gDeviceCallbackClassInfo.onDeviceError =
env->GetMethodID(clazz, "onDeviceError", "()V");
if (uhid::gDeviceCallbackClassInfo.onDeviceOpen == NULL ||
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 61a1f76..892c7cd 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -28,6 +28,7 @@
~DeviceCallback();
void onDeviceOpen();
+ void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
void onDeviceError();
private:
@@ -45,6 +46,7 @@
~Device();
void sendReport(const std::vector<uint8_t>& report) const;
+ void sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& report) const;
void close();
int handleEvents(int events);
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index 8c52a8e..616d411 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -23,6 +23,7 @@
import android.os.MessageQueue;
import android.os.SystemClock;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.os.SomeArgs;
@@ -31,11 +32,14 @@
private static final int MSG_OPEN_DEVICE = 1;
private static final int MSG_SEND_REPORT = 2;
- private static final int MSG_CLOSE_DEVICE = 3;
+ private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3;
+ private static final int MSG_CLOSE_DEVICE = 4;
private final int mId;
private final HandlerThread mThread;
private final DeviceHandler mHandler;
+ // mFeatureReports is limited to 256 entries, because the report number is 8-bit
+ private final SparseArray<byte[]> mFeatureReports;
private long mTimeToSend;
private final Object mCond = new Object();
@@ -47,13 +51,16 @@
private static native long nativeOpenDevice(String name, int id, int vid, int pid,
byte[] descriptor, DeviceCallback callback);
private static native void nativeSendReport(long ptr, byte[] data);
+ private static native void nativeSendGetFeatureReportReply(long ptr, int id, byte[] data);
private static native void nativeCloseDevice(long ptr);
- public Device(int id, String name, int vid, int pid, byte[] descriptor, byte[] report) {
+ public Device(int id, String name, int vid, int pid, byte[] descriptor,
+ byte[] report, SparseArray<byte[]> featureReports) {
mId = id;
mThread = new HandlerThread("HidDeviceHandler");
mThread.start();
mHandler = new DeviceHandler(mThread.getLooper());
+ mFeatureReports = featureReports;
SomeArgs args = SomeArgs.obtain();
args.argi1 = id;
args.argi2 = vid;
@@ -113,6 +120,13 @@
Log.e(TAG, "Tried to send report to closed device.");
}
break;
+ case MSG_SEND_GET_FEATURE_REPORT_REPLY:
+ if (mPtr != 0) {
+ nativeSendGetFeatureReportReply(mPtr, msg.arg1, (byte[]) msg.obj);
+ } else {
+ Log.e(TAG, "Tried to send feature report reply to closed device.");
+ }
+ break;
case MSG_CLOSE_DEVICE:
if (mPtr != 0) {
nativeCloseDevice(mPtr);
@@ -145,6 +159,23 @@
mHandler.resumeEvents();
}
+ public void onDeviceGetReport(int requestId, int reportId) {
+ byte[] report = mFeatureReports.get(reportId);
+
+ if (report == null) {
+ Log.e(TAG, "Requested feature report " + reportId + " is not specified");
+ }
+
+ Message msg;
+ msg = mHandler.obtainMessage(MSG_SEND_GET_FEATURE_REPORT_REPLY, requestId, 0, report);
+
+ // Message is set to asynchronous so it won't be blocked by synchronization
+ // barrier during UHID_OPEN. This is necessary for drivers that do
+ // UHID_GET_REPORT requests during probe.
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, mTimeToSend);
+ }
+
public void onDeviceError() {
Log.e(TAG, "Device error occurred, closing /dev/uhid");
Message msg = mHandler.obtainMessage(MSG_CLOSE_DEVICE);
diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java
index c6a37bd..746e372 100644
--- a/cmds/hid/src/com/android/commands/hid/Event.java
+++ b/cmds/hid/src/com/android/commands/hid/Event.java
@@ -19,6 +19,7 @@
import android.util.JsonReader;
import android.util.JsonToken;
import android.util.Log;
+import android.util.SparseArray;
import java.io.InputStreamReader;
import java.io.IOException;
@@ -39,6 +40,7 @@
private int mVid;
private int mPid;
private byte[] mReport;
+ private SparseArray<byte[]> mFeatureReports;
private int mDuration;
public int getId() {
@@ -69,6 +71,10 @@
return mReport;
}
+ public SparseArray<byte[]> getFeatureReports() {
+ return mFeatureReports;
+ }
+
public int getDuration() {
return mDuration;
}
@@ -81,6 +87,7 @@
+ ", vid=" + mVid
+ ", pid=" + mPid
+ ", report=" + Arrays.toString(mReport)
+ + ", feature_reports=" + mFeatureReports.toString()
+ ", duration=" + mDuration
+ "}";
}
@@ -112,6 +119,10 @@
mEvent.mReport = report;
}
+ public void setFeatureReports(SparseArray<byte[]> reports) {
+ mEvent.mFeatureReports = reports;
+ }
+
public void setVid(int vid) {
mEvent.mVid = vid;
}
@@ -185,6 +196,9 @@
case "report":
eb.setReport(readData());
break;
+ case "feature_reports":
+ eb.setFeatureReports(readFeatureReports());
+ break;
case "duration":
eb.setDuration(readInt());
break;
@@ -234,6 +248,47 @@
return Integer.decode(val);
}
+ private SparseArray<byte[]> readFeatureReports()
+ throws IllegalStateException, IOException {
+ SparseArray<byte[]> featureReports = new SparseArray();
+ try {
+ mReader.beginArray();
+ while (mReader.hasNext()) {
+ // If "id" is not specified, it defaults to 0, which means
+ // report does not contain report ID (based on HID specs).
+ int id = 0;
+ byte[] data = null;
+ mReader.beginObject();
+ while (mReader.hasNext()) {
+ String name = mReader.nextName();
+ switch (name) {
+ case "id":
+ id = readInt();
+ break;
+ case "data":
+ data = readData();
+ break;
+ default:
+ consumeRemainingElements();
+ mReader.endObject();
+ throw new IllegalStateException("Invalid key in feature report: "
+ + name);
+ }
+ }
+ mReader.endObject();
+ if (data != null)
+ featureReports.put(id, data);
+ }
+ mReader.endArray();
+ } catch (IllegalStateException|NumberFormatException e) {
+ consumeRemainingElements();
+ mReader.endArray();
+ throw new IllegalStateException("Encountered malformed data.", e);
+ } finally {
+ return featureReports;
+ }
+ }
+
private void consumeRemainingElements() throws IOException {
while (mReader.hasNext()) {
mReader.skipValue();
diff --git a/cmds/hid/src/com/android/commands/hid/Hid.java b/cmds/hid/src/com/android/commands/hid/Hid.java
index 234e47f..54ac1b0 100644
--- a/cmds/hid/src/com/android/commands/hid/Hid.java
+++ b/cmds/hid/src/com/android/commands/hid/Hid.java
@@ -119,7 +119,7 @@
}
int id = e.getId();
Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(),
- e.getDescriptor(), e.getReport());
+ e.getDescriptor(), e.getReport(), e.getFeatureReports());
mDevices.append(id, d);
}
diff --git a/cmds/incident_helper/OWNERS b/cmds/incident_helper/OWNERS
index 1a68a32..cede4ea 100644
--- a/cmds/incident_helper/OWNERS
+++ b/cmds/incident_helper/OWNERS
@@ -1,2 +1,3 @@
-jinyithu@google.com
+joeo@google.com
kwekua@google.com
+yanmin@google.com
diff --git a/cmds/incidentd/OWNERS b/cmds/incidentd/OWNERS
index 1a68a32..cede4ea 100644
--- a/cmds/incidentd/OWNERS
+++ b/cmds/incidentd/OWNERS
@@ -1,2 +1,3 @@
-jinyithu@google.com
+joeo@google.com
kwekua@google.com
+yanmin@google.com
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 74cda1d..04819ec 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -18,7 +18,7 @@
#include "FdBuffer.h"
-#include <cutils/log.h>
+#include <log/log.h>
#include <utils/SystemClock.h>
#include <fcntl.h>
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 3d892ad..f8fb4a6 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -29,7 +29,7 @@
#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
#include <binder/IShellCallback.h>
-#include <cutils/log.h>
+#include <log/log.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 6967e33..08f535d 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -21,7 +21,7 @@
#include <android-base/file.h>
#include <android/util/protobuf.h>
-#include <cutils/log.h>
+#include <log/log.h>
namespace android {
namespace os {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 41a2021..392d40a 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1501,17 +1501,17 @@
/**
* Where the action is happening
*/
- optional android.app.settings.PageId pageId = 3;
+ optional android.app.settings.PageId page_id = 3;
/**
* What preference changed in this event.
*/
- optional string changedPreferenceKey = 4;
+ optional string changed_preference_key = 4;
/**
* The new value of the changed preference.
*/
- optional int64 changedPreferenceIntValue = 5;
+ optional int64 changed_preference_int_value = 5;
}
/**
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 579ef93..01c7028 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2904,8 +2904,6 @@
Lcom/android/internal/telephony/dataconnection/DcTracker$RecoveryAction;->isAggressiveRecovery(I)Z
Lcom/android/internal/telephony/dataconnection/DcTracker;->cancelReconnectAlarm(Lcom/android/internal/telephony/dataconnection/ApnContext;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(ZLjava/lang/String;)Z
-Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpConnection(ZLcom/android/internal/telephony/dataconnection/ApnContext;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->createAllApnList()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->getActiveApnTypes()[Ljava/lang/String;
Lcom/android/internal/telephony/dataconnection/DcTracker;->getOverallState()Lcom/android/internal/telephony/DctConstants$State;
@@ -2936,7 +2934,6 @@
Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyOffApnsOfAvailability(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->onCleanUpAllConnections(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
@@ -2945,7 +2942,6 @@
Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->setInitialAttachApn()V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->setInternalDataEnabled(ZLandroid/os/Message;)Z
Lcom/android/internal/telephony/dataconnection/DcTracker;->setPreferredApn(I)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->setRadio(Z)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->setupDataOnConnectableApns(Ljava/lang/String;)V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f3f065a..cfda803 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -121,8 +121,8 @@
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 41166dd..492aad9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -162,7 +162,6 @@
import com.android.org.conscrypt.TrustedCertificateStore;
import com.android.server.am.MemInfoDumpProto;
-import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
@@ -5948,16 +5947,6 @@
HardwareRenderer.setIsolatedProcess(true);
}
- // If we use profiles, setup the dex reporter to notify package manager
- // of any relevant dex loads. The idle maintenance job will use the information
- // reported to optimize the loaded dex files.
- // Note that we only need one global reporter per app.
- // Make sure we do this before calling onCreate so that we can capture the
- // complete application startup.
- if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
- BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
- }
-
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 759763b..d46dbed 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -57,6 +57,7 @@
import com.android.internal.util.ArrayUtils;
+import dalvik.system.BaseDexClassLoader;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -949,6 +950,15 @@
if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
return;
}
+
+ // If we use profiles, setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before invoking app code for the first time so that we
+ // can capture the complete application startup.
+ BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
+
// Only set up profile support if the loaded apk has the same uid as the
// current process.
// Currently, we do not support profiling across different apps.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index aa1b5af..b9d5907 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4770,14 +4770,16 @@
TemplateBindResult result) {
boolean largeIconShown = bindLargeIcon(contentView, p);
boolean replyIconShown = bindReplyIcon(contentView, p);
+ boolean iconContainerVisible = largeIconShown || replyIconShown;
contentView.setViewVisibility(R.id.right_icon_container,
- largeIconShown || replyIconShown ? View.VISIBLE : View.GONE);
+ iconContainerVisible ? View.VISIBLE : View.GONE);
int marginEnd = calculateMarginEnd(largeIconShown, replyIconShown);
contentView.setViewLayoutMarginEnd(R.id.line1, marginEnd);
contentView.setViewLayoutMarginEnd(R.id.text, marginEnd);
contentView.setViewLayoutMarginEnd(R.id.progress, marginEnd);
if (result != null) {
result.setIconMarginEnd(marginEnd);
+ result.setRightIconContainerVisible(iconContainerVisible);
}
}
@@ -6777,7 +6779,8 @@
mBuilder.setTextViewColorSecondary(contentView, R.id.big_text, p);
contentView.setViewVisibility(R.id.big_text,
TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
- contentView.setBoolean(R.id.big_text, "setHasImage", mBuilder.mN.hasLargeIcon());
+ contentView.setBoolean(R.id.big_text, "setHasImage",
+ result.isRightIconContainerVisible());
return contentView;
}
@@ -9914,6 +9917,7 @@
*/
private static class TemplateBindResult {
int mIconMarginEnd;
+ boolean mRightIconContainerVisible;
/**
* Get the margin end that needs to be added to any fields that may overlap
@@ -9923,9 +9927,21 @@
return mIconMarginEnd;
}
+ /**
+ * Is the icon container visible on the right size because of the reply button or the
+ * right icon.
+ */
+ public boolean isRightIconContainerVisible() {
+ return mRightIconContainerVisible;
+ }
+
public void setIconMarginEnd(int iconMarginEnd) {
this.mIconMarginEnd = iconMarginEnd;
}
+
+ public void setRightIconContainerVisible(boolean iconContainerVisible) {
+ mRightIconContainerVisible = iconContainerVisible;
+ }
}
private static class StandardTemplateParams {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0404e80..43e1836 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -165,9 +165,9 @@
import android.view.accessibility.CaptioningManager;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutoFillManager;
+import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.IContentCaptureManager;
import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
-import android.view.intelligence.IIntelligenceManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
@@ -1070,7 +1070,7 @@
if (outerContext.isContentCaptureSupported()) {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
- IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b);
+ IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
return new ContentCaptureManager(outerContext, service);
}
return null;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3a97284..e826250 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1121,6 +1121,64 @@
"android.app.extra.PROVISIONING_USE_MOBILE_DATA";
/**
+ * A String extra holding the provisioning trigger. It could be one of
+ * {@link #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT}, {@link #PROVISIONING_TRIGGER_QR_CODE},
+ * {@link #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER} or {@link
+ * #PROVISIONING_TRIGGER_UNSPECIFIED}.
+ *
+ * <p>Use in an intent with action {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_TRIGGER =
+ "android.app.extra.PROVISIONING_TRIGGER";
+
+ /**
+ * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+ * trigger has not been specified.
+ * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+ * @see #PROVISIONING_TRIGGER_QR_CODE
+ * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+ * @hide
+ */
+ @SystemApi
+ public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0;
+
+ /**
+ * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+ * trigger is cloud enrollment.
+ * @see #PROVISIONING_TRIGGER_QR_CODE
+ * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+ * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+ * @hide
+ */
+ @SystemApi
+ public static final int PROVISIONING_TRIGGER_CLOUD_ENROLLMENT = 1;
+
+ /**
+ * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+ * trigger is the QR code scanner.
+ * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+ * @see #PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER
+ * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+ * @hide
+ */
+ @SystemApi
+ public static final int PROVISIONING_TRIGGER_QR_CODE = 2;
+
+ /**
+ * A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning
+ * trigger is persistent device owner enrollment.
+ * @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
+ * @see #PROVISIONING_TRIGGER_QR_CODE
+ * @see #PROVISIONING_TRIGGER_UNSPECIFIED
+ * @hide
+ */
+ @SystemApi
+ public static final int PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER = 3;
+
+ /**
* This MIME type is used for starting the device owner provisioning.
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 578a9ae..3cc56ae 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -47,6 +47,8 @@
public static final int REASON_TIMEOUT = JobProtoEnums.STOP_REASON_TIMEOUT; // 3.
/** @hide */
public static final int REASON_DEVICE_IDLE = JobProtoEnums.STOP_REASON_DEVICE_IDLE; // 4.
+ /** @hide */
+ public static final int REASON_DEVICE_THERMAL = JobProtoEnums.STOP_REASON_DEVICE_THERMAL; // 5.
/** @hide */
public static String getReasonName(int reason) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e2c7b85..d7d3cb5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3939,13 +3939,12 @@
public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
/**
- * Official published name of the smart suggestions service.
+ * Official published name of the content capture service.
*
* @hide
* @see #getSystemService(String)
*/
- // TODO(b/111276913): rename string (will require SELinux change first)
- public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "intelligence";
+ public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
/**
* Use with {@link #getSystemService(String)} to access the
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b7df2bf..f40be84 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2687,6 +2687,16 @@
"android.software.device_id_attestation";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
+ * the requisite kernel support for multinetworking-capable IPsec tunnels.
+ *
+ * <p>This feature implies that the device supports XFRM Interfaces (CONFIG_XFRM_INTERFACE), or
+ * VTIs with kernel patches allowing updates of output/set mark via UPDSA.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
+
+ /**
* Extra field name for the URI to a verification file. Passed to a package
* verifier.
*
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index ff58c75..eb3414d 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -152,5 +152,24 @@
Slog.w(TAG, "setActiveUser(): Service not connected");
}
}
+
+ /**
+ * Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
+ *
+ * @param token an opaque token returned by password confirmation.
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void resetTimeout(byte[] token) {
+ if (mService != null) {
+ try {
+ mService.resetTimeout(token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ } else {
+ Slog.w(TAG, "resetTimeout(): Service not connected");
+ }
+ }
}
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index 53a0761..de828f2 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -48,4 +48,7 @@
// Notify BiometricService when <Biometric>Service is ready to start the prepared client.
// Client lifecycle is still managed in <Biometric>Service.
void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId);
+
+ // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
+ void resetTimeout(in byte [] token);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index abfcfaa..86f81d8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -948,7 +948,7 @@
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
*/
- public static final String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
+ public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
/**
* Specifies if user switching is blocked on the current user.
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index bf988ae..f114b12 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -190,4 +190,5 @@
void abortIdleMaintenance() = 80;
String translateAppToSystem(String path, int pid, int uid) = 81;
String translateSystemToApp(String path, int pid, int uid) = 82;
+ void commitChanges() = 83;
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 37c84bd..4737577 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -97,8 +98,15 @@
@Deprecated
public static final String EXTRA_PACKAGE_NAME = Intent.EXTRA_PACKAGE_NAME;
- /** {@hide} */
- public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
+ /**
+ * The value is decide whether to show advance mode or not.
+ * If the value is true, the local/device storage root must be
+ * visible in DocumentsUI.
+ *
+ * {@hide}
+ */
+ @SystemApi
+ public static final String EXTRA_SHOW_ADVANCED = "android.provider.extra.SHOW_ADVANCED";
/** {@hide} */
public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
@@ -111,7 +119,6 @@
*
* @see DocumentsProvider#querySearchDocuments(String, String[],
* Bundle)
- * {@hide}
*/
public static final String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
@@ -124,7 +131,6 @@
*
* @see DocumentsProvider#querySearchDocuments(String, String[],
* Bundle)
- * {@hide}
*/
public static final String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
@@ -134,7 +140,6 @@
*
* @see DocumentsProvider#querySearchDocuments(String, String[],
* Bundle)
- * {@hide}
*/
public static final String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
@@ -146,7 +151,6 @@
* @see DocumentsProvider#querySearchDocuments(String, String[],
* Bundle)
* @see Document#COLUMN_LAST_MODIFIED
- * {@hide}
*/
public static final String QUERY_ARG_LAST_MODIFIED_AFTER =
"android:query-arg-last-modified-after";
@@ -158,7 +162,6 @@
*
* @see DocumentsProvider#querySearchDocuments(String, String[],
* Bundle)
- * {@hide}
*/
public static final String QUERY_ARG_EXCLUDE_MEDIA = "android:query-arg-exclude-media";
@@ -216,10 +219,18 @@
public static final String
ACTION_DOCUMENT_SETTINGS = "android.provider.action.DOCUMENT_SETTINGS";
- /** {@hide} */
+ /**
+ * The action to manage document in Downloads root in DocumentsUI.
+ * {@hide}
+ */
+ @SystemApi
public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
- /** {@hide} */
+ /**
+ * The action to launch the settings of this root.
+ * {@hide}
+ */
+ @SystemApi
public static final String
ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
@@ -235,10 +246,19 @@
/** {@hide} */
public static final String PACKAGE_DOCUMENTS_UI = "com.android.documentsui";
- /** {@hide} */
- public static final String METADATA_TYPES = "android:documentMetadataType";
+ /**
+ * Get string array identifies the type or types of metadata returned
+ * using DocumentsContract#getDocumentMetadata.
+ *
+ * @see #getDocumentMetadata(ContentResolver, Uri)
+ */
+ public static final String METADATA_TYPES = "android:documentMetadataTypes";
- /** {@hide} */
+ /**
+ * Get Exif information using DocumentsContract#getDocumentMetadata.
+ *
+ * @see #getDocumentMetadata(ContentResolver, Uri)
+ */
public static final String METADATA_EXIF = "android:documentExif";
/**
@@ -498,16 +518,17 @@
* if they represent a failed download.
*
* @see #COLUMN_FLAGS
- * @hide
*/
- public static final int FLAG_PARTIAL = 1 << 16;
+ public static final int FLAG_PARTIAL = 1 << 13;
/**
* Flag indicating that a document has available metadata that can be read
* using DocumentsContract#getDocumentMetadata
- * @hide
+ *
+ * @see #COLUMN_FLAGS
+ * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
*/
- public static final int FLAG_SUPPORTS_METADATA = 1 << 17;
+ public static final int FLAG_SUPPORTS_METADATA = 1 << 14;
}
/**
@@ -679,44 +700,46 @@
* @see #COLUMN_FLAGS
* @see ContentResolver#notifyChange(Uri,
* android.database.ContentObserver, boolean)
- * @hide
*/
- public static final int FLAG_EMPTY = 1 << 16;
+ public static final int FLAG_EMPTY = 1 << 6;
/**
* Flag indicating that this root should only be visible to advanced
* users.
*
* @see #COLUMN_FLAGS
- * @hide
+ * {@hide}
*/
- @UnsupportedAppUsage
- public static final int FLAG_ADVANCED = 1 << 17;
+ @SystemApi
+ public static final int FLAG_ADVANCED = 1 << 16;
/**
* Flag indicating that this root has settings.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
- * @hide
+ * {@hide}
*/
- public static final int FLAG_HAS_SETTINGS = 1 << 18;
+ @SystemApi
+ public static final int FLAG_HAS_SETTINGS = 1 << 17;
/**
* Flag indicating that this root is on removable SD card storage.
*
* @see #COLUMN_FLAGS
- * @hide
+ * {@hide}
*/
- public static final int FLAG_REMOVABLE_SD = 1 << 19;
+ @SystemApi
+ public static final int FLAG_REMOVABLE_SD = 1 << 18;
/**
* Flag indicating that this root is on removable USB storage.
*
* @see #COLUMN_FLAGS
- * @hide
+ * {@hide}
*/
- public static final int FLAG_REMOVABLE_USB = 1 << 20;
+ @SystemApi
+ public static final int FLAG_REMOVABLE_USB = 1 << 19;
}
/**
@@ -1090,8 +1113,6 @@
* Test if the given URI represents roots backed by {@link DocumentsProvider}.
*
* @see #buildRootsUri(String)
- *
- * {@hide}
*/
public static boolean isRootsUri(Context context, @Nullable Uri uri) {
return isRootUri(context, uri, 1 /* pathSize */);
@@ -1101,8 +1122,6 @@
* Test if the given URI represents specific root backed by {@link DocumentsProvider}.
*
* @see #buildRootUri(String, String)
- *
- * {@hide}
*/
public static boolean isRootUri(Context context, @Nullable Uri uri) {
return isRootUri(context, uri, 2 /* pathSize */);
@@ -1200,13 +1219,23 @@
return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
}
- /** {@hide} */
- @UnsupportedAppUsage
+ /**
+ * Build URI that append the query parameter {@link PARAM_MANAGE} to
+ * enable the manage mode.
+ * @see DocumentsProvider#queryChildDocumentsForManage(String parentDocId, String[], String)
+ * {@hide}
+ */
+ @SystemApi
public static Uri setManageMode(Uri uri) {
return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
}
- /** {@hide} */
+ /**
+ * Extract the manage mode from a URI built by
+ * {@link #setManageMode(Uri)}.
+ * {@hide}
+ */
+ @SystemApi
public static boolean isManageMode(Uri uri) {
return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
}
@@ -1287,6 +1316,31 @@
return out.getParcelable(DocumentsContract.EXTRA_URI);
}
+
+ /**
+ * Test if a document is descendant (child, grandchild, etc) from the given
+ * parent.
+ *
+ * @param parentDocumentUri parent to verify against.
+ * @param childDocumentUri child to verify.
+ * @return if given document is a descendant of the given parent.
+ * @see Root#FLAG_SUPPORTS_IS_CHILD
+ */
+ public static boolean isChildDocument(ContentResolver resolver, Uri parentDocumentUri,
+ Uri childDocumentUri) throws FileNotFoundException {
+ final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
+ parentDocumentUri.getAuthority());
+ try {
+ return isChildDocument(client, parentDocumentUri, childDocumentUri);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to query isChildDocument", e);
+ rethrowIfNecessary(resolver, e);
+ return false;
+ } finally {
+ ContentProviderClient.releaseQuietly(client);
+ }
+ }
+
/** {@hide} */
public static boolean isChildDocument(ContentProviderClient client, Uri parentDocumentUri,
Uri childDocumentUri) throws RemoteException {
@@ -1297,7 +1351,7 @@
final Bundle out = client.call(METHOD_IS_CHILD_DOCUMENT, null, in);
if (out == null) {
- throw new RemoteException("Failed to get a reponse from isChildDocument query.");
+ throw new RemoteException("Failed to get a response from isChildDocument query.");
}
if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
throw new RemoteException("Response did not include result field..");
@@ -1513,13 +1567,13 @@
/**
* Returns metadata associated with the document. The type of metadata returned
* is specific to the document type. For example the data returned for an image
- * file will likely consist primarily or soley of EXIF metadata.
+ * file will likely consist primarily or solely of EXIF metadata.
*
* <p>The returned {@link Bundle} will contain zero or more entries depending
* on the type of data supported by the document provider.
*
* <ol>
- * <li>A {@link DocumentsContract.METADATA_TYPES} containing a {@code String[]} value.
+ * <li>A {@link DocumentsContract#METADATA_TYPES} containing a {@code String[]} value.
* The string array identifies the type or types of metadata returned. Each
* value in the can be used to access a {@link Bundle} of data
* containing that type of data.
@@ -1539,7 +1593,6 @@
*
* @param documentUri a Document URI
* @return a Bundle of Bundles.
- * {@hide}
*/
public static Bundle getDocumentMetadata(ContentResolver resolver, Uri documentUri)
throws FileNotFoundException {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 6ab72c7..70c84f8 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -691,7 +691,6 @@
* @see DocumentsContract#EXTRA_LOADING
* @see DocumentsContract#EXTRA_INFO
* @see DocumentsContract#EXTRA_ERROR
- * {@hide}
*/
@SuppressWarnings("unused")
public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
@@ -711,7 +710,28 @@
throw new UnsupportedOperationException("Eject not supported");
}
- /** {@hide} */
+ /**
+ * Returns metadata associated with the document. The type of metadata returned
+ * is specific to the document type. For example the data returned for an image
+ * file will likely consist primarily or solely of EXIF metadata.
+ *
+ * <p>The returned {@link Bundle} will contain zero or more entries depending
+ * on the type of data supported by the document provider.
+ *
+ * <ol>
+ * <li>A {@link DocumentsContract#METADATA_TYPES} containing a {@code String[]} value.
+ * The string array identifies the type or types of metadata returned. Each
+ * value in the can be used to access a {@link Bundle} of data
+ * containing that type of data.
+ * <li>An entry each for each type of returned metadata. Each set of metadata is
+ * itself represented as a bundle and accessible via a string key naming
+ * the type of data.
+ * </ol>
+ *
+ * @param documentId get the metadata of the document
+ * @return a Bundle of Bundles.
+ * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
+ */
public @Nullable Bundle getDocumentMetadata(String documentId)
throws FileNotFoundException {
throw new UnsupportedOperationException("Metadata not supported");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c3217a2..f86296b8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1680,6 +1680,11 @@
*/
public static final String CALL_METHOD_TAG_KEY = "_tag";
+ /**
+ * @hide - String argument extra to the fast-path call()-based requests
+ */
+ public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
+
/** @hide - Private call() method to write to 'system' table */
public static final String CALL_METHOD_PUT_SYSTEM = "PUT_system";
@@ -1701,15 +1706,18 @@
/** @hide - Private call() method to delete from the 'global' table */
public static final String CALL_METHOD_DELETE_GLOBAL = "DELETE_global";
+ /** @hide - Private call() method to reset to defaults the 'configuration' table */
+ public static final String CALL_METHOD_DELETE_CONFIG = "DELETE_config";
+
+ /** @hide - Private call() method to reset to defaults the 'secure' table */
+ public static final String CALL_METHOD_RESET_SECURE = "RESET_secure";
+
/** @hide - Private call() method to reset to defaults the 'global' table */
public static final String CALL_METHOD_RESET_GLOBAL = "RESET_global";
/** @hide - Private call() method to reset to defaults the 'configuration' table */
public static final String CALL_METHOD_RESET_CONFIG = "RESET_config";
- /** @hide - Private call() method to reset to defaults the 'secure' table */
- public static final String CALL_METHOD_RESET_SECURE = "RESET_secure";
-
/** @hide - Private call() method to query the 'system' table */
public static final String CALL_METHOD_LIST_SYSTEM = "LIST_system";
@@ -1719,6 +1727,9 @@
/** @hide - Private call() method to query the 'global' table */
public static final String CALL_METHOD_LIST_GLOBAL = "LIST_global";
+ /** @hide - Private call() method to reset to defaults the 'configuration' table */
+ public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
+
/**
* Activity Extra: Limit available options in launched activity based on the given authority.
* <p>
@@ -12840,7 +12851,7 @@
/**
* Property used by {@code com.android.server.SystemServer} on start to decide whether
- * the Smart Suggestions service should be created or not
+ * the Content Capture service should be created or not
*
* <p>By default it should *NOT* be set (in which case the decision is based on whether
* the OEM provides an implementation for the service), but it can be overridden to:
@@ -12852,8 +12863,8 @@
*
* @hide
*/
- public static final String SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED =
- "smart_suggestions_service_explicitly_enabled";
+ public static final String CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED =
+ "content_capture_service_explicitly_enabled";
/**
* Settings to backup. This is here so that it's in the same place as the settings
@@ -13671,6 +13682,22 @@
"smart_replies_in_notifications_flags";
/**
+ * Configuration flags for the automatic generation of smart replies and smart actions in
+ * notifications. This is encoded as a key=value list, separated by commas. Ex:
+ * "generate_replies=false,generate_actions=true".
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * generate_replies (boolean)
+ * generate_actions (boolean)
+ * </pre>
+ * @hide
+ */
+ public static final String SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS =
+ "smart_suggestions_in_notifications_flags";
+
+ /**
* If nonzero, crashes in foreground processes will bring up a dialog.
* Otherwise, the process will be silently killed.
* @hide
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 573d577..f39ef9a 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -618,7 +618,7 @@
if (SERVICE_INTERFACE.equals(intent.getAction())) {
return mInterface.asBinder();
}
- Log.w(TAG, "Tried to bind to wrong intent: " + intent);
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
return null;
}
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
new file mode 100644
index 0000000..68a86f3
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill.augmented;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAugmentedAutofillManagerClient;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A service used to augment the Autofill subsystem by potentially providing autofill data when the
+ * "standard" workflow failed (for example, because the standard AutofillService didn't have data).
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class AugmentedAutofillService extends Service {
+
+ private static final String TAG = AugmentedAutofillService.class.getSimpleName();
+
+ // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+ static final boolean DEBUG = true;
+ static final boolean VERBOSE = false;
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE} permission so
+ * that other applications can not abuse it.
+ */
+ public static final String SERVICE_INTERFACE =
+ "android.service.autofill.augmented.AugmentedAutofillService";
+
+ private Handler mHandler;
+
+ private SparseArray<AutofillProxy> mAutofillProxies;
+
+ private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
+
+ @Override
+ public void onFillRequest(int sessionId, IBinder client, int taskId,
+ ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
+ long requestTime, IFillCallback callback) {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
+ AugmentedAutofillService.this, sessionId, client, taskId, componentName,
+ focusedId, focusedValue, requestTime, callback));
+ }
+
+ @Override
+ public void onDestroyFillWindowRequest(int sessionId) {
+ mHandler.sendMessage(
+ obtainMessage(AugmentedAutofillService::handleOnDestroyFillWindowRequest,
+ AugmentedAutofillService.this, sessionId));
+ }
+ };
+
+ @CallSuper
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandler = new Handler(Looper.getMainLooper(), null, true);
+ }
+
+ /** @hide */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnUnbind,
+ AugmentedAutofillService.this));
+ return false;
+ }
+
+ // TODO(b/111330312): add methods to disable autofill per app / activity?
+
+ /**
+ * Asks the service to handle an "augmented" autofill request.
+ *
+ * <p>This method is called when the "stantard" autofill service cannot handle a request, which
+ * typically occurs when:
+ * <ul>
+ * <li>Service does not recognize what should be autofilled.
+ * <li>Service does not have data to fill the request.
+ * <li>Service blacklisted that app (or activity) for autofill.
+ * <li>App disabled itself for autofill.
+ * </ul>
+ *
+ * <p>Differently from the standard autofill workflow, on augmented autofill the service is
+ * responsible to generate the autofill UI and request the Android system to autofill the
+ * activity when the user taps an action in that UI (through the
+ * {@link FillController#autofill(List)} method).
+ *
+ * <p>The service <b>MUST</b> call {@link
+ * FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)} as soon as possible,
+ * passing {@code null} when it cannot fulfill the request.
+ * @param request the request to handle.
+ * @param cancellationSignal signal for observing cancellation requests. The system will use
+ * this to notify you that the fill result is no longer needed and you should stop
+ * handling this fill request in order to save resources.
+ * @param controller object used to interact with the autofill system.
+ * @param callback object used to notify the result of the request. Service <b>must</b> call
+ * {@link FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)}.
+ */
+ public void onFillRequest(@NonNull FillRequest request,
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
+ @NonNull FillCallback callback) {
+ }
+
+ private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
+ @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue, long requestTime,
+ @NonNull IFillCallback callback) {
+ if (mAutofillProxies == null) {
+ mAutofillProxies = new SparseArray<>();
+ }
+ AutofillProxy proxy = mAutofillProxies.get(sessionId);
+ if (proxy == null) {
+ proxy = new AutofillProxy(sessionId, client, taskId, componentName, focusedId,
+ focusedValue, requestTime, callback);
+ mAutofillProxies.put(sessionId, proxy);
+ } else {
+ // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
+ if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
+ }
+ // TODO(b/111330312): set cancellation signal
+ final CancellationSignal cancellationSignal = null;
+ onFillRequest(new FillRequest(proxy), cancellationSignal, new FillController(proxy),
+ new FillCallback(proxy));
+ }
+
+ private void handleOnDestroyFillWindowRequest(@NonNull int sessionId) {
+ AutofillProxy proxy = null;
+ if (mAutofillProxies != null) {
+ proxy = mAutofillProxies.get(sessionId);
+ }
+ if (proxy == null) {
+ // TODO(b/111330312): this might be fine, in which case we should logv it
+ Log.w(TAG, "No proxy for session " + sessionId);
+ return;
+ }
+ proxy.destroy();
+ mAutofillProxies.remove(sessionId);
+ }
+
+ private void handleOnUnbind() {
+ if (mAutofillProxies == null) {
+ if (DEBUG) Log.d(TAG, "onUnbind(): no proxy to destroy");
+ return;
+ }
+ final int size = mAutofillProxies.size();
+ if (DEBUG) Log.d(TAG, "onUnbind(): destroying " + size + " proxies");
+ for (int i = 0; i < size; i++) {
+ final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+ try {
+ proxy.destroy();
+ } catch (Exception e) {
+ Log.w(TAG, "error destroying " + proxy);
+ }
+ }
+ mAutofillProxies = null;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mAutofillProxies != null) {
+ final int size = mAutofillProxies.size();
+ pw.print("Number proxies: "); pw.println(size);
+ for (int i = 0; i < size; i++) {
+ final int sessionId = mAutofillProxies.keyAt(i);
+ final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+ pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
+ proxy.dump(" ", pw);
+ }
+ }
+ }
+
+ /** @hide */
+ static final class AutofillProxy {
+
+ static final int REPORT_EVENT_ON_SUCCESS = 1;
+ static final int REPORT_EVENT_UI_SHOWN = 2;
+ static final int REPORT_EVENT_UI_DESTROYED = 3;
+
+ @IntDef(prefix = { "REPORT_EVENT_" }, value = {
+ REPORT_EVENT_ON_SUCCESS,
+ REPORT_EVENT_UI_SHOWN,
+ REPORT_EVENT_UI_DESTROYED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ReportEvent{}
+
+
+ private final Object mLock = new Object();
+ private final IAugmentedAutofillManagerClient mClient;
+ private final int mSessionId;
+ private final IFillCallback mCallback;
+ public final int taskId;
+ public final ComponentName componentName;
+ public final AutofillId focusedId;
+ public final AutofillValue focusedValue;
+
+ // Objects used to log metrics
+ private final long mRequestTime;
+ private long mOnSuccessTime;
+ private long mUiFirstShownTime;
+ private long mUiFirstDestroyedTime;
+
+ @GuardedBy("mLock")
+ private SystemPopupPresentationParams mSmartSuggestion;
+
+ @GuardedBy("mLock")
+ private FillWindow mFillWindow;
+
+ private AutofillProxy(int sessionId, @NonNull IBinder client, int taskId,
+ @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue, long requestTime,
+ @NonNull IFillCallback callback) {
+ mSessionId = sessionId;
+ mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
+ mCallback = callback;
+ this.taskId = taskId;
+ this.componentName = componentName;
+ this.focusedId = focusedId;
+ this.focusedValue = focusedValue;
+ this.mRequestTime = requestTime;
+ // TODO(b/111330312): linkToDeath
+ }
+
+ @NonNull
+ public SystemPopupPresentationParams getSmartSuggestionParams() {
+ synchronized (mLock) {
+ if (mSmartSuggestion != null) {
+ return mSmartSuggestion;
+ }
+ Rect rect;
+ try {
+ rect = mClient.getViewCoordinates(focusedId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not get coordinates for " + focusedId);
+ return null;
+ }
+ if (rect == null) {
+ if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
+ return null;
+ }
+ mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
+ return mSmartSuggestion;
+ }
+ }
+
+ public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
+ throws RemoteException {
+ final int size = pairs.size();
+ final List<AutofillId> ids = new ArrayList<>(size);
+ final List<AutofillValue> values = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
+ ids.add(pair.first);
+ values.add(pair.second);
+ }
+ mClient.autofill(mSessionId, ids, values);
+ }
+
+ public void setFillWindow(@NonNull FillWindow fillWindow) {
+ synchronized (mLock) {
+ mFillWindow = fillWindow;
+ }
+ }
+
+ public FillWindow getFillWindow() {
+ synchronized (mLock) {
+ return mFillWindow;
+ }
+ }
+
+ // Used (mostly) for metrics.
+ public void report(@ReportEvent int event) {
+ switch (event) {
+ case REPORT_EVENT_ON_SUCCESS:
+ if (mOnSuccessTime == 0) {
+ mOnSuccessTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "Service responsed in "
+ + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
+ }
+ }
+ try {
+ mCallback.onSuccess();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error reporting success: " + e);
+ }
+ break;
+ case REPORT_EVENT_UI_SHOWN:
+ if (mUiFirstShownTime == 0) {
+ mUiFirstShownTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "UI shown in "
+ + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
+ }
+ }
+ break;
+ case REPORT_EVENT_UI_DESTROYED:
+ if (mUiFirstDestroyedTime == 0) {
+ mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "UI destroyed in "
+ + TimeUtils.formatDuration(
+ mUiFirstDestroyedTime - mRequestTime));
+ }
+ }
+ break;
+ default:
+ Slog.w(TAG, "invalid event reported: " + event);
+ }
+ // TODO(b/111330312): log metrics as well
+ }
+
+ public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ pw.print(prefix); pw.print("sessionId: "); pw.println(mSessionId);
+ pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
+ pw.print(prefix); pw.print("component: ");
+ pw.println(componentName.flattenToShortString());
+ pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
+ if (focusedValue != null) {
+ pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
+ }
+ pw.print(prefix); pw.print("client: "); pw.println(mClient);
+ final String prefix2 = prefix + " ";
+ if (mFillWindow != null) {
+ pw.print(prefix); pw.println("window:");
+ mFillWindow.dump(prefix2, pw);
+ }
+ if (mSmartSuggestion != null) {
+ pw.print(prefix); pw.println("smartSuggestion:");
+ mSmartSuggestion.dump(prefix2, pw);
+ }
+ if (mOnSuccessTime > 0) {
+ final long responseTime = mOnSuccessTime - mRequestTime;
+ pw.print(prefix); pw.print("response time: ");
+ TimeUtils.formatDuration(responseTime, pw); pw.println();
+ }
+
+ if (mUiFirstShownTime > 0) {
+ final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
+ pw.print(prefix); pw.print("UI rendering time: ");
+ TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
+ }
+
+ if (mUiFirstDestroyedTime > 0) {
+ final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
+ pw.print(prefix); pw.print("UI life time: ");
+ TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
+ }
+ }
+
+ private void destroy() {
+ synchronized (mLock) {
+ if (mFillWindow != null) {
+ if (DEBUG) Log.d(TAG, "destroying window");
+ mFillWindow.destroy();
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/service/intelligence/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
similarity index 92%
rename from core/java/android/service/intelligence/FillCallback.java
rename to core/java/android/service/autofill/augmented/FillCallback.java
index ddf37f7..0546465 100644
--- a/core/java/android/service/intelligence/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
/**
* Callback used to indicate at {@link FillRequest} has been fulfilled.
diff --git a/core/java/android/service/intelligence/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
similarity index 90%
rename from core/java/android/service/intelligence/FillController.java
rename to core/java/android/service/autofill/augmented/FillController.java
index 4a9c85d..e65cf47 100644
--- a/core/java/android/service/intelligence/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.RemoteException;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.Log;
import android.util.Pair;
import android.view.autofill.AutofillId;
diff --git a/core/java/android/service/intelligence/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java
similarity index 71%
rename from core/java/android/service/intelligence/FillRequest.java
rename to core/java/android/service/autofill/augmented/FillRequest.java
index 53e99a5..fd75b15 100644
--- a/core/java/android/service/intelligence/FillRequest.java
+++ b/core/java/android/service/autofill/augmented/FillRequest.java
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.content.ComponentName;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -27,6 +28,7 @@
* @hide
*/
@SystemApi
+// TODO(b/111330312): pass a requestId and/or sessionId
public final class FillRequest {
final AutofillProxy mProxy;
@@ -37,11 +39,18 @@
}
/**
- * Gets the session associated with this request.
+ * Gets the task of the activity associated with this request.
+ */
+ public int getTaskId() {
+ return mProxy.taskId;
+ }
+
+ /**
+ * Gets the name of the activity associated with this request.
*/
@NonNull
- public InteractionSessionId getSessionId() {
- return mProxy.sessionId;
+ public ComponentName getActivityComponent() {
+ return mProxy.componentName;
}
/**
@@ -56,7 +65,7 @@
* Gets the current value of the field that triggered the request.
*/
@NonNull
- public AutofillValue getFocusedAutofillValue() {
+ public AutofillValue getFocusedValue() {
return mProxy.focusedValue;
}
@@ -72,6 +81,7 @@
@Override
public String toString() {
- return "FillRequest[id=" + mProxy.focusedId + "]";
+ return "FillRequest[act=" + getActivityComponent().flattenToShortString()
+ + ", id=" + mProxy.focusedId + "]";
}
}
diff --git a/core/java/android/service/intelligence/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
similarity index 97%
rename from core/java/android/service/intelligence/FillResponse.java
rename to core/java/android/service/autofill/augmented/FillResponse.java
index 860c027..7064b6f 100644
--- a/core/java/android/service/intelligence/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -50,7 +50,7 @@
* @hide
*/
@SystemApi
- public static class Builder {
+ public static final class Builder {
private FillWindow mFillWindow;
diff --git a/core/java/android/service/intelligence/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
similarity index 94%
rename from core/java/android/service/intelligence/FillWindow.java
rename to core/java/android/service/autofill/augmented/FillWindow.java
index 39d7e08..9e3aba4 100644
--- a/core/java/android/service/intelligence/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Dialog;
import android.graphics.Rect;
-import android.service.intelligence.PresentationParams.Area;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.Area;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -60,7 +60,7 @@
* @hide
*/
@SystemApi
-public final class FillWindow {
+public final class FillWindow implements AutoCloseable {
private static final String TAG = "FillWindow";
/** Indicates the data being shown is a physical address */
@@ -238,4 +238,10 @@
}
}
}
+
+ /** @hide */
+ @Override
+ public void close() throws Exception {
+ destroy();
+ }
}
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
new file mode 100644
index 0000000..b3ac2da
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+
+import android.service.autofill.augmented.IFillCallback;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import java.util.List;
+
+/**
+ * Interface from the system to an Augmented Autofill service.
+ *
+ * @hide
+ */
+oneway interface IAugmentedAutofillService {
+
+ void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
+ in ComponentName activityComponent, in AutofillId focusedId,
+ in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
+
+ void onDestroyFillWindowRequest(int sessionId);
+}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
new file mode 100644
index 0000000..dac7590
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.os.ICancellationSignal;
+
+/**
+ * Interface to receive the result of an autofill request.
+ *
+ * @hide
+ */
+interface IFillCallback {
+ // TODO(b/111330312): add cancellation (after we have CTS tests, so we can test it)
+// void onCancellable(in ICancellationSignal cancellation);
+ // TODO(b/111330312): might need to pass the response (once IME implements Smart Suggestions)
+ void onSuccess();
+}
diff --git a/core/java/android/service/intelligence/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
similarity index 95%
rename from core/java/android/service/intelligence/PresentationParams.java
rename to core/java/android/service/autofill/augmented/PresentationParams.java
index 9530309..0124ecc 100644
--- a/core/java/android/service/intelligence/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.graphics.Rect;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.DebugUtils;
import android.view.View;
@@ -174,11 +174,12 @@
*
* @param bounds boundaries relative to this Area.
*
- * @throws {@link IllegalArgumentException} if the {@code bounds} is not fully-contained
- * inside this full Area.
- *
* @return new subarea, or {@code null} if the Smart Suggestion host does not support such
* subaarea.
+ *
+ * @throws IllegalArgumentException if the {@code bounds} is not fully-contained inside this
+ * full Area.
+ *
*/
@Nullable
public Area getSubArea(@NonNull Rect bounds) {
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
similarity index 94%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
index 23d607d..c032cfd 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable ContentCaptureEventsRequest;
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
similarity index 95%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.java
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
index bc5b92b..df58f52 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
import java.util.List;
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
new file mode 100644
index 0000000..3dfeede
--- /dev/null
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.contentcapture;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A service used to capture the content of the screen to provide contextual data in other areas of
+ * the system such as Autofill.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class ContentCaptureService extends Service {
+
+ private static final String TAG = ContentCaptureService.class.getSimpleName();
+
+ // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+ static final boolean DEBUG = true;
+ static final boolean VERBOSE = false;
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ *
+ * <p>To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE} permission so
+ * that other applications can not abuse it.
+ */
+ public static final String SERVICE_INTERFACE =
+ "android.service.contentcapture.ContentCaptureService";
+
+ private Handler mHandler;
+
+ private final IContentCaptureService mInterface = new IContentCaptureService.Stub() {
+
+ @Override
+ public void onSessionLifecycle(InteractionContext context, String sessionId)
+ throws RemoteException {
+ if (context != null) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnCreateInteractionSession,
+ ContentCaptureService.this, context, sessionId));
+ } else {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnDestroyInteractionSession,
+ ContentCaptureService.this, sessionId));
+ }
+ }
+
+ @Override
+ public void onContentCaptureEventsRequest(String sessionId,
+ ContentCaptureEventsRequest request) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnContentCaptureEventsRequest,
+ ContentCaptureService.this, sessionId, request));
+
+ }
+
+ @Override
+ public void onActivitySnapshot(String sessionId, SnapshotData snapshotData) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnActivitySnapshot,
+ ContentCaptureService.this, sessionId, snapshotData));
+ }
+ };
+
+ @CallSuper
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandler = new Handler(Looper.getMainLooper(), null, true);
+ }
+
+ /** @hide */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
+ }
+
+ /**
+ * Explicitly limits content capture to the given packages and activities.
+ *
+ * <p>When the whitelist is set, it overrides the values passed to
+ * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
+ * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
+ *
+ * <p>To reset the whitelist, call it passing {@code null} to both arguments.
+ *
+ * <p>Useful when the service wants to restrict content capture to a category of apps, like
+ * chat apps. For example, if the service wants to support view captures on all activities of
+ * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
+ * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
+ * Arrays.asList(new ComponentName("ChatApp2", "act1"),
+ * new ComponentName("ChatApp2", "act2")));}
+ */
+ public final void setContentCaptureWhitelist(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Defines whether content capture should be enabled for activities with such
+ * {@link android.content.ComponentName}.
+ *
+ * <p>Useful to blacklist a particular activity.
+ */
+ public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
+ boolean enabled) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Defines whether content capture should be enabled for activities of the app with such
+ * {@code packageName}.
+ *
+ * <p>Useful to blacklist any activity from a particular app.
+ */
+ public final void setPackageContentCaptureEnabled(@NonNull String packageName,
+ boolean enabled) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Gets the activities where content capture was disabled by
+ * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
+ */
+ @NonNull
+ public final Set<ComponentName> getContentCaptureDisabledActivities() {
+ //TODO(b/111276913): implement
+ return null;
+ }
+
+ /**
+ * Gets the apps where content capture was disabled by
+ * {@link #setPackageContentCaptureEnabled(String, boolean)}.
+ */
+ @NonNull
+ public final Set<String> getContentCaptureDisabledPackages() {
+ //TODO(b/111276913): implement
+ return null;
+ }
+
+ /**
+ * Creates a new interaction session.
+ *
+ * @param context interaction context
+ * @param sessionId the session's Id
+ */
+ public void onCreateInteractionSession(@NonNull InteractionContext context,
+ @NonNull InteractionSessionId sessionId) {
+ if (VERBOSE) {
+ Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
+ }
+ }
+
+ /**
+ * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
+ * session.
+ *
+ * @param sessionId the session's Id
+ * @param request the events
+ */
+ public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
+ @NonNull ContentCaptureEventsRequest request);
+
+ /**
+ * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
+ *
+ * @param sessionId the session's Id
+ * @param snapshotData the data
+ */
+ public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
+ @NonNull SnapshotData snapshotData) {}
+
+ /**
+ * Destroys the interaction session.
+ *
+ * @param sessionId the id of the session to destroy
+ */
+ public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
+ if (VERBOSE) {
+ Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
+ }
+ }
+
+ //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
+ // so we don't need to create a temporary InteractionSessionId for each event.
+
+ private void handleOnCreateInteractionSession(@NonNull InteractionContext context,
+ @NonNull String sessionId) {
+ onCreateInteractionSession(context, new InteractionSessionId(sessionId));
+ }
+
+ private void handleOnContentCaptureEventsRequest(@NonNull String sessionId,
+ @NonNull ContentCaptureEventsRequest request) {
+ onContentCaptureEventsRequest(new InteractionSessionId(sessionId), request);
+ }
+
+ private void handleOnActivitySnapshot(@NonNull String sessionId,
+ @NonNull SnapshotData snapshotData) {
+ onActivitySnapshot(new InteractionSessionId(sessionId), snapshotData);
+ }
+
+ private void handleOnDestroyInteractionSession(@NonNull String sessionId) {
+ onDestroyInteractionSession(new InteractionSessionId(sessionId));
+ }
+}
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
new file mode 100644
index 0000000..29e9abb
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+
+import java.util.List;
+
+/**
+ * Interface from the system to a Content Capture service.
+ *
+ * @hide
+ */
+oneway interface IContentCaptureService {
+
+ // Called when session is created (context not null) or destroyed (context null)
+ void onSessionLifecycle(in InteractionContext context, String sessionId);
+
+ void onContentCaptureEventsRequest(String sessionId, in ContentCaptureEventsRequest request);
+
+ void onActivitySnapshot(String sessionId, in SnapshotData snapshotData);
+}
diff --git a/core/java/android/service/intelligence/InteractionContext.aidl b/core/java/android/service/contentcapture/InteractionContext.aidl
similarity index 93%
rename from core/java/android/service/intelligence/InteractionContext.aidl
rename to core/java/android/service/contentcapture/InteractionContext.aidl
index 4ce6aa4..982e095 100644
--- a/core/java/android/service/intelligence/InteractionContext.aidl
+++ b/core/java/android/service/contentcapture/InteractionContext.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable InteractionContext;
diff --git a/core/java/android/service/intelligence/InteractionContext.java b/core/java/android/service/contentcapture/InteractionContext.java
similarity index 96%
rename from core/java/android/service/intelligence/InteractionContext.java
rename to core/java/android/service/contentcapture/InteractionContext.java
index 7f4283d..f1281ff 100644
--- a/core/java/android/service/intelligence/InteractionContext.java
+++ b/core/java/android/service/contentcapture/InteractionContext.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -37,7 +37,7 @@
/**
* Flag used to indicate that the app explicitly disabled content capture for the activity
* (using
- * {@link android.view.intelligence.ContentCaptureManager#setContentCaptureEnabled()}),
+ * {@link android.view.contentcapture.ContentCaptureManager#setContentCaptureEnabled(boolean)}),
* in which case the service will just receive activity-level events.
*/
public static final int FLAG_DISABLED_BY_APP = 0x1;
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/contentcapture/InteractionSessionId.java
similarity index 90%
rename from core/java/android/service/intelligence/InteractionSessionId.java
rename to core/java/android/service/contentcapture/InteractionSessionId.java
index 667193b..8411947 100644
--- a/core/java/android/service/intelligence/InteractionSessionId.java
+++ b/core/java/android/service/contentcapture/InteractionSessionId.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -22,10 +22,12 @@
import android.os.Parcelable;
import java.io.PrintWriter;
-import java.util.UUID;
-// TODO(b/111276913): add javadocs / implement equals/hashcode/string
-/** @hide */
+/**
+ * Identifier for a Content Capture session.
+ *
+ * @hide
+ */
@SystemApi
public final class InteractionSessionId implements Parcelable {
@@ -34,15 +36,6 @@
/**
* Creates a new instance.
*
- * @hide
- */
- public InteractionSessionId() {
- this(UUID.randomUUID().toString());
- }
-
- /**
- * Creates a new instance.
- *
* @param value The internal value.
*
* @hide
diff --git a/core/java/android/service/intelligence/SnapshotData.aidl b/core/java/android/service/contentcapture/SnapshotData.aidl
similarity index 93%
rename from core/java/android/service/intelligence/SnapshotData.aidl
rename to core/java/android/service/contentcapture/SnapshotData.aidl
index 31d1339..a00e852 100644
--- a/core/java/android/service/intelligence/SnapshotData.aidl
+++ b/core/java/android/service/contentcapture/SnapshotData.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable SnapshotData;
diff --git a/core/java/android/service/intelligence/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
similarity index 98%
rename from core/java/android/service/intelligence/SnapshotData.java
rename to core/java/android/service/contentcapture/SnapshotData.java
index b9310ea..bc2116a 100644
--- a/core/java/android/service/intelligence/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl
deleted file mode 100644
index 2b924fb..0000000
--- a/core/java/android/service/intelligence/IIntelligenceService.aidl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-import android.os.IBinder;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.SnapshotData;
-
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.intelligence.ContentCaptureEvent;
-
-import java.util.List;
-
-/**
- * Interface from the system to an intelligence service.
- *
- * @hide
- */
- // TODO(b/111276913): rename / update javadoc (once the final name is defined)
-oneway interface IIntelligenceService {
-
- // Called when session is created (context not null) or destroyed (context null)
- void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId);
-
- void onContentCaptureEventsRequest(in InteractionSessionId sessionId,
- in ContentCaptureEventsRequest request);
-
- void onActivitySnapshot(in InteractionSessionId sessionId,
- in SnapshotData snapshotData);
-
- void onAutofillRequest(in InteractionSessionId sessionId, in IBinder autofillManagerClient,
- int autofilSessionId, in AutofillId focusedId,
- in AutofillValue focusedValue, long requestTime);
-
- void onDestroyAutofillWindowsRequest(in InteractionSessionId sessionId);
-}
diff --git a/core/java/android/service/intelligence/InteractionSessionId.aidl b/core/java/android/service/intelligence/InteractionSessionId.aidl
deleted file mode 100644
index a5392b6..0000000
--- a/core/java/android/service/intelligence/InteractionSessionId.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-parcelable InteractionSessionId;
diff --git a/core/java/android/service/intelligence/SmartSuggestionsService.java b/core/java/android/service/intelligence/SmartSuggestionsService.java
deleted file mode 100644
index b684b02..0000000
--- a/core/java/android/service/intelligence/SmartSuggestionsService.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.intelligence;
-
-import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
-
-import android.annotation.CallSuper;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.PresentationParams.SystemPopupPresentationParams;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.TimeUtils;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAugmentedAutofillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A service used to capture the content of the screen to provide contextual data in other areas of
- * the system such as Autofill.
- *
- * @hide
- */
-@SystemApi
-public abstract class SmartSuggestionsService extends Service {
-
- private static final String TAG = "SmartSuggestionsService";
-
- // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
- static final boolean DEBUG = true;
- static final boolean VERBOSE = false;
-
- /**
- * The {@link Intent} that must be declared as handled by the service.
- * To be supported, the service must also require the
- * {@link android.Manifest.permission#BIND_SMART_SUGGESTIONS_SERVICE} permission so
- * that other applications can not abuse it.
- */
- public static final String SERVICE_INTERFACE =
- "android.service.intelligence.SmartSuggestionsService";
-
- private Handler mHandler;
-
- private ArrayMap<InteractionSessionId, AutofillProxy> mAutofillProxies;
-
- private final IIntelligenceService mInterface = new IIntelligenceService.Stub() {
-
- @Override
- public void onSessionLifecycle(InteractionContext context, InteractionSessionId sessionId)
- throws RemoteException {
- if (context != null) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onCreateInteractionSession,
- SmartSuggestionsService.this, context, sessionId));
- } else {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onDestroyInteractionSession,
- SmartSuggestionsService.this, sessionId));
- }
- }
-
- @Override
- public void onContentCaptureEventsRequest(InteractionSessionId sessionId,
- ContentCaptureEventsRequest request) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onContentCaptureEventsRequest,
- SmartSuggestionsService.this, sessionId, request));
-
- }
-
- @Override
- public void onActivitySnapshot(InteractionSessionId sessionId,
- SnapshotData snapshotData) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onActivitySnapshot,
- SmartSuggestionsService.this, sessionId, snapshotData));
- }
-
- @Override
- public void onAutofillRequest(InteractionSessionId sessionId, IBinder client,
- int autofilSessionId, AutofillId focusedId, AutofillValue focusedValue,
- long requestTime) {
- mHandler.sendMessage(obtainMessage(SmartSuggestionsService::handleOnAutofillRequest,
- SmartSuggestionsService.this, sessionId, client, autofilSessionId, focusedId,
- focusedValue, requestTime));
- }
-
- @Override
- public void onDestroyAutofillWindowsRequest(InteractionSessionId sessionId) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::handleOnDestroyAutofillWindowsRequest,
- SmartSuggestionsService.this, sessionId));
- }
- };
-
- @CallSuper
- @Override
- public void onCreate() {
- super.onCreate();
- mHandler = new Handler(Looper.getMainLooper(), null, true);
- }
-
- /** @hide */
- @Override
- public final IBinder onBind(Intent intent) {
- if (SERVICE_INTERFACE.equals(intent.getAction())) {
- return mInterface.asBinder();
- }
- Log.w(TAG, "Tried to bind to wrong intent: " + intent);
- return null;
- }
-
- /**
- * Explicitly limits content capture to the given packages and activities.
- *
- * <p>When the whitelist is set, it overrides the values passed to
- * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
- * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
- *
- * <p>To reset the whitelist, call it passing {@code null} to both arguments.
- *
- * <p>Useful when the service wants to restrict content capture to a category of apps, like
- * chat apps. For example, if the service wants to support view captures on all activities of
- * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
- * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
- * Arrays.asList(new ComponentName("ChatApp2", "act1"),
- * new ComponentName("ChatApp2", "act2")));}
- */
- public final void setContentCaptureWhitelist(@Nullable List<String> packages,
- @Nullable List<ComponentName> activities) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Defines whether content capture should be enabled for activities with such
- * {@link android.content.ComponentName}.
- *
- * <p>Useful to blacklist a particular activity.
- */
- public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
- boolean enabled) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Defines whether content capture should be enabled for activities of the app with such
- * {@code packageName}.
- *
- * <p>Useful to blacklist any activity from a particular app.
- */
- public final void setPackageContentCaptureEnabled(@NonNull String packageName,
- boolean enabled) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Gets the activities where content capture was disabled by
- * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
- */
- @NonNull
- public final Set<ComponentName> getContentCaptureDisabledActivities() {
- //TODO(b/111276913): implement
- return null;
- }
-
- /**
- * Gets the apps where content capture was disabled by
- * {@link #setPackageContentCaptureEnabled(String, boolean)}.
- */
- @NonNull
- public final Set<String> getContentCaptureDisabledPackages() {
- //TODO(b/111276913): implement
- return null;
- }
-
- /**
- * Creates a new interaction session.
- *
- * @param context interaction context
- * @param sessionId the session's Id
- */
- public void onCreateInteractionSession(@NonNull InteractionContext context,
- @NonNull InteractionSessionId sessionId) {
- if (VERBOSE) {
- Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
- }
- }
-
- /**
- * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
- * session.
- *
- * @param sessionId the session's Id
- * @param request the events
- */
- // TODO(b/111276913): rename to onContentCaptureEvents or something like that; also, pass a
- // Request object so it can be extended
- public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
- @NonNull ContentCaptureEventsRequest request);
-
- private void handleOnAutofillRequest(@NonNull InteractionSessionId sessionId,
- @NonNull IBinder client, int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue, long requestTime) {
- if (mAutofillProxies == null) {
- mAutofillProxies = new ArrayMap<>();
- }
- AutofillProxy proxy = mAutofillProxies.get(sessionId);
- if (proxy == null) {
- proxy = new AutofillProxy(sessionId, client, autofillSessionId, focusedId, focusedValue,
- requestTime);
- mAutofillProxies.put(sessionId, proxy);
- } else {
- // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
- if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
- }
- // TODO(b/111330312): set cancellation signal
- final CancellationSignal cancellationSignal = null;
- onFillRequest(sessionId, new FillRequest(proxy), cancellationSignal,
- new FillController(proxy), new FillCallback(proxy));
- }
-
- /**
- * Asks the service to handle an "augmented" autofill request.
- *
- * <p>This method is called when the "stantard" autofill service cannot handle a request, which
- * typically occurs when:
- * <ul>
- * <li>Service does not recognize what should be autofilled.
- * <li>Service does not have data to fill the request.
- * <li>Service blacklisted that app (or activity) for autofill.
- * <li>App disabled itself for autofill.
- * </ul>
- *
- * <p>Differently from the standard autofill workflow, on augmented autofill the service is
- * responsible to generate the autofill UI and request the Android system to autofill the
- * activity when the user taps an action in that UI (through the
- * {@link FillController#autofill(List)} method).
- *
- * <p>The service <b>MUST</b> call {@link
- * FillCallback#onSuccess(android.service.intelligence.FillResponse)} as soon as possible,
- * passing {@code null} when it cannot fulfill the request.
- *
- * @param sessionId the session's id
- * @param request the request to handle.
- * @param cancellationSignal signal for observing cancellation requests. The system will use
- * this to notify you that the fill result is no longer needed and you should stop
- * handling this fill request in order to save resources.
- * @param controller object used to interact with the autofill system.
- * @param callback object used to notify the result of the request. Service <b>must</b> call
- * {@link FillCallback#onSuccess(android.service.intelligence.FillResponse)}.
- */
- public void onFillRequest(@NonNull InteractionSessionId sessionId, @NonNull FillRequest request,
- @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
- @NonNull FillCallback callback) {
- }
-
- private void handleOnDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
- AutofillProxy proxy = null;
- if (mAutofillProxies != null) {
- proxy = mAutofillProxies.get(sessionId);
- }
- if (proxy == null) {
- // TODO(b/111330312): this might be fine, in which case we should logv it
- Log.w(TAG, "No proxy for session " + sessionId);
- return;
- }
- proxy.destroy();
- mAutofillProxies.remove(sessionId);
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mAutofillProxies != null) {
- final int size = mAutofillProxies.size();
- pw.print("Number proxies: "); pw.println(size);
- for (int i = 0; i < size; i++) {
- final InteractionSessionId sessionId = mAutofillProxies.keyAt(i);
- final AutofillProxy proxy = mAutofillProxies.valueAt(i);
- pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
- proxy.dump(" ", pw);
- }
- }
- }
-
- /**
- * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
- *
- * @param sessionId the session's Id
- * @param snapshotData the data
- */
- public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {}
-
- /**
- * Destroys the interaction session.
- *
- * @param sessionId the id of the session to destroy
- */
- public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
- if (VERBOSE) {
- Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
- }
- }
-
- /** @hide */
- static final class AutofillProxy {
-
- static final int REPORT_EVENT_ON_SUCCESS = 1;
- static final int REPORT_EVENT_UI_SHOWN = 2;
- static final int REPORT_EVENT_UI_DESTROYED = 3;
-
- @IntDef(prefix = { "REPORT_EVENT_" }, value = {
- REPORT_EVENT_ON_SUCCESS,
- REPORT_EVENT_UI_SHOWN,
- REPORT_EVENT_UI_DESTROYED
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface ReportEvent{}
-
-
- private final Object mLock = new Object();
- private final IAugmentedAutofillManagerClient mClient;
- private final int mAutofillSessionId;
- public final InteractionSessionId sessionId;
- public final AutofillId focusedId;
- public final AutofillValue focusedValue;
-
- // Objects used to log metrics
- private final long mRequestTime;
- private long mOnSuccessTime;
- private long mUiFirstShownTime;
- private long mUiFirstDestroyedTime;
-
- @GuardedBy("mLock")
- private SystemPopupPresentationParams mSmartSuggestion;
-
- @GuardedBy("mLock")
- private FillWindow mFillWindow;
-
- private AutofillProxy(@NonNull InteractionSessionId sessionId, @NonNull IBinder client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue, long requestTime) {
- this.sessionId = sessionId;
- mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
- mAutofillSessionId = autofillSessionId;
- this.focusedId = focusedId;
- this.focusedValue = focusedValue;
- this.mRequestTime = requestTime;
- // TODO(b/111330312): linkToDeath
- }
-
- @NonNull
- public SystemPopupPresentationParams getSmartSuggestionParams() {
- synchronized (mLock) {
- if (mSmartSuggestion != null) {
- return mSmartSuggestion;
- }
- Rect rect;
- try {
- rect = mClient.getViewCoordinates(focusedId);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not get coordinates for " + focusedId);
- return null;
- }
- if (rect == null) {
- if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
- return null;
- }
- mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
- return mSmartSuggestion;
- }
- }
-
- public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
- throws RemoteException {
- final int size = pairs.size();
- final List<AutofillId> ids = new ArrayList<>(size);
- final List<AutofillValue> values = new ArrayList<>(size);
- for (int i = 0; i < size; i++) {
- final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
- ids.add(pair.first);
- values.add(pair.second);
- }
- mClient.autofill(mAutofillSessionId, ids, values);
- }
-
- public void setFillWindow(@NonNull FillWindow fillWindow) {
- synchronized (mLock) {
- mFillWindow = fillWindow;
- }
- }
-
- public FillWindow getFillWindow() {
- synchronized (mLock) {
- return mFillWindow;
- }
- }
-
- // Used for metrics.
- public void report(@ReportEvent int event) {
- switch (event) {
- case REPORT_EVENT_ON_SUCCESS:
- if (mOnSuccessTime == 0) {
- mOnSuccessTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "Service responsed in "
- + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
- }
- }
- break;
- case REPORT_EVENT_UI_SHOWN:
- if (mUiFirstShownTime == 0) {
- mUiFirstShownTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "UI shown in "
- + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
- }
- }
- break;
- case REPORT_EVENT_UI_DESTROYED:
- if (mUiFirstDestroyedTime == 0) {
- mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "UI destroyed in "
- + TimeUtils.formatDuration(
- mUiFirstDestroyedTime - mRequestTime));
- }
- }
- break;
- default:
- Slog.w(TAG, "invalid event reported: " + event);
- }
- // TODO(b/111330312): log metrics as well
- }
-
-
- public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("afSessionId: "); pw.println(mAutofillSessionId);
- pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
- if (focusedValue != null) {
- pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
- }
- pw.print(prefix); pw.print("client: "); pw.println(mClient);
- final String prefix2 = prefix + " ";
- if (mFillWindow != null) {
- pw.print(prefix); pw.println("window:");
- mFillWindow.dump(prefix2, pw);
- }
- if (mSmartSuggestion != null) {
- pw.print(prefix); pw.println("smartSuggestion:");
- mSmartSuggestion.dump(prefix2, pw);
- }
- if (mOnSuccessTime > 0) {
- final long responseTime = mOnSuccessTime - mRequestTime;
- pw.print(prefix); pw.print("response time: ");
- TimeUtils.formatDuration(responseTime, pw); pw.println();
- }
-
- if (mUiFirstShownTime > 0) {
- final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
- pw.print(prefix); pw.print("UI rendering time: ");
- TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
- }
-
- if (mUiFirstDestroyedTime > 0) {
- final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
- pw.print(prefix); pw.print("UI life time: ");
- TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
- }
- }
-
- private void destroy() {
- synchronized (mLock) {
- if (mFillWindow != null) {
- if (DEBUG) Log.d(TAG, "destroying window");
- mFillWindow.destroy();
- }
- }
- }
- }
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd2aa64..4297efb7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -109,13 +109,13 @@
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumMap;
import android.view.inspector.InspectableProperty.FlagMap;
-import android.view.intelligence.ContentCaptureManager;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
similarity index 94%
rename from core/java/android/view/intelligence/ContentCaptureEvent.aidl
rename to core/java/android/view/contentcapture/ContentCaptureEvent.aidl
index c66a6cb..abaf9ed 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
parcelable ContentCaptureEvent;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
similarity index 91%
rename from core/java/android/view/intelligence/ContentCaptureEvent.java
rename to core/java/android/view/contentcapture/ContentCaptureEvent.java
index f636281..66fa530 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -42,22 +42,38 @@
/**
* Called when the activity is started.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_STARTED = 1;
/**
* Called when the activity is resumed.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_RESUMED = 2;
/**
* Called when the activity is paused.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_PAUSED = 3;
/**
* Called when the activity is stopped.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_STOPPED = 4;
/**
@@ -163,7 +179,7 @@
* Gets optional flags associated with the event.
*
* @return either {@code 0} or
- * {@link android.view.intelligence.ContentCaptureManager#FLAG_USER_INPUT}.
+ * {@link android.view.contentcapture.ContentCaptureManager#FLAG_USER_INPUT}.
*/
public int getFlags() {
return mFlags;
diff --git a/core/java/android/view/intelligence/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
similarity index 95%
rename from core/java/android/view/intelligence/ContentCaptureManager.java
rename to core/java/android/view/contentcapture/ContentCaptureManager.java
index 45518d5..48831da 100644
--- a/core/java/android/view/intelligence/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -31,18 +31,18 @@
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
import android.util.Log;
import android.view.View;
import android.view.ViewStructure;
import android.view.autofill.AutofillId;
-import android.view.intelligence.ContentCaptureEvent.EventType;
+import android.view.contentcapture.ContentCaptureEvent.EventType;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
/*
@@ -58,7 +58,7 @@
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
- private static final String TAG = "ContentCaptureManager";
+ private static final String TAG = ContentCaptureManager.class.getSimpleName();
// TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
private static final boolean VERBOSE = false;
@@ -113,10 +113,10 @@
private final Context mContext;
@Nullable
- private final IIntelligenceManager mService;
+ private final IContentCaptureManager mService;
@Nullable
- private InteractionSessionId mId;
+ private String mId;
private int mState = STATE_UNKNOWN;
@@ -137,7 +137,8 @@
private final Handler mHandler;
/** @hide */
- public ContentCaptureManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
+ public ContentCaptureManager(@NonNull Context context,
+ @Nullable IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
if (VERBOSE) {
Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -165,7 +166,7 @@
return;
}
mState = STATE_WAITING_FOR_SERVER;
- mId = new InteractionSessionId();
+ mId = UUID.randomUUID().toString();
mApplicationToken = token;
mComponentName = componentName;
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
new file mode 100644
index 0000000..8704dad
--- /dev/null
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentcapture;
+
+import android.content.ComponentName;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.os.IBinder;
+
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+oneway interface IContentCaptureManager {
+ void startSession(int userId, IBinder activityToken, in ComponentName componentName,
+ String sessionId, int flags, in IResultReceiver result);
+ void finishSession(int userId, String sessionId, in List<ContentCaptureEvent> events);
+ void sendEvents(int userId, in String sessionId, in List<ContentCaptureEvent> events);
+}
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
similarity index 99%
rename from core/java/android/view/intelligence/ViewNode.java
rename to core/java/android/view/contentcapture/ViewNode.java
index ea57461..86b89adb 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
deleted file mode 100644
index 882fb26..0000000
--- a/core/java/android/view/intelligence/IIntelligenceManager.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.intelligence;
-
-import android.content.ComponentName;
-import android.os.IBinder;
-import android.service.intelligence.InteractionSessionId;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-
-import java.util.List;
-
-/**
- * {@hide}
- */
-// TODO(b/111276913): rename once the final name is defined
-oneway interface IIntelligenceManager {
- /**
- * Starts a session, sending the "remote" sessionId to the receiver.
- */
- void startSession(int userId, IBinder activityToken, in ComponentName componentName,
- in InteractionSessionId sessionId, int flags, in IResultReceiver result);
-
- /**
- * Finishes a session.
- */
- void finishSession(int userId, in InteractionSessionId sessionId,
- in List<ContentCaptureEvent> events);
-
- /**
- * Sends a batch of events
- */
- void sendEvents(int userId, in InteractionSessionId sessionId,
- in List<ContentCaptureEvent> events);
-}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 90cf871..2a42232 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -157,6 +157,7 @@
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -166,7 +167,6 @@
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationContext;
import android.view.textclassifier.TextClassificationManager;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index c96bacd..d5dc703 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -840,6 +840,11 @@
+ "of length " + MIN_LOCK_PASSWORD_SIZE);
}
+ if (requestedQuality < PASSWORD_QUALITY_NUMERIC) {
+ throw new IllegalArgumentException("quality must be at least NUMERIC, but was "
+ + requestedQuality);
+ }
+
final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
setKeyguardStoredPasswordQuality(
computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality),
diff --git a/core/proto/android/app/job/enums.proto b/core/proto/android/app/job/enums.proto
index 2290b2f..bba8328 100644
--- a/core/proto/android/app/job/enums.proto
+++ b/core/proto/android/app/job/enums.proto
@@ -30,4 +30,5 @@
STOP_REASON_PREEMPT = 2;
STOP_REASON_TIMEOUT = 3;
STOP_REASON_DEVICE_IDLE = 4;
+ STOP_REASON_DEVICE_THERMAL = 5;
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 8e4eb00..fd64c65 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -73,5 +73,8 @@
// OPEN: Settings > Privacy
TOP_LEVEL_PRIVACY = 1587;
+
+ // OPEN: Settings > Developer options > Disable > Info dialog
+ DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591;
}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 0b9e347..a5350c9 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -34,6 +34,7 @@
import "frameworks/base/core/proto/android/server/fingerprint.proto";
import "frameworks/base/core/proto/android/server/jobscheduler.proto";
import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
+import "frameworks/base/core/proto/android/server/rolemanagerservice.proto";
import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
import "frameworks/base/core/proto/android/service/appwidget.proto";
import "frameworks/base/core/proto/android/service/battery.proto";
@@ -308,6 +309,11 @@
(section).userdebug_and_eng_only = true
];
+ optional com.android.server.role.RoleManagerServiceDumpProto role = 3024 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "role --proto"
+ ];
+
// Reserved for OEMs.
extensions 50000 to 100000;
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 4c1fc5c..ca8da55 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -222,6 +222,13 @@
}
optional Connectivity connectivity = 32;
+ message ContentCapture {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional ContentCapture content_capture = 145;
+
optional SettingProto contact_metadata_sync_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto contacts_database_wal_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -628,6 +635,9 @@
// separated by commas.
optional SettingProto snooze_options = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto smart_replies_in_notifications_flags = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Configuration options for smart replies and smart actions in notifications. This is
+ // encoded as a key=value list separated by commas.
+ optional SettingProto smart_suggestions_in_notifications_flags = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Notification notification = 82;
@@ -761,13 +771,6 @@
}
optional SmartSelection smart_selection = 108;
- message SmartSuggestions {
- option (android.msg_privacy).dest = DEST_EXPLICIT;
-
- optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
- }
- optional SmartSuggestions smart_suggestions = 145;
-
message Sms {
option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 231caab..c2bc7bf 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -41,6 +41,7 @@
optional int64 last_heartbeat_time_millis = 16;
optional int64 next_heartbeat_time_millis = 17;
optional bool in_parole = 18;
+ optional bool in_thermal = 19;
repeated int32 started_users = 2;
diff --git a/core/proto/android/server/rolemanagerservice.proto b/core/proto/android/server/rolemanagerservice.proto
new file mode 100644
index 0000000..3453a66
--- /dev/null
+++ b/core/proto/android/server/rolemanagerservice.proto
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.server.role;
+
+option java_multiple_files = true;
+
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+message RoleManagerServiceDumpProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ // List of per-user states for all users.
+ repeated RoleUserStateProto user_states = 1;
+}
+
+message RoleUserStateProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ // The user id of this state.
+ optional int32 user_id = 1;
+
+ // The version of this state.
+ optional int32 version = 2;
+
+ // The hash of packages for this state.
+ optional string packages_hash = 3;
+
+ // The set of roles in this state.
+ repeated RoleProto roles = 4;
+}
+
+message RoleProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ // The name of this role, e.g. "android.app.role.DIALER".
+ optional string name = 1;
+
+ // The package names of the holders of this role.
+ repeated string holders = 2;
+}
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 8fbea12..5726d9a 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -44,7 +44,7 @@
SET_PERMISSION_GRANT_STATE = 19;
INSTALL_KEY_PAIR = 20;
INSTALL_CA_CERT = 21;
- ON_CHOOSE_KEY_ALIAS = 22;
+ CHOOSE_PRIVATE_KEY_ALIAS = 22;
REMOVE_KEY_PAIR = 23;
UNINSTALL_CA_CERTS = 24;
SET_CERT_INSTALLER_PACKAGE = 25;
@@ -68,12 +68,12 @@
SET_SHORT_SUPPORT_MESSAGE = 43;
SET_LONG_SUPPORT_MESSAGE = 44;
SET_CROSS_PROFILE_CONTACTS_SEARCH_DISABLED = 45;
- SET_CROSS_PROFILE_CALLER_DISABLED = 46;
+ SET_CROSS_PROFILE_CALLER_ID_DISABLED = 46;
SET_BLUETOOTH_CONTACT_SHARING_DISABLED = 47;
ADD_CROSS_PROFILE_INTENT_FILTER = 48;
ADD_CROSS_PROFILE_WIDGET_PROVIDER = 49;
SET_SYSTEM_UPDATE_POLICY = 50;
- SET_LOCKTASK_PACKAGES = 51;
+ SET_LOCKTASK_MODE_ENABLED = 51;
ADD_PERSISTENT_PREFERRED_ACTIVITY = 52;
REQUEST_BUGREPORT = 53;
GET_WIFI_MAC_ADDRESS = 54;
@@ -99,13 +99,13 @@
INSTALL_SYSTEM_UPDATE_ERROR = 74;
IS_MANAGED_KIOSK = 75;
IS_UNATTENDED_MANAGED_KIOSK = 76;
- PROVISIONING_TO_COMP = 77;
- PROVISIONING_FORCED_DO = 78;
+ PROVISIONING_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 77;
+ PROVISIONING_PERSISTENT_DEVICE_OWNER = 78;
// existing Tron logs to be migrated to WestWorld
PROVISIONING_ENTRY_POINT_NFC = 79;
PROVISIONING_ENTRY_POINT_QR_CODE = 80;
- PROVISIONING_ENTRY_POINT_ZERO_TOUCH = 81;
+ PROVISIONING_ENTRY_POINT_CLOUD_ENROLLMENT = 81;
PROVISIONING_ENTRY_POINT_ADB = 82;
PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE = 83;
PROVISIONING_DPC_PACKAGE_NAME = 84;
@@ -134,4 +134,9 @@
PROVISIONING_TERMS_ACTIVITY_TIME_MS = 107;
PROVISIONING_TERMS_COUNT = 108;
PROVISIONING_TERMS_READ = 109;
+
+ SEPARATE_PROFILE_CHALLENGE_CHANGED = 110;
+ SET_GLOBAL_SETTING = 111;
+ PM_IS_INSTALLER_DEVICE_OWNER_OR_AFFILIATED_PROFILE_OWNER = 112;
+ PM_UNINSTALL = 113;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3018614..594ae6b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3047,12 +3047,20 @@
<permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
android:protectionLevel="signature" />
- <!-- Must be required by a android.service.intelligence.SmartSuggestionsService,
+ <!-- Must be required by a android.service.contentcapture.ContentCaptureService,
to ensure that only the system can bind to it.
@SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
<p>Protection level: signature
-->
- <permission android:name="android.permission.BIND_SMART_SUGGESTIONS_SERVICE"
+ <permission android:name="android.permission.BIND_CONTENT_CAPTURE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"
android:protectionLevel="signature" />
<!-- Must be required by hotword enrollment application,
@@ -4177,9 +4185,9 @@
<permission android:name="android.permission.MANAGE_AUTO_FILL"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to manage the smart suggestions service.
+ <!-- @SystemApi Allows an application to manage the content capture service.
@hide <p>Not for use by third-party applications.</p> -->
- <permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS"
+ <permission android:name="android.permission.MANAGE_CONTENT_CAPTURE"
android:protectionLevel="signature" />
<!-- Allows an app to set the theme overlay in /vendor/overlay
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 499278c..62ec5c4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3350,13 +3350,21 @@
-->
<string name="config_defaultTextClassifierPackage" translatable="false"></string>
- <!-- The package name for the system's smart suggestion service.
+ <!-- The package name for the system's content capture service.
This service must be trusted, as it can be activated without explicit consent of the user.
- If no service with the specified name exists on the device, content capture and
- smart suggestions will be disabled.
- Example: "com.android.intelligence/.SmartSuggestionsService"
+ If no service with the specified name exists on the device, content capture will be
+ disabled.
+ Example: "com.android.contentcapture/.ContentcaptureService"
-->
- <string name="config_defaultSmartSuggestionsService" translatable="false"></string>
+ <string name="config_defaultContentCaptureService" translatable="false"></string>
+
+ <!-- The package name for the system's augmented autofill service.
+ This service must be trusted, as it can be activated without explicit consent of the user.
+ If no service with the specified name exists on the device, augmented autofill wil be
+ disabled.
+ Example: "com.android.augmentedautofill/.AugmentedAutofillService"
+ -->
+ <string name="config_defaultAugmentedAutofillService" translatable="false"></string>
<!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
<bool name="config_useDefaultFocusHighlight">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6854a84e..82a679e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3265,7 +3265,8 @@
<java-symbol type="string" name="notification_channel_do_not_disturb" />
<java-symbol type="string" name="config_defaultAutofillService" />
<java-symbol type="string" name="config_defaultTextClassifierPackage" />
- <java-symbol type="string" name="config_defaultSmartSuggestionsService" />
+ <java-symbol type="string" name="config_defaultContentCaptureService" />
+ <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
<java-symbol type="string" name="notification_channel_foreground_service" />
<java-symbol type="string" name="foreground_service_app_in_background" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ed9c3d5..1d72a03 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -183,6 +183,7 @@
Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
Settings.Global.CONTACT_METADATA_SYNC_ENABLED,
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
Settings.Global.CONVERSATION_ACTIONS_UPDATE_CONTENT_URL,
Settings.Global.CONVERSATION_ACTIONS_UPDATE_METADATA_URL,
Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
@@ -247,6 +248,7 @@
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
+ Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
Settings.Global.ENHANCED_4G_MODE_ENABLED,
Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -415,7 +417,6 @@
Settings.Global.SHOW_TEMPERATURE_WARNING,
Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT,
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 108585d..04e8802 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -16,6 +16,10 @@
package android.provider;
+import static org.hamcrest.Matchers.aMapWithSize;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.junit.Assert.assertThat;
+
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -26,6 +30,7 @@
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.AndroidTestCase;
@@ -33,10 +38,19 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Suppress;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/** Unit test for SettingsProvider. */
public class SettingsProviderTest extends AndroidTestCase {
+ /**
+ * TODO(b/113100523): Move this to DeviceConfig.java when it is added, and expose it as a System
+ * API.
+ */
+ private static final Uri CONFIG_CONTENT_URI =
+ Uri.parse("content://" + Settings.AUTHORITY + "/config");
+
@MediumTest
public void testNameValueCache() {
ContentResolver r = getContext().getContentResolver();
@@ -379,4 +393,109 @@
assertTrue(ssaid.equals(ssaid2));
}
+
+ @MediumTest
+ public void testCall_putAndGetConfig() {
+ ContentResolver r = getContext().getContentResolver();
+ String name = "key1";
+ String value = "value1";
+ String newValue = "value2";
+ Bundle args = new Bundle();
+ args.putString(Settings.NameValueTable.VALUE, value);
+
+ try {
+ // value is empty
+ Bundle results =
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+ assertNull(results.get(Settings.NameValueTable.VALUE));
+
+ // save value
+ results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+ assertNull(results);
+
+ // value is no longer empty
+ results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+ assertEquals(value, results.get(Settings.NameValueTable.VALUE));
+
+ // save new value
+ args.putString(Settings.NameValueTable.VALUE, newValue);
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+
+ // new value is returned
+ results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+ assertEquals(newValue, results.get(Settings.NameValueTable.VALUE));
+ } finally {
+ // clean up
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+ }
+ }
+
+ @MediumTest
+ public void testCall_deleteConfig() {
+ ContentResolver r = getContext().getContentResolver();
+ String name = "key1";
+ String value = "value1";
+ Bundle args = new Bundle();
+ args.putString(Settings.NameValueTable.VALUE, value);
+
+ try {
+ // save value
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+
+ // get value
+ Bundle results =
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+ assertEquals(value, results.get(Settings.NameValueTable.VALUE));
+
+ // delete value
+ results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+
+ // value is empty now
+ results = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_GET_CONFIG, name, null);
+ assertNull(results.get(Settings.NameValueTable.VALUE));
+ } finally {
+ // clean up
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+ }
+ }
+
+ @MediumTest
+ public void testCall_listConfig() {
+ ContentResolver r = getContext().getContentResolver();
+ String prefix = "foo";
+ String newPrefix = "bar";
+ String name = prefix + "/" + "key1";
+ String newName = newPrefix + "/" + "key1";
+ String value = "value1";
+ String newValue = "value2";
+ Bundle args = new Bundle();
+ args.putString(Settings.NameValueTable.VALUE, value);
+
+ try {
+ // save both values
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, name, args);
+ args.putString(Settings.NameValueTable.VALUE, newValue);
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, newName, args);
+
+ // list all values
+ Bundle result = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG,
+ null, null);
+ Map<String, String> keyValueMap =
+ (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
+ assertThat(keyValueMap.size(), greaterThanOrEqualTo(2));
+ assertEquals(value, keyValueMap.get(name));
+ assertEquals(newValue, keyValueMap.get(newName));
+
+ // list values for prefix
+ args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
+ result = r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_LIST_CONFIG, null, args);
+ keyValueMap = (HashMap) result.getSerializable(Settings.NameValueTable.VALUE);
+ assertThat(keyValueMap, aMapWithSize(1));
+ assertEquals(value, keyValueMap.get(name));
+ } finally {
+ // clean up
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, name, null);
+ r.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_DELETE_CONFIG, newName, null);
+ }
+ }
}
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index fbc21e5..26261ef 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -18,7 +18,7 @@
#include <android/os/IncidentReportArgs.h>
-#include <cutils/log.h>
+#include <log/log.h>
namespace android {
namespace os {
diff --git a/media/java/android/media/CallbackDataSourceDesc.java b/media/java/android/media/CallbackDataSourceDesc.java
index cb9669b..cd36414 100644
--- a/media/java/android/media/CallbackDataSourceDesc.java
+++ b/media/java/android/media/CallbackDataSourceDesc.java
@@ -21,10 +21,8 @@
/**
* Structure of data source descriptor for sources using callback.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
*
* <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}.
*
@@ -37,7 +35,6 @@
/**
* Return the DataSourceCallback of this data source.
- * It's meaningful only when {@code getType} returns {@link #TYPE_CALLBACK}.
* @return the DataSourceCallback of this data source
*/
public DataSourceCallback getDataSourceCallback() {
diff --git a/media/java/android/media/DataSourceDesc.java b/media/java/android/media/DataSourceDesc.java
index 9109ea5..7fc6f79 100644
--- a/media/java/android/media/DataSourceDesc.java
+++ b/media/java/android/media/DataSourceDesc.java
@@ -21,10 +21,8 @@
/**
* Base class of data source descriptor.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
*
* <p>Users should use subclasses' builder to change {@link DataSourceDesc}.
*
diff --git a/media/java/android/media/FileDataSourceDesc.java b/media/java/android/media/FileDataSourceDesc.java
index 14ef180..aca8dbe 100644
--- a/media/java/android/media/FileDataSourceDesc.java
+++ b/media/java/android/media/FileDataSourceDesc.java
@@ -25,10 +25,8 @@
/**
* Structure of data source descriptor for sources using file descriptor.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
*
* <p>Users should use {@link Builder} to create {@link FileDataSourceDesc}.
*
@@ -165,9 +163,9 @@
* Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
* seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
* created by this builder is passed to {@link MediaPlayer2} via
- * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+ * {@link MediaPlayer2#setDataSource},
+ * {@link MediaPlayer2#setNextDataSource} or
+ * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
* close the ParcelFileDescriptor.
*
* @param pfd the ParcelFileDescriptor for the file to play
@@ -185,9 +183,9 @@
* Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
* seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
* created by this builder is passed to {@link MediaPlayer2} via
- * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+ * {@link MediaPlayer2#setDataSource},
+ * {@link MediaPlayer2#setNextDataSource} or
+ * {@link MediaPlayer2#setNextDataSources}, MediaPlayer2 will
* close the ParcelFileDescriptor.
*
* Any negative number for offset is treated as 0.
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index e6ad444..4805780 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -98,11 +98,10 @@
* <p>The MediaPlayer2 object has five states:</p>
* <ol>
* <li><p>{@link #PLAYER_STATE_IDLE}: MediaPlayer2 is in the <strong>Idle</strong>
- * state after you create it using
- * {@link #create()}, or after calling {@link #reset()}.</p>
+ * state after it's created, or after calling {@link #reset()}.</p>
*
* <p>While in this state, you should call
- * {@link #setDataSource(DataSourceDesc2) setDataSource()}. It is a good
+ * {@link #setDataSource setDataSource}. It is a good
* programming practice to register an {@link EventCallback#onCallCompleted onCallCompleted}
* <a href="#Callbacks">callback</a> and watch for {@link #CALL_STATUS_BAD_VALUE} and
* {@link #CALL_STATUS_ERROR_IO}, which might be caused by <code>setDataSource</code>.
@@ -134,7 +133,7 @@
* while streaming audio/video.</p>
*
* <p> When the playback reaches the end of stream, the behavior depends on whether or
- * not you've enabled looping by calling {@link #loopCurrent(boolean) loopCurrent}:</p>
+ * not you've enabled looping by calling {@link #loopCurrent}:</p>
* <ul>
* <li>If the looping mode was set to <code>false</code>, the player will transfer
* to the <strong>Paused</strong> state. If you registered an {@link EventCallback#onInfo
@@ -161,15 +160,15 @@
* <p>If you register an {@link EventCallback#onError onError}}
* <a href="#Callbacks">callback</a>,
* the callback will be performed when entering the state. When programming errors happen,
- * such as calling {@link #prepare() prepare} and
- * {@link #setDataSource(DataSourceDesc) setDataSource} methods
+ * such as calling {@link #prepare()} and
+ * {@link #setDataSource} methods
* from an <a href="#InvalidStates">invalid state</a>, the callback is called with
* {@link #CALL_STATUS_INVALID_OPERATION}. The MediaPlayer2 object enters the
* <strong>Error</strong> state whether or not a callback exists. </p>
*
* <p>To recover from an error and reuse a MediaPlayer2 object that is in the <strong>
* Error</strong> state,
- * call {@link #reset() reset}. The object will return to the <strong>Idle</strong>
+ * call {@link #reset()}. The object will return to the <strong>Idle</strong>
* state and all state information will be lost.</p>
* </li>
* </ol>
@@ -180,26 +179,26 @@
*
* <li>Use <a href="#Callbacks">callbacks</a> to respond to state changes and errors.</li>
*
- * <li>When a MediaPlayer2 object is no longer being used, call {@link #close() close} as soon as
+ * <li>When a MediaPlayer2 object is no longer being used, call {@link #close()} as soon as
* possible to release the resources used by the internal player engine associated with the
- * MediaPlayer2. Failure to call {@link #close() close} may cause subsequent instances of
+ * MediaPlayer2. Failure to call {@link #close()} may cause subsequent instances of
* MediaPlayer2 objects to fallback to software implementations or fail altogether.
* You cannot use MediaPlayer2
- * after you call {@link #close() close}. There is no way to bring it back to any other state.</li>
+ * after you call {@link #close()}. There is no way to bring it back to any other state.</li>
*
* <li>The current playback position can be retrieved with a call to
- * {@link #getCurrentPosition() getCurrentPosition},
+ * {@link #getCurrentPosition()},
* which is helpful for applications such as a Music player that need to keep track of the playback
* progress.</li>
*
- * <li>The playback position can be adjusted with a call to {@link #seekTo seekTo}. Although the
- * asynchronous {@link #seekTo seekTo} call returns right away, the actual seek operation may take a
+ * <li>The playback position can be adjusted with a call to {@link #seekTo}. Although the
+ * asynchronous {@link #seekTo} call returns right away, the actual seek operation may take a
* while to finish, especially for audio/video being streamed. If you register an
* {@link EventCallback#onCallCompleted onCallCompleted} <a href="#Callbacks">callback</a>,
* the callback is
* called When the seek operation completes with {@link #CALL_COMPLETED_SEEK_TO}.</li>
*
- * <li>You can call {@link #seekTo seekTo} from the <strong>Paused</strong> state.
+ * <li>You can call {@link #seekTo} from the <strong>Paused</strong> state.
* In this case, if you are playing a video stream and
* the requested position is valid one video frame is displayed.</li>
*
@@ -208,13 +207,13 @@
* <h3 id="InvalidStates">Invalid method calls</h3>
*
* <p>The only methods you safely call from the <strong>Error</strong> state are
- * {@link #close() close},
- * {@link #reset() reset},
- * {@link #notifyWhenCommandLabelReached notifyWhenCommandLabelReached},
- * {@link #clearPendingCommands() clearPendingCommands},
- * {@link #setEventCallback setEventCallback},
- * {@link #clearEventCallback() clearEventCallback}
- * and {@link #getState() getState}.
+ * {@link #close},
+ * {@link #reset},
+ * {@link #notifyWhenCommandLabelReached},
+ * {@link #clearPendingCommands},
+ * {@link #registerEventCallback},
+ * {@link #unregisterEventCallback}
+ * and {@link #getState}.
* Any other methods might throw an exception, return meaningless data, or invoke a
* {@link EventCallback#onCallCompleted onCallCompleted} with an error code.</p>
*
@@ -248,8 +247,7 @@
* <h3 id="Callbacks">Callbacks</h3>
* <p>Many errors do not result in a transition to the <strong>Error</strong> state.
* It is good programming practice to register callback listeners using
- * {@link #setEventCallback(Executor, EventCallback) setEventCallback} and
- * {@link #setDrmEventCallback(Executor, DrmEventCallback) setDrmEventCallback}).
+ * {@link #registerEventCallback}.
* You can receive a callback at any time and from any state.</p>
*
* <p>If it's important for your app to respond to state changes (for instance, to update the
@@ -1445,7 +1443,7 @@
* @return the size of the video. The width and height of size could be 0 if there is no video,
* no display surface was set, or the size has not been determined yet.
* The {@code EventCallback} can be registered via
- * {@link #setEventCallback(Executor, EventCallback)} to provide a
+ * {@link #registerEventCallback(Executor, EventCallback)} to provide a
* notification {@code EventCallback.onVideoSizeChanged} when the size
* is available.
*/
@@ -3060,7 +3058,7 @@
public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED =
SEPARATE_CALL_COMPLETED_CALLBACK_START;
- /** The player just completed a call {@link #prepareDrm(DataSourceDesc, UUID)}.
+ /** The player just completed a call {@link #prepareDrm}.
* @see DrmEventCallback#onDrmPrepared
* @hide
*/
@@ -3138,9 +3136,10 @@
public static final int CALL_STATUS_SKIPPED = 5;
/** Status code represents that DRM operation is called before preparing a DRM scheme through
- * {@link #prepareDrm(DataSourceDesc, UUID)}.
+ * {@code prepareDrm}.
* @see EventCallback#onCallCompleted
*/
+ // TODO: change @code to @link when DRM is unhidden
public static final int CALL_STATUS_NO_DRM_SCHEME = 6;
/**
@@ -3186,7 +3185,7 @@
* Register a callback to be invoked for configuration of the DRM object before
* the session is created.
* The callback will be invoked synchronously during the execution
- * of {@link #prepareDrm(DataSourceDesc, UUID)}.
+ * of {@link #prepareDrm}.
*
* @param listener the callback that will be run
* @hide
diff --git a/media/java/android/media/UriDataSourceDesc.java b/media/java/android/media/UriDataSourceDesc.java
index e39f53c..4eb9e8d 100644
--- a/media/java/android/media/UriDataSourceDesc.java
+++ b/media/java/android/media/UriDataSourceDesc.java
@@ -32,10 +32,8 @@
/**
* Structure of data source descriptor for sources using URI.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
- * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
- * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
- * to set data source for playback.
+ * Used by {@link MediaPlayer2#setDataSource}, {@link MediaPlayer2#setNextDataSource} and
+ * {@link MediaPlayer2#setNextDataSources} to set data source for playback.
*
* <p>Users should use {@link Builder} to change {@link UriDataSourceDesc}.
*
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index d91cf87..5a9a7c8 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -626,12 +626,24 @@
private final int mUid;
private final IBinder mCallerBinder;
+ /**
+ * Create a new remote user information.
+ *
+ * @param packageName The package name of the remote user
+ * @param pid The pid of the remote user
+ * @param uid The uid of the remote user
+ */
public RemoteUserInfo(@NonNull String packageName, int pid, int uid) {
this(packageName, pid, uid, null);
}
/**
- * @hide
+ * Create a new remote user information.
+ *
+ * @param packageName The package name of the remote user
+ * @param pid The pid of the remote user
+ * @param uid The uid of the remote user
+ * @param callerBinder The binder of the remote user. Can be {@code null}.
*/
public RemoteUserInfo(String packageName, int pid, int uid, IBinder callerBinder) {
mPackageName = packageName;
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 12df263..d087176 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -108,7 +108,13 @@
private CarAudioManager mCarAudioManager;
private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() {
@Override
- public void onGroupVolumeChanged(int groupId, int flags) {
+ public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
+ // TODO: Include zoneId into consideration.
+ // For instance
+ // - single display + single-zone, ignore zoneId
+ // - multi-display + single-zone, zoneId is fixed, may show volume bar on all displays
+ // - single-display + multi-zone, may show volume bar on primary display only
+ // - multi-display + multi-zone, may show volume bar on display specified by zoneId
VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
int value = getSeekbarValue(mCarAudioManager, groupId);
// Do not update the progress if it is the same as before. When car audio manager sets
@@ -124,7 +130,7 @@
}
@Override
- public void onMasterMuteChanged(int flags) {
+ public void onMasterMuteChanged(int zoneId, int flags) {
// ignored
}
};
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index df5b146..5e7fb85 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -418,6 +418,12 @@
Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
GlobalSettingsProto.CONTACTS_DATABASE_WAL_ENABLED);
+ final long contentCaptureToken = p.start(GlobalSettingsProto.CONTENT_CAPTURE);
+ dumpSetting(s, p,
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
+ GlobalSettingsProto.ContentCapture.SERVICE_EXPLICITLY_ENABLED);
+ p.end(contentCaptureToken);
+
final long dataToken = p.start(GlobalSettingsProto.DATA);
// Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA intentionally excluded.
dumpSetting(s, p,
@@ -998,6 +1004,9 @@
dumpSetting(s, p,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
GlobalSettingsProto.Notification.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS);
+ dumpSetting(s, p,
+ Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
+ GlobalSettingsProto.Notification.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS);
p.end(notificationToken);
dumpSetting(s, p,
@@ -1165,12 +1174,6 @@
GlobalSettingsProto.SmartSelection.UPDATE_METADATA_URL);
p.end(smartSelectToken);
- final long smartSuggestionsToken = p.start(GlobalSettingsProto.SMART_SUGGESTIONS);
- dumpSetting(s, p,
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
- GlobalSettingsProto.SmartSuggestions.SERVICE_EXPLICITLY_ENABLED);
- p.end(smartSuggestionsToken);
-
final long smsToken = p.start(GlobalSettingsProto.SMS);
dumpSetting(s, p,
Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 00ea45c..140a5a3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -94,6 +94,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
@@ -147,6 +148,7 @@
private static final String TABLE_SYSTEM = "system";
private static final String TABLE_SECURE = "secure";
private static final String TABLE_GLOBAL = "global";
+ private static final String TABLE_CONFIG = "config";
// Old tables no longer exist.
private static final String TABLE_FAVORITES = "favorites";
@@ -414,9 +416,8 @@
case Settings.CALL_METHOD_PUT_CONFIG: {
String value = getSettingValue(args);
- String tag = getSettingTag(args);
final boolean makeDefault = getSettingMakeDefault(args);
- insertConfigSetting(name, value, tag, makeDefault, requestingUserId, false);
+ insertConfigSetting(name, value, null, makeDefault, requestingUserId, false);
break;
}
@@ -444,8 +445,8 @@
case Settings.CALL_METHOD_RESET_CONFIG: {
final int mode = getResetModeEnforcingPermission(args);
- String tag = getSettingTag(args);
- resetConfigSetting(requestingUserId, mode, tag);
+ String prefix = getSettingPrefix(args);
+ resetConfigSetting(requestingUserId, mode, prefix);
break;
}
@@ -463,15 +464,8 @@
break;
}
- case Settings.CALL_METHOD_DELETE_SYSTEM: {
- int rows = deleteSystemSetting(name, requestingUserId) ? 1 : 0;
- Bundle result = new Bundle();
- result.putInt(RESULT_ROWS_DELETED, rows);
- return result;
- }
-
- case Settings.CALL_METHOD_DELETE_SECURE: {
- int rows = deleteSecureSetting(name, requestingUserId, false) ? 1 : 0;
+ case Settings.CALL_METHOD_DELETE_CONFIG: {
+ int rows = deleteConfigSetting(name, requestingUserId, false) ? 1 : 0;
Bundle result = new Bundle();
result.putInt(RESULT_ROWS_DELETED, rows);
return result;
@@ -484,10 +478,32 @@
return result;
}
- case Settings.CALL_METHOD_LIST_SYSTEM: {
+ case Settings.CALL_METHOD_DELETE_SECURE: {
+ int rows = deleteSecureSetting(name, requestingUserId, false) ? 1 : 0;
+ Bundle result = new Bundle();
+ result.putInt(RESULT_ROWS_DELETED, rows);
+ return result;
+ }
+
+ case Settings.CALL_METHOD_DELETE_SYSTEM: {
+ int rows = deleteSystemSetting(name, requestingUserId) ? 1 : 0;
+ Bundle result = new Bundle();
+ result.putInt(RESULT_ROWS_DELETED, rows);
+ return result;
+ }
+
+ case Settings.CALL_METHOD_LIST_CONFIG: {
+ String prefix = getSettingPrefix(args);
+ Bundle result = new Bundle();
+ result.putSerializable(
+ Settings.NameValueTable.VALUE, (HashMap) getAllConfigFlags(prefix));
+ return result;
+ }
+
+ case Settings.CALL_METHOD_LIST_GLOBAL: {
Bundle result = new Bundle();
result.putStringArrayList(RESULT_SETTINGS_LIST,
- buildSettingsList(getAllSystemSettings(requestingUserId, null)));
+ buildSettingsList(getAllGlobalSettings(null)));
return result;
}
@@ -498,10 +514,10 @@
return result;
}
- case Settings.CALL_METHOD_LIST_GLOBAL: {
+ case Settings.CALL_METHOD_LIST_SYSTEM: {
Bundle result = new Bundle();
result.putStringArrayList(RESULT_SETTINGS_LIST,
- buildSettingsList(getAllGlobalSettings(null)));
+ buildSettingsList(getAllSystemSettings(requestingUserId, null)));
return result;
}
@@ -1061,36 +1077,47 @@
MUTATION_OPERATION_INSERT, forceNotify, 0);
}
- private void resetConfigSetting(int requestingUserId, int mode, String tag) {
+ private boolean deleteConfigSetting(String name, int requestingUserId, boolean forceNotify) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ", " + requestingUserId
+ + ", " + forceNotify + ")");
+ }
+ return mutateConfigSetting(name, null, null, false, requestingUserId,
+ MUTATION_OPERATION_DELETE, forceNotify, 0);
+ }
+
+ private void resetConfigSetting(int requestingUserId, int mode, String prefix) {
if (DEBUG) {
Slog.v(LOG_TAG, "resetConfigSetting(" + requestingUserId + ", "
- + mode + ", " + tag + ")");
+ + mode + ", " + prefix + ")");
}
- mutateConfigSetting(null, null, tag, false, requestingUserId,
+ mutateConfigSetting(null, null, prefix, false, requestingUserId,
MUTATION_OPERATION_RESET, false, mode);
}
- private boolean mutateConfigSetting(String name, String value, String tag,
+ private boolean mutateConfigSetting(String name, String value, String prefix,
boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
int mode) {
// TODO(b/117663715): check the new permission when it's added.
// enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
- // Resolve the userId on whose behalf the call is made.
- final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
-
// Perform the mutation.
synchronized (mLock) {
switch (operation) {
case MUTATION_OPERATION_INSERT: {
return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_CONFIG,
- UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
+ UserHandle.USER_SYSTEM, name, value, null, makeDefault,
getCallingPackage(), forceNotify, null);
}
+ case MUTATION_OPERATION_DELETE: {
+ return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_CONFIG,
+ UserHandle.USER_SYSTEM, name, forceNotify, null);
+ }
+
case MUTATION_OPERATION_RESET: {
mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_CONFIG,
- UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
+ UserHandle.USER_SYSTEM, getCallingPackage(), mode, null, prefix);
} return true;
}
}
@@ -1098,6 +1125,34 @@
return false;
}
+ private Map<String, String> getAllConfigFlags(@Nullable String prefix) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix);
+ }
+
+ synchronized (mLock) {
+ // Get the settings.
+ SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
+ SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
+
+ List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_CONFIG,
+ UserHandle.USER_SYSTEM);
+
+ final int nameCount = names.size();
+ Map<String, String> flagsToValues = new HashMap<>(names.size());
+
+ for (int i = 0; i < nameCount; i++) {
+ String name = names.get(i);
+ Setting setting = settingsState.getSettingLocked(name);
+ if (prefix == null || setting.getName().startsWith(prefix)) {
+ flagsToValues.put(setting.getName(), setting.getValue());
+ }
+ }
+
+ return flagsToValues;
+ }
+ }
+
private Cursor getAllGlobalSettings(String[] projection) {
if (DEBUG) {
Slog.v(LOG_TAG, "getAllGlobalSettings()");
@@ -2085,6 +2140,13 @@
return (args != null) ? args.getString(Settings.CALL_METHOD_TAG_KEY) : null;
}
+ private static String getSettingPrefix(Bundle args) {
+ String prefix = (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
+ // Append '/' to ensure we only match properties with this exact prefix.
+ // i.e. "foo" should match "foo/property" but not "foobar/property"
+ return prefix != null ? prefix + "/" : null;
+ }
+
private static boolean getSettingMakeDefault(Bundle args) {
return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
}
@@ -2644,6 +2706,11 @@
public void resetSettingsLocked(int type, int userId, String packageName, int mode,
String tag) {
+ resetSettingsLocked(type, userId, packageName, mode, tag, null);
+ }
+
+ public void resetSettingsLocked(int type, int userId, String packageName, int mode,
+ String tag, @Nullable String prefix) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
if (settingsState == null) {
@@ -2656,7 +2723,8 @@
boolean someSettingChanged = false;
Setting setting = settingsState.getSettingLocked(name);
if (packageName.equals(setting.getPackageName())) {
- if (tag != null && !tag.equals(setting.getTag())) {
+ if ((tag != null && !tag.equals(setting.getTag()))
+ || (prefix != null && !setting.getName().startsWith(prefix))) {
continue;
}
if (settingsState.resetSettingLocked(name)) {
@@ -2676,6 +2744,9 @@
Setting setting = settingsState.getSettingLocked(name);
if (!SettingsState.isSystemPackage(getContext(),
setting.getPackageName())) {
+ if (prefix != null && !setting.getName().startsWith(prefix)) {
+ continue;
+ }
if (settingsState.resetSettingLocked(name)) {
someSettingChanged = true;
notifyForSettingsChange(key, name);
@@ -2693,6 +2764,9 @@
Setting setting = settingsState.getSettingLocked(name);
if (!SettingsState.isSystemPackage(getContext(),
setting.getPackageName())) {
+ if (prefix != null && !setting.getName().startsWith(prefix)) {
+ continue;
+ }
if (setting.isDefaultFromSystem()) {
if (settingsState.resetSettingLocked(name)) {
someSettingChanged = true;
@@ -2713,6 +2787,9 @@
for (String name : settingsState.getSettingNamesLocked()) {
Setting setting = settingsState.getSettingLocked(name);
boolean someSettingChanged = false;
+ if (prefix != null && !setting.getName().startsWith(prefix)) {
+ continue;
+ }
if (setting.isDefaultFromSystem()) {
if (settingsState.resetSettingLocked(name)) {
someSettingChanged = true;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 83e8369..e564711 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -130,7 +130,7 @@
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.MANAGE_AUTO_FILL" />
- <uses-permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS" />
+ <uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME" />
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 555f443..9245c30 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -31,7 +31,7 @@
<!-- Max Height of the sliding KeyguardSecurityContainer
(includes 2x keyguard_security_view_top_margin) -->
- <dimen name="keyguard_security_max_height">450dp</dimen>
+ <dimen name="keyguard_security_max_height">455dp</dimen>
<!-- Margin around the various security views -->
<dimen name="keyguard_security_view_top_margin">8dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 5c259d5..1e91ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -32,6 +32,7 @@
import android.view.WindowManager;
import android.widget.FrameLayout;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
@@ -72,7 +73,8 @@
private Point mDisplaySize;
// Bubbles get added to the status bar view
- private StatusBarWindowController mStatusBarWindowController;
+ @VisibleForTesting
+ protected StatusBarWindowController mStatusBarWindowController;
// Used for determining view rect for touch interaction
private Rect mTempRect = new Rect();
@@ -302,6 +304,11 @@
return mTempRect;
}
+ @VisibleForTesting
+ public BubbleStackView getStackView() {
+ return mStackView;
+ }
+
// TODO: factor in PIP location / maybe last place user had it
/**
* Gets an appropriate starting point to position the bubble stack.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 986a86d..cb6e300 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -84,7 +84,7 @@
}
@VisibleForTesting
- StatusBarWindowController(Context context, WindowManager windowManager,
+ public StatusBarWindowController(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters) {
mContext = context;
mWindowManager = windowManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
new file mode 100644
index 0000000..16ef63f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.IActivityManager;
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class BubbleControllerTest extends SysuiTestCase {
+
+ @Mock
+ private WindowManager mWindowManager;
+ @Mock
+ private IActivityManager mActivityManager;
+ @Mock
+ private DozeParameters mDozeParameters;
+ @Mock
+ private FrameLayout mStatusBarView;
+
+ private TestableBubbleController mBubbleController;
+ private StatusBarWindowController mStatusBarWindowController;
+
+ private NotificationTestHelper mNotificationTestHelper;
+ private ExpandableNotificationRow mRow;
+ private ExpandableNotificationRow mRow2;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ // Bubbles get added to status bar window view
+ mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+ mActivityManager, mDozeParameters);
+ mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
+
+ // Need notifications for bubbles
+ mNotificationTestHelper = new NotificationTestHelper(mContext);
+ mRow = mNotificationTestHelper.createBubble();
+ mRow2 = mNotificationTestHelper.createBubble();
+
+ mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController);
+ }
+
+ @Test
+ public void testIsBubble() {
+ assertTrue(mRow.getEntry().isBubble());
+ }
+
+ @Test
+ public void testAddBubble() {
+ mBubbleController.addBubble(mRow.getEntry());
+ assertTrue(mBubbleController.hasBubbles());
+ }
+
+ @Test
+ public void testHasBubbles() {
+ assertFalse(mBubbleController.hasBubbles());
+ mBubbleController.addBubble(mRow.getEntry());
+ assertTrue(mBubbleController.hasBubbles());
+ }
+
+ @Test
+ public void testRemoveBubble() {
+ mBubbleController.addBubble(mRow.getEntry());
+ assertTrue(mBubbleController.hasBubbles());
+
+ mBubbleController.removeBubble(mRow.getEntry().key);
+ assertFalse(mStatusBarWindowController.getBubblesShowing());
+ }
+
+ @Test
+ public void testDismissStack() {
+ mBubbleController.addBubble(mRow.getEntry());
+ mBubbleController.addBubble(mRow2.getEntry());
+ assertTrue(mBubbleController.hasBubbles());
+
+ mBubbleController.dismissStack();
+ assertFalse(mStatusBarWindowController.getBubblesShowing());
+ }
+
+ @Test
+ public void testIsStackExpanded() {
+ assertFalse(mBubbleController.isStackExpanded());
+ mBubbleController.addBubble(mRow.getEntry());
+
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.animateExpansion(true /* expanded */);
+ assertTrue(mBubbleController.isStackExpanded());
+
+ stackView.animateExpansion(false /* expanded */);
+ assertFalse(mBubbleController.isStackExpanded());
+ }
+
+ @Test
+ public void testCollapseStack() {
+ mBubbleController.addBubble(mRow.getEntry());
+ mBubbleController.addBubble(mRow2.getEntry());
+
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.animateExpansion(true /* expanded */);
+ assertTrue(mBubbleController.isStackExpanded());
+
+ mBubbleController.collapseStack();
+ assertFalse(mBubbleController.isStackExpanded());
+ }
+
+ static class TestableBubbleController extends BubbleController {
+
+ TestableBubbleController(Context context,
+ StatusBarWindowController statusBarWindowController) {
+ super(context);
+ mStatusBarWindowController = statusBarWindowController;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index 9bed59b..fb5e875 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -33,9 +33,9 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationInflaterTest;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -86,7 +86,8 @@
* @throws Exception
*/
public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception {
- return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */);
+ return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */,
+ false /* isBubble */);
}
/**
@@ -97,7 +98,8 @@
* @throws Exception
*/
public ExpandableNotificationRow createRow(Notification notification) throws Exception {
- return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */);
+ return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */,
+ false /* isBubble */);
}
/**
@@ -110,7 +112,8 @@
*/
public ExpandableNotificationRow createRow(@InflationFlag int extraInflationFlags)
throws Exception {
- return generateRow(createNotification(), PKG, UID, extraInflationFlags);
+ return generateRow(createNotification(), PKG, UID, extraInflationFlags,
+ false /* isBubble */);
}
/**
@@ -131,12 +134,20 @@
return createGroup(2);
}
+ /**
+ * Retursn an {@link ExpandableNotificationRow} that should be a bubble.
+ */
+ public ExpandableNotificationRow createBubble() throws Exception {
+ return createRow(PKG, UID, false /* isGroupSummary */, null /* groupKey */,
+ true /* isBubble */);
+ }
+
private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception {
- return createRow(PKG, UID, true /* isGroupSummary */, groupkey);
+ return createRow(PKG, UID, true /* isGroupSummary */, groupkey, false);
}
private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception {
- return createRow(PKG, UID, false /* isGroupSummary */, groupkey);
+ return createRow(PKG, UID, false /* isGroupSummary */, groupkey, false);
}
/**
@@ -146,6 +157,7 @@
* @param uid uid used for creating a {@link StatusBarNotification}
* @param isGroupSummary whether the notification row is a group summary
* @param groupKey the group key for the notification group used across notifications
+ * @param isBubble
* @return a row with that's either a standalone notification or a group notification if the
* groupKey is non-null
* @throws Exception
@@ -154,10 +166,10 @@
String pkg,
int uid,
boolean isGroupSummary,
- @Nullable String groupKey)
+ @Nullable String groupKey, boolean isBubble)
throws Exception {
Notification notif = createNotification(isGroupSummary, groupKey);
- return generateRow(notif, pkg, uid, 0 /* inflationFlags */);
+ return generateRow(notif, pkg, uid, 0 /* inflationFlags */, isBubble);
}
/**
@@ -202,7 +214,7 @@
Notification notification,
String pkg,
int uid,
- @InflationFlag int extraInflationFlags)
+ @InflationFlag int extraInflationFlags, boolean isBubble)
throws Exception {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
mContext.LAYOUT_INFLATER_SERVICE);
@@ -232,6 +244,7 @@
entry.channel = new NotificationChannel(
notification.getChannelId(), notification.getChannelId(), IMPORTANCE_DEFAULT);
entry.channel.setBlockableSystem(true);
+ entry.setIsBubble(isBubble);
row.setEntry(entry);
row.getNotificationInflater().addInflationFlags(extraInflationFlags);
NotificationInflaterTest.runThenWaitForInflation(
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
similarity index 65%
copy from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
copy to packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
index 6a1ce41..c5ed415 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+ <string name="experiment_navigationbar_overlay" msgid="3475628315769912732">"Default Navigation Bar Experiment (48dp)"</string>
</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
deleted file mode 100644
index 21a0003..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment met dun navigasiebalk"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
deleted file mode 100644
index 6a7d644..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ቀጭን የአሰሳ አሞሌ ሙከራ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
deleted file mode 100644
index 2cebf40..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"تجربة شريط التنقُّل النحيف"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
deleted file mode 100644
index 266c051..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Sabit Naviqasiya Paneli Təcrübəsi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index dc57a3f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment sa tankom trakom za navigaciju"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
deleted file mode 100644
index 8b53bcd..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Эксперымент з тонкай панэллю навігацыі"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
deleted file mode 100644
index 4bf000e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент с тънка лента за навигация"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
deleted file mode 100644
index 9814209..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment s tankom trakom za navigaciju"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
deleted file mode 100644
index 4a9b598..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment amb barra de navegació fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
deleted file mode 100644
index d923a3c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzký navigační panel (experiment)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
deleted file mode 100644
index 12bb2f2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Test med smal navigationslinje"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
deleted file mode 100644
index 960a7d9..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment mit schmaler Navigationsleiste"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
deleted file mode 100644
index 119b7e6..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Πείραμα λεπτής γραμμής πλοήγησης"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
deleted file mode 100644
index 5ebf403..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
index 79884ce..40d9fbc 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Slim Navigation Bar Experiment"</string>
+ <string name="experiment_navigationbar_overlay" msgid="9207872199884142345">"Slim Navigation Bar Experiment (24dp)"</string>
</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
deleted file mode 100644
index 00b0444..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegación delgada"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
deleted file mode 100644
index 58bdaa2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra navegación delgada"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
deleted file mode 100644
index 4c5023c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Kitsa navigeerimisriba katse"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
deleted file mode 100644
index fc16eeb..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Nabigazio-barra finaren esperimentua"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
deleted file mode 100644
index e4246d7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"آزمایش نوار پیمایش باریک"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
deleted file mode 100644
index 9385a47..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ohuen navigointipalkin kokeilu"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
deleted file mode 100644
index d22848b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Expérience de barre de navigation mince"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
deleted file mode 100644
index cfa1db2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Test relatif à la barre de navigation fine"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
deleted file mode 100644
index d2194ce..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegación estreita"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
deleted file mode 100644
index d51cee3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"स्लिम नेविगेशन बार प्रयोग"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
deleted file mode 100644
index 410c58e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment s tankom navigacijskom trakom"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
deleted file mode 100644
index d7eafed..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Kísérleti keskeny navigációs sáv"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
deleted file mode 100644
index b0200ca..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Նավարկման նեղ գոտու փորձարկում"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
deleted file mode 100644
index 3e0bded..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimen Menu Navigasi Ramping"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
deleted file mode 100644
index 03ccaf3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Tilraun með þunna yfirlitsstiku"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
deleted file mode 100644
index f7c5d253..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Esperimento Barra di navigazione sottile"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
deleted file mode 100644
index 0d0ec2c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ניסוי של סרגל ניווט דק"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
deleted file mode 100644
index a3d6874..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"スリム ナビゲーション バー テスト"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
deleted file mode 100644
index ffddf3b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ნავიგაციის მჭიდრო ზოლის ექსპერიმენტი"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
deleted file mode 100644
index f34ac08..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Жіңішке навигация жолағы (эксперимент)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
deleted file mode 100644
index 114a782..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ការពិសោធនៃរបាររុករកស្ដើង"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
deleted file mode 100644
index fca02c3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"슬림한 탐색 메뉴 실험"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
deleted file mode 100644
index 449de4f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Чакан чабыттоо тилкесин сыноо"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
deleted file mode 100644
index 6ec48ca..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ການທົດລອງແຖບການນຳທາງແບບບາງ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
deleted file mode 100644
index 1df54aa..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Plonos naršymo juostos eksperimentas"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
deleted file mode 100644
index 5c6c565..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Plānas navigācijas joslas eksperiments"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
deleted file mode 100644
index 3517813..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент со тенка лента за навигација"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
deleted file mode 100644
index a2282c4..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Нимгэн навигацийн самбарын туршилт"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
deleted file mode 100644
index c714370..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"स्लिम नॅव्हिगेशन बार प्रयोग"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
deleted file mode 100644
index 68f831e..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Percubaan Bar Navigasi Langsing"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
deleted file mode 100644
index 84db279..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ပါးလွှာသော လမ်းညွှန်ဘား စမ်းသပ်မှု"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
deleted file mode 100644
index e1ff863..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperiment med tynn navigasjonsrad"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
deleted file mode 100644
index 01190bc..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment voor smalle navigatiebalk"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
deleted file mode 100644
index 1742aad..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperyment z wąskim paskiem nawigacyjnym"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 22194b7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
deleted file mode 100644
index f6c0309..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiência de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
deleted file mode 100644
index 22194b7..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimento de barra de navegação fina"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
deleted file mode 100644
index e1655f2..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experiment cu bară de navigare subțire"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
deleted file mode 100644
index cac66dc..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Узкая панель навигации (эксперимент)"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
deleted file mode 100644
index beab7b6..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Preizkus z vitko vrstico za krmarjenje"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
deleted file mode 100644
index b7a28d5..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimenti i shiritit të hollë të navigimit"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
deleted file mode 100644
index 048f649..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент са танком траком за навигацију"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
deleted file mode 100644
index b94438f..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Experimentellt tunt navigeringsfält"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
deleted file mode 100644
index 3a5a73c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Jaribio la Sehemu ya Viungo Muhimu Inayoweza Kupunguzwa"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
deleted file mode 100644
index 945297b..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"การทดสอบแถบนำทางแบบบาง"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
deleted file mode 100644
index 0c8087c..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Eksperimentong Slim na Navigation Bar"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
deleted file mode 100644
index a3ca754..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"İnce Gezinme Çubuğu Denemesi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
deleted file mode 100644
index 656c4a9..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Експеримент із тонкою панеллю навігації"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
deleted file mode 100644
index bcd6bc3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"سلم نیویگیشن بار کا تجربہ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
deleted file mode 100644
index 0d40981..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ingichka navigatsiya paneli tajribasi"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
deleted file mode 100644
index dad56b4..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Thử nghiệm thanh điều hướng mỏng"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
deleted file mode 100644
index b2602e0..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"精简导航栏实验"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
deleted file mode 100644
index d5259d3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"精簡導覽列實驗"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 6586a57..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"細長導覽列實驗"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
deleted file mode 100644
index 12d04d3..0000000
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Ukuhlolwa kwebha yokuzula encane"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
similarity index 65%
rename from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
rename to packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
index 6a1ce41..ca8c4fa 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+ <string name="experiment_navigationbar_overlay" msgid="2616250866244714325">"Slim Navigation Bar Experiment (32dp)"</string>
</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
similarity index 65%
copy from packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
copy to packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
index 6a1ce41..9209c2b 100644
--- a/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values-en-rXC/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Úzky navigačný panel (experiment)"</string>
+ <string name="experiment_navigationbar_overlay" msgid="6415947279345789008">"Slim Navigation Bar Experiment (40dp)"</string>
</resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3e07d12..89220d5 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6604,6 +6604,11 @@
// OS: Q
NOTIFICATION_DIRECT_REPLY_ACTION = 1590;
+ // OPEN: Settings > Developer options > Disable > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/Android.bp b/services/Android.bp
index 3390438..58a0997 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -21,9 +21,9 @@
"services.autofill",
"services.backup",
"services.companion",
+ "services.contentcapture",
"services.coverage",
"services.devicepolicy",
- "services.intelligence",
"services.midi",
"services.net",
"services.print",
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 944ee33..e8887e7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -74,7 +74,6 @@
import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -100,6 +99,7 @@
private static final Object sLock = AutofillManagerService.class;
+ private static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
/**
* IME supports Smart Suggestions.
@@ -155,7 +155,7 @@
private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
private final LocalService mLocalService = new LocalService();
- final IntelligenceManagerInternal mIntelligenceManagerInternal;
+ private final ActivityManagerInternal mAm;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -184,7 +184,7 @@
public AutofillManagerService(Context context) {
super(context, UserManager.DISALLOW_AUTOFILL);
mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
- mIntelligenceManagerInternal = LocalServices.getService(IntelligenceManagerInternal.class);
+ mAm = LocalServices.getService(ActivityManagerInternal.class);
setLogLevelFromSettings();
setMaxPartitionsFromSettings();
@@ -288,6 +288,11 @@
return mSupportedSmartSuggestionModes;
}
+ // Called by AutofillManagerServiceImpl, doesn't need to check permission
+ boolean isInstantServiceAllowed() {
+ return mAllowInstantService;
+ }
+
// Called by Shell command.
void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
Slog.i(TAG, "destroySessions() for userId " + userId);
@@ -502,6 +507,39 @@
sFullScreenMode = mode;
}
+ // Called by Shell command.
+ void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName,
+ int durationMs) {
+ Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName
+ + " for " + durationMs + "ms");
+ enforceCallingPermissionForManagement();
+
+ Preconditions.checkNotNull(serviceName);
+ if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) {
+ throw new IllegalArgumentException("Max duration is "
+ + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")");
+ }
+
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.setTemporaryServiceLocked(serviceName,
+ durationMs);
+ }
+ }
+ }
+
+ // Called by Shell command
+ void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) {
+ enforceCallingPermissionForManagement();
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.resetTemporaryServiceLocked();
+ }
+ }
+ }
+
private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
com.android.server.autofill.Helper.sDebug = debug;
android.view.autofill.Helper.sDebug = debug;
@@ -877,14 +915,9 @@
throw new IllegalArgumentException(packageName + " is not a valid package", e);
}
- // TODO(b/113281366): rather than always call AM here, call it on demand on
- // getPreviousSessionsLocked()? That way we save space / time here, and don't set
- // a callback on AM unnecessarily (see TODO below :-)
- final ActivityManagerInternal am = LocalServices
- .getService(ActivityManagerInternal.class);
// TODO(b/113281366): add a callback method on AM to be notified when a task is finished
// so we can clean up sessions kept alive
- final int taskId = am.getTaskIdForActivity(activityToken, false);
+ final int taskId = mAm.getTaskIdForActivity(activityToken, false);
final int sessionId;
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3945c23..5a0d12c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -73,8 +73,11 @@
import com.android.server.LocalServices;
import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.AutofillManagerService.SmartSuggestionMode;
+import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractPerUserSystemService;
+import com.android.server.infra.AbstractRemoteService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.io.PrintWriter;
@@ -152,6 +155,19 @@
/** When was {@link PruneTask} last executed? */
private long mLastPrune = 0;
+ /**
+ * Object used to set the name of the augmented autofill service.
+ */
+ @NonNull
+ final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver;
+
+ /**
+ * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
+
AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState, boolean disabled) {
@@ -164,6 +180,12 @@
mUi = ui;
mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
mAutofillCompatState = autofillCompatState;
+
+ mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(),
+ userId, lock, com.android.internal.R.string.config_defaultAugmentedAutofillService);
+ mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
+ () -> updateRemoteAugmentedAutofillService());
+
updateLocked(disabled);
}
@@ -851,6 +873,12 @@
}
pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
.getString(R.string.config_defaultAutofillService));
+ pw.print(prefix); pw.print("mAugmentedAutofillNamer: ");
+ mAugmentedAutofillResolver.dumpShortLocked(pw); pw.println();
+ if (mRemoteAugmentedAutofillService != null) {
+ pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
+ mRemoteAugmentedAutofillService.dump(prefix2, pw);
+ }
pw.print(prefix); pw.print("Field classification enabled: ");
pw.println(isFieldClassificationEnabledLocked());
pw.print(prefix); pw.print("Compat pkgs: ");
@@ -992,6 +1020,52 @@
return null;
}
+ @GuardedBy("mLock")
+ @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
+ if (mRemoteAugmentedAutofillService == null) {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set");
+ }
+ return null;
+ }
+ final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
+ getContext(), serviceName, mUserId,
+ mAugmentedAutofillResolver.isTemporaryLocked());
+ if (componentName == null) return null;
+ if (sVerbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
+ }
+
+ mRemoteAugmentedAutofillService = new RemoteAugmentedAutofillService(getContext(),
+ componentName, mUserId, new RemoteAugmentedAutofillServiceCallbacks() {
+ @Override
+ public void onServiceDied(
+ AbstractRemoteService<? extends AbstractRemoteService<?>> service) {
+ // TODO(b/111330312): properly implement
+ Slog.w(TAG, "remote augmented autofill service died");
+ }
+ }, mMaster.isInstantServiceAllowed(), mMaster.verbose);
+ }
+
+ return mRemoteAugmentedAutofillService;
+ }
+
+ /**
+ * Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
+ */
+ private void updateRemoteAugmentedAutofillService() {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
+ if (mRemoteAugmentedAutofillService != null) {
+ mRemoteAugmentedAutofillService.destroy();
+ mRemoteAugmentedAutofillService = null;
+ }
+ }
+ }
+
private void sendStateToClients(boolean resetClient) {
final RemoteCallbackList<IAutoFillManagerClient> clients;
final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 522280e..35c5102 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -104,6 +104,11 @@
pw.println(" set bind-instant-service-allowed [true | false]");
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
+ pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
+ pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
+ pw.println(" To reset, call with just the USER_ID argument.");
+ pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
pw.println("");
@@ -151,6 +156,8 @@
return setFullScreenMode(pw);
case "bind-instant-service-allowed":
return setBindInstantService(pw);
+ case "temporary-augmented-service":
+ return setTemporaryAugmentedService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -293,6 +300,20 @@
}
}
+ private int setTemporaryAugmentedService(PrintWriter pw) {
+ final int userId = getNextIntArgRequired();
+ final String serviceName = getNextArg();
+ if (serviceName == null) {
+ mService.resetTemporaryAugmentedAutofillService(userId);
+ return 0;
+ }
+ final int duration = getNextIntArgRequired();
+ mService.setTemporaryAugmentedAutofillService(userId, serviceName, duration);
+ pw.println("AugmentedAutofillService temporarily set to " + serviceName + " for "
+ + duration + "ms");
+ return 0;
+ }
+
private int requestDestroy(PrintWriter pw) {
if (!isNextArgSessions(pw)) {
return -1;
@@ -371,4 +392,8 @@
}
return UserHandle.USER_ALL;
}
+
+ private int getNextIntArgRequired() {
+ return Integer.parseInt(getNextArgRequired());
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
new file mode 100644
index 0000000..222888c
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService;
+import android.service.autofill.augmented.IAugmentedAutofillService;
+import android.service.autofill.augmented.IFillCallback;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAutoFillManagerClient;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.server.infra.AbstractSinglePendingRequestRemoteService;
+
+final class RemoteAugmentedAutofillService
+ extends AbstractSinglePendingRequestRemoteService<RemoteAugmentedAutofillService> {
+
+ private static final String TAG = RemoteAugmentedAutofillService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final RemoteAugmentedAutofillServiceCallbacks mCallbacks;
+ private IAugmentedAutofillService mService;
+
+ RemoteAugmentedAutofillService(Context context, ComponentName serviceName,
+ int userId, RemoteAugmentedAutofillServiceCallbacks callbacks,
+ boolean bindInstantServiceAllowed, boolean verbose) {
+ super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
+ bindInstantServiceAllowed, verbose);
+ mCallbacks = callbacks;
+ }
+
+ @Nullable
+ public static ComponentName getComponentName(@NonNull Context context,
+ @NonNull String componentName, @UserIdInt int userId, boolean isTemporary) {
+ int flags = PackageManager.GET_META_DATA;
+ if (!isTemporary) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
+ final ComponentName serviceComponent;
+ ServiceInfo serviceInfo = null;
+ try {
+ serviceComponent = ComponentName.unflattenFromString(componentName);
+ serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags,
+ userId);
+ if (serviceInfo == null) {
+ Slog.e(TAG, "Bad service name for flags " + flags + ": " + componentName);
+ return null;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
+ return null;
+ }
+ return serviceComponent;
+ }
+
+ @Override // from AbstractRemoteService
+ protected IInterface getServiceInterface(IBinder service) {
+ mService = IAugmentedAutofillService.Stub.asInterface(service);
+ return mService;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getTimeoutIdleBindMillis() {
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getRemoteRequestMillis() {
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link Session} to request augmented autofill.
+ */
+ public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client,
+ int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingAutofillRequest(this, sessionId, client, taskId,
+ activityComponent, focusedId, focusedValue));
+ }
+
+ /**
+ * Called by {@link Session} when it's time to destroy all augmented autofill requests.
+ */
+ public void onDestroyAutofillWindowsRequest(int sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteAugmentedAutofillService> {
+ protected final int mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteAugmentedAutofillService service, int sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+ }
+
+ private static final class PendingAutofillRequest extends MyPendingRequest {
+ private final @NonNull AutofillId mFocusedId;
+ private final @Nullable AutofillValue mFocusedValue;
+ private final @NonNull IAutoFillManagerClient mClient;
+ private final @NonNull ComponentName mActivityComponent;
+ private final int mTaskId;
+ private final long mRequestTime = SystemClock.elapsedRealtime();
+ private final @NonNull IFillCallback mCallback;
+
+ protected PendingAutofillRequest(@NonNull RemoteAugmentedAutofillService service,
+ int sessionId, @NonNull IAutoFillManagerClient client, int taskId,
+ @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ super(service, sessionId);
+ mClient = client;
+ mTaskId = taskId;
+ mActivityComponent = activityComponent;
+ mFocusedId = focusedId;
+ mFocusedValue = focusedValue;
+ mCallback = new IFillCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ if (!finish()) return;
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ }
+ };
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ final IResultReceiver receiver = new IResultReceiver.Stub() {
+
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ final IBinder realClient = resultData
+ .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
+ remoteService.mService.onFillRequest(mSessionId, realClient, mTaskId,
+ mActivityComponent, mFocusedId, mFocusedValue, mRequestTime, mCallback);
+ }
+ };
+
+ // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
+ // cache IAugmentedAutofillManagerClient reference, etc...
+ try {
+ mClient.getAugmentedAutofillClient(receiver);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "exception handling getAugmentedAutofillClient() for "
+ + mSessionId + ": " + e);
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ Slog.wtf(TAG, "timed out: " + this);
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ finish();
+ }
+
+ }
+
+ private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
+
+ protected PendingDestroyAutofillWindowsRequest(
+ @NonNull RemoteAugmentedAutofillService service, @NonNull int sessionId) {
+ super(service, sessionId);
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ try {
+ remoteService.mService.onDestroyFillWindowRequest(mSessionId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling onDestroyAutofillWindowsRequest() for "
+ + mSessionId + ": " + e);
+ } finally {
+ // Service is not calling back, so we finish right away.
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ // Should not happen because we called finish() on run(), although currently it might
+ // be called if the service is destroyed while showing it.
+ Slog.e(TAG, "timed out: " + this);
+ }
+ }
+
+ public interface RemoteAugmentedAutofillServiceCallbacks extends VultureCallback {
+ // NOTE: so far we don't need to notify the callback implementation (an inner class on
+ // AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this
+ // callback interface is empty.
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index fb64cb2..d76a5df 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,8 +99,6 @@
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -248,9 +246,18 @@
@GuardedBy("mLock")
private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
+ /**
+ * Destroys the augmented Autofill UI.
+ */
+ // TODO(b/111330312): this runnable is called when the Autofill session is destroyed, the
+ // main reason being the cases where user tap HOME.
+ // Right now it's completely destroying the UI, but we need to decide whether / how to
+ // properly recover it later (for example, if the user switches back to the activity,
+ // should it be restored? Right not it kind of is, because Autofill's Session trigger a
+ // new FillRequest, which in turn triggers the Augmented Autofill request again)
@GuardedBy("mLock")
@Nullable
- private AugmentedAutofillCallback mAugmentedAutofillCallback;
+ private Runnable mAugmentedAutofillDestroyer;
/**
* Receiver of assist data from the app's {@link Activity}.
@@ -2516,8 +2523,8 @@
// The default autofill service cannot fullfill the request, let's check if the intelligence
// service can.
- mAugmentedAutofillCallback = triggerAugmentedAutofillLocked();
- if (mAugmentedAutofillCallback == null) {
+ mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked();
+ if (mAugmentedAutofillDestroyer == null) {
if (sVerbose) {
Slog.v(TAG, "canceling session " + id + " when server returned null and there is no"
+ " AugmentedAutofill for user");
@@ -2539,21 +2546,22 @@
/**
* Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
*
- * @return callback to the Augmented Autofill service, or {@code null} if not supported.
+ * @return callback to destroy the autofill UI, or {@code null} if not supported.
*/
// TODO(b/111330312): might need to call it in other places, like when the service returns a
// non-null response but without datasets (for example, just SaveInfo)
@GuardedBy("mLock")
- private AugmentedAutofillCallback triggerAugmentedAutofillLocked() {
+ private Runnable triggerAugmentedAutofillLocked() {
// Check if Smart Suggestions is supported...
final @SmartSuggestionMode int supportedModes = mService
.getSupportedSmartSuggestionModesLocked();
if (supportedModes == 0) return null;
// ...then if the service is set for the user
- final IntelligenceManagerInternal intelligenceManagerInternal = mService
- .getMaster().mIntelligenceManagerInternal;
- if (intelligenceManagerInternal == null) return null;
+
+ final RemoteAugmentedAutofillService remoteService = mService
+ .getRemoteAugmentedAutofillServiceLocked();
+ if (remoteService == null) return null;
// Define which mode will be used
final int mode;
@@ -2584,8 +2592,13 @@
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
// furgher AFM -> AFMS calls.
// TODO(b/119638958): add CTS tests
- return intelligenceManagerInternal.requestAutofill(mService.getUserId(), mClient,
- mActivityToken, this.id, mCurrentViewId, currentValue);
+ remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, mCurrentViewId,
+ currentValue);
+
+ if (mAugmentedAutofillDestroyer == null) {
+ mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(id);
+ }
+ return mAugmentedAutofillDestroyer;
}
@GuardedBy("mLock")
@@ -2866,8 +2879,8 @@
pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println(
mSaveOnAllViewsInvisible);
pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
- if (mAugmentedAutofillCallback != null) {
- pw.print(prefix); pw.println("has AugmentedAutofillCallback");
+ if (mAugmentedAutofillDestroyer != null) {
+ pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
}
mRemoteFillService.dump(prefix, pw);
}
@@ -3045,8 +3058,9 @@
@GuardedBy("mLock")
void destroyAugmentedAutofillWindowsLocked() {
- if (mAugmentedAutofillCallback != null) {
- mAugmentedAutofillCallback.destroy();
+ if (mAugmentedAutofillDestroyer != null) {
+ mAugmentedAutofillDestroyer.run();
+ mAugmentedAutofillDestroyer = null;
}
}
diff --git a/services/intelligence/Android.bp b/services/contentcapture/Android.bp
similarity index 69%
rename from services/intelligence/Android.bp
rename to services/contentcapture/Android.bp
index 2df1235..57e859e 100644
--- a/services/intelligence/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,5 @@
java_library_static {
- name: "services.intelligence",
+ name: "services.contentcapture",
srcs: ["java/**/*.java"],
libs: ["services.core"],
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
similarity index 68%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index a760cbd..872fe42 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static android.Manifest.permission.MANAGE_SMART_SUGGESTIONS;
+import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import android.annotation.NonNull;
@@ -32,13 +32,9 @@
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
-import android.service.intelligence.InteractionSessionId;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.IIntelligenceManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -58,11 +54,10 @@
* <p>The data collected by this service can be analyzed and combined with other sources to provide
* contextual data in other areas of the system such as Autofill.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceManagerService extends
- AbstractMasterSystemService<IntelligenceManagerService, IntelligencePerUserService> {
+public final class ContentCaptureManagerService extends
+ AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
- private static final String TAG = "IntelligenceManagerService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
@@ -73,32 +68,32 @@
private final LocalService mLocalService = new LocalService();
- public IntelligenceManagerService(Context context) {
- super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
+ public ContentCaptureManagerService(Context context) {
+ super(context, UserManager.DISALLOW_CONTENT_CAPTURE);
}
@Override // from AbstractMasterSystemService
- protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
+ protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
- return new IntelligencePerUserService(this, mLock, resolvedUserId);
+ return new ContentCapturePerUserService(this, mLock, resolvedUserId);
}
@Override // from SystemService
public void onStart() {
publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE,
- new IntelligenceManagerServiceStub());
- publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+ new ContentCaptureManagerServiceStub());
+ publishLocalService(ContentCaptureManagerInternal.class, mLocalService);
}
@Override // from AbstractMasterSystemService
- protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+ protected void onServiceRemoved(@NonNull ContentCapturePerUserService service,
@UserIdInt int userId) {
service.destroyLocked();
}
@Override // from AbstractMasterSystemService
protected void enforceCallingPermissionForManagement() {
- getContext().enforceCallingPermission(MANAGE_SMART_SUGGESTIONS, TAG);
+ getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG);
}
@Override // from AbstractMasterSystemService
@@ -113,7 +108,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.destroySessionsLocked();
}
@@ -139,7 +134,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.listSessionsLocked(sessions);
}
@@ -165,11 +160,11 @@
return mAm;
}
- final class IntelligenceManagerServiceStub extends IIntelligenceManager.Stub {
+ final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@Override
public void startSession(@UserIdInt int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+ @NonNull ComponentName componentName, @NonNull String sessionId,
int flags, @NonNull IResultReceiver result) {
Preconditions.checkNotNull(activityToken);
Preconditions.checkNotNull(componentName);
@@ -183,31 +178,31 @@
final int displayId = 0;
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, componentName, taskId, displayId,
sessionId, flags, mAllowInstantService, result);
}
}
@Override
- public void sendEvents(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void sendEvents(@UserIdInt int userId, @NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
Preconditions.checkNotNull(events);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.sendEventsLocked(sessionId, events);
}
}
@Override
- public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void finishSession(@UserIdInt int userId, @NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.finishSessionLocked(sessionId, events);
}
}
@@ -225,19 +220,19 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
- new IntelligenceServiceShellCommand(IntelligenceManagerService.this).exec(
+ new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec(
this, in, out, err, args, callback, resultReceiver);
}
}
- private final class LocalService extends IntelligenceManagerInternal {
+ private final class LocalService extends ContentCaptureManagerInternal {
@Override
- public boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId) {
+ public boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
- return service.isIntelligenceServiceForUserLocked(uid);
+ return service.isContentCaptureServiceForUserLocked(uid);
}
}
return false;
@@ -247,27 +242,12 @@
public boolean sendActivityAssistData(@UserIdInt int userId, @NonNull IBinder activityToken,
@NonNull Bundle data) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
return service.sendActivityAssistDataLocked(activityToken, data);
}
}
return false;
}
-
- @Override
- public AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
- if (service != null) {
- return service.requestAutofill(client, activityToken, autofillSessionId,
- focusedId, focusedValue);
- }
- }
- return null;
- }
}
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
similarity index 89%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 0d92a97..2f78276 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static com.android.server.intelligence.IntelligenceManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
+import static com.android.server.contentcapture.ContentCaptureManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
import android.annotation.NonNull;
import android.os.Bundle;
@@ -30,14 +30,13 @@
import java.util.concurrent.TimeUnit;
/**
- * Shell Command implementation for {@link IntelligenceManagerService}.
+ * Shell Command implementation for {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceServiceShellCommand extends ShellCommand {
+public final class ContentCaptureManagerServiceShellCommand extends ShellCommand {
- private final IntelligenceManagerService mService;
+ private final ContentCaptureManagerService mService;
- public IntelligenceServiceShellCommand(@NonNull IntelligenceManagerService service) {
+ public ContentCaptureManagerServiceShellCommand(@NonNull ContentCaptureManagerService service) {
mService = service;
}
@@ -64,8 +63,7 @@
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
- // TODO(b/111276913): rename "intelligence" once SELinux rule changed
- pw.println("Intelligence Service (intelligence) commands:");
+ pw.println("ContentCapture Service (content_capture) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
@@ -106,7 +104,7 @@
case "bind-instant-service-allowed":
return setBindInstantService(pw);
case "temporary-service":
- return setTemporaryService();
+ return setTemporaryService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -137,7 +135,7 @@
}
}
- private int setTemporaryService() {
+ private int setTemporaryService(PrintWriter pw) {
final int userId = getNextIntArgRequired();
final String serviceName = getNextArg();
if (serviceName == null) {
@@ -146,6 +144,8 @@
}
final int duration = getNextIntArgRequired();
mService.setTemporaryService(userId, serviceName, duration);
+ pw.println("ContentCaptureService temporarily set to " + serviceName + " for "
+ + duration + "ms");
return 0;
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
similarity index 77%
rename from services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index e2b8d48..aa171f4 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -34,46 +34,40 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
- * Per-user instance of {@link IntelligenceManagerService}.
+ * Per-user instance of {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-final class IntelligencePerUserService
- extends AbstractPerUserSystemService<IntelligencePerUserService,
- IntelligenceManagerService> {
+final class ContentCapturePerUserService
+ extends
+ AbstractPerUserSystemService<ContentCapturePerUserService, ContentCaptureManagerService> {
- private static final String TAG = "IntelligencePerUserService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
@GuardedBy("mLock")
- private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+ private final ArrayMap<String, ContentCaptureSession> mSessions =
new ArrayMap<>();
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
- protected IntelligencePerUserService(
- IntelligenceManagerService master, Object lock, @UserIdInt int userId) {
+ protected ContentCapturePerUserService(
+ ContentCaptureManagerService master, Object lock, @UserIdInt int userId) {
super(master, new FrameworkResourcesServiceNameResolver(master.getContext(), userId, lock,
- com.android.internal.R.string.config_defaultSmartSuggestionsService), lock, userId);
+ com.android.internal.R.string.config_defaultContentCaptureService), lock, userId);
}
@Override // from PerUserSystemService
@@ -98,12 +92,12 @@
+ " " + serviceComponent.flattenToShortString());
return null;
}
- if (!Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE.equals(si.permission)) {
- Slog.w(TAG, "SmartSuggestionsService from '" + si.packageName
+ if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+ Slog.w(TAG, "ContentCaptureService from '" + si.packageName
+ "' does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
throw new SecurityException("Service does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
}
return si;
}
@@ -119,7 +113,7 @@
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
@NonNull ComponentName componentName, int taskId, int displayId,
- @NonNull InteractionSessionId sessionId, int flags, boolean bindInstantServiceAllowed,
+ @NonNull String sessionId, int flags, boolean bindInstantServiceAllowed,
@NonNull IResultReceiver resultReceiver) {
if (!isEnabledLocked()) {
sendToClient(resultReceiver, ContentCaptureManager.STATE_DISABLED);
@@ -163,7 +157,7 @@
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
- public void finishSessionLocked(@NonNull InteractionSessionId sessionId,
+ public void finishSessionLocked(@NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -180,7 +174,7 @@
// TODO(b/111276913): for now we're sending the events and the onDestroy() in 2 separate
// calls because it's not clear yet whether we'll change the manager to send events
// to the service directly (i.e., without passing through system server). Once we
- // decide, we might need to split IIntelligenceService.onSessionLifecycle() in 2
+ // decide, we might need to split IContentCaptureManager.onSessionLifecycle() in 2
// methods, one for start and another for finish (and passing the events to finish),
// otherwise the service might receive the 2 calls out of order.
session.sendEventsLocked(events);
@@ -193,9 +187,9 @@
}
// TODO(b/111276913): need to figure out why some events are sent before session is started;
- // probably because IntelligenceManager is not buffering them until it gets the session back
+ // probably because ContentCaptureManager is not buffering them until it gets the session back
@GuardedBy("mLock")
- public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+ public void sendEventsLocked(@NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -216,7 +210,7 @@
@GuardedBy("mLock")
public boolean sendActivityAssistDataLocked(@NonNull IBinder activityToken,
@NonNull Bundle data) {
- final InteractionSessionId id = getInteractionSessionId(activityToken);
+ final String id = getSessionId(activityToken);
if (id != null) {
final ContentCaptureSession session = mSessions.get(id);
final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
@@ -233,12 +227,12 @@
}
@GuardedBy("mLock")
- public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+ public void removeSessionLocked(@NonNull String sessionId) {
mSessions.remove(sessionId);
}
@GuardedBy("mLock")
- public boolean isIntelligenceServiceForUserLocked(int uid) {
+ public boolean isContentCaptureServiceForUserLocked(int uid) {
return uid == getServiceUidLocked();
}
@@ -283,24 +277,6 @@
}
}
- public AugmentedAutofillCallback requestAutofill(@NonNull IAutoFillManagerClient client,
- @NonNull IBinder activityToken, int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final ContentCaptureSession session = getSession(activityToken);
- if (session != null) {
- // TODO(b/111330312): log metrics
- if (mMaster.verbose) Slog.v(TAG, "requestAugmentedAutofill()");
- return session.requestAutofillLocked(client, autofillSessionId, focusedId,
- focusedValue);
- }
- if (mMaster.debug) {
- Slog.d(TAG, "requestAutofill(): no session for " + activityToken);
- }
- return null;
- }
- }
-
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -319,10 +295,10 @@
}
/**
- * Returns the InteractionSessionId associated with the given activity.
+ * Returns the session id associated with the given activity.
*/
@GuardedBy("mLock")
- private InteractionSessionId getInteractionSessionId(@NonNull IBinder activityToken) {
+ private String getSessionId(@NonNull IBinder activityToken) {
for (int i = 0; i < mSessions.size(); i++) {
ContentCaptureSession session = mSessions.valueAt(i);
if (session.isActivitySession(activityToken)) {
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
similarity index 63%
rename from services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
index 05b8201..2302b7d 100644
--- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
@@ -13,55 +13,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SmartSuggestionsService;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.InteractionSessionId;
+import android.service.contentcapture.SnapshotData;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
-import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
import java.io.PrintWriter;
import java.util.List;
-final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
+final class ContentCaptureSession implements ContentCaptureServiceCallbacks {
private static final String TAG = "ContentCaptureSession";
private final Object mLock;
final IBinder mActivityToken;
- private final IntelligencePerUserService mService;
- private final RemoteIntelligenceService mRemoteService;
+ private final ContentCapturePerUserService mService;
+ private final RemoteContentCaptureService mRemoteService;
private final InteractionContext mInterationContext;
- private final InteractionSessionId mId;
- private AugmentedAutofillCallback mAutofillCallback;
+ private final String mId;
ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
- @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
+ @NonNull IBinder activityToken, @NonNull ContentCapturePerUserService service,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
- int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
+ int taskId, int displayId, @NonNull String sessionId, int flags,
boolean bindInstantServiceAllowed, boolean verbose) {
mLock = lock;
mActivityToken = activityToken;
mService = service;
mId = Preconditions.checkNotNull(sessionId);
- mRemoteService = new RemoteIntelligenceService(context,
- SmartSuggestionsService.SERVICE_INTERFACE, serviceComponentName, userId, this,
+ mRemoteService = new RemoteContentCaptureService(context,
+ ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, userId, this,
bindInstantServiceAllowed, verbose);
mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
}
@@ -74,7 +68,7 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} that the service started.
+ * Notifies the {@link ContentCaptureService} that the service started.
*/
@GuardedBy("mLock")
public void notifySessionStartedLocked() {
@@ -82,14 +76,14 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} of a batch of events.
+ * Notifies the {@link ContentCaptureService} of a batch of events.
*/
public void sendEventsLocked(@NonNull List<ContentCaptureEvent> events) {
mRemoteService.onContentCaptureEventsRequest(mId, events);
}
/**
- * Notifies the {@link SmartSuggestionsService} of a snapshot of an activity.
+ * Notifies the {@link ContentCaptureService} of a snapshot of an activity.
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
@@ -97,24 +91,10 @@
}
/**
- * Requests the service to autofill the given field.
- */
- public AugmentedAutofillCallback requestAutofillLocked(@NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- mRemoteService.onRequestAutofillLocked(mId, client, autofillSessionId, focusedId,
- focusedValue);
- if (mAutofillCallback == null) {
- mAutofillCallback = () -> mRemoteService.onDestroyAutofillWindowsRequest(mId);
- }
- return mAutofillCallback;
- }
-
- /**
* Cleans up the session and removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -130,7 +110,7 @@
* Cleans up the session, but not removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -138,11 +118,6 @@
if (mService.isVerbose()) {
Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
}
- if (mAutofillCallback != null) {
- mAutofillCallback.destroy();
- mAutofillCallback = null;
- }
-
// TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
if (notifyRemoteService) {
mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
@@ -173,19 +148,18 @@
@GuardedBy("mLock")
public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("id: "); mId.dump(pw); pw.println();
+ pw.print(prefix); pw.print("id: "); pw.print(mId); pw.println();
pw.print(prefix); pw.print("context: "); mInterationContext.dump(pw); pw.println();
pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("has autofill callback: ");
- pw.println(mAutofillCallback != null);
}
String toShortString() {
- return mId.getValue() + ":" + mActivityToken;
+ return mId + ":" + mActivityToken;
}
@Override
public String toString() {
- return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+ return "ContentCaptureSession[id=" + mId + ", act=" + mActivityToken + "]";
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
new file mode 100644
index 0000000..6a111f2
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
+
+import java.util.List;
+
+final class RemoteContentCaptureService
+ extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService> {
+
+ private static final String TAG = RemoteContentCaptureService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final ContentCaptureServiceCallbacks mCallbacks;
+ private IContentCaptureService mService;
+
+ RemoteContentCaptureService(Context context, String serviceInterface,
+ ComponentName componentName, int userId,
+ ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+ boolean verbose) {
+ super(context, serviceInterface, componentName, userId, callbacks,
+ bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+ mCallbacks = callbacks;
+ }
+
+ @Override // from RemoteService
+ protected IInterface getServiceInterface(@NonNull IBinder service) {
+ mService = IContentCaptureService.Stub.asInterface(service);
+ return mService;
+ }
+
+ // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
+ @Override // from RemoteService
+ protected long getTimeoutIdleBindMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from RemoteService
+ protected long getRemoteRequestMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to generate a call to the
+ * {@link RemoteContentCaptureService} to indicate the session was created (when {@code context}
+ * is not {@code null} or destroyed (when {@code context} is {@code null}).
+ */
+ public void onSessionLifecycleRequest(@Nullable InteractionContext context,
+ @NonNull String sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+ */
+ public void onContentCaptureEventsRequest(@NonNull String sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send snapshot data to the service.
+ */
+ public void onActivitySnapshotRequest(@NonNull String sessionId,
+ @NonNull SnapshotData snapshotData) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteContentCaptureService> {
+ protected final String mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+
+ @Override // from PendingRequest
+ protected final void onTimeout(RemoteContentCaptureService remoteService) {
+ Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+ + mSessionId);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+ }
+
+ @Override // from PendingRequest
+ public final void run() {
+ final RemoteContentCaptureService remoteService = getService();
+ if (remoteService != null) {
+ try {
+ // We don't expect the service to call us back, so we finish right away.
+ myRun(remoteService);
+ // TODO(b/111330312): not true anymore!!
+ finish();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+ + mSessionId + ": " + e);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
+ }
+ }
+ }
+
+ protected abstract void myRun(@NonNull RemoteContentCaptureService service)
+ throws RemoteException;
+
+ }
+
+ private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+ private final InteractionContext mContext;
+
+ protected PendingSessionLifecycleRequest(@NonNull RemoteContentCaptureService service,
+ @Nullable InteractionContext context, @NonNull String sessionId) {
+ super(service, sessionId);
+ mContext = context;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+ }
+ }
+
+ private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+ private final List<ContentCaptureEvent> mEvents;
+
+ protected PendingOnContentCaptureEventsRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull List<ContentCaptureEvent> events) {
+ super(service, sessionId);
+ mEvents = events;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onContentCaptureEventsRequest(mSessionId,
+ new ContentCaptureEventsRequest(mEvents));
+ }
+ }
+
+ private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
+
+ private final SnapshotData mSnapshotData;
+
+ protected PendingOnActivitySnapshotRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull SnapshotData snapshotData) {
+ super(service, sessionId);
+ mSnapshotData = snapshotData;
+ }
+
+ @Override // from MyPendingRequest
+ protected void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
+ }
+ }
+
+ public interface ContentCaptureServiceCallbacks extends VultureCallback {
+ // To keep it simple, we use the same callback for all failures / timeouts.
+ void onFailureOrTimeout(boolean timedOut);
+ }
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 784d398..70b8339 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -15,14 +15,14 @@
"java/**/*.java",
":dumpstate_aidl",
":idmap2_aidl",
- ":netd_aidl",
- ":netd_metrics_aidl",
":installd_aidl",
":storaged_aidl",
":vold_aidl",
":mediaupdateservice_aidl",
"java/com/android/server/EventLogTags.logtags",
"java/com/android/server/am/EventLogTags.logtags",
+ ":netd_aidl",
+ ":netd_metrics_aidl",
],
libs: [
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index dbea529..4b092b2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2526,6 +2526,19 @@
}
}
+ /**
+ * Signal that checkpointing partitions should commit changes
+ */
+ @Override
+ public void commitChanges() throws RemoteException {
+ // Only the system process is permitted to commit checkpoints
+ if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ throw new SecurityException("no permission to commit checkpoint changes");
+ }
+
+ mVold.commitChanges();
+ }
+
@Override
public String getPassword() throws RemoteException {
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 271b37e..bcce052 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -67,6 +67,7 @@
import android.os.IUserManager;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -332,6 +333,14 @@
return;
}
}
+ // Inform checkpointing systems of success
+ try {
+ getStorageManager().commitChanges();
+ } catch (Exception e) {
+ PowerManager pm = (PowerManager)
+ mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+ pm.reboot("Checkpoint commit failed");
+ }
// We always walk through all the user lifecycle states to send
// consistent developer events. We step into RUNNING_LOCKED here,
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index add55ea..1882be2 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -813,6 +813,24 @@
}
}
+ @Override // Binder call
+ public void resetTimeout(byte[] token) {
+ checkInternalPermission();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mFingerprintService != null) {
+ mFingerprintService.resetTimeout(token);
+ }
+ if (mFaceService != null) {
+ mFaceService.resetTimeout(token);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 65537ad..258c325 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,7 +55,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -158,7 +158,7 @@
private final IUserManager mUm;
private final PackageManager mPm;
private final AppOpsManager mAppOps;
- private final IntelligenceManagerInternal mIm;
+ private final ContentCaptureManagerInternal mContentCaptureInternal;
private final IBinder mPermissionOwner;
private HostClipboardMonitor mHostClipboardMonitor = null;
private Thread mHostMonitorThread = null;
@@ -178,7 +178,7 @@
mPm = getContext().getPackageManager();
mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
- mIm = LocalServices.getService(IntelligenceManagerInternal.class);
+ mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
@@ -652,9 +652,10 @@
case AppOpsManager.OP_READ_CLIPBOARD:
// Clipboard can only be read by applications with focus..
boolean allowed = mWm.isUidFocused(callingUid);
- if (!allowed && mIm != null) {
+ if (!allowed && mContentCaptureInternal != null) {
// ...or the Intelligence Service
- allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
+ allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
+ userId);
}
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
new file mode 100644
index 0000000..726362a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * ContentCapture Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class ContentCaptureManagerInternal {
+
+ /**
+ * Checks whether the given {@code uid} owns the
+ * {@link android.service.contentcapture.ContentCaptureService} implementation associated with
+ * the given {@code userId}.
+ */
+ public abstract boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId);
+
+ /**
+ * Notifies the intelligence service of new assist data for the given activity.
+ *
+ * @return {@code false} if there was no service set for the given user
+ */
+ public abstract boolean sendActivityAssistData(@UserIdInt int userId,
+ @NonNull IBinder activityToken, @NonNull Bundle data);
+}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index ef9ad8a..c0c4a6e 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -58,7 +58,7 @@
* <ul>
* <li>Disabling the service when {@link UserManager} restrictions change.
* <li>Refreshing the service when its underlying
- * {@link #getSettingsProperty() Settings property} changed.
+ * {@link #getServiceSettingsProperty() Settings property} changed.
* <li>Calling the service when other Settings properties changed.
* </ul>
*
diff --git a/services/core/java/com/android/server/infra/AbstractRemoteService.java b/services/core/java/com/android/server/infra/AbstractRemoteService.java
index 7af1d4c..67b3ecf 100644
--- a/services/core/java/com/android/server/infra/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractRemoteService.java
@@ -248,7 +248,7 @@
if (checkIfDestroyed() || mCompleted) return;
if (!handleIsBound()) {
- if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing" + pendingRequest);
+ if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing " + pendingRequest);
handlePendingRequestWhileUnBound(pendingRequest);
handleEnsureBound();
} else {
@@ -379,6 +379,7 @@
final S remoteService = mWeakService.get();
if (remoteService != null) {
+ // TODO(b/117779333): we should probably ignore it if service is destroyed.
Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
onTimeout(remoteService);
} else {
diff --git a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
index 8f8b448..37a1f54 100644
--- a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
@@ -73,7 +73,8 @@
void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) {
if (mPendingRequest != null) {
if (mVerbose) {
- Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest);
+ Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest
+ + " to handle " + pendingRequest);
}
mPendingRequest.cancel();
}
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
deleted file mode 100644
index f424869..0000000
--- a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-
-/**
- * Intelligence Manager local system service interface.
- *
- * @hide Only for use within the system server.
- */
-//TODO(b/111276913): rename once the final name is defined
-public abstract class IntelligenceManagerInternal {
-
- /**
- * Checks whether the given {@code uid} owns the
- * {@link android.service.intelligence.SmartSuggestionsService} implementation associated with
- * the given {@code userId}.
- */
- public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
-
- /**
- * Notifies the intelligence service of new assist data for the given activity.
- *
- * @return {@code false} if there was no service set for the given user
- */
- public abstract boolean sendActivityAssistData(@UserIdInt int userId,
- @NonNull IBinder activityToken, @NonNull Bundle data);
-
- /**
- * Asks the intelligence service to provide Augmented Autofill for a given activity.
- *
- * @param userId user handle
- * @param client binder used to communicate with the activity that originated this request.
- * @param activityToken activity that originated this request.
- * @param autofillSessionId autofill session id (must be used on {@code client} calls.
- * @param focusedId id of the the field that triggered this request.
- * @param focusedValue current value of the field that triggered this request.
- *
- * @return {@code false} if the service cannot handle this request, {@code true} otherwise.
- * <b>NOTE: </b> it must return right away; typically it will return {@code false} if the
- * service is disabled (or the activity blacklisted).
- */
- public abstract AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue);
-
- /**
- * Callback used by the Autofill Session to communicate with the Augmented Autofill service.
- */
- public interface AugmentedAutofillCallback {
- // TODO(b/111330312): this method is calling when the Autofill session is destroyed, the
- // main reason being the cases where user tap HOME.
- // Right now it's completely destroying the UI, but we need to decide whether / how to
- // properly recover it later (for example, if the user switches back to the activity,
- // should it be restored? Right not it kind of is, because Autofill's Session trigger a
- // new FillRequest, which in turn triggers the Augmented Autofill request again)
- /**
- * Destroys the Autofill UI.
- */
- void destroy();
- }
-}
diff --git a/services/core/java/com/android/server/job/JobConcurrencyManager.java b/services/core/java/com/android/server/job/JobConcurrencyManager.java
new file mode 100644
index 0000000..ee1d847
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobConcurrencyManager.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.job;
+
+import android.app.ActivityManager;
+import android.app.job.JobInfo;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.server.job.controllers.JobStatus;
+import com.android.server.job.controllers.StateController;
+
+import java.util.Iterator;
+import java.util.List;
+
+class JobConcurrencyManager {
+ private static final String TAG = JobSchedulerService.TAG;
+ private static final boolean DEBUG = JobSchedulerService.DEBUG;
+
+ private final Object mLock;
+ private final JobSchedulerService mService;
+ private final JobSchedulerService.Constants mConstants;
+
+ private static final int MAX_JOB_CONTEXTS_COUNT = JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+
+ /**
+ * This array essentially stores the state of mActiveServices array.
+ * The ith index stores the job present on the ith JobServiceContext.
+ * We manipulate this array until we arrive at what jobs should be running on
+ * what JobServiceContext.
+ */
+ JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
+
+ /**
+ * Indicates whether we need to act on this jobContext id
+ */
+ boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
+
+ /**
+ * The uid whose jobs we would like to assign to a context.
+ */
+ int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
+
+ JobConcurrencyManager(JobSchedulerService service) {
+ mService = service;
+ mLock = mService.mLock;
+ mConstants = service.mConstants;
+ }
+
+ /**
+ * Takes jobs from pending queue and runs them on available contexts.
+ * If no contexts are available, preempts lower priority jobs to
+ * run higher priority ones.
+ * Lock on mJobs before calling this function.
+ */
+ void assignJobsToContextsLocked() {
+ if (DEBUG) {
+ Slog.d(TAG, printPendingQueueLocked());
+ }
+
+ final JobPackageTracker tracker = mService.mJobPackageTracker;
+ final List<JobStatus> pendingJobs = mService.mPendingJobs;
+ final List<JobServiceContext> activeServices = mService.mActiveServices;
+ final List<StateController> controllers = mService.mControllers;
+
+ int memLevel;
+ try {
+ memLevel = ActivityManager.getService().getMemoryTrimLevel();
+ } catch (RemoteException e) {
+ memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+ switch (memLevel) {
+ case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+ mService.mMaxActiveJobs = mConstants.BG_MODERATE_JOB_COUNT;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ mService.mMaxActiveJobs = mConstants.BG_LOW_JOB_COUNT;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ mService.mMaxActiveJobs = mConstants.BG_CRITICAL_JOB_COUNT;
+ break;
+ default:
+ mService.mMaxActiveJobs = mConstants.BG_NORMAL_JOB_COUNT;
+ break;
+ }
+
+ JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
+ boolean[] act = mTmpAssignAct;
+ int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
+ int numActive = 0;
+ int numForeground = 0;
+ for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+ final JobServiceContext js = mService.mActiveServices.get(i);
+ final JobStatus status = js.getRunningJobLocked();
+ if ((contextIdToJobMap[i] = status) != null) {
+ numActive++;
+ if (status.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+ numForeground++;
+ }
+ }
+ act[i] = false;
+ preferredUidForContext[i] = js.getPreferredUid();
+ }
+ if (DEBUG) {
+ Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
+ }
+ for (int i=0; i<pendingJobs.size(); i++) {
+ JobStatus nextPending = pendingJobs.get(i);
+
+ // If job is already running, go to next job.
+ int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
+ if (jobRunningContext != -1) {
+ continue;
+ }
+
+ final int priority = mService.evaluateJobPriorityLocked(nextPending);
+ nextPending.lastEvaluatedPriority = priority;
+
+ // Find a context for nextPending. The context should be available OR
+ // it should have lowest priority among all running jobs
+ // (sharing the same Uid as nextPending)
+ int minPriority = Integer.MAX_VALUE;
+ int minPriorityContextId = -1;
+ for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
+ JobStatus job = contextIdToJobMap[j];
+ int preferredUid = preferredUidForContext[j];
+ if (job == null) {
+ if ((numActive < mService.mMaxActiveJobs ||
+ (priority >= JobInfo.PRIORITY_TOP_APP &&
+ numForeground < mConstants.FG_JOB_COUNT)) &&
+ (preferredUid == nextPending.getUid() ||
+ preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
+ // This slot is free, and we haven't yet hit the limit on
+ // concurrent jobs... we can just throw the job in to here.
+ minPriorityContextId = j;
+ break;
+ }
+ // No job on this context, but nextPending can't run here because
+ // the context has a preferred Uid or we have reached the limit on
+ // concurrent jobs.
+ continue;
+ }
+ if (job.getUid() != nextPending.getUid()) {
+ continue;
+ }
+ if (mService.evaluateJobPriorityLocked(job) >= nextPending.lastEvaluatedPriority) {
+ continue;
+ }
+ if (minPriority > nextPending.lastEvaluatedPriority) {
+ minPriority = nextPending.lastEvaluatedPriority;
+ minPriorityContextId = j;
+ }
+ }
+ if (minPriorityContextId != -1) {
+ contextIdToJobMap[minPriorityContextId] = nextPending;
+ act[minPriorityContextId] = true;
+ numActive++;
+ if (priority >= JobInfo.PRIORITY_TOP_APP) {
+ numForeground++;
+ }
+ }
+ }
+ if (DEBUG) {
+ Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
+ }
+ tracker.noteConcurrency(numActive, numForeground);
+ for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+ boolean preservePreferredUid = false;
+ if (act[i]) {
+ JobStatus js = activeServices.get(i).getRunningJobLocked();
+ if (js != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "preempting job: "
+ + activeServices.get(i).getRunningJobLocked());
+ }
+ // preferredUid will be set to uid of currently running job.
+ activeServices.get(i).preemptExecutingJobLocked();
+ preservePreferredUid = true;
+ } else {
+ final JobStatus pendingJob = contextIdToJobMap[i];
+ if (DEBUG) {
+ Slog.d(TAG, "About to run job on context "
+ + String.valueOf(i) + ", job: " + pendingJob);
+ }
+ for (int ic=0; ic<controllers.size(); ic++) {
+ controllers.get(ic).prepareForExecutionLocked(pendingJob);
+ }
+ if (!activeServices.get(i).executeRunnableJob(pendingJob)) {
+ Slog.d(TAG, "Error executing " + pendingJob);
+ }
+ if (pendingJobs.remove(pendingJob)) {
+ tracker.noteNonpending(pendingJob);
+ }
+ }
+ }
+ if (!preservePreferredUid) {
+ activeServices.get(i).clearPreferredUid();
+ }
+ }
+ }
+
+ int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) {
+ for (int i=0; i<map.length; i++) {
+ if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private String printPendingQueueLocked() {
+ StringBuilder s = new StringBuilder("Pending queue: ");
+ Iterator<JobStatus> it = mService.mPendingJobs.iterator();
+ while (it.hasNext()) {
+ JobStatus js = it.next();
+ s.append("(")
+ .append(js.getJob().getId())
+ .append(", ")
+ .append(js.getUid())
+ .append(") ");
+ }
+ return s.toString();
+ }
+
+ private String printContextIdToJobMap(JobStatus[] map, String initial) {
+ StringBuilder s = new StringBuilder(initial + ": ");
+ for (int i=0; i<map.length; i++) {
+ s.append("(")
+ .append(map[i] == null? -1: map[i].getJobId())
+ .append(map[i] == null? -1: map[i].getUid())
+ .append(")" );
+ }
+ return s.toString();
+ }
+
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index ea295de..e8b2e8b 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -54,6 +54,8 @@
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Handler;
+import android.os.IThermalService;
+import android.os.IThermalStatusListener;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
@@ -62,6 +64,7 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemClock;
+import android.os.Temperature;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.provider.Settings;
@@ -75,9 +78,9 @@
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -111,7 +114,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -135,7 +137,7 @@
public static final boolean DEBUG_STANDBY = DEBUG || false;
/** The maximum number of concurrent jobs we run at one time. */
- private static final int MAX_JOB_CONTEXTS_COUNT = 16;
+ static final int MAX_JOB_CONTEXTS_COUNT = 16;
/** Enforce a per-app limit on scheduled jobs? */
private static final boolean ENFORCE_MAX_JOBS = true;
/** The maximum number of jobs that we allow an unprivileged app to schedule */
@@ -156,6 +158,7 @@
final StandbyTracker mStandbyTracker;
/** Tracking amount of time each package runs for. */
final JobPackageTracker mJobPackageTracker = new JobPackageTracker();
+ final JobConcurrencyManager mConcurrencyManager;
static final int MSG_JOB_EXPIRED = 0;
static final int MSG_CHECK_JOB = 1;
@@ -173,13 +176,18 @@
final List<JobServiceContext> mActiveServices = new ArrayList<>();
/** List of controllers that will notify this service of updates to jobs. */
- private final List<StateController> mControllers;
+ final List<StateController> mControllers;
/** Need direct access to this for testing. */
private final BatteryController mBatteryController;
/** Need direct access to this for testing. */
private final StorageController mStorageController;
/** Need directly for sending uid state changes */
private final DeviceIdleJobsController mDeviceIdleJobsController;
+ /** Need directly for receiving thermal events */
+ private IThermalService mThermalService;
+ /** Thermal constraint. */
+ @GuardedBy("mLock")
+ private boolean mThermalConstraint = false;
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
@@ -268,22 +276,6 @@
// -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
- /**
- * This array essentially stores the state of mActiveServices array.
- * The ith index stores the job present on the ith JobServiceContext.
- * We manipulate this array until we arrive at what jobs should be running on
- * what JobServiceContext.
- */
- JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
- /**
- * Indicates whether we need to act on this jobContext id
- */
- boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
- /**
- * The uid whose jobs we would like to assign to a context.
- */
- int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
-
private class ConstantsObserver extends ContentObserver {
private ContentResolver mResolver;
@@ -327,6 +319,19 @@
}
/**
+ * Thermal event received from Thermal Service
+ */
+ private final class ThermalStatusListener extends IThermalStatusListener.Stub {
+ @Override public void onStatusChange(int status) {
+ // Throttle for Temperature.THROTTLING_SEVERE and above
+ synchronized (mLock) {
+ mThermalConstraint = status >= Temperature.THROTTLING_SEVERE;
+ }
+ onControllerStateChanged();
+ }
+ }
+
+ /**
* All times are in milliseconds. These constants are kept synchronized with the system
* global Settings. Any access to this class or its fields should be done while
* holding the JobSchedulerService.mLock lock.
@@ -1267,6 +1272,8 @@
mConstantsObserver = new ConstantsObserver(mHandler);
mJobSchedulerStub = new JobSchedulerStub();
+ mConcurrencyManager = new JobConcurrencyManager(this);
+
// Set up the app standby bucketing tracker
mStandbyTracker = new StandbyTracker();
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
@@ -1381,6 +1388,16 @@
}
// Remove any jobs that are not associated with any of the current users.
cancelJobsForNonExistentUsers();
+ // Register thermal callback
+ mThermalService = IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ if (mThermalService != null) {
+ try {
+ mThermalService.registerThermalStatusListener(new ThermalStatusListener());
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal callback.", e);
+ }
+ }
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
// Let's go!
@@ -1804,14 +1821,26 @@
}
}
+ private boolean isJobThermalConstrainedLocked(JobStatus job) {
+ return mThermalConstraint && job.hasConnectivityConstraint()
+ && (evaluateJobPriorityLocked(job) < JobInfo.PRIORITY_FOREGROUND_APP);
+ }
+
private void stopNonReadyActiveJobsLocked() {
for (int i=0; i<mActiveServices.size(); i++) {
JobServiceContext serviceContext = mActiveServices.get(i);
final JobStatus running = serviceContext.getRunningJobLocked();
- if (running != null && !running.isReady()) {
+ if (running == null) {
+ continue;
+ }
+ if (!running.isReady()) {
serviceContext.cancelExecutingJobLocked(
JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
"cancelled due to unsatisfied constraints");
+ } else if (isJobThermalConstrainedLocked(running)) {
+ serviceContext.cancelExecutingJobLocked(
+ JobParameters.REASON_DEVICE_THERMAL,
+ "cancelled due to thermal condition");
}
}
}
@@ -2099,6 +2128,10 @@
return false;
}
+ if (isJobThermalConstrainedLocked(job)) {
+ return false;
+ }
+
final boolean jobPending = mPendingJobs.contains(job);
final boolean jobActive = isCurrentlyActiveLocked(job);
@@ -2193,7 +2226,7 @@
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
}
- assignJobsToContextsLocked();
+ mConcurrencyManager.assignJobsToContextsLocked();
reportActiveLocked();
}
@@ -2209,7 +2242,7 @@
return curPriority;
}
- private int evaluateJobPriorityLocked(JobStatus job) {
+ int evaluateJobPriorityLocked(JobStatus job) {
int priority = job.getPriority();
if (priority >= JobInfo.PRIORITY_FOREGROUND_APP) {
return adjustJobPriority(priority, job);
@@ -2221,161 +2254,6 @@
return adjustJobPriority(priority, job);
}
- /**
- * Takes jobs from pending queue and runs them on available contexts.
- * If no contexts are available, preempts lower priority jobs to
- * run higher priority ones.
- * Lock on mJobs before calling this function.
- */
- private void assignJobsToContextsLocked() {
- if (DEBUG) {
- Slog.d(TAG, printPendingQueue());
- }
-
- int memLevel;
- try {
- memLevel = ActivityManager.getService().getMemoryTrimLevel();
- } catch (RemoteException e) {
- memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
- }
- switch (memLevel) {
- case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
- mMaxActiveJobs = mConstants.BG_MODERATE_JOB_COUNT;
- break;
- case ProcessStats.ADJ_MEM_FACTOR_LOW:
- mMaxActiveJobs = mConstants.BG_LOW_JOB_COUNT;
- break;
- case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
- mMaxActiveJobs = mConstants.BG_CRITICAL_JOB_COUNT;
- break;
- default:
- mMaxActiveJobs = mConstants.BG_NORMAL_JOB_COUNT;
- break;
- }
-
- JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
- boolean[] act = mTmpAssignAct;
- int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
- int numActive = 0;
- int numForeground = 0;
- for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
- final JobServiceContext js = mActiveServices.get(i);
- final JobStatus status = js.getRunningJobLocked();
- if ((contextIdToJobMap[i] = status) != null) {
- numActive++;
- if (status.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
- numForeground++;
- }
- }
- act[i] = false;
- preferredUidForContext[i] = js.getPreferredUid();
- }
- if (DEBUG) {
- Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
- }
- for (int i=0; i<mPendingJobs.size(); i++) {
- JobStatus nextPending = mPendingJobs.get(i);
-
- // If job is already running, go to next job.
- int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
- if (jobRunningContext != -1) {
- continue;
- }
-
- final int priority = evaluateJobPriorityLocked(nextPending);
- nextPending.lastEvaluatedPriority = priority;
-
- // Find a context for nextPending. The context should be available OR
- // it should have lowest priority among all running jobs
- // (sharing the same Uid as nextPending)
- int minPriority = Integer.MAX_VALUE;
- int minPriorityContextId = -1;
- for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
- JobStatus job = contextIdToJobMap[j];
- int preferredUid = preferredUidForContext[j];
- if (job == null) {
- if ((numActive < mMaxActiveJobs ||
- (priority >= JobInfo.PRIORITY_TOP_APP &&
- numForeground < mConstants.FG_JOB_COUNT)) &&
- (preferredUid == nextPending.getUid() ||
- preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
- // This slot is free, and we haven't yet hit the limit on
- // concurrent jobs... we can just throw the job in to here.
- minPriorityContextId = j;
- break;
- }
- // No job on this context, but nextPending can't run here because
- // the context has a preferred Uid or we have reached the limit on
- // concurrent jobs.
- continue;
- }
- if (job.getUid() != nextPending.getUid()) {
- continue;
- }
- if (evaluateJobPriorityLocked(job) >= nextPending.lastEvaluatedPriority) {
- continue;
- }
- if (minPriority > nextPending.lastEvaluatedPriority) {
- minPriority = nextPending.lastEvaluatedPriority;
- minPriorityContextId = j;
- }
- }
- if (minPriorityContextId != -1) {
- contextIdToJobMap[minPriorityContextId] = nextPending;
- act[minPriorityContextId] = true;
- numActive++;
- if (priority >= JobInfo.PRIORITY_TOP_APP) {
- numForeground++;
- }
- }
- }
- if (DEBUG) {
- Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
- }
- mJobPackageTracker.noteConcurrency(numActive, numForeground);
- for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
- boolean preservePreferredUid = false;
- if (act[i]) {
- JobStatus js = mActiveServices.get(i).getRunningJobLocked();
- if (js != null) {
- if (DEBUG) {
- Slog.d(TAG, "preempting job: " + mActiveServices.get(i).getRunningJobLocked());
- }
- // preferredUid will be set to uid of currently running job.
- mActiveServices.get(i).preemptExecutingJobLocked();
- preservePreferredUid = true;
- } else {
- final JobStatus pendingJob = contextIdToJobMap[i];
- if (DEBUG) {
- Slog.d(TAG, "About to run job on context "
- + String.valueOf(i) + ", job: " + pendingJob);
- }
- for (int ic=0; ic<mControllers.size(); ic++) {
- mControllers.get(ic).prepareForExecutionLocked(pendingJob);
- }
- if (!mActiveServices.get(i).executeRunnableJob(pendingJob)) {
- Slog.d(TAG, "Error executing " + pendingJob);
- }
- if (mPendingJobs.remove(pendingJob)) {
- mJobPackageTracker.noteNonpending(pendingJob);
- }
- }
- }
- if (!preservePreferredUid) {
- mActiveServices.get(i).clearPreferredUid();
- }
- }
- }
-
- int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) {
- for (int i=0; i<map.length; i++) {
- if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) {
- return i;
- }
- }
- return -1;
- }
-
final class LocalService implements JobSchedulerInternal {
/**
@@ -3150,31 +3028,6 @@
getContext().sendBroadcastAsUser(dockIntent, UserHandle.ALL);
}
- private String printContextIdToJobMap(JobStatus[] map, String initial) {
- StringBuilder s = new StringBuilder(initial + ": ");
- for (int i=0; i<map.length; i++) {
- s.append("(")
- .append(map[i] == null? -1: map[i].getJobId())
- .append(map[i] == null? -1: map[i].getUid())
- .append(")" );
- }
- return s.toString();
- }
-
- private String printPendingQueue() {
- StringBuilder s = new StringBuilder("Pending queue: ");
- Iterator<JobStatus> it = mPendingJobs.iterator();
- while (it.hasNext()) {
- JobStatus js = it.next();
- s.append("(")
- .append(js.getJob().getId())
- .append(", ")
- .append(js.getUid())
- .append(") ");
- }
- return s.toString();
- }
-
static void dumpHelp(PrintWriter pw) {
pw.println("Job Scheduler (jobscheduler) dump options:");
pw.println(" [-h] [package] ...");
@@ -3228,6 +3081,9 @@
pw.print(" In parole?: ");
pw.print(mInParole);
pw.println();
+ pw.print(" In thermal throttling?: ");
+ pw.print(mThermalConstraint);
+ pw.println();
pw.println();
pw.println("Started users: " + Arrays.toString(mStartedUsers));
@@ -3403,6 +3259,7 @@
proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT_TIME_MILLIS,
mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME - nowUptime);
proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
+ proto.write(JobSchedulerServiceDumpProto.IN_THERMAL, mThermalConstraint);
for (int u : mStartedUsers) {
proto.write(JobSchedulerServiceDumpProto.STARTED_USERS, u);
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 6612d02..675e59e 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -237,7 +237,7 @@
Supplier<Intent> supplier =
() -> createIntent(ContextHubManager.EVENT_NANOAPP_MESSAGE, message.getNanoAppId())
.putExtra(ContextHubManager.EXTRA_MESSAGE, message);
- sendPendingIntent(supplier);
+ sendPendingIntent(supplier, message.getNanoAppId());
}
/**
@@ -247,7 +247,8 @@
*/
/* package */ void onNanoAppLoaded(long nanoAppId) {
invokeCallback(callback -> callback.onNanoAppLoaded(nanoAppId));
- sendPendingIntent(() -> createIntent(ContextHubManager.EVENT_NANOAPP_LOADED, nanoAppId));
+ sendPendingIntent(
+ () -> createIntent(ContextHubManager.EVENT_NANOAPP_LOADED, nanoAppId), nanoAppId);
}
/**
@@ -257,7 +258,8 @@
*/
/* package */ void onNanoAppUnloaded(long nanoAppId) {
invokeCallback(callback -> callback.onNanoAppUnloaded(nanoAppId));
- sendPendingIntent(() -> createIntent(ContextHubManager.EVENT_NANOAPP_UNLOADED, nanoAppId));
+ sendPendingIntent(
+ () -> createIntent(ContextHubManager.EVENT_NANOAPP_UNLOADED, nanoAppId), nanoAppId);
}
/**
@@ -280,7 +282,7 @@
Supplier<Intent> supplier =
() -> createIntent(ContextHubManager.EVENT_NANOAPP_ABORTED, nanoAppId)
.putExtra(ContextHubManager.EXTRA_NANOAPP_ABORT_CODE, abortCode);
- sendPendingIntent(supplier);
+ sendPendingIntent(supplier, nanoAppId);
}
/**
@@ -360,18 +362,40 @@
*/
private synchronized void sendPendingIntent(Supplier<Intent> supplier) {
if (mPendingIntentRequest.hasPendingIntent()) {
- Intent intent = supplier.get();
- try {
- mPendingIntentRequest.getPendingIntent().send(
- mContext, 0 /* code */, intent, null /* onFinished */, null /* Handler */,
- Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
- null /* options */);
- } catch (PendingIntent.CanceledException e) {
- // The PendingIntent is no longer valid
- Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
- + " (host endpoint ID " + mHostEndPointId + ")");
- close();
- }
+ doSendPendingIntent(mPendingIntentRequest.getPendingIntent(), supplier.get());
+ }
+ }
+
+ /**
+ * Sends an intent to any existing PendingIntent
+ *
+ * @param supplier method to create the extra Intent
+ * @param nanoAppId the ID of the nanoapp which this event is for
+ */
+ private synchronized void sendPendingIntent(Supplier<Intent> supplier, long nanoAppId) {
+ if (mPendingIntentRequest.hasPendingIntent()
+ && mPendingIntentRequest.getNanoAppId() == nanoAppId) {
+ doSendPendingIntent(mPendingIntentRequest.getPendingIntent(), supplier.get());
+ }
+ }
+
+ /**
+ * Sends a PendingIntent with extra Intent data
+ *
+ * @param pendingIntent the PendingIntent
+ * @param intent the extra Intent data
+ */
+ private void doSendPendingIntent(PendingIntent pendingIntent, Intent intent) {
+ try {
+ pendingIntent.send(
+ mContext, 0 /* code */, intent, null /* onFinished */, null /* Handler */,
+ Manifest.permission.LOCATION_HARDWARE /* requiredPermission */,
+ null /* options */);
+ } catch (PendingIntent.CanceledException e) {
+ // The PendingIntent is no longer valid
+ Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
+ + " (host endpoint ID " + mHostEndPointId + ")");
+ close();
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
index c4f1f3d..4480435 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
@@ -24,8 +24,7 @@
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.biometrics.BiometricManager;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteCallbackList;
@@ -62,7 +61,7 @@
private final Context mContext;
private AlarmManager mAlarmManager;
- private FingerprintManager mFingerprintManager;
+ private BiometricManager mBiometricManager;
public LockSettingsStrongAuth(Context context) {
mContext = context;
@@ -71,9 +70,8 @@
}
public void systemReady() {
- final PackageManager pm = mContext.getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
- mFingerprintManager = mContext.getSystemService(FingerprintManager.class);
+ if (BiometricManager.hasBiometrics(mContext)) {
+ mBiometricManager = mContext.getSystemService(BiometricManager.class);
}
}
@@ -187,9 +185,9 @@
}
public void reportSuccessfulStrongAuthUnlock(int userId) {
- if (mFingerprintManager != null) {
- byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */
- mFingerprintManager.resetTimeout(token);
+ if (mBiometricManager != null) {
+ byte[] token = null; /* TODO: pass real auth token once HAL supports it */
+ mBiometricManager.resetTimeout(token);
}
final int argNotUsed = 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dab4e79..dca92ea 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8631,16 +8631,8 @@
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
// The version of the application on the /system partition is less than or
- // equal to the version on the /data partition. Even though the disabled system package
- // is likely to be replaced by a version on the /data partition, we make assumptions
- // that it's part of the mPackages collection during package manager initialization. So,
- // add it to mPackages if there isn't already a package in the collection and then throw
- // an exception to use the application already installed on the /data partition.
- synchronized (mPackages) {
- if (!mPackages.containsKey(pkg.packageName)) {
- mPackages.put(pkg.packageName, pkg);
- }
- }
+ // equal to the version on the /data partition. Throw an exception and use
+ // the application already installed on the /data partition.
throw new PackageManagerException(Log.WARN, "Package " + pkg.packageName + " at "
+ pkg.codePath + " ignored: updated version " + pkgSetting.versionCode
+ " better than this " + pkg.getLongVersionCode());
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
index cb89780..cc3064e 100644
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -34,8 +34,8 @@
import android.rolecontrollerservice.RoleControllerService;
import android.util.Slog;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.FgThread;
import java.util.ArrayDeque;
import java.util.Queue;
@@ -48,10 +48,6 @@
static final boolean DEBUG = false;
private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
- // TODO: STOPSHIP: This isn't the right thread, as we are also using it to write to disk.
- @NonNull
- private static final Handler sCallbackHandler = BackgroundThread.getHandler();
-
@NonNull
private final Connection mConnection;
@@ -99,8 +95,8 @@
* @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
*/
public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
- mConnection.enqueueCall(
- new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback));
+ mConnection.enqueueCall(new Connection.Call(IRoleControllerService::onGrantDefaultRoles,
+ callback));
}
private static final class Connection implements ServiceConnection {
@@ -113,6 +109,9 @@
@NonNull
private final Context mContext;
+ @NonNull
+ private final Handler mHandler = FgThread.getHandler();
+
private boolean mBound;
@Nullable
@@ -161,8 +160,8 @@
if (DEBUG) {
Slog.i(LOG_TAG, "Enqueue " + call);
}
- sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage(
- Connection::executeCall, this, call));
+ mHandler.executeOrSendMessage(PooledLambda.obtainMessage(Connection::executeCall, this,
+ call));
}
@WorkerThread
@@ -181,7 +180,7 @@
@WorkerThread
private void ensureBound() {
- sCallbackHandler.removeCallbacks(mUnbindRunnable);
+ mHandler.removeCallbacks(mUnbindRunnable);
if (!mBound) {
Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
intent.setPackage(mContext.getPackageManager()
@@ -191,13 +190,13 @@
//
// Note that as a result, onServiceConnected may happen not on main thread!
mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
- sCallbackHandler, UserHandle.of(mUserId));
+ mHandler, UserHandle.of(mUserId));
}
}
private void scheduleUnbind() {
- sCallbackHandler.removeCallbacks(mUnbindRunnable);
- sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
+ mHandler.removeCallbacks(mUnbindRunnable);
+ mHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
}
@WorkerThread
@@ -220,6 +219,9 @@
private final IRoleManagerCallback mCallback;
@NonNull
+ private final Handler mHandler = FgThread.getHandler();
+
+ @NonNull
private final Runnable mTimeoutRunnable = this::notifyTimeout;
private boolean mCallbackNotified;
@@ -236,7 +238,7 @@
Slog.i(LOG_TAG, "Executing " + this);
}
try {
- sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
+ mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
mCallExecutor.execute(service, new CallbackDelegate());
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
@@ -256,7 +258,7 @@
return;
}
mCallbackNotified = true;
- sCallbackHandler.removeCallbacks(mTimeoutRunnable);
+ mHandler.removeCallbacks(mTimeoutRunnable);
try {
if (success) {
mCallback.onSuccess();
@@ -286,14 +288,14 @@
@Override
public void onSuccess() throws RemoteException {
- sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
- Call::notifyCallback, Call.this, true));
+ mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
+ true));
}
@Override
public void onFailure() throws RemoteException {
- sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
- Call::notifyCallback, Call.this, false));
+ mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this,
+ false));
}
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index d5faab5..8711ddf 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -42,17 +42,23 @@
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.BitUtils;
import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.FunctionalUtils;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -150,21 +156,16 @@
@MainThread
private void performInitialGrantsIfNecessary(@UserIdInt int userId) {
RoleUserState userState;
- synchronized (mLock) {
- userState = getUserStateLocked(userId);
- }
+ userState = getOrCreateUserState(userId);
String packagesHash = computeComponentStateHash(userId);
- String lastGrantPackagesHash;
- synchronized (mLock) {
- lastGrantPackagesHash = userState.getLastGrantPackagesHashLocked();
- }
- boolean needGrant = !Objects.equals(packagesHash, lastGrantPackagesHash);
+ String oldPackagesHash = userState.getPackagesHash();
+ boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
if (needGrant) {
// Some vital packages state has changed since last role grant
// Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
- getControllerService(userId).onGrantDefaultRoles(
+ getOrCreateControllerService(userId).onGrantDefaultRoles(
new IRoleManagerCallback.Stub() {
@Override
public void onSuccess() {
@@ -177,9 +178,7 @@
});
try {
result.get(5, TimeUnit.SECONDS);
- synchronized (mLock) {
- userState.setLastGrantPackagesHashLocked(packagesHash);
- }
+ userState.setPackagesHash(packagesHash);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
}
@@ -219,35 +218,38 @@
return PackageUtils.computeSha256Digest(out.toByteArray());
}
- @GuardedBy("mLock")
@NonNull
- private RoleUserState getUserStateLocked(@UserIdInt int userId) {
- RoleUserState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = RoleUserState.newInstanceLocked(userId);
- mUserStates.put(userId, userState);
+ private RoleUserState getOrCreateUserState(@UserIdInt int userId) {
+ synchronized (mLock) {
+ RoleUserState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new RoleUserState(userId);
+ mUserStates.put(userId, userState);
+ }
+ return userState;
}
- return userState;
}
- @GuardedBy("mLock")
@NonNull
- private RemoteRoleControllerService getControllerService(@UserIdInt int userId) {
- RemoteRoleControllerService controllerService = mControllerServices.get(userId);
- if (controllerService == null) {
- controllerService = new RemoteRoleControllerService(userId, getContext());
- mControllerServices.put(userId, controllerService);
+ private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) {
+ synchronized (mLock) {
+ RemoteRoleControllerService controllerService = mControllerServices.get(userId);
+ if (controllerService == null) {
+ controllerService = new RemoteRoleControllerService(userId, getContext());
+ mControllerServices.put(userId, controllerService);
+ }
+ return controllerService;
}
- return controllerService;
}
private void onRemoveUser(@UserIdInt int userId) {
+ RoleUserState userState;
synchronized (mLock) {
mControllerServices.remove(userId);
- RoleUserState userState = mUserStates.removeReturnOld(userId);
- if (userState != null) {
- userState.destroySyncLocked();
- }
+ userState = mUserStates.removeReturnOld(userId);
+ }
+ if (userState != null) {
+ userState.destroy();
}
}
@@ -258,10 +260,8 @@
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
int userId = UserHandle.getUserId(getCallingUid());
- synchronized (mLock) {
- RoleUserState userState = getUserStateLocked(userId);
- return userState.isRoleAvailableLocked(roleName);
- }
+ RoleUserState userState = getOrCreateUserState(userId);
+ return userState.isRoleAvailable(roleName);
}
@Override
@@ -301,10 +301,8 @@
@Nullable
private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName,
@UserIdInt int userId) {
- synchronized (mLock) {
- RoleUserState userState = getUserStateLocked(userId);
- return userState.getRoleHoldersLocked(roleName);
- }
+ RoleUserState userState = getOrCreateUserState(userId);
+ return userState.getRoleHolders(roleName);
}
@Override
@@ -321,7 +319,7 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"addRoleHolderAsUser");
- getControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
+ getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
}
@Override
@@ -338,7 +336,7 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"removeRoleHolderAsUser");
- getControllerService(userId).onRemoveRoleHolder(roleName, packageName,
+ getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName,
callback);
}
@@ -355,7 +353,7 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
"clearRoleHoldersAsUser");
- getControllerService(userId).onClearRoleHolders(roleName, callback);
+ getOrCreateControllerService(userId).onClearRoleHolders(roleName, callback);
}
@Override
@@ -366,10 +364,8 @@
"setRoleNamesFromController");
int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- RoleUserState userState = getUserStateLocked(userId);
- userState.setRoleNamesLocked(roleNames);
- }
+ RoleUserState userState = getOrCreateUserState(userId);
+ userState.setRoleNames(roleNames);
}
@Override
@@ -382,10 +378,8 @@
"addRoleHolderFromController");
int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- RoleUserState userState = getUserStateLocked(userId);
- return userState.addRoleHolderLocked(roleName, packageName);
- }
+ RoleUserState userState = getOrCreateUserState(userId);
+ return userState.addRoleHolder(roleName, packageName);
}
@Override
@@ -398,10 +392,8 @@
"removeRoleHolderFromController");
int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- RoleUserState userState = getUserStateLocked(userId);
- return userState.removeRoleHolderLocked(roleName, packageName);
- }
+ RoleUserState userState = getOrCreateUserState(userId);
+ return userState.removeRoleHolder(roleName, packageName);
}
@CheckResult
@@ -417,5 +409,34 @@
new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
resultReceiver);
}
+
+ @Override
+ protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
+ @Nullable String[] args) {
+ if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
+ return;
+ }
+
+ boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
+ DualDumpOutputStream dumpOutputStream;
+ if (dumpAsProto) {
+ dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
+ } else {
+ fout.println("ROLE MANAGER STATE (dumpsys role):");
+ dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
+ }
+
+ int[] userIds = mUserManagerInternal.getUserIds();
+ int userIdsLength = userIds.length;
+ for (int i = 0; i < userIdsLength; i++) {
+ int userId = userIds[i];
+
+ RoleUserState userState = getOrCreateUserState(userId);
+ userState.dump(dumpOutputStream, "user_states",
+ RoleManagerServiceDumpProto.USER_STATES);
+ }
+
+ dumpOutputStream.flush();
+ }
}
}
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index ce05974..81adb11 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -32,6 +32,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.internal.util.function.pooled.PooledLambda;
import libcore.io.IoUtils;
@@ -73,54 +74,51 @@
@UserIdInt
private final int mUserId;
- @GuardedBy("RoleManagerService.mLock")
+ @NonNull
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
private int mVersion = VERSION_UNDEFINED;
- @GuardedBy("RoleManagerService.mLock")
+ @GuardedBy("mLock")
@Nullable
- private String mLastGrantPackagesHash;
+ private String mPackagesHash;
/**
* Maps role names to its holders' package names. The values should never be null.
*/
- @GuardedBy("RoleManagerService.mLock")
+ @GuardedBy("mLock")
@NonNull
private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
- @GuardedBy("RoleManagerService.mLock")
+ @GuardedBy("mLock")
private long mWritePendingSinceMillis;
- @GuardedBy("RoleManagerService.mLock")
+ @GuardedBy("mLock")
private boolean mDestroyed;
@NonNull
private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper());
- private RoleUserState(@UserIdInt int userId) {
- mUserId = userId;
-
- readSyncLocked();
- }
-
/**
* Create a new instance of user state, and read its state from disk if previously persisted.
*
* @param userId the user id for the new user state
- *
- * @return the new user state
*/
- @GuardedBy("RoleManagerService.mLock")
- public static RoleUserState newInstanceLocked(@UserIdInt int userId) {
- return new RoleUserState(userId);
+ public RoleUserState(@UserIdInt int userId) {
+ mUserId = userId;
+
+ readFile();
}
/**
* Get the version of this user state.
*/
- @GuardedBy("RoleManagerService.mLock")
- public int getVersionLocked() {
- throwIfDestroyedLocked();
- return mVersion;
+ public int getVersion() {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ return mVersion;
+ }
}
/**
@@ -128,14 +126,15 @@
*
* @param version the version to set
*/
- @GuardedBy("RoleManagerService.mLock")
- public void setVersionLocked(int version) {
- throwIfDestroyedLocked();
- if (mVersion == version) {
- return;
+ public void setVersion(int version) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (mVersion == version) {
+ return;
+ }
+ mVersion = version;
+ scheduleWriteFileLocked();
}
- mVersion = version;
- writeAsyncLocked();
}
/**
@@ -143,24 +142,27 @@
*
* @return the hash representing the state of packages
*/
- @GuardedBy("RoleManagerService.mLock")
- public String getLastGrantPackagesHashLocked() {
- return mLastGrantPackagesHash;
+ @Nullable
+ public String getPackagesHash() {
+ synchronized (mLock) {
+ return mPackagesHash;
+ }
}
/**
* Set the hash representing the state of packages during the last time initial grants was run.
*
- * @param lastGrantPackagesHash the hash representing the state of packages
+ * @param packagesHash the hash representing the state of packages
*/
- @GuardedBy("RoleManagerService.mLock")
- public void setLastGrantPackagesHashLocked(@Nullable String lastGrantPackagesHash) {
- throwIfDestroyedLocked();
- if (Objects.equals(mLastGrantPackagesHash, lastGrantPackagesHash)) {
- return;
+ public void setPackagesHash(@Nullable String packagesHash) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ if (Objects.equals(mPackagesHash, packagesHash)) {
+ return;
+ }
+ mPackagesHash = packagesHash;
+ scheduleWriteFileLocked();
}
- mLastGrantPackagesHash = lastGrantPackagesHash;
- writeAsyncLocked();
}
/**
@@ -170,10 +172,11 @@
*
* @return whether the role is available
*/
- @GuardedBy("RoleManagerService.mLock")
- public boolean isRoleAvailableLocked(@NonNull String roleName) {
- throwIfDestroyedLocked();
- return mRoles.containsKey(roleName);
+ public boolean isRoleAvailable(@NonNull String roleName) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ return mRoles.containsKey(roleName);
+ }
}
/**
@@ -183,11 +186,12 @@
*
* @return the set of role holders. {@code null} should not be returned and indicates an issue.
*/
- @GuardedBy("RoleManagerService.mLock")
@Nullable
- public ArraySet<String> getRoleHoldersLocked(@NonNull String roleName) {
- throwIfDestroyedLocked();
- return mRoles.get(roleName);
+ public ArraySet<String> getRoleHolders(@NonNull String roleName) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ return new ArraySet<>(mRoles.get(roleName));
+ }
}
/**
@@ -195,33 +199,35 @@
*
* @param roleNames the names of all the available roles
*/
- @GuardedBy("RoleManagerService.mLock")
- public void setRoleNamesLocked(@NonNull List<String> roleNames) {
- throwIfDestroyedLocked();
- boolean changed = false;
- for (int i = mRoles.size() - 1; i >= 0; i--) {
- String roleName = mRoles.keyAt(i);
- if (!roleNames.contains(roleName)) {
- ArraySet<String> packageNames = mRoles.valueAt(i);
- if (!packageNames.isEmpty()) {
- Slog.e(LOG_TAG, "Holders of a removed role should have been cleaned up, role: "
- + roleName + ", holders: " + packageNames);
+ public void setRoleNames(@NonNull List<String> roleNames) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ boolean changed = false;
+ for (int i = mRoles.size() - 1; i >= 0; i--) {
+ String roleName = mRoles.keyAt(i);
+ if (!roleNames.contains(roleName)) {
+ ArraySet<String> packageNames = mRoles.valueAt(i);
+ if (!packageNames.isEmpty()) {
+ Slog.e(LOG_TAG,
+ "Holders of a removed role should have been cleaned up, role: "
+ + roleName + ", holders: " + packageNames);
+ }
+ mRoles.removeAt(i);
+ changed = true;
}
- mRoles.removeAt(i);
- changed = true;
}
- }
- int roleNamesSize = roleNames.size();
- for (int i = 0; i < roleNamesSize; i++) {
- String roleName = roleNames.get(i);
- if (!mRoles.containsKey(roleName)) {
- mRoles.put(roleName, new ArraySet<>());
- Slog.i(LOG_TAG, "Added new role: " + roleName);
- changed = true;
+ int roleNamesSize = roleNames.size();
+ for (int i = 0; i < roleNamesSize; i++) {
+ String roleName = roleNames.get(i);
+ if (!mRoles.containsKey(roleName)) {
+ mRoles.put(roleName, new ArraySet<>());
+ Slog.i(LOG_TAG, "Added new role: " + roleName);
+ changed = true;
+ }
}
- }
- if (changed) {
- writeAsyncLocked();
+ if (changed) {
+ scheduleWriteFileLocked();
+ }
}
}
@@ -235,20 +241,21 @@
* indicates an issue.
*/
@CheckResult
- @GuardedBy("RoleManagerService.mLock")
- public boolean addRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
- throwIfDestroyedLocked();
- ArraySet<String> roleHolders = mRoles.get(roleName);
- if (roleHolders == null) {
- Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName
- + ", package: " + packageName);
- return false;
+ public boolean addRoleHolder(@NonNull String roleName, @NonNull String packageName) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ ArraySet<String> roleHolders = mRoles.get(roleName);
+ if (roleHolders == null) {
+ Slog.e(LOG_TAG, "Cannot add role holder for unknown role, role: " + roleName
+ + ", package: " + packageName);
+ return false;
+ }
+ boolean changed = roleHolders.add(packageName);
+ if (changed) {
+ scheduleWriteFileLocked();
+ }
+ return true;
}
- boolean changed = roleHolders.add(packageName);
- if (changed) {
- writeAsyncLocked();
- }
- return true;
}
/**
@@ -261,38 +268,30 @@
* indicates an issue.
*/
@CheckResult
- @GuardedBy("RoleManagerService.mLock")
- public boolean removeRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
- throwIfDestroyedLocked();
- ArraySet<String> roleHolders = mRoles.get(roleName);
- if (roleHolders == null) {
- Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName
- + ", package: " + packageName);
- return false;
+ public boolean removeRoleHolder(@NonNull String roleName, @NonNull String packageName) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ ArraySet<String> roleHolders = mRoles.get(roleName);
+ if (roleHolders == null) {
+ Slog.e(LOG_TAG, "Cannot remove role holder for unknown role, role: " + roleName
+ + ", package: " + packageName);
+ return false;
+ }
+ boolean changed = roleHolders.remove(packageName);
+ if (changed) {
+ scheduleWriteFileLocked();
+ }
+ return true;
}
- boolean changed = roleHolders.remove(packageName);
- if (changed) {
- writeAsyncLocked();
- }
- return true;
}
/**
* Schedule writing the state to file.
*/
- @GuardedBy("RoleManagerService.mLock")
- private void writeAsyncLocked() {
+ @GuardedBy("mLock")
+ private void scheduleWriteFileLocked() {
throwIfDestroyedLocked();
- ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
- for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
- String roleName = mRoles.keyAt(i);
- ArraySet<String> roleHolders = mRoles.valueAt(i);
-
- roleHolders = new ArraySet<>(roleHolders);
- roles.put(roleName, roleHolders);
- }
-
long currentTimeMillis = System.currentTimeMillis();
long writeDelayMillis;
if (!mWriteHandler.hasMessagesOrCallbacks()) {
@@ -310,14 +309,26 @@
}
}
- mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeSync, this,
- mVersion, mLastGrantPackagesHash, roles), writeDelayMillis);
+ mWriteHandler.sendMessageDelayed(PooledLambda.obtainMessage(RoleUserState::writeFile, this),
+ writeDelayMillis);
Slog.i(LOG_TAG, "Scheduled writing roles.xml");
}
@WorkerThread
- private void writeSync(int version, @Nullable String packagesHash,
- @NonNull ArrayMap<String, ArraySet<String>> roles) {
+ private void writeFile() {
+ int version;
+ String packagesHash;
+ ArrayMap<String, ArraySet<String>> roles;
+ synchronized (mLock) {
+ if (mDestroyed) {
+ return;
+ }
+
+ version = mVersion;
+ packagesHash = mPackagesHash;
+ roles = snapshotRolesLocked();
+ }
+
AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
FileOutputStream out = null;
try {
@@ -384,18 +395,19 @@
/**
* Read the state from file.
*/
- @GuardedBy("RoleManagerService.mLock")
- private void readSyncLocked() {
- File file = getFile(mUserId);
- try (FileInputStream in = new AtomicFile(file).openRead()) {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- parseXmlLocked(parser);
- Slog.i(LOG_TAG, "Read roles.xml successfully");
- } catch (FileNotFoundException e) {
- Slog.i(LOG_TAG, "roles.xml not found");
- } catch (XmlPullParserException | IOException e) {
- throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
+ private void readFile() {
+ synchronized (mLock) {
+ File file = getFile(mUserId);
+ try (FileInputStream in = new AtomicFile(file).openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseXmlLocked(parser);
+ Slog.i(LOG_TAG, "Read roles.xml successfully");
+ } catch (FileNotFoundException e) {
+ Slog.i(LOG_TAG, "roles.xml not found");
+ } catch (XmlPullParserException | IOException e) {
+ throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
+ }
}
}
@@ -421,7 +433,7 @@
private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
XmlPullParserException {
mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
- mLastGrantPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
+ mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
mRoles.clear();
int type;
@@ -465,18 +477,76 @@
}
/**
+ * Dump this user state.
+ *
+ * @param dumpOutputStream the output stream to dump to
+ */
+ public void dump(@NonNull DualDumpOutputStream dumpOutputStream, @NonNull String fieldName,
+ long fieldId) {
+ int version;
+ String packagesHash;
+ ArrayMap<String, ArraySet<String>> roles;
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+
+ version = mVersion;
+ packagesHash = mPackagesHash;
+ roles = snapshotRolesLocked();
+ }
+
+ long fieldToken = dumpOutputStream.start(fieldName, fieldId);
+ dumpOutputStream.write("user_id", RoleUserStateProto.USER_ID, mUserId);
+ dumpOutputStream.write("version", RoleUserStateProto.VERSION, version);
+ dumpOutputStream.write("packages_hash", RoleUserStateProto.PACKAGES_HASH, packagesHash);
+
+ int rolesSize = roles.size();
+ for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
+ String roleName = roles.keyAt(rolesIndex);
+ ArraySet<String> roleHolders = roles.valueAt(rolesIndex);
+
+ long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
+ dumpOutputStream.write("name", RoleProto.NAME, roleName);
+
+ int roleHoldersSize = roleHolders.size();
+ for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
+ String roleHolder = roleHolders.valueAt(roleHoldersIndex);
+
+ dumpOutputStream.write("holders", RoleProto.HOLDERS, roleHolder);
+ }
+
+ dumpOutputStream.end(rolesToken);
+ }
+
+ dumpOutputStream.end(fieldToken);
+ }
+
+ @GuardedBy("mLock")
+ private ArrayMap<String, ArraySet<String>> snapshotRolesLocked() {
+ ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
+ for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
+ String roleName = mRoles.keyAt(i);
+ ArraySet<String> roleHolders = mRoles.valueAt(i);
+
+ roleHolders = new ArraySet<>(roleHolders);
+ roles.put(roleName, roleHolders);
+ }
+ return roles;
+ }
+
+ /**
* Destroy this state and delete the corresponding file. Any pending writes to the file will be
* cancelled and any future interaction with this state will throw an exception.
*/
- @GuardedBy("RoleManagerService.mLock")
- public void destroySyncLocked() {
- throwIfDestroyedLocked();
- mWriteHandler.removeCallbacksAndMessages(null);
- getFile(mUserId).delete();
- mDestroyed = true;
+ public void destroy() {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ mWriteHandler.removeCallbacksAndMessages(null);
+ getFile(mUserId).delete();
+ mDestroyed = true;
+ }
}
- @GuardedBy("RoleManagerService.mLock")
+ @GuardedBy("mLock")
private void throwIfDestroyedLocked() {
if (mDestroyed) {
throw new IllegalStateException("This RoleUserState has already been destroyed");
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/services/core/java/com/android/server/signedconfig/InvalidConfigException.java
similarity index 61%
copy from core/java/android/view/intelligence/ContentCaptureEvent.aidl
copy to services/core/java/com/android/server/signedconfig/InvalidConfigException.java
index c66a6cb..f01baa4 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/services/core/java/com/android/server/signedconfig/InvalidConfigException.java
@@ -14,6 +14,20 @@
* limitations under the License.
*/
-package android.view.intelligence;
+package com.android.server.signedconfig;
-parcelable ContentCaptureEvent;
+/**
+ * Thrown when there is a problem parsing the config embedded in an APK.
+ */
+public class InvalidConfigException extends Exception {
+
+ public InvalidConfigException(String message) {
+ super(message);
+ }
+
+ public InvalidConfigException(String message, Exception cause) {
+ super(message, cause);
+ }
+
+
+}
diff --git a/services/core/java/com/android/server/signedconfig/SignedConfig.java b/services/core/java/com/android/server/signedconfig/SignedConfig.java
new file mode 100644
index 0000000..a3f452c
--- /dev/null
+++ b/services/core/java/com/android/server/signedconfig/SignedConfig.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.signedconfig;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents signed configuration.
+ *
+ * <p>This configuration should only be used if the signature has already been verified.
+ */
+public class SignedConfig {
+
+ private static final String KEY_VERSION = "version";
+ private static final String KEY_CONFIG = "config";
+
+ private static final String CONFIG_KEY_MIN_SDK = "minSdk";
+ private static final String CONFIG_KEY_MAX_SDK = "maxSdk";
+ private static final String CONFIG_KEY_VALUES = "values";
+ // TODO it may be better to use regular key/value pairs in a JSON object, rather than an array
+ // of objects with the 2 keys below.
+ private static final String CONFIG_KEY_KEY = "key";
+ private static final String CONFIG_KEY_VALUE = "value";
+
+ /**
+ * Represents config values targetting to an SDK range.
+ */
+ public static class PerSdkConfig {
+ public final int minSdk;
+ public final int maxSdk;
+ public final Map<String, String> values;
+
+ public PerSdkConfig(int minSdk, int maxSdk, Map<String, String> values) {
+ this.minSdk = minSdk;
+ this.maxSdk = maxSdk;
+ this.values = Collections.unmodifiableMap(values);
+ }
+
+ }
+
+ public final int version;
+ public final List<PerSdkConfig> perSdkConfig;
+
+ public SignedConfig(int version, List<PerSdkConfig> perSdkConfig) {
+ this.version = version;
+ this.perSdkConfig = Collections.unmodifiableList(perSdkConfig);
+ }
+
+ /**
+ * Find matching sdk config for a given SDK level.
+ *
+ * @param sdkVersion SDK version of device.
+ * @return Matching config, of {@code null} if there is none.
+ */
+ public PerSdkConfig getMatchingConfig(int sdkVersion) {
+ for (PerSdkConfig config : perSdkConfig) {
+ if (config.minSdk <= sdkVersion && sdkVersion <= config.maxSdk) {
+ return config;
+ }
+ }
+ // nothing matching
+ return null;
+ }
+
+ /**
+ * Parse configuration from an APK.
+ *
+ * @param config config as read from the APK metadata.
+ * @return Parsed configuration.
+ * @throws InvalidConfigException If there's a problem parsing the config.
+ */
+ public static SignedConfig parse(String config, Set<String> allowedKeys)
+ throws InvalidConfigException {
+ try {
+ JSONObject json = new JSONObject(config);
+ int version = json.getInt(KEY_VERSION);
+
+ JSONArray perSdkConfig = json.getJSONArray(KEY_CONFIG);
+ List<PerSdkConfig> parsedConfigs = new ArrayList<>();
+ for (int i = 0; i < perSdkConfig.length(); ++i) {
+ parsedConfigs.add(parsePerSdkConfig(perSdkConfig.getJSONObject(i), allowedKeys));
+ }
+
+ return new SignedConfig(version, parsedConfigs);
+ } catch (JSONException e) {
+ throw new InvalidConfigException("Could not parse JSON", e);
+ }
+
+ }
+
+ @VisibleForTesting
+ static PerSdkConfig parsePerSdkConfig(JSONObject json, Set<String> allowedKeys)
+ throws JSONException, InvalidConfigException {
+ int minSdk = json.getInt(CONFIG_KEY_MIN_SDK);
+ int maxSdk = json.getInt(CONFIG_KEY_MAX_SDK);
+ JSONArray valueArray = json.getJSONArray(CONFIG_KEY_VALUES);
+ Map<String, String> values = new HashMap<>();
+ for (int i = 0; i < valueArray.length(); ++i) {
+ JSONObject keyValuePair = valueArray.getJSONObject(i);
+ String key = keyValuePair.getString(CONFIG_KEY_KEY);
+ String value = keyValuePair.has(CONFIG_KEY_VALUE)
+ ? keyValuePair.getString(CONFIG_KEY_VALUE)
+ : null;
+ if (!allowedKeys.contains(key)) {
+ throw new InvalidConfigException("Config key " + key + " is not allowed");
+ }
+ values.put(key, value);
+ }
+ return new PerSdkConfig(minSdk, maxSdk, values);
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 7bf2c94..da997ba 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -183,7 +183,7 @@
@Override
public void onInitializeOverrideConfiguration(Configuration config) {
- getOverrideConfiguration().updateFrom(config);
+ getRequestedOverrideConfiguration().updateFrom(config);
}
void addChild(ActivityStack stack, int position) {
@@ -953,15 +953,16 @@
}
@Override
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
- final int currRotation = getOverrideConfiguration().windowConfiguration.getRotation();
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ final int currRotation =
+ getRequestedOverrideConfiguration().windowConfiguration.getRotation();
if (currRotation != ROTATION_UNDEFINED
&& currRotation != overrideConfiguration.windowConfiguration.getRotation()
&& getWindowContainerController() != null) {
getWindowContainerController().applyRotation(currRotation,
overrideConfiguration.windowConfiguration.getRotation());
}
- super.onOverrideConfigurationChanged(overrideConfiguration);
+ super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index daf4b8b..26a4cef 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -441,8 +441,13 @@
mLastReportedConfiguration.dump(pw, prefix + " ");
pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
- if (!getOverrideConfiguration().equals(EMPTY)) {
- pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
+ if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
+ pw.println(prefix + "RequestedOverrideConfiguration="
+ + getRequestedOverrideConfiguration());
+ }
+ if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
+ pw.println(prefix + "ResolvedOverrideConfiguration="
+ + getResolvedOverrideConfiguration());
}
if (!matchParentBounds()) {
pw.println(prefix + "bounds=" + getBounds());
@@ -2531,13 +2536,13 @@
mTmpConfig.unset();
computeBounds(mTmpBounds);
- if (mTmpBounds.equals(getOverrideBounds())) {
+ if (mTmpBounds.equals(getRequestedOverrideBounds())) {
return;
}
setBounds(mTmpBounds);
- final Rect updatedBounds = getOverrideBounds();
+ final Rect updatedBounds = getRequestedOverrideBounds();
// Bounds changed...update configuration to match.
if (!matchParentBounds()) {
@@ -2545,7 +2550,7 @@
false /* overrideWidth */, false /* overrideHeight */);
}
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
}
/** Returns true if the configuration is compatible with this activity. */
@@ -2602,11 +2607,11 @@
if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
// The display matches or is less than the activity aspect ratio, so nothing else to do.
// Return the existing bounds. If this method is running for the first time,
- // {@link #getOverrideBounds()} will be empty (representing no override). If the method has run
- // before, then effect of {@link #getOverrideBounds()} will already have been applied to the
- // value returned from {@link getConfiguration}. Refer to
- // {@link TaskRecord#computeOverrideConfiguration}.
- outBounds.set(getOverrideBounds());
+ // {@link #getRequestedOverrideBounds()} will be empty (representing no override). If
+ // the method has run before, then effect of {@link #getRequestedOverrideBounds()} will
+ // already have been applied to the value returned from {@link getConfiguration}. Refer
+ // to {@link TaskRecord#computeOverrideConfiguration}.
+ outBounds.set(getRequestedOverrideBounds());
return;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 3ccede0..c41a173 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -264,8 +264,8 @@
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
- mStackSupervisor.resizeDockedStackLocked(
- getOverrideBounds(), mTmpRect2, mTmpRect2, null, null, PRESERVE_WINDOWS);
+ mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect2,
+ mTmpRect2, null, null, PRESERVE_WINDOWS);
}
mRootActivityContainer.updateUIDsPresentOnDisplay();
}
@@ -562,7 +562,7 @@
// Update bounds if applicable
boolean hasNewOverrideBounds = false;
// Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+ if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
// Pinned calculation already includes rotation
mTmpRect2.set(mTmpRect);
hasNewOverrideBounds = getWindowContainerController().mContainer
@@ -589,8 +589,8 @@
|| prevScreenH != getConfiguration().screenHeightDp) {
// Use override windowing mode to prevent extra bounds changes if inheriting
// the mode.
- if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || getOverrideWindowingMode()
+ if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || getRequestedOverrideWindowingMode()
== WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
mTmpRect2.set(mTmpRect);
getWindowContainerController().mContainer
@@ -602,11 +602,12 @@
}
if (getWindowingMode() != prevWindowingMode) {
// Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
getStackDockedModeBounds(null, null, mTmpRect2, mTmpRect3);
// immediately resize so docked bounds are available in onSplitScreenModeActivated
resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
- } else if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+ } else if (
+ getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds();
final boolean isMinimizedDock = getDisplay().getWindowContainerController()
.mContainer.getDockedDividerController().isMinimizedDock();
@@ -672,7 +673,7 @@
void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
final int currentMode = getWindowingMode();
- final int currentOverrideMode = getOverrideWindowingMode();
+ final int currentOverrideMode = getRequestedOverrideWindowingMode();
final ActivityDisplay display = getDisplay();
final TaskRecord topTask = topTask();
final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
@@ -725,7 +726,7 @@
// You are already in the window mode, so we can skip most of the work below. However,
// it's possible that we have inherited the current windowing mode from a parent. So,
// fulfill this method's contract by setting the override mode directly.
- getOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
+ getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
return;
}
@@ -791,7 +792,7 @@
mWindowContainerController.getRawBounds(mTmpRect2);
}
- if (!Objects.equals(getOverrideBounds(), mTmpRect2)) {
+ if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
}
} finally {
@@ -4934,8 +4935,8 @@
// For freeform stack we don't adjust the size of the tasks to match that
// of the stack, but we do try to make sure the tasks are still contained
// with the bounds of the stack.
- if (task.getOverrideBounds() != null) {
- mTmpRect2.set(task.getOverrideBounds());
+ if (task.getRequestedOverrideBounds() != null) {
+ mTmpRect2.set(task.getRequestedOverrideBounds());
fitWithinBounds(mTmpRect2, bounds);
task.updateOverrideConfiguration(mTmpRect2);
}
@@ -4946,9 +4947,9 @@
if (task.hasDisplayedBounds()) {
mTmpBounds.put(task.taskId, task.getDisplayedBounds());
- mTmpInsetBounds.put(task.taskId, task.getOverrideBounds());
+ mTmpInsetBounds.put(task.taskId, task.getRequestedOverrideBounds());
} else {
- mTmpBounds.put(task.taskId, task.getOverrideBounds());
+ mTmpBounds.put(task.taskId, task.getRequestedOverrideBounds());
mTmpInsetBounds.put(task.taskId, null);
}
}
@@ -5191,7 +5192,7 @@
pw.println("");
}
pw.println(prefix + "Task id #" + task.taskId);
- pw.println(prefix + "mBounds=" + task.getOverrideBounds());
+ pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds());
pw.println(prefix + "mMinWidth=" + task.mMinWidth);
pw.println(prefix + "mMinHeight=" + task.mMinHeight);
pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
@@ -5349,7 +5350,7 @@
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
- task.updateOverrideConfiguration(getOverrideBounds());
+ task.updateOverrideConfiguration(getRequestedOverrideBounds());
}
task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
return task;
@@ -5541,7 +5542,7 @@
}
proto.write(DISPLAY_ID, mDisplayId);
if (!matchParentBounds()) {
- final Rect bounds = getOverrideBounds();
+ final Rect bounds = getRequestedOverrideBounds();
bounds.writeToProto(proto, BOUNDS);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index f3c5630..d92a9f2 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2410,7 +2410,7 @@
return;
}
- scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getOverrideBounds());
+ scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getRequestedOverrideBounds());
}
void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index e779d1b..ded45c9 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -49,20 +49,28 @@
*/
public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
- * {@link #Rect} returned from {@link #getOverrideBounds()} to prevent original value from being
- * set directly.
+ * {@link #Rect} returned from {@link #getRequestedOverrideBounds()} to prevent original value
+ * from being set directly.
*/
private Rect mReturnBounds = new Rect();
- /** Contains override configuration settings applied to this configuration container. */
- private Configuration mOverrideConfiguration = new Configuration();
+ /**
+ * Contains requested override configuration settings applied to this configuration container.
+ */
+ private Configuration mRequestedOverrideConfiguration = new Configuration();
- /** True if mOverrideConfiguration is not empty */
+ /**
+ * Contains the requested override configuration with parent and policy constraints applied.
+ * This is the set of overrides that gets applied to the full and merged configurations.
+ */
+ private Configuration mResolvedOverrideConfiguration = new Configuration();
+
+ /** True if mRequestedOverrideConfiguration is not empty */
private boolean mHasOverrideConfiguration;
/**
* Contains full configuration applied to this configuration container. Corresponds to full
- * parent's config with applied {@link #mOverrideConfiguration}.
+ * parent's config with applied {@link #mResolvedOverrideConfiguration}.
*/
private Configuration mFullConfiguration = new Configuration();
@@ -102,41 +110,62 @@
* @see #mFullConfiguration
*/
public void onConfigurationChanged(Configuration newParentConfig) {
+ mTmpConfig.setTo(mResolvedOverrideConfiguration);
+ resolveOverrideConfiguration(newParentConfig);
mFullConfiguration.setTo(newParentConfig);
- mFullConfiguration.updateFrom(mOverrideConfiguration);
+ mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
+ if (!mTmpConfig.equals(mResolvedOverrideConfiguration)) {
+ onMergedOverrideConfigurationChanged();
+ // This depends on the assumption that change-listeners don't do
+ // their own override resolution. This way, dependent hierarchies
+ // can stay properly synced-up with a primary hierarchy's constraints.
+ // Since the hierarchies will be merged, this whole thing will go away
+ // before the assumption will be broken.
+ // Inform listeners of the change.
+ for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
+ mChangeListeners.get(i).onRequestedOverrideConfigurationChanged(
+ mResolvedOverrideConfiguration);
+ }
+ }
for (int i = getChildCount() - 1; i >= 0; --i) {
final ConfigurationContainer child = getChildAt(i);
child.onConfigurationChanged(mFullConfiguration);
}
}
- /** Returns override configuration applied to this configuration container. */
- public Configuration getOverrideConfiguration() {
- return mOverrideConfiguration;
+ /**
+ * Resolves the current requested override configuration into
+ * {@link #mResolvedOverrideConfiguration}
+ *
+ * @param newParentConfig The new parent configuration to resolve overrides against.
+ */
+ void resolveOverrideConfiguration(Configuration newParentConfig) {
+ mResolvedOverrideConfiguration.setTo(mRequestedOverrideConfiguration);
+ }
+
+ /** Returns requested override configuration applied to this configuration container. */
+ public Configuration getRequestedOverrideConfiguration() {
+ return mRequestedOverrideConfiguration;
+ }
+
+ /** Returns the resolved override configuration. */
+ Configuration getResolvedOverrideConfiguration() {
+ return mResolvedOverrideConfiguration;
}
/**
* Update override configuration and recalculate full config.
- * @see #mOverrideConfiguration
+ * @see #mRequestedOverrideConfiguration
* @see #mFullConfiguration
*/
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
// Pre-compute this here, so we don't need to go through the entire Configuration when
// writing to proto (which has significant cost if we write a lot of empty configurations).
mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration);
- mOverrideConfiguration.setTo(overrideConfiguration);
+ mRequestedOverrideConfiguration.setTo(overrideConfiguration);
// Update full configuration of this container and all its children.
final ConfigurationContainer parent = getParent();
onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
- // Update merged override config of this container and all its children.
- onMergedOverrideConfigurationChanged();
-
- // Use the updated override configuration to notify listeners.
- mTmpConfig.setTo(mOverrideConfiguration);
- // Inform listeners of the change.
- for (int i = mChangeListeners.size() - 1; i >=0; --i) {
- mChangeListeners.get(i).onOverrideConfigurationChanged(mTmpConfig);
- }
}
/**
@@ -157,9 +186,9 @@
final ConfigurationContainer parent = getParent();
if (parent != null) {
mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration());
- mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration);
+ mMergedOverrideConfiguration.updateFrom(mResolvedOverrideConfiguration);
} else {
- mMergedOverrideConfiguration.setTo(mOverrideConfiguration);
+ mMergedOverrideConfiguration.setTo(mResolvedOverrideConfiguration);
}
for (int i = getChildCount() - 1; i >= 0; --i) {
final ConfigurationContainer child = getChildAt(i);
@@ -168,24 +197,26 @@
}
/**
- * Indicates whether this container has not specified any bounds different from its parent. In
- * this case, it will inherit the bounds of the first ancestor which specifies a bounds.
- * @return {@code true} if no explicit bounds have been set at this container level.
+ * Indicates whether this container has not requested any bounds different from its parent. In
+ * this case, it will inherit the bounds of the first ancestor which specifies a bounds subject
+ * to policy constraints.
+ *
+ * @return {@code true} if no explicit bounds have been requested at this container level.
* {@code false} otherwise.
*/
public boolean matchParentBounds() {
- return getOverrideBounds().isEmpty();
+ return getRequestedOverrideBounds().isEmpty();
}
/**
- * Returns whether the bounds specified is considered the same as the existing override bounds.
- * This is either when the two bounds are equal or the override bounds is empty and the
- * specified bounds is null.
+ * Returns whether the bounds specified are considered the same as the existing requested
+ * override bounds. This is either when the two bounds are equal or the requested override
+ * bounds are empty and the specified bounds is null.
*
* @return {@code true} if the bounds are equivalent, {@code false} otherwise
*/
- public boolean equivalentOverrideBounds(Rect bounds) {
- return equivalentBounds(getOverrideBounds(), bounds);
+ public boolean equivalentRequestedOverrideBounds(Rect bounds) {
+ return equivalentBounds(getRequestedOverrideBounds(), bounds);
}
/**
@@ -212,50 +243,52 @@
}
/**
- * Returns the current bounds explicitly set on this container. The {@link Rect} handed back is
+ * Returns the bounds requested on this container. These may not be the actual bounds the
+ * container ends up with due to policy constraints. The {@link Rect} handed back is
* shared for all calls to this method and should not be modified.
*/
- public Rect getOverrideBounds() {
- mReturnBounds.set(getOverrideConfiguration().windowConfiguration.getBounds());
+ public Rect getRequestedOverrideBounds() {
+ mReturnBounds.set(getRequestedOverrideConfiguration().windowConfiguration.getBounds());
return mReturnBounds;
}
/**
- * Returns {@code true} if the {@link WindowConfiguration} in the override
+ * Returns {@code true} if the {@link WindowConfiguration} in the requested override
* {@link Configuration} specifies bounds.
*/
public boolean hasOverrideBounds() {
- return !getOverrideBounds().isEmpty();
+ return !getRequestedOverrideBounds().isEmpty();
}
/**
* Sets the passed in {@link Rect} to the current bounds.
- * @see {@link #getOverrideBounds()}.
+ * @see {@link #getRequestedOverrideBounds()}.
*/
- public void getOverrideBounds(Rect outBounds) {
- outBounds.set(getOverrideBounds());
+ public void getRequestedOverrideBounds(Rect outBounds) {
+ outBounds.set(getRequestedOverrideBounds());
}
/**
* Sets the bounds at the current hierarchy level, overriding any bounds set on an ancestor.
- * This value will be reported when {@link #getBounds()} and {@link #getOverrideBounds()}. If
+ * This value will be reported when {@link #getBounds()} and
+ * {@link #getRequestedOverrideBounds()}. If
* an empty {@link Rect} or null is specified, this container will be considered to match its
* parent bounds {@see #matchParentBounds} and will inherit bounds from its parent.
* @param bounds The bounds defining the container size.
* @return a bitmask representing the types of changes made to the bounds.
*/
public int setBounds(Rect bounds) {
- int boundsChange = diffOverrideBounds(bounds);
+ int boundsChange = diffRequestedOverrideBounds(bounds);
if (boundsChange == BOUNDS_CHANGE_NONE) {
return boundsChange;
}
- mTmpConfig.setTo(getOverrideConfiguration());
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
mTmpConfig.windowConfiguration.setBounds(bounds);
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
return boundsChange;
}
@@ -265,14 +298,14 @@
return setBounds(mTmpRect);
}
- int diffOverrideBounds(Rect bounds) {
- if (equivalentOverrideBounds(bounds)) {
+ int diffRequestedOverrideBounds(Rect bounds) {
+ if (equivalentRequestedOverrideBounds(bounds)) {
return BOUNDS_CHANGE_NONE;
}
int boundsChange = BOUNDS_CHANGE_NONE;
- final Rect existingBounds = getOverrideBounds();
+ final Rect existingBounds = getRequestedOverrideBounds();
if (bounds == null || existingBounds.left != bounds.left
|| existingBounds.top != bounds.top) {
@@ -296,15 +329,16 @@
return mFullConfiguration.windowConfiguration.getWindowingMode();
}
- public int getOverrideWindowingMode() {
- return mOverrideConfiguration.windowConfiguration.getWindowingMode();
+ /** Returns the windowing mode override that is requested by this container. */
+ public int getRequestedOverrideWindowingMode() {
+ return mRequestedOverrideConfiguration.windowConfiguration.getWindowingMode();
}
- /** Sets the windowing mode for the configuration container. */
+ /** Sets the requested windowing mode override for the configuration container. */
public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) {
- mTmpConfig.setTo(getOverrideConfiguration());
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
mTmpConfig.windowConfiguration.setWindowingMode(windowingMode);
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
}
/** Sets the always on top flag for this configuration container.
@@ -314,16 +348,16 @@
* - {@Link ActivityDisplay#positionChildAtTop(ActivityStack)};
* */
public void setAlwaysOnTop(boolean alwaysOnTop) {
- mTmpConfig.setTo(getOverrideConfiguration());
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
mTmpConfig.windowConfiguration.setAlwaysOnTop(alwaysOnTop);
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
}
/** Sets the windowing mode for the configuration container. */
void setDisplayWindowingMode(int windowingMode) {
- mTmpConfig.setTo(getOverrideConfiguration());
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
mTmpConfig.windowConfiguration.setDisplayWindowingMode(windowingMode);
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
}
/**
@@ -393,9 +427,9 @@
throw new IllegalStateException("Can't change activity type once set: " + this
+ " activityType=" + activityTypeToString(activityType));
}
- mTmpConfig.setTo(getOverrideConfiguration());
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
mTmpConfig.windowConfiguration.setActivityType(activityType);
- onOverrideConfigurationChanged(mTmpConfig);
+ onRequestedOverrideConfigurationChanged(mTmpConfig);
}
public boolean isActivityTypeHome() {
@@ -472,7 +506,7 @@
return;
}
mChangeListeners.add(listener);
- listener.onOverrideConfigurationChanged(mOverrideConfiguration);
+ listener.onRequestedOverrideConfigurationChanged(mResolvedOverrideConfiguration);
}
public void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
@@ -508,7 +542,7 @@
public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
if (!trim || mHasOverrideConfiguration) {
- mOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION);
+ mRequestedOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION);
}
if (!trim) {
mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION);
@@ -526,7 +560,7 @@
pw.println(getName()
+ " type=" + activityTypeToString(getActivityType())
+ " mode=" + windowingModeToString(getWindowingMode())
- + " override-mode=" + windowingModeToString(getOverrideWindowingMode()));
+ + " override-mode=" + windowingModeToString(getRequestedOverrideWindowingMode()));
for (int i = getChildCount() - 1; i >= 0; --i) {
final E cc = getChildAt(i);
pw.print(childPrefix + "#" + i + " ");
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
index ff14d97..dc4939d 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
@@ -23,5 +23,6 @@
*/
public interface ConfigurationContainerListener {
- void onOverrideConfigurationChanged(Configuration overrideConfiguration);
+ /** {@see ConfigurationContainer#onRequestedOverrideConfigurationChanged} */
+ void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration);
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index 55b3def..c7eadf9 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -87,7 +87,7 @@
}
@Override
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
synchronized (mGlobalLock) {
if (mContainer != null) {
mContainer.mWmService.setNewDisplayOverrideConfiguration(overrideConfiguration,
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 1e287b4..9422182 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -47,7 +47,7 @@
import com.android.server.LocalServices;
import com.android.server.am.AssistDataRequester;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
import java.util.List;
@@ -225,8 +225,8 @@
public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
int activityCount) {
// Try to notify the intelligence service first
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder activityToken = topActivities.get(activityIndex);
if (imService == null
|| !imService.sendActivityAssistData(userId, activityToken, data)) {
@@ -236,8 +236,8 @@
}
};
} else {
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
if (imService == null) {
// There is no intelligence service, so there is no point requesting assist data
return;
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 1d86b46..f7877c0 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -864,7 +864,7 @@
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
- resizeStack(stack, task.getOverrideBounds(), null /* tempTaskBounds */,
+ resizeStack(stack, task.getRequestedOverrideBounds(), null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
@@ -1297,7 +1297,7 @@
throw new IllegalArgumentException("No display found with id: " + displayId);
}
- return activityDisplay.getOverrideConfiguration();
+ return activityDisplay.getRequestedOverrideConfiguration();
}
void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
@@ -1306,7 +1306,7 @@
throw new IllegalArgumentException("No display found with id: " + displayId);
}
- activityDisplay.onOverrideConfigurationChanged(overrideConfiguration);
+ activityDisplay.onRequestedOverrideConfigurationChanged(overrideConfiguration);
}
void prepareForShutdown() {
@@ -2161,7 +2161,7 @@
for (int i = 0; i < displayCount; i++) {
final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
- pw.println(activityDisplay.getOverrideConfiguration());
+ pw.println(activityDisplay.getRequestedOverrideConfiguration());
}
}
@@ -2190,7 +2190,7 @@
+ ": type=" + activityTypeToString(stack.getActivityType())
+ " mode=" + windowingModeToString(stack.getWindowingMode()));
pw.println(" isSleeping=" + stack.shouldSleepActivities());
- pw.println(" mBounds=" + stack.getOverrideBounds());
+ pw.println(" mBounds=" + stack.getRequestedOverrideBounds());
printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
needSep);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b98d154..3a5c578 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -265,7 +265,7 @@
DisplayContent displayContent) {
if (controller != null && controller.mListener != null) {
controller.mListener.onInitializeOverrideConfiguration(
- displayContent.getOverrideConfiguration());
+ displayContent.getRequestedOverrideConfiguration());
}
}
@@ -356,13 +356,13 @@
void setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration,
@NonNull DisplayContent displayContent) {
- final Configuration currentConfig = displayContent.getOverrideConfiguration();
+ final Configuration currentConfig = displayContent.getRequestedOverrideConfiguration();
final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
if (!configChanged) {
return;
}
- displayContent.onOverrideConfigurationChanged(newConfiguration);
+ displayContent.onRequestedOverrideConfigurationChanged(newConfiguration);
if (displayContent.getDisplayId() == DEFAULT_DISPLAY) {
// Override configuration of the default display duplicates global config. In this case
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c70f075..67657d0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -119,7 +119,7 @@
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
setController(controller);
- setBounds(getOverrideBounds());
+ setBounds(getRequestedOverrideBounds());
mTaskDescription = taskDescription;
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
@@ -369,7 +369,7 @@
* the adjusted bounds's top.
*/
void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
- if (!isResizeable() || EMPTY.equals(getOverrideConfiguration())) {
+ if (!isResizeable() || EMPTY.equals(getRequestedOverrideConfiguration())) {
return;
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 3cf0bd7..b6a6009 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -506,7 +506,7 @@
// If this is a forced resize, let it go through even if the bounds is not changing,
// as we might need a relayout due to surface size change (to/from fullscreen).
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
- if (equivalentOverrideBounds(bounds) && !forced) {
+ if (equivalentRequestedOverrideBounds(bounds) && !forced) {
// Nothing to do here...
return true;
}
@@ -720,12 +720,12 @@
// Make sure the task has the appropriate bounds/size for the stack it is in.
final boolean toStackSplitScreenPrimary =
toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- final Rect configBounds = getOverrideBounds();
+ final Rect configBounds = getRequestedOverrideBounds();
if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
|| toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
- && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
- kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
- deferResume);
+ && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
+ kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
+ !mightReplaceWindow, deferResume);
} else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Rect bounds = getLaunchBounds();
if (bounds == null) {
@@ -739,8 +739,8 @@
// mode
mService.mStackSupervisor.moveRecentsStackToFront(reason);
}
- kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
- deferResume);
+ kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
+ !mightReplaceWindow, deferResume);
}
} finally {
windowManager.continueSurfaceLayout();
@@ -1546,7 +1546,7 @@
return true;
}
final boolean landscape = bounds.width() > bounds.height();
- final Rect configBounds = getOverrideBounds();
+ final Rect configBounds = getRequestedOverrideBounds();
if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
return configBounds.isEmpty()
|| landscape == (configBounds.width() > configBounds.height());
@@ -1709,7 +1709,7 @@
return;
}
- final Rect configBounds = getOverrideBounds();
+ final Rect configBounds = getRequestedOverrideBounds();
if (adjustWidth) {
if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
bounds.left = bounds.right - minWidth;
@@ -1739,7 +1739,7 @@
// (bounds == null), then leave the override config unset
final Configuration newOverrideConfig = new Configuration();
if (bounds != null) {
- newOverrideConfig.setTo(getOverrideConfiguration());
+ newOverrideConfig.setTo(getRequestedOverrideConfiguration());
if (insetBounds != null && !insetBounds.isEmpty()) {
mTmpRect.set(insetBounds);
setDisplayedBounds(bounds);
@@ -1781,13 +1781,13 @@
* @return True if the override configuration was updated.
*/
boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
- if (equivalentOverrideBounds(bounds)) {
+ if (equivalentRequestedOverrideBounds(bounds)) {
return false;
}
- final Rect currentBounds = getOverrideBounds();
+ final Rect currentBounds = getRequestedOverrideBounds();
- mTmpConfig.setTo(getOverrideConfiguration());
- final Configuration newConfig = getOverrideConfiguration();
+ mTmpConfig.setTo(getRequestedOverrideConfiguration());
+ final Configuration newConfig = getRequestedOverrideConfiguration();
final boolean matchParentBounds = bounds == null || bounds.isEmpty();
final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
@@ -1810,12 +1810,12 @@
setBounds(mTmpRect);
if (mStack == null || persistBounds) {
- setLastNonFullscreenBounds(getOverrideBounds());
+ setLastNonFullscreenBounds(getRequestedOverrideBounds());
}
computeOverrideConfiguration(newConfig, mTmpRect,
mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
}
- onOverrideConfigurationChanged(newConfig);
+ onRequestedOverrideConfigurationChanged(newConfig);
return !mTmpConfig.equals(newConfig);
}
@@ -1949,7 +1949,7 @@
if (bounds != null && !bounds.isEmpty()) {
// TODO: Review if we actually want to do this - we are setting the launch bounds
// directly here.
- bounds.set(getOverrideBounds());
+ bounds.set(getRequestedOverrideBounds());
}
return bounds;
}
@@ -1975,7 +1975,7 @@
mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
}
} else {
- updateOverrideConfiguration(inStack.getOverrideBounds());
+ updateOverrideConfiguration(inStack.getRequestedOverrideBounds());
}
}
@@ -1989,9 +1989,9 @@
if (!isActivityTypeStandardOrUndefined()
|| windowingMode == WINDOWING_MODE_FULLSCREEN
|| (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
- return isResizeable() ? mStack.getOverrideBounds() : null;
+ return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
} else if (!getWindowConfiguration().persistTaskBounds()) {
- return mStack.getOverrideBounds();
+ return mStack.getRequestedOverrideBounds();
}
return mLastNonFullscreenBounds;
}
@@ -2210,7 +2210,7 @@
proto.write(FULLSCREEN, matchParentBounds());
if (!matchParentBounds()) {
- final Rect bounds = getOverrideBounds();
+ final Rect bounds = getRequestedOverrideBounds();
bounds.writeToProto(proto, BOUNDS);
}
proto.write(MIN_WIDTH, mMinWidth);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b16e184c..11d9ebb 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -282,7 +282,7 @@
@Override
public int setBounds(Rect bounds) {
- return setBounds(getOverrideBounds(), bounds);
+ return setBounds(getRequestedOverrideBounds(), bounds);
}
private int setBounds(Rect existing, Rect bounds) {
@@ -304,8 +304,8 @@
/** Bounds of the stack without adjusting for other factors in the system like visibility
* of docked stack.
- * Most callers should be using {@link ConfigurationContainer#getOverrideBounds} as it take into
- * consideration other system factors. */
+ * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
+ * it takes into consideration other system factors. */
void getRawBounds(Rect out) {
out.set(getRawBounds());
}
@@ -448,7 +448,8 @@
* @param inOutBounds the bounds to update (both input and output).
*/
void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
- final boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ final boolean primary =
+ getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index ec64d2e..b87b65e 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -157,7 +157,8 @@
throw new IllegalArgumentException("resizeTask: taskId " + mTaskId + " not found.");
}
- if (mContainer.setBounds(mContainer.getOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
+ if (mContainer.setBounds(
+ mContainer.getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE
&& relayout) {
mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index c30cc17..651089d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -469,15 +469,16 @@
/**
* Update override configuration and recalculate full config.
- * @see #mOverrideConfiguration
+ * @see #mRequestedOverrideConfiguration
* @see #mFullConfiguration
*/
@Override
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
// We must diff before the configuration is applied so that we can capture the change
// against the existing bounds.
- final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
- super.onOverrideConfigurationChanged(overrideConfiguration);
+ final int diff = diffRequestedOverrideBounds(
+ overrideConfiguration.windowConfiguration.getBounds());
+ super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
if (mParent != null) {
mParent.onDescendantOverrideConfigurationChanged();
}
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
index 7cb89c5..17bc0e2 100644
--- a/services/core/java/com/android/server/wm/WindowContainerController.java
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -72,12 +72,12 @@
}
@Override
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
synchronized (mGlobalLock) {
if (mContainer == null) {
return;
}
- mContainer.onOverrideConfigurationChanged(overrideConfiguration);
+ mContainer.onRequestedOverrideConfigurationChanged(overrideConfiguration);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2dec4dd..f7f7528 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -770,8 +770,8 @@
}
@Override
- public void onOverrideConfigurationChanged(Configuration newOverrideConfig) {
- super.onOverrideConfigurationChanged(newOverrideConfig);
+ public void onRequestedOverrideConfigurationChanged(Configuration newOverrideConfig) {
+ super.onRequestedOverrideConfigurationChanged(newOverrideConfig);
updateConfiguration();
}
@@ -924,7 +924,7 @@
}
}
pw.println(prefix + " Configuration=" + getConfiguration());
- pw.println(prefix + " OverrideConfiguration=" + getOverrideConfiguration());
+ pw.println(prefix + " OverrideConfiguration=" + getRequestedOverrideConfiguration());
pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e115fed..d2dfa76 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2836,6 +2836,7 @@
break;
}
}
+ cropRegionToStackBoundsIfNeeded(outRegion);
if (forSurface) {
if (mTouchableInsets != TOUCHABLE_INSETS_REGION) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f68f4d7..bca3b1f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4890,14 +4890,16 @@
private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
int flags, int callingUid, int userHandle) {
int quality;
+ final int realQuality;
synchronized (getLockObject()) {
quality = getPasswordQuality(null, userHandle, /* parent */ false);
if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
quality = PASSWORD_QUALITY_UNSPECIFIED;
}
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
+ realQuality = metrics.quality;
if (quality != PASSWORD_QUALITY_UNSPECIFIED) {
- final int realQuality = metrics.quality;
+
if (realQuality < quality
&& quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
Slog.w(LOG_TAG, "resetPassword: password quality 0x"
@@ -4984,7 +4986,7 @@
try {
if (token == null) {
if (!TextUtils.isEmpty(password)) {
- mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
+ mLockPatternUtils.saveLockPassword(password, null, realQuality, userHandle);
} else {
mLockPatternUtils.clearLock(null, userHandle);
}
@@ -4993,7 +4995,7 @@
result = mLockPatternUtils.setLockCredentialWithToken(password,
TextUtils.isEmpty(password) ? LockPatternUtils.CREDENTIAL_TYPE_NONE
: LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
- quality, tokenHandle, token, userHandle);
+ realQuality, tokenHandle, token, userHandle);
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
deleted file mode 100644
index c4fbdca..0000000
--- a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.IIntelligenceService;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
-
-import java.util.List;
-
-//TODO(b/111276913): rename once the final name is defined
-final class RemoteIntelligenceService
- extends AbstractMultiplePendingRequestsRemoteService<RemoteIntelligenceService> {
-
- private static final String TAG = "RemoteIntelligenceService";
-
- private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
- private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
-
- private final RemoteIntelligenceServiceCallbacks mCallbacks;
- private IIntelligenceService mService;
-
- RemoteIntelligenceService(Context context, String serviceInterface,
- ComponentName componentName, int userId,
- RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
- boolean verbose) {
- super(context, serviceInterface, componentName, userId, callbacks,
- bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
- mCallbacks = callbacks;
- }
-
- @Override // from RemoteService
- protected IInterface getServiceInterface(@NonNull IBinder service) {
- mService = IIntelligenceService.Stub.asInterface(service);
- return mService;
- }
-
- // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
- @Override // from RemoteService
- protected long getTimeoutIdleBindMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_IDLE_BIND_MILLIS;
- }
-
- @Override // from RemoteService
- protected long getRemoteRequestMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_REMOTE_REQUEST_MILLIS;
- }
-
- /**
- * Called by {@link ContentCaptureSession} to generate a call to the
- * {@link RemoteIntelligenceService} to indicate the session was created (when {@code context}
- * is not {@code null} or destroyed (when {@code context} is {@code null}).
- */
- public void onSessionLifecycleRequest(@Nullable InteractionContext context,
- @NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send a batch of events to the service.
- */
- public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send snapshot data to the service.
- */
- public void onActivitySnapshotRequest(@NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to request augmented autofill.
- */
- public void onRequestAutofillLocked(@NonNull InteractionSessionId sessionId,
- @NonNull IAutoFillManagerClient client, int autofillSessionId,
- @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingAutofillRequest(this, sessionId, client, autofillSessionId,
- focusedId, focusedValue));
- }
-
- /**
- * Called by {@link ContentCaptureSession} when it's time to destroy all augmented autofill
- * requests.
- */
- public void onDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
- }
-
- private abstract static class MyPendingRequest
- extends PendingRequest<RemoteIntelligenceService> {
- protected final InteractionSessionId mSessionId;
-
- private MyPendingRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service);
- mSessionId = sessionId;
- }
-
- @Override // from PendingRequest
- protected final void onTimeout(RemoteIntelligenceService remoteService) {
- Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
- + mSessionId);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
- }
-
- @Override // from PendingRequest
- public final void run() {
- final RemoteIntelligenceService remoteService = getService();
- if (remoteService != null) {
- try {
- // We don't expect the service to call us back, so we finish right away.
- myRun(remoteService);
- // TODO(b/111330312): not true anymore!!
- finish();
- } catch (RemoteException e) {
- Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
- + mSessionId + ": " + e);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
- }
- }
- }
-
- protected abstract void myRun(@NonNull RemoteIntelligenceService service)
- throws RemoteException;
-
- }
-
- private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
-
- private final InteractionContext mContext;
-
- protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
- @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- mContext = context;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onSessionLifecycle(mContext, mSessionId);
- }
- }
-
- private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
-
- private final List<ContentCaptureEvent> mEvents;
-
- protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- super(service, sessionId);
- mEvents = events;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onContentCaptureEventsRequest(mSessionId,
- new ContentCaptureEventsRequest(mEvents));
- }
- }
-
- private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
-
- private final SnapshotData mSnapshotData;
-
- protected PendingOnActivitySnapshotRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- super(service, sessionId);
- mSnapshotData = snapshotData;
- }
-
- @Override // from MyPendingRequest
- protected void myRun(@NonNull RemoteIntelligenceService remoteService)
- throws RemoteException {
- remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
- }
- }
-
- private static final class PendingAutofillRequest extends MyPendingRequest {
- private final @NonNull AutofillId mFocusedId;
- private final @Nullable AutofillValue mFocusedValue;
- private final @NonNull IAutoFillManagerClient mClient;
- private final int mAutofillSessionId;
- private final long mRequestTime = SystemClock.elapsedRealtime();
-
- protected PendingAutofillRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId, @NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- super(service, sessionId);
- mClient = client;
- mAutofillSessionId = autofillSessionId;
- mFocusedId = focusedId;
- mFocusedValue = focusedValue;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- final IResultReceiver receiver = new IResultReceiver.Stub() {
-
- @Override
- public void send(int resultCode, Bundle resultData) throws RemoteException {
- final IBinder realClient = resultData
- .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
- remoteService.mService.onAutofillRequest(mSessionId, realClient,
- mAutofillSessionId, mFocusedId, mFocusedValue, mRequestTime);
- }
- };
-
- // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
- // cache IAugmentedAutofillManagerClient reference, etc...
- mClient.getAugmentedAutofillClient(receiver);
- }
- }
-
- private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
-
- protected PendingDestroyAutofillWindowsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- }
-
- @Override
- protected void myRun(@NonNull RemoteIntelligenceService service) throws RemoteException {
- service.mService.onDestroyAutofillWindowsRequest(mSessionId);
- // TODO(b/111330312): implement timeout
- }
- }
-
- public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
- // To keep it simple, we use the same callback for all failures / timeouts.
- void onFailureOrTimeout(boolean timedOut);
- }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c4d2a91..2baef6af 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -239,8 +239,8 @@
"com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
"com.android.server.autofill.AutofillManagerService";
- private static final String INTELLIGENCE_MANAGER_SERVICE_CLASS =
- "com.android.server.intelligence.IntelligenceManagerService";
+ private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
+ "com.android.server.contentcapture.ContentCaptureManagerService";
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
"com.android.server.timezone.RulesManagerService$Lifecycle";
private static final String IOT_SERVICE_CLASS =
@@ -1136,7 +1136,7 @@
traceEnd();
}
- startIntelligenceService(context);
+ startContentCaptureService(context);
// NOTE: ClipboardService indirectly depends on IntelligenceService
traceBeginAndSlog("StartClipboardService");
@@ -1398,6 +1398,15 @@
traceEnd();
}
+ // Start ADB Debugging Service
+ traceBeginAndSlog("StartAdbService");
+ try {
+ mSystemServiceManager.startService(ADB_SERVICE_CLASS);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting AdbService");
+ }
+ traceEnd();
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
|| mPackageManager.hasSystemFeature(
PackageManager.FEATURE_USB_ACCESSORY)
@@ -1408,15 +1417,6 @@
traceEnd();
}
- // Start ADB Debugging Service
- traceBeginAndSlog("StartAdbService");
- try {
- mSystemServiceManager.startService(ADB_SERVICE_CLASS);
- } catch (Throwable e) {
- Slog.e(TAG, "Failure starting AdbService");
- }
- traceEnd();
-
if (!isWatch) {
traceBeginAndSlog("StartSerialService");
try {
@@ -2100,18 +2100,18 @@
}, BOOT_TIMINGS_TRACE_LOG);
}
- private void startIntelligenceService(@NonNull Context context) {
+ private void startContentCaptureService(@NonNull Context context) {
// First check if it was explicitly enabled by Settings
boolean explicitlySupported = false;
final String settings = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED);
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED);
if (settings != null) {
explicitlySupported = Boolean.parseBoolean(settings);
if (explicitlySupported) {
- Slog.d(TAG, "IntelligenceService explicitly enabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly enabled by Settings");
} else {
- Slog.d(TAG, "IntelligenceService explicitly disabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly disabled by Settings");
return;
}
}
@@ -2119,15 +2119,15 @@
// Then check if OEM overlaid the resource that defines the service.
if (!explicitlySupported) {
final String serviceName = context
- .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService);
+ .getString(com.android.internal.R.string.config_defaultContentCaptureService);
if (TextUtils.isEmpty(serviceName)) {
- Slog.d(TAG, "IntelligenceService disabled because config resource is not overlaid");
+ Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
return;
}
}
- traceBeginAndSlog("StartIntelligenceService");
- mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+ traceBeginAndSlog("StartContentCaptureService");
+ mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
traceEnd();
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 5dc6d83..c3a0dda 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4163,7 +4163,7 @@
// test reset password with token
when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password),
eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD),
- eq(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED), eq(handle), eq(token),
+ eq(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC), eq(handle), eq(token),
eq(UserHandle.USER_SYSTEM)))
.thenReturn(true);
assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
diff --git a/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java b/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java
new file mode 100644
index 0000000..a9d4519
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/signedconfig/SignedConfigTest.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.signedconfig;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import static java.util.Collections.emptySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Sets;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+
+/**
+ * Tests for {@link SignedConfig}
+ */
+@RunWith(AndroidJUnit4.class)
+public class SignedConfigTest {
+
+ private static Set<String> setOf(String... values) {
+ return Sets.newHashSet(values);
+ }
+
+ @Test
+ public void testParsePerSdkConfigSdkMinMax() throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject("{\"minSdk\":2, \"maxSdk\": 3, \"values\": []}");
+ SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, emptySet());
+ assertThat(config.minSdk).isEqualTo(2);
+ assertThat(config.maxSdk).isEqualTo(3);
+ }
+
+ @Test
+ public void testParsePerSdkConfigNoMinSdk() throws JSONException {
+ JSONObject json = new JSONObject("{\"maxSdk\": 3, \"values\": []}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigNoMaxSdk() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"values\": []}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigNoValues() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigSdkNullMinSdk() throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject("{\"minSdk\":null, \"maxSdk\": 3, \"values\": []}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigSdkNullMaxSdk() throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject("{\"minSdk\":1, \"maxSdk\": null, \"values\": []}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigNullValues() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3, \"values\": null}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigZeroValues()
+ throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 3, \"values\": []}");
+ SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+ assertThat(config.values).hasSize(0);
+ }
+
+ @Test
+ public void testParsePerSdkConfigSingleKey()
+ throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject(
+ "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}]}");
+ SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+ assertThat(config.values).containsExactly("a", "1");
+ }
+
+ @Test
+ public void testParsePerSdkConfigMultiKeys()
+ throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject(
+ "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}, "
+ + "{\"key\":\"c\", \"value\": \"2\"}]}");
+ SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(
+ json, setOf("a", "b", "c"));
+ assertThat(config.values).containsExactly("a", "1", "c", "2");
+ }
+
+ @Test
+ public void testParsePerSdkConfigSingleKeyNotAllowed() throws JSONException {
+ JSONObject json = new JSONObject(
+ "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\", \"value\": \"1\"}]}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, setOf("b"));
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigSingleKeyNoValue()
+ throws JSONException, InvalidConfigException {
+ JSONObject json = new JSONObject(
+ "{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [{\"key\":\"a\"}]}");
+ SignedConfig.PerSdkConfig config = SignedConfig.parsePerSdkConfig(json, setOf("a", "b"));
+ assertThat(config.values).containsExactly("a", null);
+ }
+
+ @Test
+ public void testParsePerSdkConfigValuesInvalid() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1, \"values\": \"foo\"}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigConfigEntryInvalid() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [1, 2]}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParsePerSdkConfigConfigEntryNull() throws JSONException {
+ JSONObject json = new JSONObject("{\"minSdk\": 1, \"maxSdk\": 1, \"values\": [null]}");
+ try {
+ SignedConfig.parsePerSdkConfig(json, emptySet());
+ fail("Expected InvalidConfigException or JSONException");
+ } catch (JSONException | InvalidConfigException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParseVersion() throws InvalidConfigException {
+ SignedConfig config = SignedConfig.parse(
+ "{\"version\": 1, \"config\": []}", emptySet());
+ assertThat(config.version).isEqualTo(1);
+ }
+
+ @Test
+ public void testParseVersionInvalid() {
+ try {
+ SignedConfig.parse("{\"version\": \"notanint\", \"config\": []}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseNoVersion() {
+ try {
+ SignedConfig.parse("{\"config\": []}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseNoConfig() {
+ try {
+ SignedConfig.parse("{\"version\": 1}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseConfigNull() {
+ try {
+ SignedConfig.parse("{\"version\": 1, \"config\": null}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseVersionNull() {
+ try {
+ SignedConfig.parse("{\"version\": null, \"config\": []}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseConfigInvalidEntry() {
+ try {
+ SignedConfig.parse("{\"version\": 1, \"config\": [{}]}", emptySet());
+ fail("Expected InvalidConfigException");
+ } catch (InvalidConfigException e) {
+ //expected
+ }
+ }
+
+ @Test
+ public void testParseSdkConfigSingle() throws InvalidConfigException {
+ SignedConfig config = SignedConfig.parse(
+ "{\"version\": 1, \"config\":[{\"minSdk\": 1, \"maxSdk\": 1, \"values\": []}]}",
+ emptySet());
+ assertThat(config.perSdkConfig).hasSize(1);
+ }
+
+ @Test
+ public void testParseSdkConfigMultiple() throws InvalidConfigException {
+ SignedConfig config = SignedConfig.parse(
+ "{\"version\": 1, \"config\":[{\"minSdk\": 1, \"maxSdk\": 1, \"values\": []}, "
+ + "{\"minSdk\": 2, \"maxSdk\": 2, \"values\": []}]}", emptySet());
+ assertThat(config.perSdkConfig).hasSize(2);
+ }
+
+ @Test
+ public void testGetMatchingConfigFirst() {
+ SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+ 1, 1, Collections.emptyMap());
+ SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+ 2, 2, Collections.emptyMap());
+ SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+ assertThat(config.getMatchingConfig(1)).isEqualTo(sdk1);
+ }
+
+ @Test
+ public void testGetMatchingConfigSecond() {
+ SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+ 1, 1, Collections.emptyMap());
+ SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+ 2, 2, Collections.emptyMap());
+ SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+ assertThat(config.getMatchingConfig(2)).isEqualTo(sdk2);
+ }
+
+ @Test
+ public void testGetMatchingConfigInRange() {
+ SignedConfig.PerSdkConfig sdk13 = new SignedConfig.PerSdkConfig(
+ 1, 3, Collections.emptyMap());
+ SignedConfig.PerSdkConfig sdk46 = new SignedConfig.PerSdkConfig(
+ 4, 6, Collections.emptyMap());
+ SignedConfig config = new SignedConfig(0, Arrays.asList(sdk13, sdk46));
+ assertThat(config.getMatchingConfig(2)).isEqualTo(sdk13);
+ }
+
+ @Test
+ public void testGetMatchingConfigNoMatch() {
+ SignedConfig.PerSdkConfig sdk1 = new SignedConfig.PerSdkConfig(
+ 1, 1, Collections.emptyMap());
+ SignedConfig.PerSdkConfig sdk2 = new SignedConfig.PerSdkConfig(
+ 2, 2, Collections.emptyMap());
+ SignedConfig config = new SignedConfig(0, Arrays.asList(sdk1, sdk2));
+ assertThat(config.getMatchingConfig(3)).isNull();
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 048384e..f6871b3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -162,7 +162,8 @@
assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
// Ensure that the override mode is restored to undefined
- assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_UNDEFINED,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
}
@Test
@@ -184,7 +185,8 @@
assertEquals(0, mDefaultDisplay.getIndexOf(primarySplitScreen));
// Ensure that the override mode is restored to what it was (fullscreen)
- assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_FULLSCREEN,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
}
@Test
@@ -193,11 +195,13 @@
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
- assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_UNDEFINED,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(WINDOWING_MODE_FREEFORM, primarySplitScreen.getWindowingMode());
- assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_UNDEFINED,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
}
@Test
@@ -206,11 +210,13 @@
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
- assertEquals(WINDOWING_MODE_UNDEFINED, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_UNDEFINED,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
primarySplitScreen.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
// setting windowing mode should still work even though resolved mode is already fullscreen
- assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getOverrideWindowingMode());
+ assertEquals(WINDOWING_MODE_FULLSCREEN,
+ primarySplitScreen.getRequestedOverrideWindowingMode());
mDefaultDisplay.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 5c918b4..7c43cf3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -135,8 +135,8 @@
final Rect bounds = new Rect(10, 10, 100, 100);
mStarter.updateBounds(task, bounds);
- assertEquals(bounds, task.getOverrideBounds());
- assertEquals(new Rect(), task.getStack().getOverrideBounds());
+ assertEquals(bounds, task.getRequestedOverrideBounds());
+ assertEquals(new Rect(), task.getStack().getRequestedOverrideBounds());
// When in a resizeable stack, the stack bounds should be updated as well.
final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
@@ -151,10 +151,10 @@
// In the case of no animation, the stack and task bounds should be set immediately.
if (!ANIMATE) {
- assertEquals(bounds, task2.getStack().getOverrideBounds());
- assertEquals(bounds, task2.getOverrideBounds());
+ assertEquals(bounds, task2.getStack().getRequestedOverrideBounds());
+ assertEquals(bounds, task2.getRequestedOverrideBounds());
} else {
- assertEquals(new Rect(), task2.getOverrideBounds());
+ assertEquals(new Rect(), task2.getRequestedOverrideBounds());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 0ee532d..92b4dbb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -155,15 +155,15 @@
// Set initial orientation and update.
mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
- mWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
- mDisplayContent.getDisplayId());
+ mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
+ null, mDisplayContent.getDisplayId());
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
appWindow.mResizeReported = false;
// Update the orientation to perform 180 degree rotation and check that resize was reported.
mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
- mWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
- mDisplayContent.getDisplayId());
+ mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
+ null, mDisplayContent.getDisplayId());
mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
assertTrue(appWindow.mResizeReported);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
index 82a200b..e7f7d21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
@@ -27,6 +27,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -55,22 +56,22 @@
public void testConfigurationInit() {
// Check root container initial config.
final TestConfigurationContainer root = new TestConfigurationContainer();
- assertEquals(EMPTY, root.getOverrideConfiguration());
+ assertEquals(EMPTY, root.getRequestedOverrideConfiguration());
assertEquals(EMPTY, root.getMergedOverrideConfiguration());
assertEquals(EMPTY, root.getConfiguration());
// Check child initial config.
final TestConfigurationContainer child1 = root.addChild();
- assertEquals(EMPTY, child1.getOverrideConfiguration());
+ assertEquals(EMPTY, child1.getRequestedOverrideConfiguration());
assertEquals(EMPTY, child1.getMergedOverrideConfiguration());
assertEquals(EMPTY, child1.getConfiguration());
// Check child initial config if root has overrides.
final Configuration rootOverrideConfig = new Configuration();
rootOverrideConfig.fontScale = 1.3f;
- root.onOverrideConfigurationChanged(rootOverrideConfig);
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
final TestConfigurationContainer child2 = root.addChild();
- assertEquals(EMPTY, child2.getOverrideConfiguration());
+ assertEquals(EMPTY, child2.getRequestedOverrideConfiguration());
assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
assertEquals(rootOverrideConfig, child2.getConfiguration());
@@ -83,7 +84,7 @@
rootFullConfig.updateFrom(rootOverrideConfig);
final TestConfigurationContainer child3 = root.addChild();
- assertEquals(EMPTY, child3.getOverrideConfiguration());
+ assertEquals(EMPTY, child3.getRequestedOverrideConfiguration());
assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
assertEquals(rootFullConfig, child3.getConfiguration());
}
@@ -94,24 +95,24 @@
final TestConfigurationContainer root = new TestConfigurationContainer();
final Configuration rootOverrideConfig = new Configuration();
rootOverrideConfig.fontScale = 1.3f;
- root.onOverrideConfigurationChanged(rootOverrideConfig);
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
// Init child's config.
final TestConfigurationContainer child = root.addChild();
final Configuration childOverrideConfig = new Configuration();
childOverrideConfig.densityDpi = 320;
- child.onOverrideConfigurationChanged(childOverrideConfig);
+ child.onRequestedOverrideConfigurationChanged(childOverrideConfig);
final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
mergedOverrideConfig.updateFrom(childOverrideConfig);
// Check configuration update when child is removed from parent.
root.removeChild(child);
- assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+ assertEquals(childOverrideConfig, child.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
assertEquals(mergedOverrideConfig, child.getConfiguration());
// It may be paranoia... but let's check if parent's config didn't change after removal.
- assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
assertEquals(rootOverrideConfig, root.getConfiguration());
@@ -119,13 +120,13 @@
final TestConfigurationContainer root2 = new TestConfigurationContainer();
final Configuration rootOverrideConfig2 = new Configuration();
rootOverrideConfig2.fontScale = 1.1f;
- root2.onOverrideConfigurationChanged(rootOverrideConfig2);
+ root2.onRequestedOverrideConfigurationChanged(rootOverrideConfig2);
// Check configuration update when child is added to different parent.
mergedOverrideConfig.setTo(rootOverrideConfig2);
mergedOverrideConfig.updateFrom(childOverrideConfig);
root2.addChild(child);
- assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+ assertEquals(childOverrideConfig, child.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
assertEquals(mergedOverrideConfig, child.getConfiguration());
}
@@ -141,24 +142,24 @@
final Configuration rootOverrideConfig = new Configuration();
rootOverrideConfig.fontScale = 1.3f;
rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
- root.onOverrideConfigurationChanged(rootOverrideConfig);
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
// Init children.
final TestConfigurationContainer child1 = root.addChild();
final Configuration childOverrideConfig1 = new Configuration();
childOverrideConfig1.densityDpi = 320;
childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
- child1.onOverrideConfigurationChanged(childOverrideConfig1);
+ child1.onRequestedOverrideConfigurationChanged(childOverrideConfig1);
final TestConfigurationContainer child2 = child1.addChild();
final Configuration childOverrideConfig2 = new Configuration();
childOverrideConfig2.screenWidthDp = 150;
childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
- child2.onOverrideConfigurationChanged(childOverrideConfig2);
+ child2.onRequestedOverrideConfigurationChanged(childOverrideConfig2);
// Check configuration on all levels when root override is updated.
rootOverrideConfig.smallestScreenWidthDp = 200;
- root.onOverrideConfigurationChanged(rootOverrideConfig);
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
mergedOverrideConfig1.updateFrom(childOverrideConfig1);
@@ -168,15 +169,15 @@
mergedOverrideConfig2.updateFrom(childOverrideConfig2);
final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
- assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
assertEquals(rootOverrideConfig, root.getConfiguration());
- assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+ assertEquals(childOverrideConfig1, child1.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
assertEquals(mergedConfig1, child1.getConfiguration());
- assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+ assertEquals(childOverrideConfig2, child2.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
assertEquals(mergedConfig2, child2.getConfiguration());
@@ -194,15 +195,15 @@
mergedConfig2.setTo(mergedConfig1);
mergedConfig2.updateFrom(mergedOverrideConfig2);
- assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getRequestedOverrideConfiguration());
assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
assertEquals(mergedRootConfig, root.getConfiguration());
- assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+ assertEquals(childOverrideConfig1, child1.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
assertEquals(mergedConfig1, child1.getConfiguration());
- assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+ assertEquals(childOverrideConfig2, child2.getRequestedOverrideConfiguration());
assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
assertEquals(mergedConfig2, child2.getConfiguration());
}
@@ -274,15 +275,55 @@
final Configuration config = new Configuration();
config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
config.windowConfiguration.setAppBounds(10, 10, 10, 10);
- container.onOverrideConfigurationChanged(config);
+ container.onRequestedOverrideConfigurationChanged(config);
container.registerConfigurationChangeListener(listener);
// Assert listener got the current config. of the container after it was registered.
assertEquals(config, listener.mOverrideConfiguration);
// Assert listener gets changes to override configuration.
- container.onOverrideConfigurationChanged(EMPTY);
+ container.onRequestedOverrideConfigurationChanged(EMPTY);
assertEquals(EMPTY, listener.mOverrideConfiguration);
}
+ @Test
+ public void testConfigurationConstraints() {
+ // Init root config.
+ final TestConfigurationContainer root = new TestConfigurationContainer();
+ final Configuration rootOverrideConfig = new Configuration();
+ rootOverrideConfig.smallestScreenWidthDp = 140;
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+ // Init child with constraint
+ final TestConfigurationChangeListener listener = new TestConfigurationChangeListener();
+ final TestConfigurationContainer child1 = root.addConstraintChild();
+ child1.registerConfigurationChangeListener(listener);
+ final Configuration childOverrideConfig1 = new Configuration();
+ childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+ child1.onRequestedOverrideConfigurationChanged(childOverrideConfig1);
+
+ assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+ child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+ assertEquals(100, child1.getConfiguration().smallestScreenWidthDp);
+ assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
+
+ // Check configuration on all levels when root override is updated.
+ rootOverrideConfig.smallestScreenWidthDp = 80;
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+ assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+ child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+ assertEquals(80, child1.getConfiguration().smallestScreenWidthDp);
+ assertEquals(80, listener.mOverrideConfiguration.smallestScreenWidthDp);
+
+ rootOverrideConfig.smallestScreenWidthDp = 180;
+ root.onRequestedOverrideConfigurationChanged(rootOverrideConfig);
+
+ assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED,
+ child1.getRequestedOverrideConfiguration().smallestScreenWidthDp);
+ assertEquals(100, child1.getConfiguration().smallestScreenWidthDp);
+ assertEquals(100, child1.getMergedOverrideConfiguration().smallestScreenWidthDp);
+ assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
+ }
+
/**
* Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
* for testing.
@@ -303,6 +344,10 @@
return addChild(new TestConfigurationContainer());
}
+ TestConfigurationContainer addConstraintChild() {
+ return addChild(new TestConfigurationContainerWithConstraints());
+ }
+
void removeChild(TestConfigurationContainer child) {
child.mParent = null;
child.onParentChanged();
@@ -324,12 +369,35 @@
}
}
+ /**
+ * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
+ * for testing.
+ */
+ private class TestConfigurationContainerWithConstraints
+ extends TestConfigurationContainer {
+
+ @Override
+ public void resolveOverrideConfiguration(Configuration newParentConfig) {
+ // Restrict smallestScreenWidthDp to 100
+ getResolvedOverrideConfiguration().setTo(getRequestedOverrideConfiguration());
+ int smallestScreenWidthDp =
+ getResolvedOverrideConfiguration().smallestScreenWidthDp
+ == SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+ ? newParentConfig.smallestScreenWidthDp
+ : getResolvedOverrideConfiguration().smallestScreenWidthDp;
+ if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+ getResolvedOverrideConfiguration().smallestScreenWidthDp =
+ Math.min(smallestScreenWidthDp, 100);
+ }
+ }
+ }
+
private static class TestConfigurationChangeListener implements ConfigurationContainerListener {
final Configuration mOverrideConfiguration = new Configuration();
@Override
- public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
mOverrideConfiguration.setTo(overrideConfiguration);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3b8d71d..7c83ecc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -227,7 +227,8 @@
*/
@Test
public void testDisplayOverrideConfigUpdate() {
- final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
+ final Configuration currentOverrideConfig =
+ mDisplayContent.getRequestedOverrideConfiguration();
// Create new, slightly changed override configuration and apply it to the display.
final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
@@ -237,7 +238,7 @@
mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
// Check that override config is applied.
- assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
+ assertEquals(newOverrideConfig, mDisplayContent.getRequestedOverrideConfiguration());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 105f826..fe632d4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -949,10 +949,11 @@
@Test
public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() {
- final Configuration overrideConfig = mRootActivityContainer.getOverrideConfiguration();
+ final Configuration overrideConfig =
+ mRootActivityContainer.getRequestedOverrideConfiguration();
// Egyptian Arabic is a RTL language.
overrideConfig.setLayoutDirection(new Locale("ar", "EG"));
- mRootActivityContainer.onOverrideConfigurationChanged(overrideConfig);
+ mRootActivityContainer.onRequestedOverrideConfigurationChanged(overrideConfig);
final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
index 7592f1c..de3567e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -93,19 +93,19 @@
controller.setContainer(container);
assertEquals(controller.mContainer, container);
- assertEquals(EMPTY, container.getOverrideConfiguration());
+ assertEquals(EMPTY, container.getRequestedOverrideConfiguration());
final Configuration config = new Configuration();
config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
config.windowConfiguration.setAppBounds(10, 10, 10, 10);
// Assert that the config change through the controller is propagated to the container.
- controller.onOverrideConfigurationChanged(config);
- assertEquals(config, container.getOverrideConfiguration());
+ controller.onRequestedOverrideConfigurationChanged(config);
+ assertEquals(config, container.getRequestedOverrideConfiguration());
// Assert the container configuration isn't changed after removal from the controller.
controller.removeContainer();
- controller.onOverrideConfigurationChanged(EMPTY);
- assertEquals(config, container.getOverrideConfiguration());
+ controller.onRequestedOverrideConfigurationChanged(EMPTY);
+ assertEquals(config, container.getRequestedOverrideConfiguration());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index d4a32cf..60f957f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -424,7 +424,7 @@
final TestWindowContainer parent = grandparent.addChildWindow();
final TestWindowContainer child = parent.addChildWindow();
- child.onOverrideConfigurationChanged(new Configuration());
+ child.onRequestedOverrideConfigurationChanged(new Configuration());
assertTrue(grandparent.mOnDescendantOverrideCalled);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 60a8aeb..d9ef10d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -96,7 +96,7 @@
}
@Override
- public void getOverrideBounds(Rect outBounds) {
+ public void getRequestedOverrideBounds(Rect outBounds) {
outBounds.set(mBounds);
}
@Override
@@ -448,9 +448,9 @@
final int xInset = logicalWidth / 10;
final int yInset = logicalWidth / 10;
final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
- Configuration config = new Configuration(w.mAppToken.getOverrideConfiguration());
+ Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
config.windowConfiguration.setBounds(cf);
- w.mAppToken.onOverrideConfigurationChanged(config);
+ w.mAppToken.onRequestedOverrideConfigurationChanged(config);
pf.set(0, 0, logicalWidth, logicalHeight);
task.mFullscreenForTest = true;
windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b3f56e7..4394f9a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -339,7 +339,7 @@
final int stackId = ++sNextStackId;
final StackWindowController controller = new StackWindowController(stackId, null,
dc.getDisplayId(), true /* onTop */, new Rect(), mWm);
- controller.onOverrideConfigurationChanged(overrideConfig);
+ controller.onRequestedOverrideConfigurationChanged(overrideConfig);
return controller;
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 62cead1..0a60e34 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2361,6 +2361,32 @@
public static final String KEY_CALL_WAITING_SERVICE_CLASS_INT =
"call_waiting_service_class_int";
+ /**
+ * This configuration allow the system UI to display different 5G icon for different 5G status.
+ *
+ * There are four 5G status:
+ * 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using
+ * millimeter wave.
+ * 2. connected: device currently connected to 5G cell as the secondary cell but not using
+ * millimeter wave.
+ * 3. not_restricted: device camped on a network that has 5G capability(not necessary to connect
+ * a 5G cell as a secondary cell) and the use of 5G is not restricted.
+ * 4. restricted: device camped on a network that has 5G capability(not necessary to connect a
+ * 5G cell as a secondary cell) but the use of 5G is restricted.
+ *
+ * The configured string contains multiple key-value pairs separated by comma. For each pair,
+ * the key and value is separated by a colon. The key is corresponded to a 5G status above and
+ * the value is the icon name. Use "None" as the icon name if no icon should be shown in a
+ * specific 5G status.
+ *
+ * Here is an example of the configuration:
+ * "connected_mmwave:5GPlus,connected:5G,not_restricted:None,restricted:None"
+ *
+ * @hide
+ */
+ public static final String KEY_5G_ICON_CONFIGURATION_STRING =
+ "5g_icon_configuration_string";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2722,6 +2748,8 @@
sDefaults.putBoolean(KEY_USE_CALL_FORWARDING_USSD_BOOL, false);
sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
+ sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
+ "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java
index d65156f..dba803b 100644
--- a/telephony/java/android/telephony/PhoneNumberRange.java
+++ b/telephony/java/android/telephony/PhoneNumberRange.java
@@ -71,10 +71,10 @@
public PhoneNumberRange(@NonNull String countryCode, @NonNull String prefix,
@NonNull String lowerBound, @NonNull String upperBound) {
validateLowerAndUpperBounds(lowerBound, upperBound);
- if (!Pattern.matches("[0-9]+", countryCode)) {
+ if (!Pattern.matches("[0-9]*", countryCode)) {
throw new IllegalArgumentException("Country code must be all numeric");
}
- if (!Pattern.matches("[0-9]+", prefix)) {
+ if (!Pattern.matches("[0-9]*", prefix)) {
throw new IllegalArgumentException("Prefix must be all numeric");
}
mCountryCode = countryCode;
@@ -133,10 +133,10 @@
if (lowerBound.length() != upperBound.length()) {
throw new IllegalArgumentException("Lower and upper bounds must have the same length");
}
- if (!Pattern.matches("[0-9]+", lowerBound)) {
+ if (!Pattern.matches("[0-9]*", lowerBound)) {
throw new IllegalArgumentException("Lower bound must be all numeric");
}
- if (!Pattern.matches("[0-9]+", upperBound)) {
+ if (!Pattern.matches("[0-9]*", upperBound)) {
throw new IllegalArgumentException("Upper bound must be all numeric");
}
if (Integer.parseInt(lowerBound) > Integer.parseInt(upperBound)) {