diff options
619 files changed, 16417 insertions, 4039 deletions
diff --git a/Android.bp b/Android.bp index ecdc0827e851..8d25704883fd 100644 --- a/Android.bp +++ b/Android.bp @@ -746,6 +746,7 @@ java_defaults { "game-driver-protos", "mediaplayer2-protos", "android.hidl.base-V1.0-java", + "android.hardware.cas-V1.1-java", "android.hardware.cas-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hardware.health-V1.0-java-constants", diff --git a/api/current.txt b/api/current.txt index 64f38857be09..131237a77277 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11465,11 +11465,12 @@ package android.content.pm { method public boolean isSessionReady(); method public boolean isStaged(); method public void writeToParcel(android.os.Parcel, int); - field public static final int ACTIVATION_FAILED = 2; // 0x2 field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR; field public static final int INVALID_ID = -1; // 0xffffffff - field public static final int NO_ERROR = 0; // 0x0 - field public static final int VERIFICATION_FAILED = 1; // 0x1 + field public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; // 0x2 + field public static final int STAGED_SESSION_NO_ERROR = 0; // 0x0 + field public static final int STAGED_SESSION_UNKNOWN = 3; // 0x3 + field public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; // 0x1 } public static class PackageInstaller.SessionParams implements android.os.Parcelable { @@ -16934,6 +16935,7 @@ package android.hardware.camera2 { field public static final int REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING = 4; // 0x4 field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3 field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5 + field public static final int REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA = 13; // 0xd field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7 field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0 field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1 @@ -24050,7 +24052,8 @@ package android.media { } public static interface MediaCas.EventListener { - method public void onEvent(android.media.MediaCas, int, int, @Nullable byte[]); + method public void onEvent(@NonNull android.media.MediaCas, int, int, @Nullable byte[]); + method public default void onSessionEvent(@NonNull android.media.MediaCas, @NonNull android.media.MediaCas.Session, int, int, @Nullable byte[]); } public static class MediaCas.PluginDescriptor { @@ -24062,6 +24065,7 @@ package android.media { method public void close(); method public void processEcm(@NonNull byte[], int, int) throws android.media.MediaCasException; method public void processEcm(@NonNull byte[]) throws android.media.MediaCasException; + method public void sendSessionEvent(int, int, @Nullable byte[]) throws android.media.MediaCasException; method public void setPrivateData(@NonNull byte[]) throws android.media.MediaCasException; } @@ -24139,8 +24143,10 @@ package android.media { field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff field public static final String PARAMETER_KEY_HDR10_PLUS_INFO = "hdr10-plus-info"; + field public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us"; field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync"; field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames"; + field public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us"; field public static final String PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate"; field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1 field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2 @@ -24985,6 +24991,7 @@ package android.media { field public static final String KEY_COLOR_STANDARD = "color-standard"; field public static final String KEY_COLOR_TRANSFER = "color-transfer"; field public static final String KEY_COMPLEXITY = "complexity"; + field public static final String KEY_CREATE_INPUT_SURFACE_SUSPENDED = "create-input-buffers-suspended"; field public static final String KEY_DURATION = "durationUs"; field public static final String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level"; field public static final String KEY_FRAME_RATE = "frame-rate"; @@ -44130,7 +44137,7 @@ package android.telephony { } public final class AvailableNetworkInfo implements android.os.Parcelable { - ctor public AvailableNetworkInfo(int, int, java.util.ArrayList<java.lang.String>); + ctor public AvailableNetworkInfo(int, int, java.util.List<java.lang.String>); method public int describeContents(); method public java.util.List<java.lang.String> getMccMncs(); method public int getPriority(); @@ -45092,7 +45099,7 @@ package android.telephony { method public int getNetworkType(); method public int getPhoneCount(); method public int getPhoneType(); - method public int getPreferredOpportunisticDataSubscription(); + method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.ServiceState getServiceState(); method @Nullable public android.telephony.SignalStrength getSignalStrength(); method public int getSimCarrierId(); @@ -45128,6 +45135,7 @@ package android.telephony { method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled(); method public boolean isHearingAidCompatibilitySupported(); method public boolean isNetworkRoaming(); + method public boolean isRttSupported(); method public boolean isSmsCapable(); method @Deprecated public boolean isTtyModeSupported(); method public boolean isVoiceCapable(); @@ -45660,9 +45668,9 @@ package android.telephony.mbms { } public interface GroupCallCallback { - method public void onBroadcastSignalStrengthUpdated(@IntRange(from=0xffffffff, to=4) int); - method public void onError(int, @Nullable String); - method public void onGroupCallStateChanged(int, int); + method public default void onBroadcastSignalStrengthUpdated(@IntRange(from=0xffffffff, to=4) int); + method public default void onError(int, @Nullable String); + method public default void onGroupCallStateChanged(int, int); field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff } @@ -45720,10 +45728,10 @@ package android.telephony.mbms { } public interface MbmsGroupCallSessionCallback { - method public void onAvailableSaisUpdated(@NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.util.List<java.lang.Integer>>); - method public void onError(int, @Nullable String); - method public void onMiddlewareReady(); - method public void onServiceInterfaceAvailable(@NonNull String, int); + method public default void onAvailableSaisUpdated(@NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.util.List<java.lang.Integer>>); + method public default void onError(int, @Nullable String); + method public default void onMiddlewareReady(); + method public default void onServiceInterfaceAvailable(@NonNull String, int); } public class MbmsStreamingSessionCallback { @@ -50662,7 +50670,7 @@ package android.view { method public void setClickable(boolean); method public void setClipBounds(android.graphics.Rect); method public void setClipToOutline(boolean); - method public void setContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSession); + method public void setContentCaptureSession(@Nullable android.view.contentcapture.ContentCaptureSession); method public void setContentDescription(CharSequence); method public void setContextClickable(boolean); method public void setDefaultFocusHighlightEnabled(boolean); @@ -50770,6 +50778,7 @@ package android.view { method public void setTouchDelegate(android.view.TouchDelegate); method public void setTransitionAlpha(float); method public final void setTransitionName(String); + method public void setTransitionVisibility(int); method public void setTranslationX(float); method public void setTranslationY(float); method public void setTranslationZ(float); @@ -53404,6 +53413,11 @@ package android.view.inputmethod { package android.view.inspector { + public class GeneratedInspectionCompanionProvider implements android.view.inspector.InspectionCompanionProvider { + ctor public GeneratedInspectionCompanionProvider(); + method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>); + } + public interface InspectionCompanion<T> { method @Nullable public default String getNodeName(); method public void mapProperties(@NonNull android.view.inspector.PropertyMapper); @@ -53414,6 +53428,10 @@ package android.view.inspector { ctor public InspectionCompanion.UninitializedPropertyMapException(); } + public interface InspectionCompanionProvider { + method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>); + } + public final class IntEnumMapping { method @Nullable public String get(int); } @@ -54844,6 +54862,7 @@ package android.widget { method public int getCheckedItemPosition(); method public android.util.SparseBooleanArray getCheckedItemPositions(); method public int getChoiceMode(); + method public boolean getDrawSelectorOnTop(); method public int getListPaddingBottom(); method public int getListPaddingLeft(); method public int getListPaddingRight(); @@ -56244,6 +56263,7 @@ package android.widget { method public android.view.Menu getMenu(); method public android.view.MenuInflater getMenuInflater(); method public void inflate(@MenuRes int); + method public void setForceShowIcon(boolean); method public void setGravity(int); method public void setOnDismissListener(android.widget.PopupMenu.OnDismissListener); method public void setOnMenuItemClickListener(android.widget.PopupMenu.OnMenuItemClickListener); @@ -56457,6 +56477,7 @@ package android.widget { ctor public RelativeLayout(android.content.Context, android.util.AttributeSet, int, int); method public android.widget.RelativeLayout.LayoutParams generateLayoutParams(android.util.AttributeSet); method public int getGravity(); + method public int getIgnoreGravity(); method public void setGravity(int); method public void setHorizontalGravity(int); method public void setIgnoreGravity(int); @@ -56673,8 +56694,9 @@ package android.widget { method public CharSequence getQuery(); method @Nullable public CharSequence getQueryHint(); method public android.widget.CursorAdapter getSuggestionsAdapter(); - method public boolean isIconfiedByDefault(); + method @Deprecated public boolean isIconfiedByDefault(); method public boolean isIconified(); + method public boolean isIconifiedByDefault(); method public boolean isQueryRefinementEnabled(); method public boolean isSubmitButtonEnabled(); method public void onActionViewCollapsed(); @@ -57397,6 +57419,7 @@ package android.widget { ctor public ToggleButton(android.content.Context, android.util.AttributeSet, int); ctor public ToggleButton(android.content.Context, android.util.AttributeSet); ctor public ToggleButton(android.content.Context); + method public float getDisabledAlpha(); method public CharSequence getTextOff(); method public CharSequence getTextOn(); method public void setBackgroundDrawable(android.graphics.drawable.Drawable); @@ -57557,6 +57580,7 @@ package android.widget { @android.widget.RemoteViews.RemoteView public class ViewFlipper extends android.widget.ViewAnimator { ctor public ViewFlipper(android.content.Context); ctor public ViewFlipper(android.content.Context, android.util.AttributeSet); + method public int getFlipInterval(); method public boolean isAutoStart(); method public boolean isFlipping(); method public void setAutoStart(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index bf3c0a2716eb..c3088c0cdeb7 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3317,11 +3317,11 @@ package android.location { method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize(); method public int getGnssCapabilities(); method @Nullable public String getLocationControllerExtraPackage(); - method @Nullable public String getNetworkProviderPackage(); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections); method public boolean isLocationControllerExtraPackageEnabled(); method public boolean isLocationEnabledForUser(android.os.UserHandle); method public boolean isProviderEnabledForUser(String, android.os.UserHandle); + method public boolean isProviderPackage(String); method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler); method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener); method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener); @@ -5546,6 +5546,8 @@ package android.permission { method @NonNull public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onGetPermissionUsages(boolean, long); method public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream); method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String); + method @BinderThread public abstract boolean onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle); + method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream); method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String); method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String); field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService"; @@ -5763,10 +5765,19 @@ package android.provider { field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled"; } + public static interface DeviceConfig.Runtime { + field public static final String NAMESPACE = "runtime"; + field public static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled"; + } + public static interface DeviceConfig.RuntimeNative { field public static final String NAMESPACE = "runtime_native"; } + public static interface DeviceConfig.RuntimeNativeBoot { + field public static final String NAMESPACE = "runtime_native_boot"; + } + public static interface DeviceConfig.Storage { field public static final String ISOLATED_STORAGE_ENABLED = "isolated_storage_enabled"; field public static final String NAMESPACE = "storage"; @@ -5960,7 +5971,6 @@ package android.provider { field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length"; field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length"; field public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category."; - field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled"; field public static final String DOZE_ALWAYS_ON = "doze_always_on"; field public static final String HUSH_GESTURE_USED = "hush_gesture_used"; field public static final String INSTANT_APPS_ENABLED = "instant_apps_enabled"; @@ -6024,6 +6034,7 @@ package android.rolecontrollerservice { method public abstract void onClearRoleHolders(@NonNull String, @NonNull android.app.role.RoleManagerCallback); method public abstract void onGrantDefaultRoles(@NonNull android.app.role.RoleManagerCallback); method public abstract void onRemoveRoleHolder(@NonNull String, @NonNull String, @NonNull android.app.role.RoleManagerCallback); + method public abstract void onSmsKillSwitchToggled(boolean); field public static final String SERVICE_INTERFACE = "android.rolecontrollerservice.RoleControllerService"; } @@ -6302,8 +6313,6 @@ package android.service.contentcapture { public abstract class ContentCaptureService extends android.app.Service { ctor public ContentCaptureService(); - method @NonNull public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities(); - method @NonNull public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages(); method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData); method public void onConnected(); method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent); @@ -6312,9 +6321,7 @@ package android.service.contentcapture { method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId); method public void onDisconnected(); method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); - method public final void setActivityContentCaptureEnabled(@NonNull android.content.ComponentName, boolean); method public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>); - method public final void setPackageContentCaptureEnabled(@NonNull String, boolean); field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; } @@ -7847,6 +7854,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); method public void updateServiceLocation(); + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT"; field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; @@ -7854,6 +7862,8 @@ package android.telephony { field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff + field public static final String EXTRA_DEBUG_EVENT_DESCRIPTION = "android.telephony.extra.DEBUG_EVENT_DESCRIPTION"; + field public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID"; field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; @@ -9262,11 +9272,7 @@ package android.view.accessibility { package android.view.autofill { public final class AutofillManager { - method @NonNull public java.util.Set<android.content.ComponentName> getAugmentedAutofillDisabledActivities(); - method @NonNull public java.util.Set<java.lang.String> getAugmentedAutofillDisabledPackages(); - method public void setActivityAugmentedAutofillEnabled(@NonNull android.content.ComponentName, boolean); method public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>); - method public void setPackageAugmentedAutofillEnabled(@NonNull String, boolean); } } @@ -9296,6 +9302,8 @@ package android.view.contentcapture { method @Nullable public android.view.contentcapture.ViewNode getViewNode(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR; + field public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5; // 0x5 + field public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4; // 0x4 field public static final int TYPE_VIEW_APPEARED = 1; // 0x1 field public static final int TYPE_VIEW_DISAPPEARED = 2; // 0x2 field public static final int TYPE_VIEW_TEXT_CHANGED = 3; // 0x3 diff --git a/api/test-current.txt b/api/test-current.txt index 2a9a149063a7..49c4e6853212 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -322,6 +322,14 @@ package android.app.admin { } +package android.app.assist { + + public static class AssistStructure.ViewNode { + ctor public AssistStructure.ViewNode(); + } + +} + package android.app.backup { public class BackupManager { @@ -792,6 +800,33 @@ package android.location { public class LocationManager { method public String[] getBackgroundThrottlingWhitelist(); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, android.os.UserHandle); + } + + public final class LocationRequest implements android.os.Parcelable { + method public static android.location.LocationRequest create(); + method public int describeContents(); + method public long getExpireAt(); + method public long getFastestInterval(); + method public long getInterval(); + method public int getNumUpdates(); + method public int getQuality(); + method public android.location.LocationRequest setExpireAt(long); + method public android.location.LocationRequest setExpireIn(long); + method public android.location.LocationRequest setFastestInterval(long); + method public android.location.LocationRequest setInterval(long); + method public android.location.LocationRequest setNumUpdates(int); + method public android.location.LocationRequest setQuality(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final int ACCURACY_BLOCK = 102; // 0x66 + field public static final int ACCURACY_CITY = 104; // 0x68 + field public static final int ACCURACY_FINE = 100; // 0x64 + field public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR; + field public static final int POWER_HIGH = 203; // 0xcb + field public static final int POWER_LOW = 201; // 0xc9 + field public static final int POWER_NONE = 200; // 0xc8 } } @@ -1761,6 +1796,7 @@ package android.provider { method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException; method @NonNull public static java.io.File getVolumePath(@NonNull String) throws java.io.FileNotFoundException; method @NonNull public static java.util.Collection<java.io.File> getVolumeScanPaths(@NonNull String) throws java.io.FileNotFoundException; + field public static final String EXTRA_ORIGINATED_FROM_SHELL = "android.intent.extra.originated_from_shell"; field public static final String SCAN_FILE_CALL = "scan_file"; field public static final String SCAN_VOLUME_CALL = "scan_volume"; } @@ -2042,6 +2078,40 @@ package android.service.autofill.augmented { } +package android.service.contentcapture { + + @Deprecated public final class ContentCaptureEventsRequest implements android.os.Parcelable { + method @Deprecated public int describeContents(); + method @Deprecated @NonNull public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents(); + method @Deprecated public void writeToParcel(android.os.Parcel, int); + field @Deprecated 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 void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData); + method public void onConnected(); + method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent); + method @Deprecated public void onContentCaptureEventsRequest(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.ContentCaptureEventsRequest); + method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId); + method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId); + method public void onDisconnected(); + method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest); + method public final void setContentCaptureWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>); + field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService"; + } + + 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(@NonNull android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR; + } + +} + package android.service.notification { @Deprecated public abstract class ConditionProviderService extends android.app.Service { @@ -2122,7 +2192,6 @@ package android.telephony { public class TelephonyManager { method public int checkCarrierPrivilegesForPackage(String); method public int getCarrierIdListVersion(); - method public boolean isRttSupported(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile(); method public void setCarrierTestOverride(String, String, String, String, String, String, String); field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe @@ -2597,17 +2666,56 @@ package android.view.autofill { } public final class AutofillManager { - method @NonNull public java.util.Set<android.content.ComponentName> getAugmentedAutofillDisabledActivities(); - method @NonNull public java.util.Set<java.lang.String> getAugmentedAutofillDisabledPackages(); - method public void setActivityAugmentedAutofillEnabled(@NonNull android.content.ComponentName, boolean); method public void setAugmentedAutofillWhitelist(@Nullable java.util.List<java.lang.String>, @Nullable java.util.List<android.content.ComponentName>); - method public void setPackageAugmentedAutofillEnabled(@NonNull String, boolean); field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1 field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0 } } +package android.view.contentcapture { + + public final class ContentCaptureContext implements android.os.Parcelable { + method @Nullable public String getAction(); + method @Nullable public android.content.ComponentName getActivityComponent(); + method public int getDisplayId(); + method @Nullable public android.os.Bundle getExtras(); + method public int getFlags(); + method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId(); + method public int getTaskId(); + method @Nullable public android.net.Uri getUri(); + 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 ContentCaptureEvent implements android.os.Parcelable { + method public int describeContents(); + method public long getEventTime(); + method @Nullable public android.view.autofill.AutofillId getId(); + method @Nullable public java.util.List<android.view.autofill.AutofillId> getIds(); + method @Nullable public CharSequence getText(); + method public int getType(); + method @Nullable public android.view.contentcapture.ViewNode getViewNode(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR; + field public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5; // 0x5 + field public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4; // 0x4 + field public static final int TYPE_VIEW_APPEARED = 1; // 0x1 + field public static final int TYPE_VIEW_DISAPPEARED = 2; // 0x2 + field public static final int TYPE_VIEW_TEXT_CHANGED = 3; // 0x3 + } + + public final class ContentCaptureManager { + method public boolean isContentCaptureFeatureEnabled(); + method public void setContentCaptureFeatureEnabled(boolean); + } + + public final class ViewNode extends android.app.assist.AssistStructure.ViewNode { + method @Nullable public android.view.autofill.AutofillId getParentAutofillId(); + } + +} + package android.view.inputmethod { public final class InputMethodManager { @@ -2664,7 +2772,7 @@ package android.widget { } public class DatePicker extends android.widget.FrameLayout { - method public int getMode(); + method @android.view.inspector.InspectableProperty(name="datePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumMap(value=android.widget.DatePicker.MODE_SPINNER, name="spinner"), @android.view.inspector.InspectableProperty.EnumMap(value=android.widget.DatePicker.MODE_CALENDAR, name="calendar")}) public int getMode(); field public static final int MODE_CALENDAR = 2; // 0x2 field public static final int MODE_SPINNER = 1; // 0x1 } @@ -2700,7 +2808,7 @@ package android.widget { method public android.view.View getAmView(); method public android.view.View getHourView(); method public android.view.View getMinuteView(); - method public int getMode(); + method @android.view.inspector.InspectableProperty(name="timePickerMode", enumMapping={@android.view.inspector.InspectableProperty.EnumMap(name="clock", value=android.widget.TimePicker.MODE_CLOCK), @android.view.inspector.InspectableProperty.EnumMap(name="spinner", value=android.widget.TimePicker.MODE_SPINNER)}) public int getMode(); method public android.view.View getPmView(); field public static final int MODE_CLOCK = 2; // 0x2 field public static final int MODE_SPINNER = 1; // 0x1 diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 5f47e06fb876..63f9b5954792 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -2144,30 +2144,24 @@ message HardwareFailed { } optional HardwareType hardware_type = 1; - /* hardware_location allows vendors to differentiate between multiple instances of + /** + * hardware_location allows vendors to differentiate between multiple instances of * the same hardware_type. The specific locations are vendor defined integers, * referring to board-specific numbering schemes. */ optional int32 hardware_location = 2; - /* failure_code is specific to the HardwareType of the failed hardware. - * It should use the enum values defined below. + /** + * failure_code is specific to the HardwareType of the failed hardware. + * It should use one of the enum values defined below. */ - enum MicrophoneFailureCode { - MICROPHONE_FAILURE_COMPLETE = 0; - } - enum CodecFailureCode { - CODEC_FAILURE_COMPLETE = 0; - } - enum SpeakerFailureCode { - SPEAKER_FAILURE_COMPLETE = 0; - SPEAKER_FAILURE_HIGH_Z = 1; - SPEAKER_FAILURE_SHORT = 2; - } - enum FingerprintFailureCode { - FINGERPRINT_FAILURE_COMPLETE = 0; - FINGERPRINT_SENSOR_BROKEN = 1; - FINGERPRINT_TOO_MANY_DEAD_PIXELS = 2; + enum HardwareErrorCode { + UNKNOWN = 0; + COMPLETE = 1; + SPEAKER_HIGH_Z = 2; + SPEAKER_SHORT = 3; + FINGERPRINT_SENSOR_BROKEN = 4; + FINGERPRINT_TOO_MANY_DEAD_PIXELS = 5; } optional int32 failure_code = 3; } diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp index eaba9bee6bf0..40a4070d2974 100644 --- a/cmds/statsd/src/logd/LogEvent.cpp +++ b/cmds/statsd/src/logd/LogEvent.cpp @@ -559,7 +559,7 @@ void LogEvent::init(android_log_context context) { // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { - pos[depth] = 4; + pos[depth] = 5; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32))); @@ -575,7 +575,7 @@ void LogEvent::init(android_log_context context) { // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { - pos[depth] = 3; + pos[depth] = 4; } mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(string(elem.data.string, elem.len)))); @@ -593,7 +593,7 @@ void LogEvent::init(android_log_context context) { } // Handles the oneof field in KeyValuePair atom. if (isKeyValuePairAtom && depth == 2) { - pos[depth] = 2; + pos[depth] = 3; } mValues.push_back( FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64))); diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp index 3a5be43ed695..eec3c735057c 100644 --- a/cmds/statsd/tests/LogEvent_test.cpp +++ b/cmds/statsd/tests/LogEvent_test.cpp @@ -155,7 +155,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(33, item5.mValue.int_value); const FieldValue& item6 = event1.getValues()[6]; - EXPECT_EQ(0x2010482, item6.mField.getField()); + EXPECT_EQ(0x2010483, item6.mField.getField()); EXPECT_EQ(Type::LONG, item6.mValue.getType()); EXPECT_EQ(678L, item6.mValue.int_value); @@ -165,7 +165,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(44, item7.mValue.int_value); const FieldValue& item8 = event1.getValues()[8]; - EXPECT_EQ(0x2010582, item8.mField.getField()); + EXPECT_EQ(0x2010583, item8.mField.getField()); EXPECT_EQ(Type::LONG, item8.mValue.getType()); EXPECT_EQ(890L, item8.mValue.int_value); @@ -175,7 +175,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(1, item9.mValue.int_value); const FieldValue& item10 = event1.getValues()[10]; - EXPECT_EQ(0x2010683, item10.mField.getField()); + EXPECT_EQ(0x2010684, item10.mField.getField()); EXPECT_EQ(Type::STRING, item10.mValue.getType()); EXPECT_EQ("test2", item10.mValue.str_value); @@ -185,7 +185,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(2, item11.mValue.int_value); const FieldValue& item12 = event1.getValues()[12]; - EXPECT_EQ(0x2010783, item12.mField.getField()); + EXPECT_EQ(0x2010784, item12.mField.getField()); EXPECT_EQ(Type::STRING, item12.mValue.getType()); EXPECT_EQ("test1", item12.mValue.str_value); @@ -195,7 +195,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(111, item13.mValue.int_value); const FieldValue& item14 = event1.getValues()[14]; - EXPECT_EQ(0x2010884, item14.mField.getField()); + EXPECT_EQ(0x2010885, item14.mField.getField()); EXPECT_EQ(Type::FLOAT, item14.mValue.getType()); EXPECT_EQ(2.2f, item14.mValue.float_value); @@ -205,7 +205,7 @@ TEST(LogEventTest, TestKeyValuePairsAtomParsing) { EXPECT_EQ(222, item15.mValue.int_value); const FieldValue& item16 = event1.getValues()[16]; - EXPECT_EQ(0x2018984, item16.mField.getField()); + EXPECT_EQ(0x2018985, item16.mField.getField()); EXPECT_EQ(Type::FLOAT, item16.mValue.getType()); EXPECT_EQ(1.1f, item16.mValue.float_value); } diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt index 7f4d1d0db5a2..6061b66a2ae8 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -32559,7 +32559,7 @@ HSPLandroid/util/apk/ApkSignatureSchemeV3Verifier;->verify(Ljava/io/RandomAccess HSPLandroid/util/apk/ApkSignatureSchemeV3Verifier;->verify(Ljava/lang/String;Z)Landroid/util/apk/ApkSignatureSchemeV3Verifier$VerifiedSigner; HSPLandroid/util/apk/ApkSignatureSchemeV3Verifier;->verifyAdditionalAttributes(Ljava/nio/ByteBuffer;Ljava/util/List;Ljava/security/cert/CertificateFactory;)Landroid/util/apk/ApkSignatureSchemeV3Verifier$VerifiedSigner; HSPLandroid/util/apk/ApkSignatureSchemeV3Verifier;->verifySigner(Ljava/nio/ByteBuffer;Ljava/util/Map;Ljava/security/cert/CertificateFactory;)Landroid/util/apk/ApkSignatureSchemeV3Verifier$VerifiedSigner; -HSPLandroid/util/apk/ApkSignatureVerifier;->plsCertsNoVerifyOnlyCerts(Ljava/lang/String;I)Landroid/content/pm/PackageParser$SigningDetails; +HSPLandroid/util/apk/ApkSignatureVerifier;->unsafeGetCertsWithoutVerification(Ljava/lang/String;I)Landroid/content/pm/PackageParser$SigningDetails; HSPLandroid/util/apk/ApkSigningBlockUtils;->compareContentDigestAlgorithm(II)I HSPLandroid/util/apk/ApkSigningBlockUtils;->compareSignatureAlgorithm(II)I HSPLandroid/util/apk/ApkSigningBlockUtils;->findApkSignatureSchemeBlock(Ljava/nio/ByteBuffer;I)Ljava/nio/ByteBuffer; diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index a74895947450..11bb38beee87 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -489,7 +489,6 @@ Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager; Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List; -Landroid/location/ILocationManager;->getNetworkProviderPackage()Ljava/lang/String; Landroid/location/INetInitiatedListener$Stub;-><init>()V Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index 5b3813d9c3af..c7537102d40c 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -17,6 +17,7 @@ package android.animation; import android.annotation.UnsupportedAppUsage; +import android.os.Build; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -1071,7 +1072,7 @@ public class LayoutTransition { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void cancel() { if (currentChangingAnimations.size() > 0) { LinkedHashMap<View, Animator> currentAnimCopy = @@ -1107,7 +1108,7 @@ public class LayoutTransition { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void cancel(int transitionType) { switch (transitionType) { case CHANGE_APPEARING: diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index aac8f0855ca9..0eadd1dcd903 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -7155,7 +7155,8 @@ public class Activity extends ContextThemeWrapper mInstrumentation.onEnterAnimationComplete(); onEnterAnimationComplete(); if (getWindow() != null && getWindow().getDecorView() != null) { - getWindow().getDecorView().getViewTreeObserver().dispatchOnEnterAnimationComplete(); + View decorView = getWindow().getDecorView(); + decorView.getViewTreeObserver().dispatchOnEnterAnimationComplete(); } } diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 9ee2f039ce3f..ea145f0b9d21 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -4485,6 +4485,7 @@ public class AppOpsManager { * @hide */ public int noteProxyOpNoThrow(int op, String proxiedPackageName) { + logOperationIfNeeded(op, mContext.getOpPackageName(), proxiedPackageName); try { return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(), Binder.getCallingUid(), proxiedPackageName); @@ -4500,7 +4501,7 @@ public class AppOpsManager { */ @UnsupportedAppUsage public int noteOpNoThrow(int op, int uid, String packageName) { - logNoteOpIfNeeded(op, packageName); + logOperationIfNeeded(op, packageName, null); try { return mService.noteOperation(op, uid, packageName); } catch (RemoteException e) { @@ -4608,6 +4609,7 @@ public class AppOpsManager { * @hide */ public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) { + logOperationIfNeeded(op, packageName, null); try { return mService.startOperation(getToken(mService), op, uid, packageName, startIfModeDefault); @@ -4624,6 +4626,7 @@ public class AppOpsManager { * @hide */ public void finishOp(int op, int uid, String packageName) { + logOperationIfNeeded(op, packageName, null); try { mService.finishOperation(getToken(mService), op, uid, packageName); } catch (RemoteException e) { @@ -4870,7 +4873,7 @@ public class AppOpsManager { return AppOpsManager.MODE_DEFAULT; } - private static void logNoteOpIfNeeded(int op, String callingPackage) { + private static void logOperationIfNeeded(int op, String callingPackage, String proxiedPackage) { // Check if debug logging propety is enabled. if (!SystemProperties.getBoolean(DEBUG_LOGGING_ENABLE_PROP, false)) { return; @@ -4908,6 +4911,6 @@ public class AppOpsManager { // Log a stack trace Exception here = new Exception("HERE!"); android.util.Log.i(DEBUG_LOGGING_TAG, "Note operation package= " + callingPackage - + " op= " + opStr, here); + + " proxied= " + proxiedPackage + " op= " + opStr, here); } } diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 6006ad2f5ed3..2b1e7cd9a26e 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -3,6 +3,7 @@ package android.app.assist; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Activity; import android.content.ComponentName; import android.content.Context; @@ -715,9 +716,10 @@ public class AssistStructure implements Parcelable { ViewNode[] mChildren; // TODO(b/111276913): temporarily made public / @hide until we decide what will be used by - // ScreenObservation. + // COntent Capture. /** @hide */ @SystemApi + @TestApi public ViewNode() { } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 8cbe7a33d5c6..fafea340ccc3 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -52,6 +52,14 @@ public final class UsageEvents implements Parcelable { public static final int NONE = 0; /** + * A device level event like {@link #DEVICE_SHUTDOWN} does not have package name, but some + * user code always expect a non-null {@link #mPackage} for every event. Use + * {@link #DEVICE_EVENT_PACKAGE_NAME} as packageName for these device level events. + * @hide + */ + public static final String DEVICE_EVENT_PACKAGE_NAME = "android"; + + /** * @deprecated by {@link #ACTIVITY_RESUMED} */ @Deprecated diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 8b8f3e542375..0ac4f6481fc4 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1625,26 +1625,35 @@ public class PackageInstaller { private static final int[] NO_SESSIONS = {}; /** @hide */ - @IntDef(value = {NO_ERROR, VERIFICATION_FAILED, ACTIVATION_FAILED}) + @IntDef(prefix = { "STAGED_SESSION_" }, value = { + STAGED_SESSION_NO_ERROR, + STAGED_SESSION_VERIFICATION_FAILED, + STAGED_SESSION_ACTIVATION_FAILED, + STAGED_SESSION_UNKNOWN}) @Retention(RetentionPolicy.SOURCE) public @interface StagedSessionErrorCode{} /** * Constant indicating that no error occurred during the preparation or the activation of * this staged session. */ - public static final int NO_ERROR = 0; + public static final int STAGED_SESSION_NO_ERROR = 0; /** * Constant indicating that an error occurred during the verification phase (pre-reboot) of * this staged session. */ - public static final int VERIFICATION_FAILED = 1; + public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; /** * Constant indicating that an error occurred during the activation phase (post-reboot) of * this staged session. */ - public static final int ACTIVATION_FAILED = 2; + public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; + + /** + * Constant indicating that an unknown error occurred while processing this staged session. + */ + public static final int STAGED_SESSION_UNKNOWN = 3; /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e2907e219b1f..6e52b33692c8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -866,6 +866,14 @@ public abstract class PackageManager { */ public static final int INSTALL_ENABLE_ROLLBACK = 0x00040000; + /** + * Flag parameter for {@link #installPackage} to indicate that package verification should be + * disabled for this package. + * + * @hide + */ + public static final int INSTALL_DISABLE_VERIFICATION = 0x00080000; + /** @hide */ @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = { DONT_KILL_APP diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 4a2dbe76f9c3..cfe35b061151 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -137,6 +137,32 @@ public abstract class PackageManagerInternal { } /** + * Provider for default browser + */ + public interface DefaultBrowserProvider { + + /** + * Get the package name of the default browser. + * + * @param userId the user id + * + * @return the package name of the default browser, or {@code null} if none + */ + @Nullable + String getDefaultBrowser(@UserIdInt int userId); + + /** + * Set the package name of the default browser. + * + * @param packageName package name of the default browser, or {@code null} to remove + * @param userId the user id + * + * @return whether the default browser was successfully set. + */ + boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId); + } + + /** * Sets the location provider packages provider. * @param provider The packages provider. */ @@ -843,4 +869,21 @@ public abstract class PackageManagerInternal { * {@code token} can be completed. */ public abstract void finishPackageInstall(int token, boolean didLaunch); + + /** + * Remove the default browser stored in the legacy package settings. + * + * @param userId the user id + * + * @return the package name of the default browser, or {@code null} if none + */ + @Nullable + public abstract String removeLegacyDefaultBrowserPackageName(int userId); + + /** + * Sets the default browser provider. + * + * @param provider the provider + */ + public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 2c2d6f2bb3d1..60449145a740 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1533,7 +1533,7 @@ public class PackageParser { SigningDetails verified; if (skipVerify) { // systemDir APKs are already trusted, save time by not verifying - verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts( + verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification( apkPath, minSignatureScheme); } else { verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme); diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 536a1b7ab6e5..8a9201704c47 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1096,34 +1096,38 @@ public final class Configuration implements Parcelable, Comparable<Configuration * @param protoOutputStream Stream to write the Configuration object to. * @param fieldId Field Id of the Configuration as defined in the parent message * @param persisted Note if this proto will be persisted to disk + * @param critical If true, reduce amount of data written. * @hide */ - public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted) { + public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean persisted, + boolean critical) { final long token = protoOutputStream.start(fieldId); - protoOutputStream.write(FONT_SCALE, fontScale); - protoOutputStream.write(MCC, mcc); - protoOutputStream.write(MNC, mnc); - if (mLocaleList != null) { - mLocaleList.writeToProto(protoOutputStream, LOCALES); - } - protoOutputStream.write(SCREEN_LAYOUT, screenLayout); - protoOutputStream.write(COLOR_MODE, colorMode); - protoOutputStream.write(TOUCHSCREEN, touchscreen); - protoOutputStream.write(KEYBOARD, keyboard); - protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden); - protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden); - protoOutputStream.write(NAVIGATION, navigation); - protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden); + if (!critical) { + protoOutputStream.write(FONT_SCALE, fontScale); + protoOutputStream.write(MCC, mcc); + protoOutputStream.write(MNC, mnc); + if (mLocaleList != null) { + mLocaleList.writeToProto(protoOutputStream, LOCALES); + } + protoOutputStream.write(SCREEN_LAYOUT, screenLayout); + protoOutputStream.write(COLOR_MODE, colorMode); + protoOutputStream.write(TOUCHSCREEN, touchscreen); + protoOutputStream.write(KEYBOARD, keyboard); + protoOutputStream.write(KEYBOARD_HIDDEN, keyboardHidden); + protoOutputStream.write(HARD_KEYBOARD_HIDDEN, hardKeyboardHidden); + protoOutputStream.write(NAVIGATION, navigation); + protoOutputStream.write(NAVIGATION_HIDDEN, navigationHidden); + protoOutputStream.write(UI_MODE, uiMode); + protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp); + protoOutputStream.write(DENSITY_DPI, densityDpi); + // For persistence, we do not care about window configuration + if (!persisted && windowConfiguration != null) { + windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION); + } + } protoOutputStream.write(ORIENTATION, orientation); - protoOutputStream.write(UI_MODE, uiMode); protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp); protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp); - protoOutputStream.write(SMALLEST_SCREEN_WIDTH_DP, smallestScreenWidthDp); - protoOutputStream.write(DENSITY_DPI, densityDpi); - // For persistence, we do not care about window configuration - if (!persisted && windowConfiguration != null) { - windowConfiguration.writeToProto(protoOutputStream, WINDOW_CONFIGURATION); - } protoOutputStream.end(token); } @@ -1136,7 +1140,20 @@ public final class Configuration implements Parcelable, Comparable<Configuration * @hide */ public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) { - writeToProto(protoOutputStream, fieldId, false); + writeToProto(protoOutputStream, fieldId, false /* persisted */, false /* critical */); + } + + /** + * Write to a protocol buffer output stream. + * Protocol buffer message definition at {@link android.content.ConfigurationProto} + * + * @param protoOutputStream Stream to write the Configuration object to. + * @param fieldId Field Id of the Configuration as defined in the parent message + * @param critical If true, reduce amount of data written. + * @hide + */ + public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId, boolean critical) { + writeToProto(protoOutputStream, fieldId, false /* persisted */, critical); } /** diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl index 104661f12e8d..d951756bb513 100644 --- a/core/java/android/content/rollback/IRollbackManager.aidl +++ b/core/java/android/content/rollback/IRollbackManager.aidl @@ -40,4 +40,11 @@ interface IRollbackManager { // Exposed for test purposes only. void expireRollbackForPackage(String packageName); + + // Used by the staging manager to notify the RollbackManager that a session is + // being staged. In the case of multi-package sessions, the specified sessionId + // is that of the parent session. + // + // NOTE: This call is synchronous. + boolean notifyStagedSession(int sessionId); } diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java index d4ed35a9cb71..0ec40183c319 100644 --- a/core/java/android/content/rollback/PackageRollbackInfo.java +++ b/core/java/android/content/rollback/PackageRollbackInfo.java @@ -69,6 +69,11 @@ public final class PackageRollbackInfo implements Parcelable { private final ArrayList<RestoreInfo> mPendingRestores; /** + * Whether this instance represents the PackageRollbackInfo for an APEX module. + */ + private final boolean mIsApex; + + /** * Returns the name of the package to roll back from. */ public String getPackageName() { @@ -116,18 +121,26 @@ public final class PackageRollbackInfo implements Parcelable { } /** @hide */ + public boolean isApex() { + return mIsApex; + } + + /** @hide */ public PackageRollbackInfo(VersionedPackage packageRolledBackFrom, VersionedPackage packageRolledBackTo, - @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores) { + @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores, + boolean isApex) { this.mVersionRolledBackFrom = packageRolledBackFrom; this.mVersionRolledBackTo = packageRolledBackTo; this.mPendingBackups = pendingBackups; this.mPendingRestores = pendingRestores; + this.mIsApex = isApex; } private PackageRollbackInfo(Parcel in) { this.mVersionRolledBackFrom = VersionedPackage.CREATOR.createFromParcel(in); this.mVersionRolledBackTo = VersionedPackage.CREATOR.createFromParcel(in); + this.mIsApex = in.readBoolean(); this.mPendingRestores = null; this.mPendingBackups = null; } @@ -141,6 +154,7 @@ public final class PackageRollbackInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { mVersionRolledBackFrom.writeToParcel(out, flags); mVersionRolledBackTo.writeToParcel(out, flags); + out.writeBoolean(mIsApex); } public static final Parcelable.Creator<PackageRollbackInfo> CREATOR = diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java index 3fd247670a9d..0cde6ba38099 100644 --- a/core/java/android/content/rollback/RollbackInfo.java +++ b/core/java/android/content/rollback/RollbackInfo.java @@ -22,6 +22,7 @@ import android.content.pm.VersionedPackage; import android.os.Parcel; import android.os.Parcelable; +import java.util.Collections; import java.util.List; /** @@ -42,18 +43,31 @@ public final class RollbackInfo implements Parcelable { private final List<VersionedPackage> mCausePackages; + private final boolean mIsStaged; + private final int mCommittedSessionId; + + /** @hide */ + public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged) { + this(rollbackId, packages, isStaged, Collections.emptyList(), + PackageInstaller.SessionInfo.INVALID_ID); + } + /** @hide */ - public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, - List<VersionedPackage> causePackages) { + public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged, + List<VersionedPackage> causePackages, int committedSessionId) { this.mRollbackId = rollbackId; this.mPackages = packages; + this.mIsStaged = isStaged; this.mCausePackages = causePackages; + this.mCommittedSessionId = committedSessionId; } private RollbackInfo(Parcel in) { mRollbackId = in.readInt(); mPackages = in.createTypedArrayList(PackageRollbackInfo.CREATOR); + mIsStaged = in.readBoolean(); mCausePackages = in.createTypedArrayList(VersionedPackage.CREATOR); + mCommittedSessionId = in.readInt(); } /** @@ -75,8 +89,7 @@ public final class RollbackInfo implements Parcelable { * being committed. */ public boolean isStaged() { - // TODO: Support rollback of staged installs. - return false; + return mIsStaged; } /** @@ -84,8 +97,7 @@ public final class RollbackInfo implements Parcelable { * Only applicable for rollbacks that have been committed. */ public int getCommittedSessionId() { - // TODO: Support rollback of staged installs. - return PackageInstaller.SessionInfo.INVALID_ID; + return mCommittedSessionId; } /** @@ -106,7 +118,9 @@ public final class RollbackInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(mRollbackId); out.writeTypedList(mPackages); + out.writeBoolean(mIsStaged); out.writeTypedList(mCausePackages); + out.writeInt(mCommittedSessionId); } public static final Parcelable.Creator<RollbackInfo> CREATOR = diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java index b2288fc4492d..87568e857d6d 100644 --- a/core/java/android/ddm/DdmHandleHello.java +++ b/core/java/android/ddm/DdmHandleHello.java @@ -16,14 +16,16 @@ package android.ddm; -import org.apache.harmony.dalvik.ddmc.Chunk; -import org.apache.harmony.dalvik.ddmc.ChunkHandler; -import org.apache.harmony.dalvik.ddmc.DdmServer; -import android.util.Log; import android.os.Debug; import android.os.UserHandle; +import android.util.Log; + import dalvik.system.VMRuntime; +import org.apache.harmony.dalvik.ddmc.Chunk; +import org.apache.harmony.dalvik.ddmc.ChunkHandler; +import org.apache.harmony.dalvik.ddmc.DdmServer; + import java.nio.ByteBuffer; /** @@ -35,6 +37,8 @@ public class DdmHandleHello extends ChunkHandler { public static final int CHUNK_WAIT = type("WAIT"); public static final int CHUNK_FEAT = type("FEAT"); + private static final int CLIENT_PROTOCOL_VERSION = 1; + private static DdmHandleHello mInstance = new DdmHandleHello(); private static final String[] FRAMEWORK_FEATURES = new String[] { @@ -145,7 +149,7 @@ public class DdmHandleHello extends ChunkHandler { + vmFlags.length() * 2 + 1); out.order(ChunkHandler.CHUNK_ORDER); - out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION); + out.putInt(CLIENT_PROTOCOL_VERSION); out.putInt(android.os.Process.myPid()); out.putInt(vmIdent.length()); out.putInt(appName.length()); diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 4bc270200c78..1881a0cd32e8 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1901,6 +1901,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING MOTION_TRACKING}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA LOGICAL_MULTI_CAMERA}</li> * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}</li> + * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA SECURE_IMAGE_DATA}</li> * </ul></p> * <p>This key is available on all devices.</p> * @@ -1918,6 +1919,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * @see #REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING * @see #REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA * @see #REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME + * @see #REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA */ @PublicKey public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES = diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 6302aa536214..a3e561c960ef 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -972,6 +972,14 @@ public abstract class CameraMetadata<TKey> { */ public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12; + /** + * <p>The camera device is capable of writing image data into a region of memory + * inaccessible to Android userspace or the Android kernel, and only accessible to + * trusted execution environments (TEE).</p> + * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES + */ + public static final int REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA = 13; + // // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE // diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java index 45a79e1f3cae..bff8c39e8c56 100644 --- a/core/java/android/hardware/hdmi/HdmiClient.java +++ b/core/java/android/hardware/hdmi/HdmiClient.java @@ -56,6 +56,26 @@ public abstract class HdmiClient { } /** + * Sends a volume key event to the primary audio receiver in the system. This method should only + * be called when the volume key is not handled by the local device. HDMI framework handles the + * logic of finding the address of the receiver. + * + * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}. + * @param isPressed true if this is key press event + * + * @hide + * TODO(b/110094868): unhide for Q + */ + public void sendVolumeKeyEvent(int keyCode, boolean isPressed) { + try { + mService.sendVolumeKeyEvent(getDeviceType(), keyCode, isPressed); + } catch (RemoteException e) { + Log.e(TAG, "sendVolumeKeyEvent threw exception ", e); + throw e.rethrowFromSystemServer(); + } + } + + /** * Sends vendor-specific command. * * @param targetAddress address of the target device diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 1cd9920aa250..95eaf75d6510 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -47,6 +47,7 @@ interface IHdmiControlService { void deviceSelect(int deviceId, IHdmiControlCallback callback); void portSelect(int portId, IHdmiControlCallback callback); void sendKeyEvent(int deviceType, int keyCode, boolean isPressed); + void sendVolumeKeyEvent(int deviceType, int keyCode, boolean isPressed); List<HdmiPortInfo> getPortInfo(); boolean canChangeSystemAudioMode(); boolean getSystemAudioMode(); diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index 843db6d28d30..ffae361e76d4 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -51,6 +51,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub private static final int DO_TOGGLE_SOFT_INPUT = 105; private static final int DO_FINISH_SESSION = 110; private static final int DO_VIEW_CLICKED = 115; + private static final int DO_NOTIFY_IME_HIDDEN = 120; HandlerCaller mCaller; InputMethodSession mInputMethodSession; @@ -129,6 +130,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub mInputMethodSession.viewClicked(msg.arg1 == 1); return; } + case DO_NOTIFY_IME_HIDDEN: { + mInputMethodSession.notifyImeHidden(); + return; + } } Log.w(TAG, "Unhandled message code: " + msg.what); } @@ -172,6 +177,11 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub } @Override + public void notifyImeHidden() { + mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_IME_HIDDEN)); + } + + @Override public void updateCursor(Rect newCursor) { mCaller.executeOrSendMessage( mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor)); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 333cfbd400dd..ab630fd7467b 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -592,7 +592,6 @@ public class InputMethodService extends AbstractInputMethodService { final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); if (mIsPreRendered) { - // TODO: notify visibility to insets consumer. if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } @@ -658,6 +657,11 @@ public class InputMethodService extends AbstractInputMethodService { } } + private void notifyImeHidden() { + setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); + onPreRenderedWindowVisibilityChanged(false /* setVisible */); + } + private void setImeWindowStatus(int visibilityFlags, int backDisposition) { mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition); } @@ -760,6 +764,14 @@ public class InputMethodService extends AbstractInputMethodService { } InputMethodService.this.onUpdateCursorAnchorInfo(info); } + + /** + * Notify IME that window is hidden. + * @hide + */ + public final void notifyImeHidden() { + InputMethodService.this.notifyImeHidden(); + } } /** diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java index b4b541dc5cd0..31c948a14698 100644 --- a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java +++ b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java @@ -290,6 +290,12 @@ final class MultiClientInputMethodClientCallbackAdaptor { CallbackImpl::updateCursorAnchorInfo, mCallbackImpl, info)); } } + + @Override + public final void notifyImeHidden() { + // no-op for multi-session since IME is responsible controlling navigation bar buttons. + reportNotSupported(); + } } private static final class MultiClientInputMethodSessionImpl diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 1656c6f8a1ed..ce2de9ac6307 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1816,7 +1816,7 @@ public class ConnectivityManager { @Override public void handleMessage(Message message) { switch (message.what) { - case NetworkAgent.EVENT_PACKET_KEEPALIVE: + case NetworkAgent.EVENT_SOCKET_KEEPALIVE: int error = message.arg2; try { if (error == SUCCESS) { diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 7436ad08789e..16555d8bd488 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -16,22 +16,20 @@ package android.net; -import static android.net.ConnectivityManager.PacketKeepalive.*; +import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; +import static android.net.SocketKeepalive.ERROR_INVALID_PORT; +import android.net.SocketKeepalive.InvalidPacketException; import android.net.util.IpUtils; import android.os.Parcel; import android.os.Parcelable; -import android.system.OsConstants; import android.util.Log; -import java.net.Inet4Address; import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; /** * Represents the actual packets that are sent by the - * {@link android.net.ConnectivityManager.PacketKeepalive} API. + * {@link android.net.SocketKeepalive} API. * * @hide */ @@ -53,8 +51,8 @@ public class KeepalivePacketData implements Parcelable { /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; - private static final int IPV4_HEADER_LENGTH = 20; - private static final int UDP_HEADER_LENGTH = 8; + protected static final int IPV4_HEADER_LENGTH = 20; + protected static final int UDP_HEADER_LENGTH = 8; // This should only be constructed via static factory methods, such as // nattKeepalivePacket @@ -80,53 +78,10 @@ public class KeepalivePacketData implements Parcelable { } } - public static class InvalidPacketException extends Exception { - public final int error; - public InvalidPacketException(int error) { - this.error = error; - } - } - public byte[] getPacket() { return mPacket.clone(); } - public static KeepalivePacketData nattKeepalivePacket( - InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) - throws InvalidPacketException { - - if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { - throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); - } - - if (dstPort != NATT_PORT) { - throw new InvalidPacketException(ERROR_INVALID_PORT); - } - - int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; - ByteBuffer buf = ByteBuffer.allocate(length); - buf.order(ByteOrder.BIG_ENDIAN); - buf.putShort((short) 0x4500); // IP version and TOS - buf.putShort((short) length); - buf.putInt(0); // ID, flags, offset - buf.put((byte) 64); // TTL - buf.put((byte) OsConstants.IPPROTO_UDP); - int ipChecksumOffset = buf.position(); - buf.putShort((short) 0); // IP checksum - buf.put(srcAddress.getAddress()); - buf.put(dstAddress.getAddress()); - buf.putShort((short) srcPort); - buf.putShort((short) dstPort); - buf.putShort((short) (length - 20)); // UDP length - int udpChecksumOffset = buf.position(); - buf.putShort((short) 0); // UDP checksum - buf.put((byte) 0xff); // NAT-T keepalive - buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); - buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); - - return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); - } - /* Parcelable Implementation */ public int describeContents() { return 0; diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java new file mode 100644 index 000000000000..aa9f799c6f27 --- /dev/null +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -0,0 +1,77 @@ +/* + * 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.net; + +import android.net.SocketKeepalive.InvalidPacketException; +import android.net.util.IpUtils; +import android.system.OsConstants; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** @hide */ +public final class NattKeepalivePacketData extends KeepalivePacketData { + + // This should only be constructed via static factory methods, such as + // nattKeepalivePacket + private NattKeepalivePacketData(InetAddress srcAddress, int srcPort, + InetAddress dstAddress, int dstPort, byte[] data) throws + InvalidPacketException { + super(srcAddress, srcPort, dstAddress, dstPort, data); + } + + /** + * Factory method to create Nat-T keepalive packet structure. + */ + public static NattKeepalivePacketData nattKeepalivePacket( + InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) + throws InvalidPacketException { + + if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { + throw new InvalidPacketException(SocketKeepalive.ERROR_INVALID_IP_ADDRESS); + } + + if (dstPort != NattSocketKeepalive.NATT_PORT) { + throw new InvalidPacketException(SocketKeepalive.ERROR_INVALID_PORT); + } + + int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; + ByteBuffer buf = ByteBuffer.allocate(length); + buf.order(ByteOrder.BIG_ENDIAN); + buf.putShort((short) 0x4500); // IP version and TOS + buf.putShort((short) length); + buf.putInt(0); // ID, flags, offset + buf.put((byte) 64); // TTL + buf.put((byte) OsConstants.IPPROTO_UDP); + int ipChecksumOffset = buf.position(); + buf.putShort((short) 0); // IP checksum + buf.put(srcAddress.getAddress()); + buf.put(dstAddress.getAddress()); + buf.putShort((short) srcPort); + buf.putShort((short) dstPort); + buf.putShort((short) (length - 20)); // UDP length + int udpChecksumOffset = buf.position(); + buf.putShort((short) 0); // UDP checksum + buf.put((byte) 0xff); // NAT-T keepalive + buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); + buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); + + return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); + } +} diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 204c25f01d01..c37837837a9e 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -18,7 +18,6 @@ package android.net; import android.annotation.UnsupportedAppUsage; import android.content.Context; -import android.net.ConnectivityManager.PacketKeepalive; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -155,7 +154,7 @@ public abstract class NetworkAgent extends Handler { * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. */ - public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11; + public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11; /** * Requests that the specified keepalive packet be stopped. @@ -164,20 +163,20 @@ public abstract class NetworkAgent extends Handler { * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. */ - public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12; + public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12; /** - * Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive - * request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous + * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive + * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous * error notification. * - * This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to - * so that the app's PacketKeepaliveCallback methods can be called. + * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, + * so that the app's {@link SocketKeepalive.Callback} methods can be called. * * arg1 = slot number of the keepalive * arg2 = error code */ - public static final int EVENT_PACKET_KEEPALIVE = BASE + 13; + public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13; /** * Sent by ConnectivityService to inform this network transport of signal strength thresholds @@ -305,12 +304,12 @@ public abstract class NetworkAgent extends Handler { saveAcceptUnvalidated(msg.arg1 != 0); break; } - case CMD_START_PACKET_KEEPALIVE: { - startPacketKeepalive(msg); + case CMD_START_SOCKET_KEEPALIVE: { + startSocketKeepalive(msg); break; } - case CMD_STOP_PACKET_KEEPALIVE: { - stopPacketKeepalive(msg); + case CMD_STOP_SOCKET_KEEPALIVE: { + stopSocketKeepalive(msg); break; } @@ -460,22 +459,22 @@ public abstract class NetworkAgent extends Handler { /** * Requests that the network hardware send the specified packet at the specified interval. */ - protected void startPacketKeepalive(Message msg) { - onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + protected void startSocketKeepalive(Message msg) { + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); } /** * Requests that the network hardware send the specified packet at the specified interval. */ - protected void stopPacketKeepalive(Message msg) { - onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + protected void stopSocketKeepalive(Message msg) { + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED); } /** - * Called by the network when a packet keepalive event occurs. + * Called by the network when a socket keepalive event occurs. */ - public void onPacketKeepaliveEvent(int slot, int reason) { - queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason); + public void onSocketKeepaliveEvent(int slot, int reason) { + queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, reason); } /** diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index 97d50f4bac05..a47c11af40dc 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -109,6 +109,18 @@ public abstract class SocketKeepalive implements AutoCloseable { **/ public static final int MAX_INTERVAL_SEC = 3600; + /** + * This packet is invalid. + * See the error code for details. + * @hide + */ + public static class InvalidPacketException extends Exception { + public final int error; + public InvalidPacketException(int error) { + this.error = error; + } + } + @NonNull final IConnectivityManager mService; @NonNull final Network mNetwork; @NonNull private final Executor mExecutor; @@ -135,7 +147,7 @@ public abstract class SocketKeepalive implements AutoCloseable { @Override public void handleMessage(Message message) { switch (message.what) { - case NetworkAgent.EVENT_PACKET_KEEPALIVE: + case NetworkAgent.EVENT_SOCKET_KEEPALIVE: final int status = message.arg2; try { if (status == SUCCESS) { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 141d33bc4145..1f3369376b10 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -19,6 +19,7 @@ package android.os; import android.annotation.MainThread; import android.annotation.Nullable; import android.annotation.WorkerThread; + import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; @@ -70,7 +71,7 @@ import java.util.concurrent.atomic.AtomicInteger; * protected Long doInBackground(URL... urls) { * int count = urls.length; * long totalSize = 0; - * for (int i = 0; i < count; i++) { + * for (int i = 0; i < count; i++) { * totalSize += Downloader.downloadFile(urls[i]); * publishProgress((int) ((i / (float) count) * 100)); * // Escape early if cancel() is called @@ -158,13 +159,22 @@ import java.util.concurrent.atomic.AtomicInteger; * </ul> * * <h2>Memory observability</h2> - * <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following - * operations are safe without explicit synchronizations.</p> + * <p>AsyncTask guarantees that all callback calls are synchronized to ensure the following + * without explicit synchronizations.</p> * <ul> - * <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them - * in {@link #doInBackground}. - * <li>Set member fields in {@link #doInBackground}, and refer to them in - * {@link #onProgressUpdate} and {@link #onPostExecute}. + * <li>The memory effects of {@link #onPreExecute}, and anything else + * executed before the call to {@link #execute}, including the construction + * of the AsyncTask object, are visible to {@link #doInBackground}. + * <li>The memory effects of {@link #doInBackground} are visible to + * {@link #onPostExecute}. + * <li>Any memory effects of {@link #doInBackground} preceding a call + * to {@link #publishProgress} are visible to the corresponding + * {@link #onProgressUpdate} call. (But {@link #doInBackground} continues to + * run, and care needs to be taken that later updates in {@link #doInBackground} + * do not interfere with an in-progress {@link #onProgressUpdate} call.) + * <li>Any memory effects preceding a call to {@link #cancel} are visible + * after a call to {@link #isCancelled} that returns true as a result, or + * during and after a resulting call to {@link #onCancelled}. * </ul> * * <h2>Order of execution</h2> @@ -388,6 +398,10 @@ public abstract class AsyncTask<Params, Progress, Result> { * specified parameters are the parameters passed to {@link #execute} * by the caller of this task. * + * This will normally run on a background thread. But to better + * support testing frameworks, it is recommended that this also tolerates + * direct execution on the foreground thread, as part of the {@link #execute} call. + * * This method can call {@link #publishProgress} to publish updates * on the UI thread. * @@ -404,6 +418,8 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * Runs on the UI thread before {@link #doInBackground}. + * Invoked directly by {@link #execute} or {@link #executeOnExecutor}. + * The default version does nothing. * * @see #onPostExecute * @see #doInBackground @@ -414,7 +430,10 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * <p>Runs on the UI thread after {@link #doInBackground}. The - * specified result is the value returned by {@link #doInBackground}.</p> + * specified result is the value returned by {@link #doInBackground}. + * To better support testing frameworks, it is recommended that this be + * written to tolerate direct execution as part of the execute() call. + * The default version does nothing.</p> * * <p>This method won't be invoked if the task was cancelled.</p> * @@ -432,6 +451,7 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * Runs on the UI thread after {@link #publishProgress} is invoked. * The specified values are the values passed to {@link #publishProgress}. + * The default version does nothing. * * @param values The values indicating progress. * @@ -466,7 +486,8 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * <p>Applications should preferably override {@link #onCancelled(Object)}. * This method is invoked by the default implementation of - * {@link #onCancelled(Object)}.</p> + * {@link #onCancelled(Object)}. + * The default version does nothing.</p> * * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and * {@link #doInBackground(Object[])} has finished.</p> @@ -504,12 +525,16 @@ public abstract class AsyncTask<Params, Progress, Result> { * an attempt to stop the task.</p> * * <p>Calling this method will result in {@link #onCancelled(Object)} being - * invoked on the UI thread after {@link #doInBackground(Object[])} - * returns. Calling this method guarantees that {@link #onPostExecute(Object)} - * is never invoked. After invoking this method, you should check the - * value returned by {@link #isCancelled()} periodically from - * {@link #doInBackground(Object[])} to finish the task as early as - * possible.</p> + * invoked on the UI thread after {@link #doInBackground(Object[])} returns. + * Calling this method guarantees that onPostExecute(Object) is never + * subsequently invoked, even if <tt>cancel</tt> returns false, but + * {@link #onPostExecute} has not yet run. To finish the + * task as early as possible, check {@link #isCancelled()} periodically from + * {@link #doInBackground(Object[])}.</p> + * + * <p>This only requests cancellation. It never waits for a running + * background task to terminate, even if <tt>mayInterruptIfRunning</tt> is + * true.</p> * * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 1ebb551df961..b28c2f462db2 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -967,7 +967,7 @@ public class Binder implements IBinder { * By default, we use the calling uid since we can always trust it. */ private static volatile BinderInternal.WorkSourceProvider sWorkSourceProvider = - Binder::getCallingUid; + (x) -> Binder.getCallingUid(); /** * Sets the work source provider. @@ -991,21 +991,23 @@ public class Binder implements IBinder { // Entry point from android_util_Binder.cpp's onTransact private boolean execTransact(int code, long dataObj, long replyObj, int flags) { - final int workSourceUid = sWorkSourceProvider.resolveWorkSourceUid(); - final long origWorkSource = ThreadLocalWorkSource.setUid(workSourceUid); + // At that point, the parcel request headers haven't been parsed so we do not know what + // WorkSource the caller has set. Use calling uid as the default. + final int callingUid = Binder.getCallingUid(); + final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid); try { - return execTransactInternal(code, dataObj, replyObj, flags, workSourceUid); + return execTransactInternal(code, dataObj, replyObj, flags, callingUid); } finally { ThreadLocalWorkSource.restore(origWorkSource); } } - private boolean execTransactInternal(int code, long dataObj, long replyObj, - int flags, int workSourceUid) { + private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags, + int callingUid) { // Make sure the observer won't change while processing a transaction. final BinderInternal.Observer observer = sObserver; final CallSession callSession = - observer != null ? observer.callStarted(this, code, workSourceUid) : null; + observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null; Parcel data = Parcel.obtain(dataObj); Parcel reply = Parcel.obtain(replyObj); // theoretically, we should call transact, which will call onTransact, @@ -1045,6 +1047,10 @@ public class Binder implements IBinder { Trace.traceEnd(Trace.TRACE_TAG_ALWAYS); } if (observer != null) { + // The parcel RPC headers have been called during onTransact so we can now access + // the worksource uid from the parcel. + final int workSourceUid = sWorkSourceProvider.resolveWorkSourceUid( + data.readCallingWorkSourceUid()); observer.callEnded(callSession, data.dataSize(), reply.dataSize(), workSourceUid); } } diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index 97d72f01dbb3..97c0a13e7a2b 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -493,8 +493,17 @@ public final class BinderProxy implements IBinder { // Make sure the listener won't change while processing a transaction. final Binder.ProxyTransactListener transactListener = sTransactListener; Object session = null; + if (transactListener != null) { + final int origWorkSourceUid = Binder.getCallingWorkSourceUid(); session = transactListener.onTransactStarted(this, code); + + // Allow the listener to update the work source uid. We need to update the request + // header if the uid is updated. + final int updatedWorkSourceUid = Binder.getCallingWorkSourceUid(); + if (origWorkSourceUid != updatedWorkSourceUid) { + data.replaceCallingWorkSourceUid(updatedWorkSourceUid); + } } try { diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java index 3a5b8a86204e..27f7e2296e7f 100644 --- a/core/java/android/os/BugreportManager.java +++ b/core/java/android/os/BugreportManager.java @@ -24,7 +24,8 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; -import android.os.IBinder.DeathRecipient; + +import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.lang.annotation.Retention; @@ -127,13 +128,16 @@ public class BugreportManager { @NonNull BugreportParams params, @NonNull @CallbackExecutor Executor executor, @NonNull BugreportCallback callback) { - // TODO(b/111441001): Enforce android.Manifest.permission.DUMP if necessary. + Preconditions.checkNotNull(bugreportFd); + Preconditions.checkNotNull(params); + Preconditions.checkNotNull(executor); + Preconditions.checkNotNull(callback); DumpstateListener dsListener = new DumpstateListener(executor, callback); try { // Note: mBinder can get callingUid from the binder transaction. mBinder.startBugreport(-1 /* callingUid */, mContext.getOpPackageName(), - (bugreportFd != null ? bugreportFd.getFileDescriptor() : new FileDescriptor()), + bugreportFd.getFileDescriptor(), (screenshotFd != null ? screenshotFd.getFileDescriptor() : new FileDescriptor()), params.getMode(), dsListener); @@ -154,8 +158,7 @@ public class BugreportManager { } } - private final class DumpstateListener extends IDumpstateListener.Stub - implements DeathRecipient { + private final class DumpstateListener extends IDumpstateListener.Stub { private final Executor mExecutor; private final BugreportCallback mCallback; @@ -165,11 +168,6 @@ public class BugreportManager { } @Override - public void binderDied() { - // TODO(b/111441001): implement - } - - @Override public void onProgress(int progress) throws RemoteException { final long identity = Binder.clearCallingIdentity(); try { diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index ddec688931cb..68f9288a93cf 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -103,7 +103,7 @@ public class GraphicsEnvironment { * Return the debug layer app's on-disk and in-APK lib directories */ private static String getDebugLayerAppPaths(Context context, String app) { - ApplicationInfo appInfo; + final ApplicationInfo appInfo; try { appInfo = context.getPackageManager().getApplicationInfo( app, PackageManager.MATCH_ALL); @@ -113,15 +113,15 @@ public class GraphicsEnvironment { return null; } - String abi = chooseAbi(appInfo); + final String abi = chooseAbi(appInfo); - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(appInfo.nativeLibraryDir) .append(File.pathSeparator); sb.append(appInfo.sourceDir) .append("!/lib/") .append(abi); - String paths = sb.toString(); + final String paths = sb.toString(); if (DEBUG) Log.v(TAG, "Debug layer app libs: " + paths); @@ -143,13 +143,13 @@ public class GraphicsEnvironment { if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) { - int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); + final int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); if (enable != 0) { - String gpuDebugApp = coreSettings.getString(Settings.Global.GPU_DEBUG_APP); + final String gpuDebugApp = coreSettings.getString(Settings.Global.GPU_DEBUG_APP); - String packageName = context.getPackageName(); + final String packageName = context.getPackageName(); if ((gpuDebugApp != null && packageName != null) && (!gpuDebugApp.isEmpty() && !packageName.isEmpty()) @@ -163,12 +163,12 @@ public class GraphicsEnvironment { // If there is a debug layer app specified, add its path. - String gpuDebugLayerApp = + final String gpuDebugLayerApp = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYER_APP); if (gpuDebugLayerApp != null && !gpuDebugLayerApp.isEmpty()) { Log.i(TAG, "GPU debug layer app: " + gpuDebugLayerApp); - String paths = getDebugLayerAppPaths(context, gpuDebugLayerApp); + final String paths = getDebugLayerAppPaths(context, gpuDebugLayerApp); if (paths != null) { // Append the path so files placed in the app's base directory will // override the external path @@ -176,14 +176,14 @@ public class GraphicsEnvironment { } } - String layers = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYERS); + final String layers = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYERS); Log.i(TAG, "Vulkan debug layer list: " + layers); if (layers != null && !layers.isEmpty()) { setDebugLayers(layers); } - String layersGLES = + final String layersGLES = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYERS_GLES); Log.i(TAG, "GLES debug layer list: " + layersGLES); @@ -208,7 +208,7 @@ public class GraphicsEnvironment { private static final Map<OpenGlDriverChoice, String> sDriverMap = buildMap(); private static Map<OpenGlDriverChoice, String> buildMap() { - Map<OpenGlDriverChoice, String> map = new HashMap<>(); + final Map<OpenGlDriverChoice, String> map = new HashMap<>(); map.put(OpenGlDriverChoice.DEFAULT, "default"); map.put(OpenGlDriverChoice.ANGLE, "angle"); map.put(OpenGlDriverChoice.NATIVE, "native"); @@ -219,7 +219,7 @@ public class GraphicsEnvironment { private static List<String> getGlobalSettingsString(Bundle bundle, String globalSetting) { List<String> valueList = null; - String settingsValue = bundle.getString(globalSetting); + final String settingsValue = bundle.getString(globalSetting); if (settingsValue != null) { valueList = new ArrayList<>(Arrays.asList(settingsValue.split(","))); @@ -242,18 +242,16 @@ public class GraphicsEnvironment { } private static String getDriverForPkg(Bundle bundle, String packageName) { - String allUseAngle = + final String allUseAngle = bundle.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE); if ((allUseAngle != null) && allUseAngle.equals("1")) { return sDriverMap.get(OpenGlDriverChoice.ANGLE); } - List<String> globalSettingsDriverPkgs = - getGlobalSettingsString(bundle, - Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS); - List<String> globalSettingsDriverValues = - getGlobalSettingsString(bundle, - Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES); + final List<String> globalSettingsDriverPkgs = getGlobalSettingsString( + bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS); + final List<String> globalSettingsDriverValues = getGlobalSettingsString( + bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES); // Make sure we have a good package name if ((packageName == null) || (packageName.isEmpty())) { @@ -270,7 +268,7 @@ public class GraphicsEnvironment { return sDriverMap.get(OpenGlDriverChoice.DEFAULT); } - int pkgIndex = getGlobalSettingsPkgIndex(packageName, globalSettingsDriverPkgs); + final int pkgIndex = getGlobalSettingsPkgIndex(packageName, globalSettingsDriverPkgs); if (pkgIndex < 0) { return sDriverMap.get(OpenGlDriverChoice.DEFAULT); @@ -283,10 +281,10 @@ public class GraphicsEnvironment { * Get the ANGLE package name. */ private String getAnglePackageName(Context context) { - Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID); + final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID); - List<ResolveInfo> resolveInfos = context.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); + final List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities( + intent, PackageManager.MATCH_SYSTEM_ONLY); if (resolveInfos.size() != 1) { Log.e(TAG, "Invalid number of ANGLE packages. Required: 1, Found: " + resolveInfos.size()); @@ -315,8 +313,8 @@ public class GraphicsEnvironment { * - devices that are running a userdebug build (ro.debuggable) or can inject libraries for * debugging (PR_SET_DUMPABLE). */ - boolean appIsDebuggable = isDebuggable(context); - boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1; + final boolean appIsDebuggable = isDebuggable(context); + final boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1; if (!(appIsDebuggable || deviceIsDebuggable)) { Log.v(TAG, "Skipping loading temporary rules file: " + "appIsDebuggable = " + appIsDebuggable + ", " @@ -324,7 +322,7 @@ public class GraphicsEnvironment { return false; } - String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES); + final String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES); if ((angleTempRules == null) || angleTempRules.isEmpty()) { Log.v(TAG, "System property '" + ANGLE_TEMP_RULES + "' is not set or is empty"); @@ -333,16 +331,16 @@ public class GraphicsEnvironment { Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules); - File tempRulesFile = new File(angleTempRules); + final File tempRulesFile = new File(angleTempRules); if (tempRulesFile.exists()) { Log.i(TAG, angleTempRules + " exists, loading file."); try { - FileInputStream stream = new FileInputStream(angleTempRules); + final FileInputStream stream = new FileInputStream(angleTempRules); try { - FileDescriptor rulesFd = stream.getFD(); - long rulesOffset = 0; - long rulesLength = stream.getChannel().size(); + final FileDescriptor rulesFd = stream.getFD(); + final long rulesOffset = 0; + final long rulesLength = stream.getChannel().size(); Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules); setAngleInfo(paths, packageName, devOptIn, rulesFd, rulesOffset, rulesLength); @@ -377,11 +375,11 @@ public class GraphicsEnvironment { String devOptIn) { // Pass the rules file to loader for ANGLE decisions try { - AssetManager angleAssets = + final AssetManager angleAssets = context.getPackageManager().getResourcesForApplication(angleInfo).getAssets(); try { - AssetFileDescriptor assetsFd = angleAssets.openFd(ANGLE_RULES_FILE); + final AssetFileDescriptor assetsFd = angleAssets.openFd(ANGLE_RULES_FILE); setAngleInfo(paths, packageName, devOptIn, assetsFd.getFileDescriptor(), assetsFd.getStartOffset(), assetsFd.getLength()); @@ -404,9 +402,8 @@ public class GraphicsEnvironment { * Pull ANGLE whitelist from GlobalSettings and compare against current package */ private boolean checkAngleWhitelist(Bundle bundle, String packageName) { - List<String> angleWhitelist = - getGlobalSettingsString(bundle, - Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST); + final List<String> angleWhitelist = + getGlobalSettingsString(bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST); return angleWhitelist.contains(packageName); } @@ -420,7 +417,7 @@ public class GraphicsEnvironment { return; } - String devOptIn = getDriverForPkg(bundle, packageName); + final String devOptIn = getDriverForPkg(bundle, packageName); if (DEBUG) { Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " + "set to: '" + devOptIn + "'"); @@ -438,9 +435,9 @@ public class GraphicsEnvironment { // load a driver, GraphicsEnv::shouldUseAngle() has seen the package name before // and can confidently answer yes/no based on the previously set developer // option value. - boolean whitelisted = checkAngleWhitelist(bundle, packageName); - boolean defaulted = devOptIn.equals(sDriverMap.get(OpenGlDriverChoice.DEFAULT)); - boolean rulesCheck = (whitelisted || !defaulted); + final boolean whitelisted = checkAngleWhitelist(bundle, packageName); + final boolean defaulted = devOptIn.equals(sDriverMap.get(OpenGlDriverChoice.DEFAULT)); + final boolean rulesCheck = (whitelisted || !defaulted); if (!rulesCheck) { return; } @@ -452,13 +449,13 @@ public class GraphicsEnvironment { Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn); } - String anglePkgName = getAnglePackageName(context); + final String anglePkgName = getAnglePackageName(context); if (anglePkgName.isEmpty()) { Log.e(TAG, "Failed to find ANGLE package."); return; } - ApplicationInfo angleInfo; + final ApplicationInfo angleInfo; try { angleInfo = context.getPackageManager().getApplicationInfo(anglePkgName, PackageManager.MATCH_SYSTEM_ONLY); @@ -467,10 +464,10 @@ public class GraphicsEnvironment { return; } - String abi = chooseAbi(angleInfo); + final String abi = chooseAbi(angleInfo); // Build a path that includes installed native libs and APK - String paths = angleInfo.nativeLibraryDir + final String paths = angleInfo.nativeLibraryDir + File.pathSeparator + angleInfo.sourceDir + "!/lib/" @@ -493,12 +490,12 @@ public class GraphicsEnvironment { * Choose whether the current process should use the builtin or an updated driver. */ private static void chooseDriver(Context context, Bundle coreSettings) { - String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + final String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); if (driverPackageName == null || driverPackageName.isEmpty()) { return; } - ApplicationInfo driverInfo; + final ApplicationInfo driverInfo; try { driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY); @@ -519,7 +516,7 @@ public class GraphicsEnvironment { // To minimize risk of driver updates crippling the device beyond user repair, never use an // updated driver for privileged or non-updated system apps. Presumably pre-installed apps // were tested thoroughly with the pre-installed driver. - ApplicationInfo ai = context.getApplicationInfo(); + final ApplicationInfo ai = context.getApplicationInfo(); if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); return; @@ -529,7 +526,7 @@ public class GraphicsEnvironment { // 0: Default (Invalid values fallback to default as well) // 1: All apps use Game Driver // 2: All apps use system graphics driver - int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); + final int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); if (gameDriverAllApps == 2) { if (DEBUG) { Log.w(TAG, "Game Driver is turned off on this device"); @@ -546,7 +543,7 @@ public class GraphicsEnvironment { } return; } - boolean isOptIn = + final boolean isOptIn = getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) .contains(ai.packageName); if (!isOptIn @@ -563,13 +560,13 @@ public class GraphicsEnvironment { // on the blacklist, terminate early when it's on the blacklist. try { // TODO(b/121350991) Switch to DeviceConfig with property listener. - String base64String = + final String base64String = coreSettings.getString(Settings.Global.GAME_DRIVER_BLACKLIST); if (base64String != null && !base64String.isEmpty()) { - Blacklists blacklistsProto = Blacklists.parseFrom( - Base64.decode(base64String, BASE64_FLAGS)); - List<Blacklist> blacklists = blacklistsProto.getBlacklistsList(); - long driverVersionCode = driverInfo.longVersionCode; + final Blacklists blacklistsProto = + Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS)); + final List<Blacklist> blacklists = blacklistsProto.getBlacklistsList(); + final long driverVersionCode = driverInfo.longVersionCode; for (Blacklist blacklist : blacklists) { if (blacklist.getVersionCode() == driverVersionCode) { for (String packageName : blacklist.getPackageNamesList()) { @@ -589,7 +586,7 @@ public class GraphicsEnvironment { } } - String abi = chooseAbi(driverInfo); + final String abi = chooseAbi(driverInfo); if (abi == null) { if (DEBUG) { // This is the normal case for the pre-installed empty driver package, don't spam @@ -600,13 +597,13 @@ public class GraphicsEnvironment { return; } - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(driverInfo.nativeLibraryDir) .append(File.pathSeparator); sb.append(driverInfo.sourceDir) .append("!/lib/") .append(abi); - String paths = sb.toString(); + final String paths = sb.toString(); if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths); setDriverPath(paths); @@ -623,7 +620,7 @@ public class GraphicsEnvironment { * Should only be called after chooseDriver(). */ public static void earlyInitEGL() { - Thread eglInitThread = new Thread( + final Thread eglInitThread = new Thread( () -> { EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); }, @@ -632,7 +629,7 @@ public class GraphicsEnvironment { } private static String chooseAbi(ApplicationInfo ai) { - String isa = VMRuntime.getCurrentInstructionSet(); + final String isa = VMRuntime.getCurrentInstructionSet(); if (ai.primaryCpuAbi != null && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { return ai.primaryCpuAbi; diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index e8704afd0139..e6c12c7972a2 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -469,6 +469,11 @@ public class Handler { return sendMessageDelayed(getPostMessage(r), delayMillis); } + /** @hide */ + public final boolean postDelayed(Runnable r, int what, long delayMillis) { + return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis); + } + /** * Causes the Runnable r to be added to the message queue, to be run * after the specified amount of time elapses. diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index b9cdcc096962..79e9ba5f5bcc 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -333,6 +333,12 @@ public final class Parcel { private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName); private static native void nativeEnforceInterface(long nativePtr, String interfaceName); + @CriticalNative + private static native boolean nativeReplaceCallingWorkSourceUid( + long nativePtr, int workSourceUid); + @CriticalNative + private static native int nativeReadCallingWorkSourceUid(long nativePtr); + /** Last time exception with a stack trace was written */ private static volatile long sLastWriteExceptionStackTrace; /** Used for throttling of writing stack trace, which is costly */ @@ -613,6 +619,35 @@ public final class Parcel { } /** + * Writes the work source uid to the request headers. + * + * <p>It requires the headers to have been written/read already to replace the work source. + * + * @return true if the request headers have been updated. + * + * @hide + */ + public boolean replaceCallingWorkSourceUid(int workSourceUid) { + return nativeReplaceCallingWorkSourceUid(mNativePtr, workSourceUid); + } + + /** + * Reads the work source uid from the request headers. + * + * <p>Unlike other read methods, this method does not read the parcel at the current + * {@link #dataPosition}. It will set the {@link #dataPosition} before the read and restore the + * position after reading the request header. + * + * @return the work source uid or {@link Binder#UNSET_WORKSOURCE} if headers have not been + * written/parsed yet. + * + * @hide + */ + public int readCallingWorkSourceUid() { + return nativeReadCallingWorkSourceUid(mNativePtr); + } + + /** * Write a byte array into the parcel at the current {@link #dataPosition}, * growing {@link #dataCapacity} if needed. * @param b Bytes to place into the parcel. diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 0441ba27dcd4..22ba74d70c16 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -566,7 +566,7 @@ public final class PowerManager { * @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef({ServiceType.GPS, + @IntDef({ServiceType.LOCATION, ServiceType.VIBRATION, ServiceType.ANIMATION, ServiceType.FULL_BACKUP, @@ -583,7 +583,7 @@ public final class PowerManager { }) public @interface ServiceType { int NULL = 0; - int GPS = 1; + int LOCATION = 1; int VIBRATION = 2; int ANIMATION = 3; int FULL_BACKUP = 4; @@ -1400,11 +1400,11 @@ public final class PowerManager { */ @LocationPowerSaveMode public int getLocationPowerSaveMode() { - final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.GPS); + final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.LOCATION); if (!powerSaveState.globalBatterySaverEnabled) { return LOCATION_MODE_NO_CHANGE; } - return powerSaveState.gpsMode; + return powerSaveState.locationMode; } /** diff --git a/core/java/android/os/PowerSaveState.java b/core/java/android/os/PowerSaveState.java index 4918ad107763..4a5e89479ec0 100644 --- a/core/java/android/os/PowerSaveState.java +++ b/core/java/android/os/PowerSaveState.java @@ -19,7 +19,7 @@ package android.os; * Data class for battery saver state. It contains the data * <p> * 1. Whether battery saver mode is enabled - * 2. Specific parameters to use in battery saver mode(i.e. screen brightness, gps mode) + * 2. Specific parameters to use in battery saver mode (i.e. screen brightness, location mode) * * @hide */ @@ -35,12 +35,12 @@ public class PowerSaveState implements Parcelable { * {@link PowerManager#isPowerSaveMode()} */ public final boolean globalBatterySaverEnabled; - public final int gpsMode; + public final int locationMode; public final float brightnessFactor; public PowerSaveState(Builder builder) { batterySaverEnabled = builder.mBatterySaverEnabled; - gpsMode = builder.mGpsMode; + locationMode = builder.mLocationMode; brightnessFactor = builder.mBrightnessFactor; globalBatterySaverEnabled = builder.mGlobalBatterySaverEnabled; } @@ -48,7 +48,7 @@ public class PowerSaveState implements Parcelable { public PowerSaveState(Parcel in) { batterySaverEnabled = in.readByte() != 0; globalBatterySaverEnabled = in.readByte() != 0; - gpsMode = in.readInt(); + locationMode = in.readInt(); brightnessFactor = in.readFloat(); } @@ -61,14 +61,14 @@ public class PowerSaveState implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeByte((byte) (batterySaverEnabled ? 1 : 0)); dest.writeByte((byte) (globalBatterySaverEnabled ? 1 : 0)); - dest.writeInt(gpsMode); + dest.writeInt(locationMode); dest.writeFloat(brightnessFactor); } public static final class Builder { private boolean mBatterySaverEnabled = false; private boolean mGlobalBatterySaverEnabled = false; - private int mGpsMode = 0; + private int mLocationMode = 0; private float mBrightnessFactor = 0.5f; public Builder() {} @@ -83,8 +83,8 @@ public class PowerSaveState implements Parcelable { return this; } - public Builder setGpsMode(int mode) { - mGpsMode = mode; + public Builder setLocationMode(int mode) { + mLocationMode = mode; return this; } diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl index ee6744b320f2..7e9ba5d4b628 100644 --- a/core/java/android/permission/IPermissionController.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -30,6 +30,9 @@ oneway interface IPermissionController { void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason, String callerPackageName, in RemoteCallback callback); void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe); + void restoreRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe); + void restoreDelayedRuntimePermissionBackup(String packageName, in UserHandle user, + in RemoteCallback callback); void getAppPermissions(String packageName, in RemoteCallback callback); void revokeRuntimePermission(String packageName, String permissionName); void countPermissionApps(in List<String> permissionNames, int flags, diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java index c59e5738165f..89967c325dd2 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -24,6 +24,8 @@ import static com.android.internal.util.Preconditions.checkFlagsArgument; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkStringNotEmpty; +import static java.lang.Math.min; + import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -60,6 +62,7 @@ import libcore.io.IoUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -278,6 +281,49 @@ public final class PermissionControllerManager { } /** + * Restore a backup of the runtime permissions. + * + * @param backup the backup to restore. The backup is sent asynchronously, hence it should not + * be modified after calling this method. + * @param user The user to be restore + * + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS) + public void restoreRuntimePermissionBackup(@NonNull byte[] backup, @NonNull UserHandle user) { + checkNotNull(backup); + checkNotNull(user); + + sRemoteService.scheduleAsyncRequest( + new PendingRestoreRuntimePermissionBackup(sRemoteService, backup, user)); + } + + /** + * Restore a backup of the runtime permissions that has been delayed. + * + * @param packageName The package that is ready to have it's permissions restored. + * @param user The user to restore + * @param executor Executor to execute the callback on + * @param callback Is called with {@code true} iff there is still more delayed backup left + * + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS) + public void restoreDelayedRuntimePermissionBackup(@NonNull String packageName, + @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback) { + checkNotNull(packageName); + checkNotNull(user); + checkNotNull(executor); + checkNotNull(callback); + + sRemoteService.scheduleRequest( + new PendingRestoreDelayedRuntimePermissionBackup(sRemoteService, packageName, + user, executor, callback)); + } + + /** * Gets the runtime permissions for an app. * * @param packageName The package for which to query. @@ -520,6 +566,80 @@ public final class PermissionControllerManager { } /** + * Task to send a large amount of data to a remote service. + */ + private static class FileWriterTask extends AsyncTask<byte[], Void, Void> { + private static final int CHUNK_SIZE = 4 * 1024; + + private ParcelFileDescriptor mLocalPipe; + private ParcelFileDescriptor mRemotePipe; + + @Override + protected void onPreExecute() { + ParcelFileDescriptor[] pipe; + try { + pipe = ParcelFileDescriptor.createPipe(); + } catch (IOException e) { + Log.e(TAG, "Could not create pipe needed to send runtime permission backup", + e); + return; + } + + mRemotePipe = pipe[0]; + mLocalPipe = pipe[1]; + } + + /** + * Get the file descriptor the remote service should read the data from. + * + * @return The file the data should be read from + */ + ParcelFileDescriptor getRemotePipe() { + return mRemotePipe; + } + + /** + * Send the data to the remove service. + * + * @param in The data to send + * + * @return ignored + */ + @Override + protected Void doInBackground(byte[]... in) { + byte[] buffer = in[0]; + try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(mLocalPipe)) { + for (int offset = 0; offset < buffer.length; offset += CHUNK_SIZE) { + out.write(buffer, offset, min(CHUNK_SIZE, buffer.length - offset)); + } + } catch (IOException | NullPointerException e) { + Log.e(TAG, "Error sending runtime permission backup", e); + } + + return null; + } + + /** + * Interrupt the send of the data. + * + * <p>Needs to be called when canceling this task as it might be hung. + */ + void interruptRead() { + IoUtils.closeQuietly(mLocalPipe); + } + + @Override + protected void onCancelled() { + onPostExecute(null); + } + + @Override + protected void onPostExecute(Void ignored) { + IoUtils.closeQuietly(mLocalPipe); + } + } + + /** * Request for {@link #revokeRuntimePermissions} */ private static final class PendingRevokeRuntimePermissionRequest extends @@ -668,6 +788,97 @@ public final class PermissionControllerManager { } /** + * Request for {@link #restoreRuntimePermissionBackup} + */ + private static final class PendingRestoreRuntimePermissionBackup implements + AbstractRemoteService.AsyncRequest<IPermissionController> { + private final @NonNull FileWriterTask mBackupSender; + private final @NonNull byte[] mBackup; + private final @NonNull UserHandle mUser; + + private PendingRestoreRuntimePermissionBackup(@NonNull RemoteService service, + @NonNull byte[] backup, @NonNull UserHandle user) { + mBackup = backup; + mUser = user; + + mBackupSender = new FileWriterTask(); + } + + @Override + public void run(@NonNull IPermissionController service) { + ParcelFileDescriptor remotePipe = mBackupSender.getRemotePipe(); + try { + service.restoreRuntimePermissionBackup(mUser, remotePipe); + } catch (RemoteException e) { + Log.e(TAG, "Error sending runtime permission backup", e); + mBackupSender.cancel(false); + } finally { + // Remote pipe end is duped by binder call. Local copy is not needed anymore + IoUtils.closeQuietly(remotePipe); + } + + mBackupSender.execute(mBackup); + } + } + + /** + * Request for {@link #restoreDelayedRuntimePermissionBackup(String, UserHandle, Executor, + * Consumer<Boolean>)} + */ + private static final class PendingRestoreDelayedRuntimePermissionBackup extends + AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> { + private final @NonNull String mPackageName; + private final @NonNull UserHandle mUser; + private final @NonNull Executor mExecutor; + private final @NonNull Consumer<Boolean> mCallback; + + private final @NonNull RemoteCallback mRemoteCallback; + + private PendingRestoreDelayedRuntimePermissionBackup(@NonNull RemoteService service, + @NonNull String packageName, @NonNull UserHandle user, @NonNull Executor executor, + @NonNull Consumer<Boolean> callback) { + super(service); + + mPackageName = packageName; + mUser = user; + mExecutor = executor; + mCallback = callback; + + mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> { + long token = Binder.clearCallingIdentity(); + try { + callback.accept(result.getBoolean(KEY_RESULT, false)); + } finally { + Binder.restoreCallingIdentity(token); + + finish(); + } + }), null); + } + + @Override + protected void onTimeout(RemoteService remoteService) { + long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute( + () -> mCallback.accept(true)); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void run() { + try { + getService().getServiceInterface().restoreDelayedRuntimePermissionBackup( + mPackageName, mUser, mRemoteCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error restoring delayed permissions for " + mPackageName, e); + } + } + } + + /** * Request for {@link #getAppPermissions} */ private static final class PendingGetAppPermissionRequest extends diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java index 482f4a86419e..fb6c061c536f 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -28,6 +28,7 @@ import static com.android.internal.util.Preconditions.checkStringNotEmpty; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.Manifest; +import android.annotation.BinderThread; import android.annotation.NonNull; import android.annotation.SystemApi; import android.app.Service; @@ -48,6 +49,7 @@ import android.util.Log; import com.android.internal.util.Preconditions; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -104,6 +106,28 @@ public abstract class PermissionControllerService extends Service { @NonNull OutputStream backup); /** + * Restore a backup of the runtime permissions. + * + * @param user The user to restore + * @param backup The stream to read the backup from + */ + @BinderThread + public abstract void onRestoreRuntimePermissionsBackup(@NonNull UserHandle user, + @NonNull InputStream backup); + + /** + * Restore a delayed backup of the runtime permissions. + * + * @param packageName The app to restore + * @param user The user to restore + * + * @return {@code true} iff there is still delayed backup left + */ + @BinderThread + public abstract boolean onRestoreDelayedRuntimePermissionsBackup(@NonNull String packageName, + @NonNull UserHandle user); + + /** * Gets the runtime permissions for an app. * * @param packageName The package for which to query. @@ -207,6 +231,36 @@ public abstract class PermissionControllerService extends Service { } @Override + public void restoreRuntimePermissionBackup(UserHandle user, ParcelFileDescriptor pipe) { + checkNotNull(user); + checkNotNull(pipe); + + enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null); + + try (InputStream backup = new ParcelFileDescriptor.AutoCloseInputStream(pipe)) { + onRestoreRuntimePermissionsBackup(user, backup); + } catch (IOException e) { + Log.e(LOG_TAG, "Could not open pipe to read backup from", e); + } + } + + @Override + public void restoreDelayedRuntimePermissionBackup(String packageName, UserHandle user, + RemoteCallback callback) { + checkNotNull(packageName); + checkNotNull(user); + checkNotNull(callback); + + enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null); + + boolean hasMoreBackup = onRestoreDelayedRuntimePermissionsBackup(packageName, user); + + Bundle result = new Bundle(); + result.putBoolean(PermissionControllerManager.KEY_RESULT, hasMoreBackup); + callback.sendResult(result); + } + + @Override public void getAppPermissions(String packageName, RemoteCallback callback) { checkNotNull(packageName, "packageName"); checkNotNull(callback, "callback"); diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 92650e114a66..1f587232ca05 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -150,6 +150,21 @@ public final class DeviceConfig { } /** + * Namespace for all runtime related features. + * + * @hide + */ + @SystemApi + public interface Runtime { + String NAMESPACE = "runtime"; + + /** + * Whether or not we use the precompiled layout. + */ + String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled"; + } + + /** * Namespace for all runtime native related features. * * @hide @@ -160,6 +175,17 @@ public final class DeviceConfig { } /** + * Namespace for all runtime native boot related features. Boot in this case refers to the + * fact that the properties only take affect after rebooting the device. + * + * @hide + */ + @SystemApi + public interface RuntimeNativeBoot { + String NAMESPACE = "runtime_native_boot"; + } + + /** * Namespace for all activity manager related features that are used at the native level. * These features are applied at reboot. * diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 0743c23080fd..67c840006948 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -110,6 +110,16 @@ public final class MediaStore { public static final String SCAN_VOLUME_CALL = "scan_volume"; /** + * Extra used with {@link #SCAN_FILE_CALL} or {@link #SCAN_VOLUME_CALL} to indicate that + * the file path originated from shell. + * + * {@hide} + */ + @TestApi + public static final String EXTRA_ORIGINATED_FROM_SHELL = + "android.intent.extra.originated_from_shell"; + + /** * The method name used by the media scanner and mtp to tell the media provider to * rescan and reclassify that have become unhidden because of renaming folders or * removing nomedia files diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e14bb66828a4..3a02e85eee3b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5704,7 +5704,6 @@ public final class Settings { * Defines whether Content Capture is enabled for the user. * @hide */ - @SystemApi @TestApi public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled"; diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl index ac5be06abff3..4e98201118a4 100644 --- a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl +++ b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl @@ -32,4 +32,6 @@ oneway interface IRoleControllerService { void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback); void onGrantDefaultRoles(in IRoleManagerCallback callback); + + void onSmsKillSwitchToggled(boolean smsRestrictionEnabled); } diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/rolecontrollerservice/RoleControllerService.java index 6eda504f24da..5403cfa06807 100644 --- a/core/java/android/rolecontrollerservice/RoleControllerService.java +++ b/core/java/android/rolecontrollerservice/RoleControllerService.java @@ -96,6 +96,11 @@ public abstract class RoleControllerService extends Service { RoleControllerService.this.onGrantDefaultRoles(new RoleManagerCallbackDelegate( callback)); } + + @Override + public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) { + RoleControllerService.this.onSmsKillSwitchToggled(smsRestrictionEnabled); + } }; } @@ -141,6 +146,14 @@ public abstract class RoleControllerService extends Service { @NonNull RoleManagerCallback callback); /** + * Cleanup appop/permissions state in response to sms kill switch toggle + * + * @param smsRestrictionEnabled whether kill switch was turned on + */ + //STOPSHIP: remove this api before shipping a final version + public abstract void onSmsKillSwitchToggled(boolean smsRestrictionEnabled); + + /** * Called by system to grant default permissions and roles. * <p> * This is typically when creating a new user or upgrading either system or diff --git a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java index db242a2e265e..ca6676d87479 100644 --- a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java +++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java @@ -17,6 +17,7 @@ package android.service.contentcapture; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.view.contentcapture.ContentCaptureEvent; @@ -32,6 +33,7 @@ import java.util.List; * @hide */ @SystemApi +@TestApi @Deprecated public final class ContentCaptureEventsRequest implements Parcelable { // TODO(b/121051220): remove .java and .aidl once service implementation doesn't use it anymore diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java index 020de7f24048..c98f09e13d97 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -21,6 +21,7 @@ import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.Service; import android.content.ComponentName; import android.content.Intent; @@ -48,9 +49,7 @@ import com.android.internal.os.IResultReceiver; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.Collections; 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 @@ -59,6 +58,7 @@ import java.util.Set; * @hide */ @SystemApi +@TestApi public abstract class ContentCaptureService extends Service { private static final String TAG = ContentCaptureService.class.getSimpleName(); @@ -166,10 +166,6 @@ public abstract class ContentCaptureService extends Service { /** * 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 @@ -194,76 +190,6 @@ public abstract class ContentCaptureService extends Service { } /** - * 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) { - final IContentCaptureServiceCallback callback = mCallback; - if (callback == null) { - Log.w(TAG, "setActivityContentCaptureEnabled(): no server callback"); - return; - } - try { - callback.setActivityContentCaptureEnabled(activity, enabled); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - /** - * 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) { - final IContentCaptureServiceCallback callback = mCallback; - if (callback == null) { - Log.w(TAG, "setPackageContentCaptureEnabled(): no server callback"); - return; - } - try { - callback.setPackageContentCaptureEnabled(packageName, enabled); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - /** - * Gets the activities where content capture was disabled by - * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}. - */ - @NonNull - public final Set<ComponentName> getContentCaptureDisabledActivities() { - final IContentCaptureServiceCallback callback = mCallback; - if (callback == null) { - Log.w(TAG, "getContentCaptureDisabledActivities(): no server callback"); - return Collections.emptySet(); - } - //TODO(b/122595322): implement (using SyncResultReceiver) - return null; - } - - /** - * Gets the apps where content capture was disabled by - * {@link #setPackageContentCaptureEnabled(String, boolean)}. - */ - @NonNull - public final Set<String> getContentCaptureDisabledPackages() { - final IContentCaptureServiceCallback callback = mCallback; - if (callback == null) { - Log.w(TAG, "getContentCaptureDisabledPackages(): no server callback"); - return Collections.emptySet(); - } - //TODO(b/122595322): implement (using SyncResultReceiver) - return null; - } - - /** * Called when the Android system connects to service. * * <p>You should generally do initialization here rather than in {@link #onCreate}. diff --git a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl index e84bd6fdf2b6..2a729b6dc874 100644 --- a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl +++ b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl @@ -28,8 +28,4 @@ import java.util.List; */ oneway interface IContentCaptureServiceCallback { void setContentCaptureWhitelist(in List<String> packages, in List<ComponentName> activities); - void setActivityContentCaptureEnabled(in ComponentName activity, boolean enabled); - void setPackageContentCaptureEnabled(in String packageName, boolean enabled); - void getContentCaptureDisabledActivities(in IResultReceiver receiver); - void getContentCaptureDisabledPackages(in IResultReceiver receiver); } diff --git a/core/java/android/service/contentcapture/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java index bc2116a441aa..c3af1f0cc608 100644 --- a/core/java/android/service/contentcapture/SnapshotData.java +++ b/core/java/android/service/contentcapture/SnapshotData.java @@ -19,6 +19,7 @@ package android.service.contentcapture; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.os.Bundle; @@ -31,6 +32,7 @@ import android.os.Parcelable; * @hide */ @SystemApi +@TestApi public final class SnapshotData implements Parcelable { private final @NonNull Bundle mAssistData; diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 44353b1609b7..81643e90428f 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -2182,6 +2182,13 @@ public class TextUtils { return Character.isWhitespace(codePoint) || codePoint == NBSP_CODE_POINT; } + /** @hide */ + @Nullable + public static String withoutPrefix(@Nullable String prefix, @Nullable String str) { + if (prefix == null || str == null) return str; + return str.startsWith(prefix) ? str.substring(prefix.length()) : str; + } + /** * Remove html, remove bad characters, and truncate string. * diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java index 1bbef8e9cfff..b36888e23f9c 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java @@ -120,7 +120,7 @@ public class ApkSignatureSchemeV2Verifier { * @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v2. * @throws IOException if an I/O error occurs while reading the APK file. */ - public static X509Certificate[][] plsCertsNoVerifyOnlyCerts(String apkFile) + public static X509Certificate[][] unsafeGetCertsWithoutVerification(String apkFile) throws SignatureNotFoundException, SecurityException, IOException { VerifiedSigner vSigner = verify(apkFile, false); return vSigner.certs; diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java index 1471870bd7d2..602e6df3e34f 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java @@ -117,7 +117,7 @@ public class ApkSignatureSchemeV3Verifier { * @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v3. * @throws IOException if an I/O error occurs while reading the APK file. */ - public static VerifiedSigner plsCertsNoVerifyOnlyCerts(String apkFile) + public static VerifiedSigner unsafeGetCertsWithoutVerification(String apkFile) throws SignatureNotFoundException, SecurityException, IOException { return verify(apkFile, false); } diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index ac4ea75b38e3..ab67d372021b 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -302,7 +302,7 @@ public class ApkSignatureVerifier { * @throws PackageParserException if the APK's signature failed to verify. * or greater is not found, except in the case of no JAR signature. */ - public static PackageParser.SigningDetails plsCertsNoVerifyOnlyCerts( + public static PackageParser.SigningDetails unsafeGetCertsWithoutVerification( String apkPath, int minSignatureSchemeVersion) throws PackageParserException { @@ -317,7 +317,7 @@ public class ApkSignatureVerifier { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "certsOnlyV3"); try { ApkSignatureSchemeV3Verifier.VerifiedSigner vSigner = - ApkSignatureSchemeV3Verifier.plsCertsNoVerifyOnlyCerts(apkPath); + ApkSignatureSchemeV3Verifier.unsafeGetCertsWithoutVerification(apkPath); Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); Signature[] pastSignerSigs = null; @@ -359,7 +359,7 @@ public class ApkSignatureVerifier { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "certsOnlyV2"); try { Certificate[][] signerCerts = - ApkSignatureSchemeV2Verifier.plsCertsNoVerifyOnlyCerts(apkPath); + ApkSignatureSchemeV2Verifier.unsafeGetCertsWithoutVerification(apkPath); Signature[] signerSigs = convertToSignatures(signerCerts); return new PackageParser.SigningDetails(signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V2); diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 7026d2b1389c..2ba1e016e03d 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -18,10 +18,10 @@ package android.view; import static android.view.InsetsState.TYPE_IME; +import android.inputmethodservice.InputMethodService; import android.os.Parcel; import android.text.TextUtils; import android.view.SurfaceControl.Transaction; -import android.view.WindowInsets.Type; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; @@ -73,11 +73,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { return; } - if (setVisible) { - mController.show(Type.IME); - } else { - mController.hide(Type.IME); - } + mController.applyImeVisibility(setVisible); } @Override @@ -91,6 +87,30 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { mHasWindowFocus = false; } + /** + * Request {@link InputMethodManager} to show the IME. + * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}. + */ + @Override + @ShowResult int requestShow(boolean fromIme) { + // TODO: ResultReceiver for IME. + // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag. + if (fromIme) { + return ShowResult.SHOW_IMMEDIATELY; + } + + return getImm().requestImeShow(null /* resultReceiver */) + ? ShowResult.SHOW_DELAYED : ShowResult.SHOW_FAILED; + } + + /** + * Notify {@link InputMethodService} that IME window is hidden. + */ + @Override + void notifyHidden() { + getImm().notifyImeHidden(); + } + private boolean isDummyOrEmptyEditor(EditorInfo info) { // TODO(b/123044812): Handle dummy input gracefully in IME Insets API return info == null || (info.fieldId <= 0 && info.inputType <= 0); diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 7291d0b2f10c..583651dee379 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -127,16 +127,18 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll final Insets offset = Insets.subtract(mShownInsets, mPendingInsets); ArrayList<SurfaceParams> params = new ArrayList<>(); if (offset.left != 0) { - updateLeashesForSide(INSET_SIDE_LEFT, offset.left, params, state); + updateLeashesForSide(INSET_SIDE_LEFT, offset.left, mPendingInsets.left, params, state); } if (offset.top != 0) { - updateLeashesForSide(INSET_SIDE_TOP, offset.top, params, state); + updateLeashesForSide(INSET_SIDE_TOP, offset.top, mPendingInsets.top, params, state); } if (offset.right != 0) { - updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, params, state); + updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, mPendingInsets.right, params, + state); } if (offset.bottom != 0) { - updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, params, state); + updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params, + state); } SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get(); applier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); @@ -171,21 +173,22 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll return Insets.max(Insets.min(insets, mShownInsets), mHiddenInsets); } - private void updateLeashesForSide(@InsetSide int side, int inset, + private void updateLeashesForSide(@InsetSide int side, int offset, int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state) { ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side); // TODO: Implement behavior when inset spans over multiple types for (int i = items.size() - 1; i >= 0; i--) { final InsetsSourceConsumer consumer = items.valueAt(i); final InsetsSource source = mInitialInsetsState.getSource(consumer.getType()); + final InsetsSourceControl control = consumer.getControl(); final SurfaceControl leash = consumer.getControl().getLeash(); - mTmpMatrix.setTranslate(source.getFrame().left, source.getFrame().top); + mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y); mTmpFrame.set(source.getFrame()); - addTranslationToMatrix(side, inset, mTmpMatrix, mTmpFrame); + addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame); state.getSource(source.getType()).setFrame(mTmpFrame); - surfaceParams.add(new SurfaceParams(leash, 1f, mTmpMatrix, null, 0, 0f)); + surfaceParams.add(new SurfaceParams(leash, 1f, mTmpMatrix, null, 0, 0f, inset != 0)); } } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 4f9ecd575326..7ad97a6d393e 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -29,11 +29,16 @@ import android.graphics.Rect; import android.os.RemoteException; import android.util.ArraySet; import android.util.Log; +import android.util.Pair; import android.util.Property; import android.util.SparseArray; +import android.view.InsetsSourceConsumer.ShowResult; import android.view.InsetsState.InternalInsetType; import android.view.SurfaceControl.Transaction; +import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetType; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; @@ -46,11 +51,13 @@ import java.util.ArrayList; */ public class InsetsController implements WindowInsetsController { - // TODO: Use animation scaling and more optimal duration. - private static final int ANIMATION_DURATION_MS = 400; + private static final int ANIMATION_DURATION_SHOW_MS = 275; + private static final int ANIMATION_DURATION_HIDE_MS = 340; + private static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f); private static final int DIRECTION_NONE = 0; private static final int DIRECTION_SHOW = 1; private static final int DIRECTION_HIDE = 2; + @IntDef ({DIRECTION_NONE, DIRECTION_SHOW, DIRECTION_HIDE}) private @interface AnimationDirection{} @@ -103,6 +110,8 @@ public class InsetsController implements WindowInsetsController { private ObjectAnimator mAnimator; private @AnimationDirection int mAnimationDirection; + private int mPendingTypesToShow; + public InsetsController(ViewRootImpl viewRoot) { mViewRoot = viewRoot; mAnimCallback = () -> { @@ -193,6 +202,12 @@ public class InsetsController implements WindowInsetsController { @Override public void show(@InsetType int types) { + show(types, false /* fromIme */); + } + + private void show(@InsetType int types, boolean fromIme) { + // TODO: Support a ResultReceiver for IME. + // TODO(b/123718661): Make show() work for multi-session IME. int typesReady = 0; final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { @@ -201,15 +216,18 @@ public class InsetsController implements WindowInsetsController { // Only one animator (with multiple InsetType) can run at a time. // previous one should be cancelled for simplicity. cancelExistingAnimation(); - } else if (consumer.isVisible() || mAnimationDirection == DIRECTION_SHOW) { - // no-op: already shown or animating in. + } else if (consumer.isVisible() + && (mAnimationDirection == DIRECTION_NONE + || mAnimationDirection == DIRECTION_HIDE)) { + // no-op: already shown or animating in (because window visibility is + // applied before starting animation). // TODO: When we have more than one types: handle specific case when // show animation is going on, but the current type is not becoming visible. continue; } typesReady |= InsetsState.toPublicType(consumer.getType()); } - applyAnimation(typesReady, true /* show */); + applyAnimation(typesReady, true /* show */, fromIme); } @Override @@ -220,35 +238,114 @@ public class InsetsController implements WindowInsetsController { InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); if (mAnimationDirection == DIRECTION_SHOW) { cancelExistingAnimation(); - } else if (!consumer.isVisible() || mAnimationDirection == DIRECTION_HIDE) { + } else if (!consumer.isVisible() + && (mAnimationDirection == DIRECTION_NONE + || mAnimationDirection == DIRECTION_HIDE)) { // no-op: already hidden or animating out. continue; } typesReady |= InsetsState.toPublicType(consumer.getType()); } - applyAnimation(typesReady, false /* show */); + applyAnimation(typesReady, false /* show */, false /* fromIme */); } @Override public void controlWindowInsetsAnimation(@InsetType int types, WindowInsetsAnimationControlListener listener) { + controlWindowInsetsAnimation(types, listener, false /* fromIme */); + } + + private void controlWindowInsetsAnimation(@InsetType int types, + WindowInsetsAnimationControlListener listener, boolean fromIme) { + if (types == 0) { + // nothing to animate. + return; + } // TODO: Check whether we already have a controller. final ArraySet<Integer> internalTypes = mState.toInternalType(types); final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); + + Pair<Integer, Boolean> typesReadyPair = collectConsumers(fromIme, internalTypes, consumers); + int typesReady = typesReadyPair.first; + boolean isReady = typesReadyPair.second; + if (!isReady) { + // IME isn't ready, all requested types would be shown once IME is ready. + mPendingTypesToShow = typesReady; + // TODO: listener for pending types. + return; + } + + // pending types from previous request. + typesReady = collectPendingConsumers(typesReady, consumers); + + if (typesReady == 0) { + listener.onCancelled(); + return; + } + + final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers, + mFrame, mState, listener, typesReady, + () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this); + mAnimationControls.add(controller); + } + + /** + * @return Pair of (types ready to animate, is ready to animate). + */ + private Pair<Integer, Boolean> collectConsumers(boolean fromIme, + ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers) { + int typesReady = 0; + boolean isReady = true; for (int i = internalTypes.size() - 1; i >= 0; i--) { InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); if (consumer.getControl() != null) { + if (!consumer.isVisible()) { + // Show request + switch(consumer.requestShow(fromIme)) { + case ShowResult.SHOW_IMMEDIATELY: + typesReady |= InsetsState.toPublicType(TYPE_IME); + break; + case ShowResult.SHOW_DELAYED: + isReady = false; + break; + case ShowResult.SHOW_FAILED: + // IME cannot be shown (since it didn't have focus), proceed + // with animation of other types. + if (mPendingTypesToShow != 0) { + // remove IME from pending because view no longer has focus. + mPendingTypesToShow &= ~InsetsState.toPublicType(TYPE_IME); + } + break; + } + } else { + // Hide request + // TODO: Move notifyHidden() to beginning of the hide animation + // (when visibility actually changes using hideDirectly()). + consumer.notifyHidden(); + typesReady |= InsetsState.toPublicType(consumer.getType()); + } consumers.put(consumer.getType(), consumer); } else { // TODO: Let calling app know it's not possible, or wait // TODO: Remove it from types } } - final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers, - mFrame, mState, listener, types, - () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this); - mAnimationControls.add(controller); + return new Pair<>(typesReady, isReady); + } + + private int collectPendingConsumers(@InsetType int typesReady, + SparseArray<InsetsSourceConsumer> consumers) { + if (mPendingTypesToShow != 0) { + typesReady |= mPendingTypesToShow; + final ArraySet<Integer> internalTypes = mState.toInternalType(mPendingTypesToShow); + for (int i = internalTypes.size() - 1; i >= 0; i--) { + InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); + consumers.put(consumer.getType(), consumer); + } + mPendingTypesToShow = 0; + } + return typesReady; } private void applyLocalVisibilityOverride() { @@ -293,6 +390,19 @@ public class InsetsController implements WindowInsetsController { return mViewRoot; } + /** + * Used by {@link ImeInsetsSourceConsumer} when IME decides to be shown/hidden. + * @hide + */ + @VisibleForTesting + public void applyImeVisibility(boolean setVisible) { + if (setVisible) { + show(Type.IME, true /* fromIme */); + } else { + hide(Type.IME); + } + } + private InsetsSourceConsumer createConsumerOfType(int type) { if (type == TYPE_IME) { return new ImeInsetsSourceConsumer(mState, Transaction::new, this); @@ -321,7 +431,7 @@ public class InsetsController implements WindowInsetsController { } } - private void applyAnimation(@InsetType final int types, boolean show) { + private void applyAnimation(@InsetType final int types, boolean show, boolean fromIme) { if (types == 0) { // nothing to animate. return; @@ -329,6 +439,11 @@ public class InsetsController implements WindowInsetsController { WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() { @Override public void onReady(WindowInsetsAnimationController controller, int types) { + if (show) { + showDirectly(types); + } else { + hideDirectly(types); + } mAnimator = ObjectAnimator.ofObject( controller, new InsetsProperty(), @@ -336,7 +451,10 @@ public class InsetsController implements WindowInsetsController { show ? controller.getHiddenStateInsets() : controller.getShownStateInsets(), show ? controller.getShownStateInsets() : controller.getHiddenStateInsets() ); - mAnimator.setDuration(ANIMATION_DURATION_MS); + mAnimator.setDuration(show + ? ANIMATION_DURATION_SHOW_MS + : ANIMATION_DURATION_HIDE_MS); + mAnimator.setInterpolator(INTERPOLATOR); mAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { @@ -356,27 +474,22 @@ public class InsetsController implements WindowInsetsController { private void onAnimationFinish() { mAnimationDirection = DIRECTION_NONE; - if (show) { - showOnAnimationEnd(types); - } else { - hideOnAnimationEnd(types); - } } }; // TODO: Instead of clearing this here, properly wire up // InsetsAnimationControlImpl.finish() to remove this from mAnimationControls. mAnimationControls.clear(); - controlWindowInsetsAnimation(types, listener); + controlWindowInsetsAnimation(types, listener, fromIme); } - private void hideOnAnimationEnd(@InsetType int types) { + private void hideDirectly(@InsetType int types) { final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { getSourceConsumer(internalTypes.valueAt(i)).hide(); } } - private void showOnAnimationEnd(@InsetType int types) { + private void showDirectly(@InsetType int types) { final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { getSourceConsumer(internalTypes.valueAt(i)).show(); diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index f48318cd7d0a..eab83ce34708 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -16,12 +16,15 @@ package android.view; +import android.annotation.IntDef; import android.annotation.Nullable; import android.view.InsetsState.InternalInsetType; import android.view.SurfaceControl.Transaction; import com.android.internal.annotations.VisibleForTesting; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.function.Supplier; /** @@ -30,6 +33,25 @@ import java.util.function.Supplier; */ public class InsetsSourceConsumer { + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.SHOW_DELAYED, ShowResult.SHOW_FAILED}) + @interface ShowResult { + /** + * Window type is ready to be shown, will be shown immidiately. + */ + int SHOW_IMMEDIATELY = 0; + /** + * Result will be delayed. Window needs to be prepared or request is not from controller. + * Request will be delegated to controller and may or may not be shown. + */ + int SHOW_DELAYED = 1; + /** + * Window will not be shown because one of the conditions couldn't be met. + * (e.g. in IME's case, when no editor is focused.) + */ + int SHOW_FAILED = 2; + } + protected final InsetsController mController; protected boolean mVisible; private final Supplier<Transaction> mTransactionSupplier; @@ -104,12 +126,30 @@ public class InsetsSourceConsumer { return mVisible; } + /** + * Request to show current window type. + * + * @param fromController {@code true} if request is coming from controller. + * (e.g. in IME case, controller is + * {@link android.inputmethodservice.InputMethodService}). + * @return @see {@link ShowResult}. + */ + @ShowResult int requestShow(boolean fromController) { + return ShowResult.SHOW_IMMEDIATELY; + } + + /** + * Notify listeners that window is now hidden. + */ + void notifyHidden() { + // no-op for types that always return ShowResult#SHOW_IMMEDIATELY. + } + private void setVisible(boolean visible) { if (mVisible == visible) { return; } mVisible = visible; - applyHiddenToControl(); applyLocalVisibilityOverride(); mController.notifyVisibilityChanged(); } @@ -119,7 +159,6 @@ public class InsetsSourceConsumer { return; } - // TODO: Animation final Transaction t = mTransactionSupplier.get(); if (mVisible) { t.show(mSourceControl.getLeash()); diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java index 9383e6c57854..9fb6bdba48e3 100644 --- a/core/java/android/view/InsetsSourceControl.java +++ b/core/java/android/view/InsetsSourceControl.java @@ -29,10 +29,13 @@ public class InsetsSourceControl implements Parcelable { private final @InternalInsetType int mType; private final SurfaceControl mLeash; + private final Point mSurfacePosition; - public InsetsSourceControl(@InternalInsetType int type, SurfaceControl leash) { + public InsetsSourceControl(@InternalInsetType int type, SurfaceControl leash, + Point surfacePosition) { mType = type; mLeash = leash; + mSurfacePosition = surfacePosition; } public int getType() { @@ -46,6 +49,19 @@ public class InsetsSourceControl implements Parcelable { public InsetsSourceControl(Parcel in) { mType = in.readInt(); mLeash = in.readParcelable(null /* loader */); + mSurfacePosition = in.readParcelable(null /* loader */); + } + + public boolean setSurfacePosition(int left, int top) { + if (mSurfacePosition.equals(left, top)) { + return false; + } + mSurfacePosition.set(left, top); + return true; + } + + public Point getSurfacePosition() { + return mSurfacePosition; } @Override @@ -57,6 +73,7 @@ public class InsetsSourceControl implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mType); dest.writeParcelable(mLeash, 0 /* flags*/); + dest.writeParcelable(mSurfacePosition, 0 /* flags*/); } public static final Creator<InsetsSourceControl> CREATOR diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index 6a290b7fe045..c1302503134e 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -33,6 +33,8 @@ import android.os.Handler; import android.os.Message; import android.os.SystemProperties; import android.os.Trace; +import android.provider.DeviceConfig; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; @@ -42,13 +44,14 @@ import android.widget.FrameLayout; import com.android.internal.R; import dalvik.system.PathClassLoader; -import java.io.File; -import java.lang.reflect.Method; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.HashMap; /** @@ -78,8 +81,6 @@ public abstract class LayoutInflater { private static final String TAG = LayoutInflater.class.getSimpleName(); private static final boolean DEBUG = false; - private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY - = "view.precompiled_layout_enabled"; private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex"; /** Empty stack trace used to avoid log spam in re-throw exceptions. */ @@ -400,8 +401,19 @@ public abstract class LayoutInflater { } private void initPrecompiledViews() { - initPrecompiledViews( - SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false)); + // Use the device config if enabled, otherwise default to the system property. + String usePrecompiledLayout = DeviceConfig.getProperty( + DeviceConfig.Runtime.NAMESPACE, + DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT); + boolean enabled = false; + if (TextUtils.isEmpty(usePrecompiledLayout)) { + enabled = SystemProperties.getBoolean( + DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT, + false); + } else { + enabled = Boolean.parseBoolean(usePrecompiledLayout); + } + initPrecompiledViews(enabled); } private void initPrecompiledViews(boolean enablePrecompiledViews) { diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index c189afefe5f8..dc11d3ddd1d6 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -143,7 +143,7 @@ public class ScaleGestureDetector { private long mCurrTime; private long mPrevTime; private boolean mInProgress; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768938) private int mSpanSlop; @UnsupportedAppUsage private int mMinSpan; diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index ecbec652fcf0..cd5207c50d1d 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -492,7 +492,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (mBackgroundControl == null) { return; } - if ((mSurfaceFlags & PixelFormat.OPAQUE) != 0) { + if ((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) { mBackgroundControl.show(); mBackgroundControl.setLayer(Integer.MIN_VALUE); } else { diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java index 0270acb3aea7..85457cb48218 100644 --- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java +++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java @@ -77,7 +77,11 @@ public class SyncRtSurfaceTransactionApplier { t.setAlpha(params.surface, params.alpha); t.setLayer(params.surface, params.layer); t.setCornerRadius(params.surface, params.cornerRadius); - t.show(params.surface); + if (params.visible) { + t.show(params.surface); + } else { + t.hide(params.surface); + } } /** @@ -121,13 +125,14 @@ public class SyncRtSurfaceTransactionApplier { * @param windowCrop Crop to apply. */ public SurfaceParams(SurfaceControl surface, float alpha, Matrix matrix, - Rect windowCrop, int layer, float cornerRadius) { + Rect windowCrop, int layer, float cornerRadius, boolean visible) { this.surface = surface; this.alpha = alpha; this.matrix = new Matrix(matrix); this.windowCrop = new Rect(windowCrop); this.layer = layer; this.cornerRadius = cornerRadius; + this.visible = visible; } @VisibleForTesting @@ -147,5 +152,7 @@ public class SyncRtSurfaceTransactionApplier { @VisibleForTesting public final int layer; + + public final boolean visible; } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 992b99617064..33d42d7d0873 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -82,6 +82,7 @@ import android.os.Trace; import android.sysprop.DisplayProperties; import android.text.InputType; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.LayoutDirection; @@ -126,7 +127,6 @@ import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; import com.android.internal.R; -import com.android.internal.util.Preconditions; import com.android.internal.view.TooltipPopup; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.ScrollBarUtils; @@ -813,6 +813,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture"; + private static final boolean DEBUG_CONTENT_CAPTURE = false; + /** * When set to true, this view will save its attribute data. * @@ -3393,9 +3395,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Masks for mPrivateFlags4, as generated by dumpFlags(): * * |-------|-------|-------|-------| - * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK - * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED - * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED + * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK + * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED + * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED + * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED + * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE + * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK * |-------|-------|-------|-------| */ @@ -3422,6 +3427,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10; private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20; + /* + * Flags used to cache the value returned by isImportantForContentCapture while the view + * hierarchy is being traversed. + */ + private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40; + private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80; + + private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK = + PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED + | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE; + /* End of masks for mPrivateFlags4 */ /** @hide */ @@ -4140,17 +4156,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * The layout parameters associated with this view and used by the parent * {@link android.view.ViewGroup} to determine how this view should be * laid out. + * + * The field should not be used directly. Instead {@link #getLayoutParams()} and {@link + * #setLayoutParams(ViewGroup.LayoutParams)} should be used. The setter guarantees internal + * state correctness of the class. * {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) protected ViewGroup.LayoutParams mLayoutParams; /** * The view flags hold various views states. + * + * Use {@link #setTransitionVisibility(int)} to change the visibility of this view without + * triggering updates. * {@hide} */ @ViewDebug.ExportedProperty(formatToHexString = true) - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) int mViewFlags; static class TransformationInfo { @@ -5042,12 +5065,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * view (through {@link #setContentCaptureSession(ContentCaptureSession)}. */ @Nullable - private WeakReference<ContentCaptureSession> mContentCaptureSession; + private ContentCaptureSession mContentCaptureSession; @LayoutRes private int mSourceLayoutId = ID_NULL; /** + * Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}. + */ + private ContentCaptureSession mCachedContentCaptureSession; + + /** * Simple constructor to use when creating a view from code. * * @param context The Context the view is running in, through which it can @@ -8233,15 +8261,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </ul> */ public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) { - if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { - Trace.traceBegin(Trace.TRACE_TAG_VIEW, - "onProvideContentCaptureStructure() for " + getClass().getSimpleName()); - } - try { - onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } + onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags); } /** @hide */ @@ -8952,6 +8972,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS */ public final boolean isImportantForContentCapture() { + boolean isImportant; + if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) { + isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0; + return isImportant; + } + + isImportant = calculateIsImportantForContentCapture(); + + mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE; + if (isImportant) { + mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE; + } + mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED; + return isImportant; + } + + /** + * Calculates whether the flag is important for content capture so it can be used by + * {@link #isImportantForContentCapture()} while the tree is traversed. + */ + private boolean calculateIsImportantForContentCapture() { // Check parent mode to ensure we're important ViewParent parent = mParent; while (parent instanceof View) { @@ -8992,9 +9033,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } // View group is important if at least one children also is - //TODO(b/111276913): decide if we really need to send the relevant parents or just the - // leaves (with absolute coordinates). If it's the latter, then we need to update this - // javadoc and ViewGroup's implementation. if (this instanceof ViewGroup) { final ViewGroup group = (ViewGroup) this; for (int i = 0; i < group.getChildCount(); i++) { @@ -9031,6 +9069,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </ol> */ private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) { + AttachInfo ai = mAttachInfo; + // Skip it while the view is being laided out for the first time + if (ai != null && !ai.mReadyForContentCaptureUpdates) return; + if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName()); @@ -9043,24 +9085,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) { + AttachInfo ai = mAttachInfo; + // First check if context has client, so it saves a service lookup when it doesn't if (!mContext.isContentCaptureSupported()) return; // Then check if it's enabled in the context... - final ContentCaptureManager ccm = mContext.getSystemService(ContentCaptureManager.class); + final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext) + : mContext.getSystemService(ContentCaptureManager.class); if (ccm == null || !ccm.isContentCaptureEnabled()) return; // ... and finally at the view level // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled() if (!isImportantForContentCapture()) return; - final ContentCaptureSession session = getContentCaptureSession(ccm); + ContentCaptureSession session = getContentCaptureSession(); if (session == null) return; if (appeared) { if (!isLaidOut() || getVisibility() != VISIBLE || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) { - if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { + if (DEBUG_CONTENT_CAPTURE) { Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid=" + isLaidOut() + ", visibleToUser=" + isVisibleToUser() + ", visible=" + (getVisibility() == VISIBLE) @@ -9071,8 +9116,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } return; } - mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; - mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; + setNotifiedContentCaptureAppeared(); + + // TODO(b/123307965): instead of post, we should queue it on AttachInfo and then + // dispatch on RootImpl, as we're doing with the removed ones (in that case, we should + // merge the delayNotifyContentCaptureDisappeared() into a more generic method that + // takes a session and a command, where the command is either view added or removed // The code below doesn't take much for a unique view, but it's called for all views // the first time the view hiearchy is laid off, which could acccumulative delay the @@ -9086,7 +9135,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0 || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) { - if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { + if (DEBUG_CONTENT_CAPTURE) { Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid=" + isLaidOut() + ", visibleToUser=" + isVisibleToUser() + ", visible=" + (getVisibility() == VISIBLE) @@ -9099,11 +9148,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; - Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT, - () -> session.notifyViewDisappeared(getAutofillId()), /* token= */ null); + + if (ai != null) { + ai.delayNotifyContentCaptureDisappeared(session, getAutofillId()); + } else { + if (DEBUG_CONTENT_CAPTURE) { + Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on gone for " + this); + } + Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT, + () -> session.notifyViewDisappeared(getAutofillId()), /* token= */ null); + } } } + private void setNotifiedContentCaptureAppeared() { + mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; + mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; + } + /** * Sets the (optional) {@link ContentCaptureSession} associated with this view. * @@ -9127,9 +9189,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link ContentCaptureSession#createContentCaptureSession( * android.view.contentcapture.ContentCaptureContext)}. */ - public void setContentCaptureSession(@NonNull ContentCaptureSession contentCaptureSession) { - mContentCaptureSession = new WeakReference<>( - Preconditions.checkNotNull(contentCaptureSession)); + public void setContentCaptureSession(@Nullable ContentCaptureSession contentCaptureSession) { + mContentCaptureSession = contentCaptureSession; } /** @@ -9141,8 +9202,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @Nullable public final ContentCaptureSession getContentCaptureSession() { + if (mCachedContentCaptureSession != null) { + return mCachedContentCaptureSession; + } + + mCachedContentCaptureSession = getAndCacheContentCaptureSession(); + return mCachedContentCaptureSession; + } + + @Nullable + private ContentCaptureSession getAndCacheContentCaptureSession() { // First try the session explicitly set by setContentCaptureSession() - if (mContentCaptureSession != null) return mContentCaptureSession.get(); + if (mContentCaptureSession != null) return mContentCaptureSession; // Then the session explicitly set in an ancestor ContentCaptureSession session = null; @@ -9159,21 +9230,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return session; } - /** - * Optimized version of {@link #getContentCaptureSession()} that avoids a service lookup. - */ - @Nullable - private ContentCaptureSession getContentCaptureSession(@NonNull ContentCaptureManager ccm) { - if (mContentCaptureSession != null) return mContentCaptureSession.get(); - - ContentCaptureSession session = null; - if (mParent instanceof View) { - session = ((View) mParent).getContentCaptureSession(ccm); - } - - return session != null ? session : ccm.getMainContentCaptureSession(); - } - @Nullable private AutofillManager getAutofillManager() { return mContext.getSystemService(AutofillManager.class); @@ -9346,6 +9402,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Dispatches the initial Content Capture events for a view structure. + * + * @hide + */ + public void dispatchInitialProvideContentCaptureStructure(@NonNull ContentCaptureManager ccm) { + AttachInfo ai = mAttachInfo; + if (ai == null) { + Log.w(CONTENT_CAPTURE_LOG_TAG, + "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this); + return; + } + + // We must set it before checkign if the view itself is important, because it might + // initially not be (for example, if it's empty), although that might change later (for + // example, if important views are added) + ai.mReadyForContentCaptureUpdates = true; + + if (!isImportantForContentCapture()) { + if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) { + Log.d(CONTENT_CAPTURE_LOG_TAG, + "dispatchProvideContentCaptureStructure(): decorView is not important"); + } + return; + } + + ai.mContentCaptureManager = ccm; + + ContentCaptureSession session = getContentCaptureSession(); + if (session == null) { + if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) { + Log.d(CONTENT_CAPTURE_LOG_TAG, + "dispatchProvideContentCaptureStructure(): no session for " + this); + } + return; + } + + session.internalNotifyViewHierarchyEvent(/* started= */ true); + try { + dispatchProvideContentCaptureStructure(); + } finally { + session.internalNotifyViewHierarchyEvent(/* started= */ false); + } + } + + /** @hide */ + void dispatchProvideContentCaptureStructure() { + ContentCaptureSession session = getContentCaptureSession(); + if (session != null) { + ViewStructure structure = session.newViewStructure(this); + onProvideContentCaptureStructure(structure, /* flags= */ 0); + setNotifiedContentCaptureAppeared(); + session.notifyViewAppeared(structure); + } + } + + /** * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) * * Note: Called from the default {@link AccessibilityDelegate}. @@ -12801,14 +12913,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Change the visibility of the View without triggering any other changes. This is - * important for transitions, where visibility changes should not adjust focus or - * trigger a new layout. This is only used when the visibility has already been changed - * and we need a transient value during an animation. When the animation completes, - * the original visibility value is always restored. + * Changes the visibility of this View without triggering any other changes. This should only + * be used by animation frameworks, such as {@link android.transition.Transition}, where + * visibility changes should not adjust focus or trigger a new layout. Application developers + * should use {@link #setVisibility} instead to ensure that the hierarchy is correctly updated. + * + * <p>Only call this method when a temporary visibility must be applied during an + * animation and the original visibility value is guaranteed to be reset after the + * animation completes. Use {@link #setVisibility} in all other cases.</p> * * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. - * @hide + * @see #setVisibility(int) */ public void setTransitionVisibility(@Visibility int visibility) { mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility; @@ -17457,6 +17572,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } + // Reset content capture caches + mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK; + mCachedContentCaptureSession = null; + if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED @@ -21614,6 +21733,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return The known solid color background for this view, or 0 if the color may vary */ @ViewDebug.ExportedProperty(category = "drawing") + @InspectableProperty @ColorInt public int getSolidColor() { return 0; @@ -27963,6 +28083,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, View mTooltipHost; /** + * The initial structure has been reported so the view is ready to report updates. + */ + boolean mReadyForContentCaptureUpdates; + + /** + * Map of ids (per session) that need to be notified after as gone the view hierchy is + * traversed. + */ + // TODO(b/121197119): use SparseArray once session id becomes integer + ArrayMap<String, ArrayList<AutofillId>> mContentCaptureRemovedIds; + + /** + * Cached reference to the {@link ContentCaptureManager}. + */ + ContentCaptureManager mContentCaptureManager; + + /** * Creates a new set of attachment information with the specified * events handler and thread. * @@ -27980,6 +28117,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mRootCallbacks = effectPlayer; mTreeObserver = new ViewTreeObserver(context); } + + private void delayNotifyContentCaptureDisappeared(@NonNull ContentCaptureSession session, + @NonNull AutofillId id) { + if (mContentCaptureRemovedIds == null) { + // Most of the time there will be just one session, so intial capacity is 1 + mContentCaptureRemovedIds = new ArrayMap<>(1); + } + String sessionId = session.getId(); + // TODO: life would be much easier if we provided a MultiMap implementation somwhere... + ArrayList<AutofillId> ids = mContentCaptureRemovedIds.get(sessionId); + if (ids == null) { + ids = new ArrayList<>(); + mContentCaptureRemovedIds.put(sessionId, ids); + } + ids.add(id); + } + + @Nullable + private ContentCaptureManager getContentCaptureManager(@NonNull Context context) { + if (mContentCaptureManager != null) { + return mContentCaptureManager; + } + mContentCaptureManager = context.getSystemService(ContentCaptureManager.class); + return mContentCaptureManager; + } } /** diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 0986cfa454b6..d2b40f75a6a8 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -60,6 +60,8 @@ import android.view.animation.AnimationUtils; import android.view.animation.LayoutAnimationController; import android.view.animation.Transformation; import android.view.autofill.Helper; +import android.view.inspector.InspectableProperty; +import android.view.inspector.InspectableProperty.EnumMap; import com.android.internal.R; @@ -773,6 +775,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @ViewDebug.IntToString(from = FOCUS_AFTER_DESCENDANTS, to = "FOCUS_AFTER_DESCENDANTS"), @ViewDebug.IntToString(from = FOCUS_BLOCK_DESCENDANTS, to = "FOCUS_BLOCK_DESCENDANTS") }) + @InspectableProperty(enumMapping = { + @EnumMap(value = FOCUS_BEFORE_DESCENDANTS, name = "beforeDescendants"), + @EnumMap(value = FOCUS_AFTER_DESCENDANTS, name = "afterDescendants"), + @EnumMap(value = FOCUS_BLOCK_DESCENDANTS, name = "blocksDescendants") + }) public int getDescendantFocusability() { return mGroupFlags & FLAG_MASK_FOCUSABILITY; } @@ -1391,6 +1398,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Check whether this ViewGroup should ignore focus requests for itself and its children. */ @ViewDebug.ExportedProperty(category = "focus") + @InspectableProperty public boolean getTouchscreenBlocksFocus() { return (mGroupFlags & FLAG_TOUCHSCREEN_BLOCKS_FOCUS) != 0; } @@ -3116,6 +3124,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Returns true if MotionEvents dispatched to this ViewGroup can be split to multiple children. * @return true if MotionEvents dispatched to this ViewGroup can be split to multiple children. */ + @InspectableProperty(name = "splitMotionEvents") public boolean isMotionEventSplittingEnabled() { return (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) == FLAG_SPLIT_MOTION_EVENTS; } @@ -3132,6 +3141,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * {@link android.view.ViewOutlineProvider#BACKGROUND} was given to * {@link #setOutlineProvider(ViewOutlineProvider)} and false otherwise. */ + @InspectableProperty public boolean isTransitionGroup() { if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) { return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0); @@ -3603,7 +3613,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return; } - final ChildListForAutoFill children = getChildrenForAutofill(flags); + final ChildListForAutoFillOrContentCapture children = getChildrenForAutofill(flags); final int childrenCount = children.size(); structure.setChildCount(childrenCount); for (int i = 0; i < childrenCount; i++) { @@ -3614,13 +3624,31 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager children.recycle(); } + /** @hide */ + @Override + public void dispatchProvideContentCaptureStructure() { + super.dispatchProvideContentCaptureStructure(); + + if (!isLaidOut()) return; + + final ChildListForAutoFillOrContentCapture children = getChildrenForContentCapture(); + final int childrenCount = children.size(); + for (int i = 0; i < childrenCount; i++) { + final View child = children.get(i); + child.dispatchProvideContentCaptureStructure(); + } + children.recycle(); + } + /** * Gets the children for autofill. Children for autofill are the first * level descendants that are important for autofill. The returned * child list object is pooled and the caller must recycle it once done. * @hide */ - private @NonNull ChildListForAutoFill getChildrenForAutofill(@AutofillFlags int flags) { - final ChildListForAutoFill children = ChildListForAutoFill.obtain(); + private @NonNull ChildListForAutoFillOrContentCapture getChildrenForAutofill( + @AutofillFlags int flags) { + final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture + .obtain(); populateChildrenForAutofill(children, flags); return children; } @@ -3647,6 +3675,34 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } + private @NonNull ChildListForAutoFillOrContentCapture getChildrenForContentCapture() { + final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture + .obtain(); + populateChildrenForContentCapture(children); + return children; + } + + /** @hide */ + private void populateChildrenForContentCapture(ArrayList<View> list) { + final int childrenCount = mChildrenCount; + if (childrenCount <= 0) { + return; + } + final ArrayList<View> preorderedList = buildOrderedChildList(); + final boolean customOrder = preorderedList == null + && isChildrenDrawingOrderEnabled(); + for (int i = 0; i < childrenCount; i++) { + final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder); + final View child = (preorderedList == null) + ? mChildren[childIndex] : preorderedList.get(childIndex); + if (child.isImportantForContentCapture()) { + list.add(child); + } else if (child instanceof ViewGroup) { + ((ViewGroup) child).populateChildrenForContentCapture(list); + } + } + } + private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children, int childIndex) { final View child; @@ -4390,6 +4446,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * false otherwise. */ @ViewDebug.ExportedProperty(category = "drawing") + @InspectableProperty public boolean getClipChildren() { return ((mGroupFlags & FLAG_CLIP_CHILDREN) != 0); } @@ -4447,6 +4504,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @attr ref android.R.styleable#ViewGroup_clipToPadding */ @ViewDebug.ExportedProperty(category = "drawing") + @InspectableProperty public boolean getClipToPadding() { return hasBooleanFlag(FLAG_CLIP_TO_PADDING); } @@ -6294,6 +6352,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @return the current animation controller */ + @InspectableProperty public LayoutAnimationController getLayoutAnimation() { return mLayoutAnimationController; } @@ -6313,6 +6372,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Caching behavior of children may be controlled through {@link View#setLayerType(int, Paint)}. */ @Deprecated + @InspectableProperty(name = "animationCache") public boolean isAnimationCacheEnabled() { return (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE; } @@ -6350,6 +6410,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Child views may no longer have their caching behavior disabled by parents. */ @Deprecated + @InspectableProperty(name = "alwaysDrawnWithCache") public boolean isAlwaysDrawnWithCacheEnabled() { return (mGroupFlags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE; } @@ -6493,6 +6554,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @ViewDebug.IntToString(from = PERSISTENT_SCROLLING_CACHE, to = "SCROLLING"), @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ALL") }) + @InspectableProperty(enumMapping = { + @EnumMap(value = PERSISTENT_NO_CACHE, name = "none"), + @EnumMap(value = PERSISTENT_ANIMATION_CACHE, name = "animation"), + @EnumMap(value = PERSISTENT_SCROLLING_CACHE, name = "scrolling"), + @EnumMap(value = PERSISTENT_ALL_CACHES, name = "all"), + }) public int getPersistentDrawingCache() { return mPersistentDrawingCache; } @@ -6570,6 +6637,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * @see #setLayoutMode(int) */ + @InspectableProperty(enumMapping = { + @EnumMap(value = LAYOUT_MODE_CLIP_BOUNDS, name = "clipBounds"), + @EnumMap(value = LAYOUT_MODE_OPTICAL_BOUNDS, name = "opticalBounds") + }) public int getLayoutMode() { if (mLayoutMode == LAYOUT_MODE_UNDEFINED) { int inheritedLayoutMode = (mParent instanceof ViewGroup) ? @@ -7261,6 +7332,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * make a group appear to be focused when its child EditText or button * is focused. */ + @InspectableProperty public boolean addStatesFromChildren() { return (mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0; } @@ -8544,16 +8616,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Pooled class that to hold the children for autifill. */ - static class ChildListForAutoFill extends ArrayList<View> { + private static class ChildListForAutoFillOrContentCapture extends ArrayList<View> { private static final int MAX_POOL_SIZE = 32; - private static final Pools.SimplePool<ChildListForAutoFill> sPool = + private static final Pools.SimplePool<ChildListForAutoFillOrContentCapture> sPool = new Pools.SimplePool<>(MAX_POOL_SIZE); - public static ChildListForAutoFill obtain() { - ChildListForAutoFill list = sPool.acquire(); + public static ChildListForAutoFillOrContentCapture obtain() { + ChildListForAutoFillOrContentCapture list = sPool.acquire(); if (list == null) { - list = new ChildListForAutoFill(); + list = new ChildListForAutoFillOrContentCapture(); } return list; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9a317db84f5d..47528a05f5a2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -103,7 +103,10 @@ import android.view.accessibility.IAccessibilityInteractionConnection; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Interpolator; +import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; +import android.view.contentcapture.ContentCaptureManager; +import android.view.contentcapture.MainContentCaptureSession; import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; @@ -154,6 +157,7 @@ public final class ViewRootImpl implements ViewParent, private static final boolean DEBUG_FPS = false; private static final boolean DEBUG_INPUT_STAGES = false || LOCAL_LOGV; private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV; + private static final boolean DEBUG_CONTENT_CAPTURE = false || LOCAL_LOGV; /** * Set to false if we do not want to use the multi threaded renderer even though @@ -180,7 +184,7 @@ public final class ViewRootImpl implements ViewParent, * @see #USE_NEW_INSETS_PROPERTY * @hide */ - public static final int sNewInsetsMode = + public static int sNewInsetsMode = SystemProperties.getInt(USE_NEW_INSETS_PROPERTY, 0); /** @@ -412,6 +416,7 @@ public final class ViewRootImpl implements ViewParent, boolean mApplyInsetsRequested; boolean mLayoutRequested; boolean mFirst; + boolean mPerformContentCapture; boolean mReportNextDraw; boolean mFullRedrawNeeded; boolean mNewSurfaceNeeded; @@ -608,6 +613,7 @@ public final class ViewRootImpl implements ViewParent, mTransparentRegion = new Region(); mPreviousTransparentRegion = new Region(); mFirst = true; // true for the first time the view is added + mPerformContentCapture = true; // also true for the first time the view is added mAdded = false; mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); @@ -2756,6 +2762,24 @@ public final class ViewRootImpl implements ViewParent, } } + if (mAttachInfo.mContentCaptureRemovedIds != null) { + MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager + .getMainContentCaptureSession(); + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureViewsGone"); + try { + for (int i = 0; i < mAttachInfo.mContentCaptureRemovedIds.size(); i++) { + String sessionId = mAttachInfo.mContentCaptureRemovedIds + .keyAt(i); + ArrayList<AutofillId> ids = mAttachInfo.mContentCaptureRemovedIds + .valueAt(i); + mainSession.notifyViewsDisappeared(sessionId, ids); + } + mAttachInfo.mContentCaptureRemovedIds = null; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + } + mIsInTraversal = false; } @@ -3451,6 +3475,35 @@ public final class ViewRootImpl implements ViewParent, pendingDrawFinished(); } } + if (mPerformContentCapture) { + performContentCapture(); + } + } + + private void performContentCapture() { + mPerformContentCapture = false; // One-time offer! + final View rootView = mView; + if (DEBUG_CONTENT_CAPTURE) { + Log.v(mTag, "dispatchContentCapture() on " + rootView); + } + if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for " + + getClass().getSimpleName()); + } + try { + // First check if context supports it, so it saves a service lookup when it doesn't + if (!mContext.isContentCaptureSupported()) return; + + // Then check if it's enabled in the contex itself. + final ContentCaptureManager ccm = mContext + .getSystemService(ContentCaptureManager.class); + if (ccm == null || !ccm.isContentCaptureEnabled()) return; + + // Content capture is a go! + rootView.dispatchInitialProvideContentCaptureStructure(ccm); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } } private boolean draw(boolean fullRedrawNeeded) { diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 64c34f612048..1c96b87394b6 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -79,7 +79,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Set; //TODO: use java.lang.ref.Cleaner once Android supports Java 9 import sun.misc.Cleaner; @@ -1769,45 +1768,6 @@ public final class AutofillManager { } /** - * Defines whether augmented autofill should be triggered for activities with such - * {@link android.content.ComponentName}. - * - * <p>Useful to blacklist a particular activity. - * - * <p><b>Note:</b> This method should only be called by the app providing the augmented autofill - * service, and it's ignored if the caller isn't it. - * - * @hide - */ - @SystemApi - @TestApi - //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service - //in the same package as the test, and that module is compiled with SDK=test_current - public void setActivityAugmentedAutofillEnabled(@NonNull ComponentName activity, - boolean enabled) { - // TODO(b/123100824): implement - } - - /** - * Defines whether augmented autofill should be triggered for activities of the app with such - * {@code packageName}. - * - * <p>Useful to blacklist any activity from a particular app. - * - * <p><b>Note:</b> This method should only be called by the app providing the augmented autofill - * service, and it's ignored if the caller isn't it. - * - * @hide - */ - @SystemApi - @TestApi - //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service - //in the same package as the test, and that module is compiled with SDK=test_current - public void setPackageAugmentedAutofillEnabled(@NonNull String packageName, boolean enabled) { - // TODO(b/123100824): implement - } - - /** * Explicitly limits augmented autofill to the given packages and activities. * * <p>When the whitelist is set, it overrides the values passed to @@ -1838,38 +1798,6 @@ public final class AutofillManager { // TODO(b/123100824): implement } - /** - * Gets the activities where augmented autofill was disabled by - * {@link #setActivityAugmentedAutofillEnabled(ComponentName, boolean)}. - * - * <p><b>Note:</b> This method should only be called by the app providing the augmented autofill - * service, and it's ignored if the caller isn't it. - * - * @hide - */ - @SystemApi - @TestApi - @NonNull - public Set<ComponentName> getAugmentedAutofillDisabledActivities() { - return null; // TODO(b/123100824): implement - } - - /** - * Gets the apps where content capture was disabled by - * {@link #setPackageAugmentedAutofillEnabled(String, boolean)}. - * - * <p><b>Note:</b> This method should only be called by the app providing the augmented autofill - * service, and it's ignored if the caller isn't it. - * - * @hide - */ - @SystemApi - @TestApi - @NonNull - public Set<String> getAugmentedAutofillDisabledPackages() { - return null; // TODO(b/123100824): implement - } - private void requestShowFillUi(int sessionId, AutofillId id, int width, int height, Rect anchorBounds, IAutofillWindowPresenter presenter) { final View anchor = findView(id); diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java index 63c21f352e74..acb81e086461 100644 --- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java @@ -93,6 +93,11 @@ final class ChildContentCaptureSession extends ContentCaptureSession { } @Override + public void internalNotifyViewHierarchyEvent(boolean started) { + getMainCaptureSession().notifyInitialViewHierarchyEvent(mId, started); + } + + @Override boolean isContentCaptureEnabled() { return getMainCaptureSession().isContentCaptureEnabled(); } diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java index 5814759d00df..6a9759db78a0 100644 --- a/core/java/android/view/contentcapture/ContentCaptureContext.java +++ b/core/java/android/view/contentcapture/ContentCaptureContext.java @@ -19,6 +19,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; @@ -57,6 +58,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public static final int FLAG_DISABLED_BY_APP = 0x1; /** @@ -67,6 +69,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public static final int FLAG_DISABLED_BY_FLAG_SECURE = 0x2; /** @hide */ @@ -136,6 +139,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi @Nullable public Bundle getExtras() { return mExtras; @@ -147,6 +151,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi @Nullable public Uri getUri() { return mUri; @@ -158,6 +163,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi @Nullable public String getAction() { return mAction; @@ -169,6 +175,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public int getTaskId() { return mTaskId; } @@ -179,6 +186,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public @Nullable ComponentName getActivityComponent() { return mComponentName; } @@ -191,6 +199,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public @Nullable ContentCaptureSessionId getParentSessionId() { return mParentSessionId == null ? null : new ContentCaptureSessionId(mParentSessionId); } @@ -207,6 +216,7 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi + @TestApi public int getDisplayId() { return mDisplayId; } @@ -220,7 +230,8 @@ public final class ContentCaptureContext implements Parcelable { * @hide */ @SystemApi - public @ContextCreationFlags int getFlags() { + @TestApi + public @ContextCreationFlags int getFlags() { return mFlags; } diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index a6d44729aee5..dfac35ddf58b 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -21,6 +21,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; @@ -36,6 +37,7 @@ import java.util.List; /** @hide */ @SystemApi +@TestApi public final class ContentCaptureEvent implements Parcelable { private static final String TAG = ContentCaptureEvent.class.getSimpleName(); @@ -69,13 +71,33 @@ public final class ContentCaptureEvent implements Parcelable { */ public static final int TYPE_VIEW_TEXT_CHANGED = 3; - // TODO(b/111276913): add event to indicate when FLAG_SECURE was changed? + /** + * Called before events (such as {@link #TYPE_VIEW_APPEARED}) representing the initial view + * hierarchy are sent. + * + * <p><b>NOTE</b>: there is no guarantee this event will be sent. For example, it's not sent + * if the initial view hierarchy doesn't initially have any view that's important for content + * capture. + */ + public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4; + + /** + * Called after events (such as {@link #TYPE_VIEW_APPEARED}) representing the initial view + * hierarchy are sent. + * + * <p><b>NOTE</b>: there is no guarantee this event will be sent. For example, it's not sent + * if the initial view hierarchy doesn't initially have any view that's important for content + * capture. + */ + public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5; /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_VIEW_APPEARED, TYPE_VIEW_DISAPPEARED, - TYPE_VIEW_TEXT_CHANGED + TYPE_VIEW_TEXT_CHANGED, + TYPE_INITIAL_VIEW_TREE_APPEARING, + TYPE_INITIAL_VIEW_TREE_APPEARED }) @Retention(RetentionPolicy.SOURCE) public @interface EventType{} @@ -108,8 +130,10 @@ public final class ContentCaptureEvent implements Parcelable { return this; } - private void setAutofillIds(@NonNull ArrayList<AutofillId> ids) { + /** @hide */ + public ContentCaptureEvent setAutofillIds(@NonNull ArrayList<AutofillId> ids) { mIds = Preconditions.checkNotNull(ids); + return this; } /** @@ -193,7 +217,8 @@ public final class ContentCaptureEvent implements Parcelable { * Gets the type of the event. * * @return one of {@link #TYPE_VIEW_APPEARED}, {@link #TYPE_VIEW_DISAPPEARED}, - * or {@link #TYPE_VIEW_TEXT_CHANGED}. + * {@link #TYPE_VIEW_TEXT_CHANGED}, {@link #TYPE_INITIAL_VIEW_TREE_APPEARING}, or + * {@link #TYPE_INITIAL_VIEW_TREE_APPEARED}. */ public @EventType int getType() { return mType; @@ -372,6 +397,10 @@ public final class ContentCaptureEvent implements Parcelable { return "VIEW_DISAPPEARED"; case TYPE_VIEW_TEXT_CHANGED: return "VIEW_TEXT_CHANGED"; + case TYPE_INITIAL_VIEW_TREE_APPEARING: + return "INITIAL_VIEW_HIERARCHY_STARTED"; + case TYPE_INITIAL_VIEW_TREE_APPEARED: + return "INITIAL_VIEW_HIERARCHY_FINISHED"; default: return "UKNOWN_TYPE: " + type; } diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index f31856c80477..2512b95fe0ec 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.TestApi; import android.annotation.UiThread; import android.content.ComponentName; import android.content.Context; @@ -46,7 +47,7 @@ import java.io.PrintWriter; * of every method. */ /** - * TODO(b/111276913): add javadocs / implement + * TODO(b/123577059): add javadocs / implement */ @SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE) public final class ContentCaptureManager { @@ -120,6 +121,7 @@ public final class ContentCaptureManager { } /** @hide */ + @UiThread public void onActivityStarted(@NonNull IBinder applicationToken, @NonNull ComponentName activityComponent, int flags) { synchronized (mLock) { @@ -129,6 +131,7 @@ public final class ContentCaptureManager { } /** @hide */ + @UiThread public void onActivityStopped() { getMainContentCaptureSession().destroy(); } @@ -140,6 +143,7 @@ public final class ContentCaptureManager { * * @hide */ + @UiThread public void flush(@FlushReason int reason) { getMainContentCaptureSession().flush(reason); } @@ -217,6 +221,7 @@ public final class ContentCaptureManager { * @hide */ @SystemApi + @TestApi public boolean isContentCaptureFeatureEnabled() { if (mService == null) return false; @@ -249,6 +254,7 @@ public final class ContentCaptureManager { * @hide */ @SystemApi + @TestApi public void setContentCaptureFeatureEnabled(boolean enabled) { if (DEBUG) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled); diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index 68a3e8a1eb32..e028961692f9 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -204,6 +204,12 @@ public abstract class ContentCaptureSession implements AutoCloseable { return mId.hashCode(); } + /** @hide */ + @NonNull + public String getId() { + return mId; + } + /** * Creates a new {@link ContentCaptureSession}. * @@ -362,6 +368,9 @@ public abstract class ContentCaptureSession implements AutoCloseable { abstract void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text); + /** @hide */ + public abstract void internalNotifyViewHierarchyEvent(boolean started); + /** * Creates a {@link ViewStructure} for a "standard" view. * diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index 034c8fae0843..eb945b55bd7e 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -15,6 +15,8 @@ */ package android.view.contentcapture; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_INITIAL_VIEW_TREE_APPEARED; +import static android.view.contentcapture.ContentCaptureEvent.TYPE_INITIAL_VIEW_TREE_APPEARING; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED; import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED; @@ -24,10 +26,9 @@ import static android.view.contentcapture.ContentCaptureHelper.DEBUG; import static android.view.contentcapture.ContentCaptureHelper.VERBOSE; import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString; -import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; - import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UiThread; import android.content.ComponentName; import android.content.Context; import android.content.pm.ParceledListSlice; @@ -56,16 +57,14 @@ import java.util.concurrent.atomic.AtomicBoolean; * <p>This session is created when the activity starts and finished when it stops; clients can use * it to create children activities. * - * <p><b>NOTE: all methods in this class should return right away, or do the real work in a handler - * thread. Hence, the only field that must be thread-safe is {@code mEnabled}, which is called at - * the beginning of every method. - * * @hide */ public final class MainContentCaptureSession extends ContentCaptureSession { private static final String TAG = MainContentCaptureSession.class.getSimpleName(); + private static final boolean FORCE_FLUSH = true; + /** * Handler message used to flush the buffer. */ @@ -164,46 +163,28 @@ public final class MainContentCaptureSession extends ContentCaptureSession { * * @hide */ - void start(@NonNull IBinder applicationToken, @NonNull ComponentName activityComponent, + @UiThread + void start(@NonNull IBinder token, @NonNull ComponentName component, int flags) { if (!isContentCaptureEnabled()) return; if (VERBOSE) { - Log.v(TAG, "start(): token=" + applicationToken + ", comp=" - + ComponentName.flattenToShortString(activityComponent)); + Log.v(TAG, "start(): token=" + token + ", comp=" + + ComponentName.flattenToShortString(component)); } - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleStartSession, this, - applicationToken, activityComponent, flags)); - } - - @Override - void flush(@FlushReason int reason) { - mHandler.sendMessage( - obtainMessage(MainContentCaptureSession::handleForceFlush, this, reason)); - } - - @Override - void onDestroy() { - mHandler.removeMessages(MSG_FLUSH); - mHandler.sendMessage( - obtainMessage(MainContentCaptureSession::handleDestroySession, this)); - } - - private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName, - int flags) { - if (handleHasStarted()) { + if (hasStarted()) { // TODO(b/122959591): make sure this is expected (and when), or use Log.w if (DEBUG) { Log.d(TAG, "ignoring handleStartSession(" + token + "/" - + ComponentName.flattenToShortString(componentName) + " while on state " + + ComponentName.flattenToShortString(component) + " while on state " + getStateAsString(mState)); } return; } mState = STATE_WAITING_FOR_SERVER; mApplicationToken = token; - mComponentName = componentName; + mComponentName = component; if (VERBOSE) { Log.v(TAG, "handleStartSession(): token=" + token + ", act=" @@ -213,28 +194,36 @@ public final class MainContentCaptureSession extends ContentCaptureSession { try { if (mSystemServerInterface == null) return; - mSystemServerInterface.startSession(mApplicationToken, componentName, mId, flags, + mSystemServerInterface.startSession(mApplicationToken, component, mId, flags, new IResultReceiver.Stub() { @Override public void send(int resultCode, Bundle resultData) { - IBinder binder = null; + final IBinder binder; if (resultData != null) { binder = resultData.getBinder(EXTRA_BINDER); if (binder == null) { Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result"); - handleResetSession(STATE_DISABLED | STATE_INTERNAL_ERROR); + mHandler.post(() -> resetSession( + STATE_DISABLED | STATE_INTERNAL_ERROR)); return; } + } else { + binder = null; } - handleSessionStarted(resultCode, binder); + mHandler.post(() -> onSessionStarted(resultCode, binder)); } }); } catch (RemoteException e) { - Log.w(TAG, "Error starting session for " + componentName.flattenToShortString() + ": " - + e); + Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e); } } + @Override + void onDestroy() { + mHandler.removeMessages(MSG_FLUSH); + mHandler.post(() -> destroySession()); + } + /** * Callback from {@code system_server} after call to * {@link IContentCaptureManager#startSession(IBinder, ComponentName, String, int, @@ -243,7 +232,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { * @param resultCode session state * @param binder handle to {@code IContentCaptureDirectManager} */ - private void handleSessionStarted(int resultCode, @Nullable IBinder binder) { + @UiThread + private void onSessionStarted(int resultCode, @Nullable IBinder binder) { if (binder != null) { mDirectServiceInterface = IContentCaptureDirectManager.Stub.asInterface(binder); mDirectServiceVulture = () -> { @@ -258,7 +248,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } if ((resultCode & STATE_DISABLED) != 0) { - handleResetSession(resultCode); + resetSession(resultCode); } else { mState = resultCode; mDisabled.set(false); @@ -270,10 +260,16 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } } - private void handleSendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) { + @UiThread + private void sendEvent(@NonNull ContentCaptureEvent event) { + sendEvent(event, /* forceFlush= */ false); + } + + @UiThread + private void sendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) { final int eventType = event.getType(); if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event); - if (!handleHasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) { + if (!hasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) { // TODO(b/120494182): comment when this could happen (dialogs?) Log.v(TAG, "handleSendEvent(" + getDebugState() + ", " + ContentCaptureEvent.getTypeAsString(eventType) @@ -334,7 +330,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE; if (bufferEvent && !forceFlush) { - handleScheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true); + scheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true); return; } @@ -348,7 +344,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { Log.d(TAG, "Closing session for " + getDebugState() + " after " + numberEvents + " delayed events"); } - handleResetSession(STATE_DISABLED | STATE_NO_RESPONSE); + resetSession(STATE_DISABLED | STATE_NO_RESPONSE); // TODO(b/111276913): blacklist activity / use special flag to indicate that // when it's launched again return; @@ -365,19 +361,21 @@ public final class MainContentCaptureSession extends ContentCaptureSession { flushReason = FLUSH_REASON_FULL; } - handleForceFlush(flushReason); + flush(flushReason); } - private boolean handleHasStarted() { + @UiThread + private boolean hasStarted() { return mState != UNKNOWN_STATE; } - private void handleScheduleFlush(@FlushReason int reason, boolean checkExisting) { + @UiThread + private void scheduleFlush(@FlushReason int reason, boolean checkExisting) { if (VERBOSE) { Log.v(TAG, "handleScheduleFlush(" + getDebugState(reason) + ", checkExisting=" + checkExisting); } - if (!handleHasStarted()) { + if (!hasStarted()) { if (VERBOSE) Log.v(TAG, "handleScheduleFlush(): session not started yet"); return; } @@ -398,20 +396,22 @@ public final class MainContentCaptureSession extends ContentCaptureSession { Log.v(TAG, "handleScheduleFlush(): scheduled to flush in " + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush)); } - mHandler.sendMessageDelayed( - obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this, reason) - .setWhat(MSG_FLUSH), FLUSHING_FREQUENCY_MS); + // Post using a Runnable directly to trim a few μs from PooledLambda.obtainMessage() + mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, FLUSHING_FREQUENCY_MS); } - private void handleFlushIfNeeded(@FlushReason int reason) { + @UiThread + private void flushIfNeeded(@FlushReason int reason) { if (mEvents == null || mEvents.isEmpty()) { if (VERBOSE) Log.v(TAG, "Nothing to flush"); return; } - handleForceFlush(reason); + flush(reason); } - private void handleForceFlush(@FlushReason int reason) { + @Override + @UiThread + void flush(@FlushReason int reason) { if (mEvents == null) return; if (mDisabled.get()) { @@ -426,7 +426,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { + "client not ready: " + mEvents); } if (!mHandler.hasMessages(MSG_FLUSH)) { - handleScheduleFlush(reason, /* checkExisting= */ false); + scheduleFlush(reason, /* checkExisting= */ false); } return; } @@ -443,7 +443,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { mFlushHistory.log(logRecord); mHandler.removeMessages(MSG_FLUSH); - final ParceledListSlice<ContentCaptureEvent> events = handleClearEvents(); + final ParceledListSlice<ContentCaptureEvent> events = clearEvents(); mDirectServiceInterface.sendEvents(events); } catch (RemoteException e) { Log.w(TAG, "Error sending " + numberEvents + " for " + getDebugState() @@ -455,7 +455,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { * Resets the buffer and return a {@link ParceledListSlice} with the previous events. */ @NonNull - private ParceledListSlice<ContentCaptureEvent> handleClearEvents() { + @UiThread + private ParceledListSlice<ContentCaptureEvent> clearEvents() { // NOTE: we must save a reference to the current mEvents and then set it to to null, // otherwise clearing it would clear it in the receiving side if the service is also local. final List<ContentCaptureEvent> events = mEvents == null @@ -465,7 +466,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { return new ParceledListSlice<>(events); } - private void handleDestroySession() { + @UiThread + private void destroySession() { if (DEBUG) { Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with " + (mEvents == null ? 0 : mEvents.size()) + " event(s) for " @@ -484,7 +486,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // TODO(b/122454205): once we support multiple sessions, we might need to move some of these // clearings out. - private void handleResetSession(int newState) { + @UiThread + private void resetSession(int newState) { if (VERBOSE) { Log.v(TAG, "handleResetSession(" + getActivityName() + "): from " + getStateAsString(mState) + " to " + getStateAsString(newState)); @@ -518,6 +521,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } @Override + public void internalNotifyViewHierarchyEvent(boolean started) { + notifyInitialViewHierarchyEvent(mId, started); + } + + @Override boolean isContentCaptureEnabled() { return super.isContentCaptureEnabled() && mManager.isContentCaptureEnabled(); } @@ -532,37 +540,52 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // change should also get get rid of the "internalNotifyXXXX" methods above void notifyChildSessionStarted(@NonNull String parentSessionId, @NonNull String childSessionId, @NonNull ContentCaptureContext clientContext) { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(childSessionId, TYPE_SESSION_STARTED) - .setParentSessionId(parentSessionId) - .setClientContext(clientContext), - /* forceFlush= */ true)); + sendEvent(new ContentCaptureEvent(childSessionId, TYPE_SESSION_STARTED) + .setParentSessionId(parentSessionId).setClientContext(clientContext), + FORCE_FLUSH); } void notifyChildSessionFinished(@NonNull String parentSessionId, @NonNull String childSessionId) { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(childSessionId, TYPE_SESSION_FINISHED) - .setParentSessionId(parentSessionId), /* forceFlush= */ true)); + sendEvent(new ContentCaptureEvent(childSessionId, TYPE_SESSION_FINISHED) + .setParentSessionId(parentSessionId), FORCE_FLUSH); } void notifyViewAppeared(@NonNull String sessionId, @NonNull ViewStructureImpl node) { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(sessionId, TYPE_VIEW_APPEARED) - .setViewNode(node.mNode), /* forceFlush= */ false)); + sendEvent(new ContentCaptureEvent(sessionId, TYPE_VIEW_APPEARED) + .setViewNode(node.mNode)); } void notifyViewDisappeared(@NonNull String sessionId, @NonNull AutofillId id) { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED).setAutofillId(id), - /* forceFlush= */ false)); + sendEvent( + new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED).setAutofillId(id)); + } + + /** @hide */ + public void notifyViewsDisappeared(@NonNull String sessionId, + @NonNull ArrayList<AutofillId> ids) { + final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED); + if (ids.size() == 1) { + event.setAutofillId(ids.get(0)); + } else { + event.setAutofillIds(ids); + } + sendEvent(event); } void notifyViewTextChanged(@NonNull String sessionId, @NonNull AutofillId id, @Nullable CharSequence text) { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED).setAutofillId(id) - .setText(text), /* forceFlush= */ false)); + sendEvent(new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED).setAutofillId(id) + .setText(text)); + } + + void notifyInitialViewHierarchyEvent(@NonNull String sessionId, boolean started) { + if (started) { + sendEvent(new ContentCaptureEvent(sessionId, TYPE_INITIAL_VIEW_TREE_APPEARING)); + } else { + sendEvent(new ContentCaptureEvent(sessionId, TYPE_INITIAL_VIEW_TREE_APPEARED), + FORCE_FLUSH); + } } @Override diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index 0cabafa21b17..eef841da3bc5 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -18,6 +18,7 @@ package android.view.contentcapture; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.assist.AssistStructure; import android.graphics.Matrix; import android.graphics.Rect; @@ -42,6 +43,7 @@ import com.android.internal.util.Preconditions; // instead /** @hide */ @SystemApi +@TestApi public final class ViewNode extends AssistStructure.ViewNode { private static final String TAG = ViewNode.class.getSimpleName(); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 7fee3ef29a09..aee4b1f63812 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -16,6 +16,7 @@ package android.view.inputmethod; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import android.annotation.DrawableRes; @@ -26,6 +27,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; +import android.annotation.UserIdInt; import android.app.ActivityThread; import android.content.ComponentName; import android.content.ContentResolver; @@ -46,6 +48,7 @@ import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.Trace; +import android.os.UserHandle; import android.provider.Settings; import android.text.style.SuggestionSpan; import android.util.Log; @@ -954,17 +957,69 @@ public final class InputMethodManager { return mIInputContext; } + /** + * Returns the list of installed input methods. + * + * <p>On multi user environment, this API returns a result for the calling process user.</p> + * + * @return {@link List} of {@link InputMethodInfo}. + */ public List<InputMethodInfo> getInputMethodList() { try { - return mService.getInputMethodList(); + // We intentionally do not use UserHandle.getCallingUserId() here because for system + // services InputMethodManagerInternal.getInputMethodListAsUser() should be used + // instead. + return mService.getInputMethodList(UserHandle.myUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** + * Returns the list of installed input methods for the specified user. + * + * @param userId user ID to query + * @return {@link List} of {@link InputMethodInfo}. + * @hide + */ + @RequiresPermission(INTERACT_ACROSS_USERS_FULL) + public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { + try { + return mService.getInputMethodList(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the list of enabled input methods. + * + * <p>On multi user environment, this API returns a result for the calling process user.</p> + * + * @return {@link List} of {@link InputMethodInfo}. + */ public List<InputMethodInfo> getEnabledInputMethodList() { try { - return mService.getEnabledInputMethodList(); + // We intentionally do not use UserHandle.getCallingUserId() here because for system + // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used + // instead. + return mService.getEnabledInputMethodList(UserHandle.myUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the list of enabled input methods for the specified user. + * + * @param userId user ID to query + * @return {@link List} of {@link InputMethodInfo}. + * @hide + */ + @RequiresPermission(INTERACT_ACROSS_USERS_FULL) + public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) { + try { + return mService.getEnabledInputMethodList(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -972,6 +1027,9 @@ public final class InputMethodManager { /** * Returns a list of enabled input method subtypes for the specified input method info. + * + * <p>On multi user environment, this API returns a result for the calling process user.</p> + * * @param imi An input method info whose subtypes list will be returned. * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly * selected subtypes. If an input method info doesn't have enabled subtypes, the framework @@ -1887,6 +1945,36 @@ public final class InputMethodManager { } /** + * Call showSoftInput with currently focused view. + * @return {@code true} if IME can be shown. + * @hide + */ + public boolean requestImeShow(ResultReceiver resultReceiver) { + synchronized (mH) { + if (mServedView == null) { + return false; + } + showSoftInput(mServedView, 0 /* flags */, resultReceiver); + return true; + } + } + + /** + * Notify IME directly that it is no longer visible. + * @hide + */ + public void notifyImeHidden() { + synchronized (mH) { + try { + if (mCurMethod != null) { + mCurMethod.notifyImeHidden(); + } + } catch (RemoteException re) { + } + } + } + + /** * Report the current selection range. * * <p><strong>Editor authors</strong>, you need to call this method whenever diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java index de15f332d51d..eb81628f9e27 100644 --- a/core/java/android/view/inputmethod/InputMethodSession.java +++ b/core/java/android/view/inputmethod/InputMethodSession.java @@ -184,4 +184,11 @@ public interface InputMethodSession { * insertion point and composition string. */ public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo); + + /** + * Notifies {@link android.inputmethodservice.InputMethodService} that IME has been + * hidden from user. + * @hide + */ + public void notifyImeHidden(); } diff --git a/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java b/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java new file mode 100644 index 000000000000..8faae1f1da98 --- /dev/null +++ b/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 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.inspector; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * An inspection companion provider that loads pre-generated inspection companions + * + * @see android.processor.view.inspector.PlatformInspectableProcessor + */ +public class GeneratedInspectionCompanionProvider implements InspectionCompanionProvider { + /** + * The suffix used for the generated class + */ + private static final String COMPANION_SUFFIX = "$$InspectionCompanion"; + + @Override + @Nullable + @SuppressWarnings("unchecked") + public <T> InspectionCompanion<T> provide(@NonNull Class<T> cls) { + final String companionName = cls.getName() + COMPANION_SUFFIX; + + try { + final Class<InspectionCompanion<T>> companionClass = + (Class<InspectionCompanion<T>>) cls.getClassLoader().loadClass(companionName); + return companionClass.newInstance(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + return null; + } + } +} diff --git a/core/java/android/view/inspector/InspectionCompanionProvider.java b/core/java/android/view/inspector/InspectionCompanionProvider.java new file mode 100644 index 000000000000..c08f49c611ee --- /dev/null +++ b/core/java/android/view/inspector/InspectionCompanionProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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.inspector; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * An interface for services that can provide inspection companions for a class. + */ +public interface InspectionCompanionProvider { + /** + * Provide an {@link InspectionCompanion} for the supplied class. + * + * Implementing classes must not cache companion instances, and should instantiate a new one + * for each request. + * + * @param cls A {@link Class} representing the inspectable type + * @param <T> The type to find the companion for + * @return The inspection companion for the supplied type + */ + @Nullable + <T> InspectionCompanion<T> provide(@NonNull Class<T> cls); +} diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 99895bd65398..4dd7d3a2fa71 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -82,6 +82,8 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.InputMethodManager; +import android.view.inspector.InspectableProperty; +import android.view.inspector.InspectableProperty.EnumMap; import android.widget.RemoteViews.OnClickHandler; import com.android.internal.R; @@ -1221,6 +1223,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * * @return The current choice mode */ + @InspectableProperty(enumMapping = { + @EnumMap(value = CHOICE_MODE_NONE, name = "none"), + @EnumMap(value = CHOICE_MODE_SINGLE, name = "singleChoice"), + @EnumMap(value = CHOICE_MODE_MULTIPLE, name = "multipleChoice"), + @EnumMap(value = CHOICE_MODE_MULTIPLE_MODAL, name = "multipleChoiceModal") + }) public int getChoiceMode() { return mChoiceMode; } @@ -1421,6 +1429,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @return true if fast scroll is enabled, false otherwise */ @ViewDebug.ExportedProperty + @InspectableProperty public boolean isFastScrollEnabled() { if (mFastScroll == null) { return mFastScrollEnabled; @@ -1485,6 +1494,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @see #setSmoothScrollbarEnabled(boolean) */ @ViewDebug.ExportedProperty + @InspectableProperty(name = "smoothScrollbar") public boolean isSmoothScrollbarEnabled() { return mSmoothScrollbarEnabled; } @@ -1620,6 +1630,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @see View#setDrawingCacheEnabled(boolean) */ @ViewDebug.ExportedProperty + @InspectableProperty(name = "scrollingCache") public boolean isScrollingCacheEnabled() { return mScrollingCacheEnabled; } @@ -1667,6 +1678,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @see Filterable */ @ViewDebug.ExportedProperty + @InspectableProperty public boolean isTextFilterEnabled() { return mTextFilterEnabled; } @@ -1697,6 +1709,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @return true if the content is stacked from the bottom edge, false otherwise */ @ViewDebug.ExportedProperty + @InspectableProperty public boolean isStackFromBottom() { return mStackFromBottom; } @@ -2813,6 +2826,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** + * Returns whether the selection highlight drawable should be drawn on top of the item or + * behind it. + * + * @return true if selector is drawn on top, false otherwise + * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop + */ + @InspectableProperty + public boolean getDrawSelectorOnTop() { + return mDrawSelectorOnTop; + } + + /** * Set a Drawable that should be used to highlight the currently selected item. * * @param resID A Drawable resource to use as the selection highlight. @@ -2845,6 +2870,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * * @return the drawable used to display the selector */ + @InspectableProperty(name = "listSelector") public Drawable getSelector() { return mSelector; } @@ -6272,6 +6298,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @return {@link #TRANSCRIPT_MODE_DISABLED}, {@link #TRANSCRIPT_MODE_NORMAL} or * {@link #TRANSCRIPT_MODE_ALWAYS_SCROLL} */ + @InspectableProperty(enumMapping = { + @EnumMap(value = TRANSCRIPT_MODE_DISABLED, name = "disabled"), + @EnumMap(value = TRANSCRIPT_MODE_NORMAL, name = "normal"), + @EnumMap(value = TRANSCRIPT_MODE_ALWAYS_SCROLL, name = "alwaysScroll") + }) public int getTranscriptMode() { return mTranscriptMode; } @@ -6309,6 +6340,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @return The cache color hint */ @ViewDebug.ExportedProperty(category = "drawing") + @InspectableProperty @ColorInt public int getCacheColorHint() { return mCacheColorHint; diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index a85c5854d05a..c8be1d66ed4a 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -34,6 +34,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -252,6 +253,7 @@ public abstract class AbsSeekBar extends ProgressBar { * @attr ref android.R.styleable#SeekBar_thumbTint * @see #setThumbTintList(ColorStateList) */ + @InspectableProperty(name = "thumbTint") @Nullable public ColorStateList getThumbTintList() { return mThumbTintList; @@ -284,6 +286,7 @@ public abstract class AbsSeekBar extends ProgressBar { * @attr ref android.R.styleable#SeekBar_thumbTintMode * @see #setThumbTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getThumbTintMode() { return mThumbTintMode; @@ -406,6 +409,7 @@ public abstract class AbsSeekBar extends ProgressBar { * @attr ref android.R.styleable#SeekBar_tickMarkTint * @see #setTickMarkTintList(ColorStateList) */ + @InspectableProperty(name = "tickMarkTint") @Nullable public ColorStateList getTickMarkTintList() { return mTickMarkTintList; @@ -438,6 +442,7 @@ public abstract class AbsSeekBar extends ProgressBar { * @attr ref android.R.styleable#SeekBar_tickMarkTintMode * @see #setTickMarkTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getTickMarkTintMode() { return mTickMarkTintMode; diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 7d6564fd91fb..9bc055e7111b 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -35,12 +35,12 @@ import android.view.ContextThemeWrapper; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -362,27 +362,33 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * * @attr ref android.R.styleable#AutoCompleteTextView_completionHint */ + @InspectableProperty public CharSequence getCompletionHint() { return mHintText; } /** - * <p>Returns the current width for the auto-complete drop down list. This can - * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or - * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> + * Returns the current width for the auto-complete drop down list. + * + * This can be a fixed width, or {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} + * to fill the screen, or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} + * to fit the width of its anchor view. * * @return the width for the drop down list * * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth */ + @InspectableProperty public int getDropDownWidth() { return mPopup.getWidth(); } /** - * <p>Sets the current width for the auto-complete drop down list. This can - * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or - * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> + * Sets the current width for the auto-complete drop down list. + * + * This can be a fixed width, or {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} + * to fill the screen, or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} + * to fit the width of its anchor view. * * @param width the width to use * @@ -393,24 +399,27 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } /** - * <p>Returns the current height for the auto-complete drop down list. This can - * be a fixed height, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill - * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height - * of the drop down's content.</p> + * <p>Returns the current height for the auto-complete drop down list. + * + * This can be a fixed width, or {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} + * to fill the screen, or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} + * to fit the width of its anchor view. * * @return the height for the drop down list * * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight */ + @InspectableProperty public int getDropDownHeight() { return mPopup.getHeight(); } /** - * <p>Sets the current height for the auto-complete drop down list. This can - * be a fixed height, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill - * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height - * of the drop down's content.</p> + * Sets the current height for the auto-complete drop down list. + * + * This can be a fixed width, or {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} + * to fill the screen, or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} + * to fit the width of its anchor view. * * @param height the height to use * @@ -452,6 +461,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * * @attr ref android.R.styleable#PopupWindow_popupBackground */ + @InspectableProperty(name = "popupBackground") public Drawable getDropDownBackground() { return mPopup.getBackground(); } @@ -496,6 +506,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset */ + @InspectableProperty public int getDropDownVerticalOffset() { return mPopup.getVerticalOffset(); } @@ -518,6 +529,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset */ + @InspectableProperty public int getDropDownHorizontalOffset() { return mPopup.getHorizontalOffset(); } @@ -610,6 +622,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * * @attr ref android.R.styleable#AutoCompleteTextView_completionThreshold */ + @InspectableProperty(name = "completionThreshold") public int getThreshold() { return mThreshold; } diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java index 2ff815d6e309..6c74c8c24c44 100644 --- a/core/java/android/widget/CalendarView.java +++ b/core/java/android/widget/CalendarView.java @@ -34,6 +34,7 @@ import android.icu.util.Calendar; import android.icu.util.TimeZone; import android.util.AttributeSet; import android.util.Log; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -149,6 +150,7 @@ public class CalendarView extends FrameLayout { * @attr ref android.R.styleable#CalendarView_shownWeekCount * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @Deprecated public int getShownWeekCount() { return mDelegate.getShownWeekCount(); @@ -175,6 +177,7 @@ public class CalendarView extends FrameLayout { * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @ColorInt @Deprecated public int getSelectedWeekBackgroundColor() { @@ -202,6 +205,7 @@ public class CalendarView extends FrameLayout { * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @ColorInt @Deprecated public int getFocusedMonthDateColor() { @@ -229,6 +233,7 @@ public class CalendarView extends FrameLayout { * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @ColorInt @Deprecated public int getUnfocusedMonthDateColor() { @@ -256,6 +261,7 @@ public class CalendarView extends FrameLayout { * @attr ref android.R.styleable#CalendarView_weekNumberColor * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @ColorInt @Deprecated public int getWeekNumberColor() { @@ -285,6 +291,7 @@ public class CalendarView extends FrameLayout { */ @ColorInt @Deprecated + @InspectableProperty public int getWeekSeparatorLineColor() { return mDelegate.getWeekSeparatorLineColor(); } @@ -324,6 +331,7 @@ public class CalendarView extends FrameLayout { * @return The vertical bar drawable. * @deprecated No longer used by Material-style CalendarView. */ + @InspectableProperty @Deprecated public Drawable getSelectedDateVerticalBar() { return mDelegate.getSelectedDateVerticalBar(); @@ -347,6 +355,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_weekDayTextAppearance */ + @InspectableProperty public @StyleRes int getWeekDayTextAppearance() { return mDelegate.getWeekDayTextAppearance(); } @@ -369,6 +378,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_dateTextAppearance */ + @InspectableProperty public @StyleRes int getDateTextAppearance() { return mDelegate.getDateTextAppearance(); } @@ -385,6 +395,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_minDate */ + @InspectableProperty public long getMinDate() { return mDelegate.getMinDate(); } @@ -414,6 +425,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_maxDate */ + @InspectableProperty public long getMaxDate() { return mDelegate.getMaxDate(); } @@ -452,6 +464,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_showWeekNumber */ + @InspectableProperty @Deprecated public boolean getShowWeekNumber() { return mDelegate.getShowWeekNumber(); @@ -472,6 +485,7 @@ public class CalendarView extends FrameLayout { * * @attr ref android.R.styleable#CalendarView_firstDayOfWeek */ + @InspectableProperty public int getFirstDayOfWeek() { return mDelegate.getFirstDayOfWeek(); } diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index 1472b01b7af4..b7fdcbe2b399 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -35,6 +35,7 @@ import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -121,6 +122,7 @@ public class CheckedTextView extends TextView implements Checkable { } @ViewDebug.ExportedProperty + @InspectableProperty public boolean isChecked() { return mChecked; } @@ -237,6 +239,7 @@ public class CheckedTextView extends TextView implements Checkable { * @attr ref android.R.styleable#CheckedTextView_checkMarkTint * @see #setCheckMarkTintList(ColorStateList) */ + @InspectableProperty(name = "checkMarkTint") @Nullable public ColorStateList getCheckMarkTintList() { return mCheckMarkTintList; @@ -269,6 +272,7 @@ public class CheckedTextView extends TextView implements Checkable { * @attr ref android.R.styleable#CheckedTextView_checkMarkTintMode * @see #setCheckMarkTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getCheckMarkTintMode() { return mCheckMarkTintMode; @@ -328,6 +332,7 @@ public class CheckedTextView extends TextView implements Checkable { * * @attr ref android.R.styleable#CheckedTextView_checkMark */ + @InspectableProperty(name = "checkMark") public Drawable getCheckMarkDrawable() { return mCheckMarkDrawable; } diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java index d11c03ad6878..66c35d903366 100644 --- a/core/java/android/widget/Chronometer.java +++ b/core/java/android/widget/Chronometer.java @@ -29,6 +29,7 @@ import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -145,6 +146,7 @@ public class Chronometer extends TextView { * * @see #setCountDown(boolean) */ + @InspectableProperty public boolean isCountDown() { return mCountDown; } @@ -206,6 +208,7 @@ public class Chronometer extends TextView { /** * Returns the current format string as set through {@link #setFormat}. */ + @InspectableProperty public String getFormat() { return mFormat; } diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index d35bec8d08d5..a0f93da90847 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -39,6 +39,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -145,6 +146,7 @@ public abstract class CompoundButton extends Button implements Checkable { return handled; } + @InspectableProperty @ViewDebug.ExportedProperty @Override public boolean isChecked() { @@ -282,6 +284,7 @@ public abstract class CompoundButton extends Button implements Checkable { * @see #setButtonDrawable(Drawable) * @see #setButtonDrawable(int) */ + @InspectableProperty(name = "button") @Nullable public Drawable getButtonDrawable() { return mButtonDrawable; @@ -314,6 +317,7 @@ public abstract class CompoundButton extends Button implements Checkable { * @attr ref android.R.styleable#CompoundButton_buttonTint * @see #setButtonTintList(ColorStateList) */ + @InspectableProperty(name = "buttonTint") @Nullable public ColorStateList getButtonTintList() { return mButtonTintList; @@ -342,6 +346,7 @@ public abstract class CompoundButton extends Button implements Checkable { * @attr ref android.R.styleable#CompoundButton_buttonTintMode * @see #setButtonTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getButtonTintMode() { return mButtonTintMode; diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index df53795941ab..cca951ca9298 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -37,6 +37,7 @@ import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -212,6 +213,10 @@ public class DatePicker extends FrameLayout { * @attr ref android.R.styleable#DatePicker_datePickerMode * @hide Visible for testing only. */ + @InspectableProperty(name = "datePickerMode", enumMapping = { + @InspectableProperty.EnumMap(value = MODE_SPINNER, name = "spinner"), + @InspectableProperty.EnumMap(value = MODE_CALENDAR, name = "calendar") + }) @DatePickerMode @TestApi public int getMode() { @@ -257,6 +262,7 @@ public class DatePicker extends FrameLayout { /** * @return The selected year. */ + @InspectableProperty(hasAttributeId = false) public int getYear() { return mDelegate.getYear(); } @@ -264,6 +270,7 @@ public class DatePicker extends FrameLayout { /** * @return The selected month. */ + @InspectableProperty(hasAttributeId = false) public int getMonth() { return mDelegate.getMonth(); } @@ -271,6 +278,7 @@ public class DatePicker extends FrameLayout { /** * @return The selected day of month. */ + @InspectableProperty(hasAttributeId = false) public int getDayOfMonth() { return mDelegate.getDayOfMonth(); } @@ -285,6 +293,7 @@ public class DatePicker extends FrameLayout { * * @return The minimal supported date. */ + @InspectableProperty public long getMinDate() { return mDelegate.getMinDate().getTimeInMillis(); } @@ -310,6 +319,7 @@ public class DatePicker extends FrameLayout { * * @return The maximal supported date. */ + @InspectableProperty public long getMaxDate() { return mDelegate.getMaxDate().getTimeInMillis(); } @@ -411,6 +421,7 @@ public class DatePicker extends FrameLayout { * * @attr ref android.R.styleable#DatePicker_firstDayOfWeek */ + @InspectableProperty public int getFirstDayOfWeek() { return mDelegate.getFirstDayOfWeek(); } @@ -426,6 +437,7 @@ public class DatePicker extends FrameLayout { * @see #getCalendarView() * @deprecated Not supported by Material-style {@code calendar} mode */ + @InspectableProperty @Deprecated public boolean getCalendarViewShown() { return mDelegate.getCalendarViewShown(); @@ -476,6 +488,7 @@ public class DatePicker extends FrameLayout { * @return {@code true} if the spinners are shown * @deprecated Not supported by Material-style {@code calendar} mode */ + @InspectableProperty @Deprecated public boolean getSpinnersShown() { return mDelegate.getSpinnersShown(); diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java index bf2762a6d727..0469dbd00dc9 100644 --- a/core/java/android/widget/DateTimeView.java +++ b/core/java/android/widget/DateTimeView.java @@ -35,6 +35,7 @@ import android.os.Handler; import android.text.format.Time; import android.util.AttributeSet; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -142,6 +143,16 @@ public class DateTimeView extends TextView { update(); } + /** + * Returns whether this view shows relative time + * + * @return True if it shows relative time, false otherwise + */ + @InspectableProperty(name = "showReleative", hasAttributeId = false) + public boolean isShowRelativeTime() { + return mShowRelativeTime; + } + @Override @android.view.RemotableViewMethod public void setVisibility(@Visibility int visibility) { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index c82177407b61..97c37b0a8f75 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -273,7 +273,11 @@ public class Editor { boolean mDiscardNextActionUp; boolean mIgnoreActionUpEvent; - @UnsupportedAppUsage + /** + * To set a custom cursor, you should use {@link TextView#setTextCursorDrawable(Drawable)} + * or {@link TextView#setTextCursorDrawable(int)}. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private long mShowCursor; private boolean mRenderCursorRegardlessTiming; private Blink mBlink; diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 865f52082f28..5723b9467aa2 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -31,6 +31,7 @@ import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -367,6 +368,7 @@ public class FrameLayout extends ViewGroup { * * @return Whether all children are considered when measuring. */ + @InspectableProperty public boolean getMeasureAllChildren() { return mMeasureAllChildren; } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 13c086c89d8f..c8abf18f88f9 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -46,6 +46,7 @@ import android.util.Printer; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -327,6 +328,10 @@ public class GridLayout extends ViewGroup { * @attr ref android.R.styleable#GridLayout_orientation */ @Orientation + @InspectableProperty(enumMapping = { + @InspectableProperty.EnumMap(value = HORIZONTAL, name = "horizontal"), + @InspectableProperty.EnumMap(value = VERTICAL, name = "vertical") + }) public int getOrientation() { return mOrientation; } @@ -387,6 +392,7 @@ public class GridLayout extends ViewGroup { * * @attr ref android.R.styleable#GridLayout_rowCount */ + @InspectableProperty public int getRowCount() { return mVerticalAxis.getCount(); } @@ -420,6 +426,7 @@ public class GridLayout extends ViewGroup { * * @attr ref android.R.styleable#GridLayout_columnCount */ + @InspectableProperty public int getColumnCount() { return mHorizontalAxis.getCount(); } @@ -451,6 +458,7 @@ public class GridLayout extends ViewGroup { * * @attr ref android.R.styleable#GridLayout_useDefaultMargins */ + @InspectableProperty public boolean getUseDefaultMargins() { return mUseDefaultMargins; } @@ -499,6 +507,10 @@ public class GridLayout extends ViewGroup { * @attr ref android.R.styleable#GridLayout_alignmentMode */ @AlignmentMode + @InspectableProperty(enumMapping = { + @InspectableProperty.EnumMap(value = ALIGN_BOUNDS, name = "alignBounds"), + @InspectableProperty.EnumMap(value = ALIGN_MARGINS, name = "alignMargins"), + }) public int getAlignmentMode() { return mAlignmentMode; } @@ -533,6 +545,7 @@ public class GridLayout extends ViewGroup { * * @attr ref android.R.styleable#GridLayout_rowOrderPreserved */ + @InspectableProperty public boolean isRowOrderPreserved() { return mVerticalAxis.isOrderPreserved(); } @@ -569,6 +582,7 @@ public class GridLayout extends ViewGroup { * * @attr ref android.R.styleable#GridLayout_columnOrderPreserved */ + @InspectableProperty public boolean isColumnOrderPreserved() { return mHorizontalAxis.isOrderPreserved(); } diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index f78180276373..bf65ec0d5de3 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -42,6 +42,7 @@ import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.GridLayoutAnimationController; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -2061,6 +2062,7 @@ public class GridView extends AbsListView { * * @attr ref android.R.styleable#GridView_gravity */ + @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY) public int getGravity() { return mGravity; } @@ -2096,6 +2098,7 @@ public class GridView extends AbsListView { * * @attr ref android.R.styleable#GridView_horizontalSpacing */ + @InspectableProperty public int getHorizontalSpacing() { return mHorizontalSpacing; } @@ -2147,6 +2150,7 @@ public class GridView extends AbsListView { * * @attr ref android.R.styleable#GridView_verticalSpacing */ + @InspectableProperty public int getVerticalSpacing() { return mVerticalSpacing; } @@ -2167,6 +2171,13 @@ public class GridView extends AbsListView { } @StretchMode + @InspectableProperty(enumMapping = { + @InspectableProperty.EnumMap(value = NO_STRETCH, name = "none"), + @InspectableProperty.EnumMap(value = STRETCH_SPACING, name = "spacingWidth"), + @InspectableProperty.EnumMap( + value = STRETCH_SPACING_UNIFORM, name = "spacingWidthUniform"), + @InspectableProperty.EnumMap(value = STRETCH_COLUMN_WIDTH, name = "columnWidth"), + }) public int getStretchMode() { return mStretchMode; } @@ -2197,6 +2208,7 @@ public class GridView extends AbsListView { * * @attr ref android.R.styleable#GridView_columnWidth */ + @InspectableProperty public int getColumnWidth() { return mColumnWidth; } @@ -2241,6 +2253,7 @@ public class GridView extends AbsListView { * @see #setNumColumns(int) */ @ViewDebug.ExportedProperty + @InspectableProperty public int getNumColumns() { return mNumColumns; } diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index bf9dffd52e33..1c5f837728a0 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -43,6 +43,7 @@ import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AnimationUtils; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -293,6 +294,7 @@ public class HorizontalScrollView extends FrameLayout { * * @attr ref android.R.styleable#HorizontalScrollView_fillViewport */ + @InspectableProperty public boolean isFillViewport() { return mFillViewport; } diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index c21182ca597f..e9c31db8110b 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -51,6 +51,7 @@ import android.view.View; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; import android.view.accessibility.AccessibilityEvent; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -326,6 +327,7 @@ public class ImageView extends View { * * @attr ref android.R.styleable#ImageView_adjustViewBounds */ + @InspectableProperty public boolean getAdjustViewBounds() { return mAdjustViewBounds; } @@ -364,6 +366,7 @@ public class ImageView extends View { * * @attr ref android.R.styleable#ImageView_maxWidth */ + @InspectableProperty public int getMaxWidth() { return mMaxWidth; } @@ -402,6 +405,7 @@ public class ImageView extends View { * * @attr ref android.R.styleable#ImageView_maxHeight */ + @InspectableProperty public int getMaxHeight() { return mMaxHeight; } @@ -438,6 +442,7 @@ public class ImageView extends View { * @return the view's drawable, or null if no drawable has been * assigned. */ + @InspectableProperty(name = "src") public Drawable getDrawable() { if (mDrawable == mRecycleableBitmapDrawable) { // Consider our cached version dirty since app code now has a reference to it @@ -650,6 +655,7 @@ public class ImageView extends View { * @see #setImageTintList(ColorStateList) */ @Nullable + @InspectableProperty(name = "tint") public ColorStateList getImageTintList() { return mDrawableTintList; } @@ -679,6 +685,7 @@ public class ImageView extends View { * @see #setImageTintMode(PorterDuff.Mode) */ @Nullable + @InspectableProperty(name = "tintMode") public PorterDuff.Mode getImageTintMode() { return mDrawableTintMode; } @@ -844,6 +851,7 @@ public class ImageView extends View { * @see ImageView.ScaleType * @attr ref android.R.styleable#ImageView_scaleType */ + @InspectableProperty public ScaleType getScaleType() { return mScaleType; } @@ -893,6 +901,7 @@ public class ImageView extends View { * * @attr ref android.R.styleable#ImageView_cropToPadding */ + @InspectableProperty public boolean getCropToPadding() { return mCropToPadding; } @@ -1404,6 +1413,7 @@ public class ImageView extends View { * if baseline alignment is not supported. */ @Override + @InspectableProperty @ViewDebug.ExportedProperty(category = "layout") public int getBaseline() { if (mBaselineAlignBottom) { @@ -1451,6 +1461,7 @@ public class ImageView extends View { * @return True if the ImageView's baseline is considered the bottom of the view, false if otherwise. * @see #setBaselineAlignBottom(boolean) */ + @InspectableProperty public boolean getBaselineAlignBottom() { return mBaselineAlignBottom; } diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index 15910bbd36d8..64769b5337df 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -31,6 +31,7 @@ import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -342,6 +343,7 @@ public class LinearLayout extends ViewGroup { * * @attr ref android.R.styleable#LinearLayout_divider */ + @InspectableProperty(name = "divider") public Drawable getDividerDrawable() { return mDivider; } @@ -526,6 +528,7 @@ public class LinearLayout extends ViewGroup { * * @return true when widgets are baseline-aligned, false otherwise */ + @InspectableProperty public boolean isBaselineAligned() { return mBaselineAligned; } @@ -554,6 +557,7 @@ public class LinearLayout extends ViewGroup { * * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild */ + @InspectableProperty(name = "measureWithLargestChild") public boolean isMeasureWithLargestChildEnabled() { return mUseLargestChild; } @@ -633,6 +637,7 @@ public class LinearLayout extends ViewGroup { * part of a larger layout that is baseline aligned, or -1 if none has * been set. */ + @InspectableProperty public int getBaselineAlignedChildIndex() { return mBaselineAlignedChildIndex; } @@ -686,6 +691,7 @@ public class LinearLayout extends ViewGroup { * a number lower than or equals to 0.0f if not weight sum is * to be used. */ + @InspectableProperty public float getWeightSum() { return mWeightSum; } @@ -1841,6 +1847,10 @@ public class LinearLayout extends ViewGroup { * @return either {@link #HORIZONTAL} or {@link #VERTICAL} */ @OrientationMode + @InspectableProperty(enumMapping = { + @InspectableProperty.EnumMap(value = HORIZONTAL, name = "horizontal"), + @InspectableProperty.EnumMap(value = VERTICAL, name = "vertical") + }) public int getOrientation() { return mOrientation; } @@ -1877,6 +1887,7 @@ public class LinearLayout extends ViewGroup { * @return the current gravity. * @see #setGravity */ + @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY) public int getGravity() { return mGravity; } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 9b497866486d..311f8968150c 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -49,6 +49,7 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo; import android.view.accessibility.AccessibilityNodeProvider; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -3637,6 +3638,7 @@ public class ListView extends AbsListView { * @return the current drawable drawn between list elements * @attr ref R.styleable#ListView_divider */ + @InspectableProperty @Nullable public Drawable getDivider() { return mDivider; @@ -3666,6 +3668,7 @@ public class ListView extends AbsListView { /** * @return Returns the height of the divider that will be drawn between each item in the list. */ + @InspectableProperty public int getDividerHeight() { return mDividerHeight; } @@ -3701,6 +3704,7 @@ public class ListView extends AbsListView { * * @see #setHeaderDividersEnabled(boolean) */ + @InspectableProperty(name = "headerDividersEnabled") public boolean areHeaderDividersEnabled() { return mHeaderDividersEnabled; } @@ -3724,6 +3728,7 @@ public class ListView extends AbsListView { * * @see #setFooterDividersEnabled(boolean) */ + @InspectableProperty(name = "footerDividersEnabled") public boolean areFooterDividersEnabled() { return mFooterDividersEnabled; } diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java index d82e56c94d2a..b0c0c12e907a 100644 --- a/core/java/android/widget/PopupMenu.java +++ b/core/java/android/widget/PopupMenu.java @@ -259,6 +259,19 @@ public class PopupMenu { } /** + * Sets whether the popup menu's adapter is forced to show icons in the + * menu item views. + * <p> + * Changes take effect on the next call to show(). + * + * @param forceShowIcon {@code true} to force icons to be shown, or + * {@code false} for icons to be optionally shown + */ + public void setForceShowIcon(boolean forceShowIcon) { + mPopup.setForceShowIcon(forceShowIcon); + } + + /** * Interface responsible for receiving menu item click events if the items * themselves do not have individual item click listeners. */ diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index ed6f0d6bcba3..705a371e483e 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -273,7 +273,7 @@ public class PopupWindow { private int mAnchorXoff; private int mAnchorYoff; private int mAnchoredGravity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private boolean mOverlapAnchor; private boolean mPopupViewInitialLayoutDirectionInherited; diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 1fc72f5ea032..3519afd32662 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -58,6 +58,7 @@ import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.animation.Transformation; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -556,6 +557,7 @@ public class ProgressBar extends View { * * @return true if the progress bar is in indeterminate mode */ + @InspectableProperty @ViewDebug.ExportedProperty(category = "progress") public synchronized boolean isIndeterminate() { return mIndeterminate; @@ -610,6 +612,7 @@ public class ProgressBar extends View { * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable) * @see #setIndeterminate(boolean) */ + @InspectableProperty public Drawable getIndeterminateDrawable() { return mIndeterminateDrawable; } @@ -677,6 +680,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_indeterminateTint * @see #setIndeterminateTintList(ColorStateList) */ + @InspectableProperty(name = "indeterminateTint") @Nullable public ColorStateList getIndeterminateTintList() { return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintList : null; @@ -712,6 +716,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode * @see #setIndeterminateTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getIndeterminateTintMode() { return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintMode : null; @@ -768,6 +773,7 @@ public class ProgressBar extends View { * @see #setProgressDrawable(android.graphics.drawable.Drawable) * @see #setIndeterminate(boolean) */ + @InspectableProperty public Drawable getProgressDrawable() { return mProgressDrawable; } @@ -821,6 +827,7 @@ public class ProgressBar extends View { /** * @hide */ + @InspectableProperty public boolean getMirrorForRtl() { return mMirrorForRtl; } @@ -951,6 +958,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_progressTint * @see #setProgressTintList(ColorStateList) */ + @InspectableProperty(name = "progressTint") @Nullable public ColorStateList getProgressTintList() { return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintList : null; @@ -988,6 +996,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_progressTintMode * @see #setProgressTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getProgressTintMode() { return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintMode : null; @@ -1033,6 +1042,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint * @see #setProgressBackgroundTintList(ColorStateList) */ + @InspectableProperty(name = "progressBackgroundTint") @Nullable public ColorStateList getProgressBackgroundTintList() { return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintList : null; @@ -1067,6 +1077,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode * @see #setProgressBackgroundTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getProgressBackgroundTintMode() { return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintMode : null; @@ -1112,6 +1123,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint * @see #setSecondaryProgressTintList(ColorStateList) */ + @InspectableProperty(name = "secondaryProgressTint") @Nullable public ColorStateList getSecondaryProgressTintList() { return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintList : null; @@ -1150,6 +1162,7 @@ public class ProgressBar extends View { * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode * @see #setSecondaryProgressTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getSecondaryProgressTintMode() { return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintMode : null; @@ -1477,6 +1490,7 @@ public class ProgressBar extends View { * @see #getMax() */ @ViewDebug.ExportedProperty(category = "progress") + @InspectableProperty public synchronized int getProgress() { return mIndeterminate ? 0 : mProgress; } @@ -1494,6 +1508,7 @@ public class ProgressBar extends View { * @see #getMax() */ @ViewDebug.ExportedProperty(category = "progress") + @InspectableProperty public synchronized int getSecondaryProgress() { return mIndeterminate ? 0 : mSecondaryProgress; } @@ -1508,6 +1523,7 @@ public class ProgressBar extends View { * @see #getSecondaryProgress() */ @ViewDebug.ExportedProperty(category = "progress") + @InspectableProperty public synchronized int getMin() { return mMin; } @@ -1522,6 +1538,7 @@ public class ProgressBar extends View { * @see #getSecondaryProgress() */ @ViewDebug.ExportedProperty(category = "progress") + @InspectableProperty public synchronized int getMax() { return mMax; } @@ -1687,6 +1704,7 @@ public class ProgressBar extends View { * * @return the {@link Interpolator} associated to this animation */ + @InspectableProperty public Interpolator getInterpolator() { return mInterpolator; } diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java index d343d499a712..9f9fdee46fdf 100644 --- a/core/java/android/widget/RatingBar.java +++ b/core/java/android/widget/RatingBar.java @@ -23,6 +23,7 @@ import android.graphics.drawable.shapes.RectShape; import android.graphics.drawable.shapes.Shape; import android.util.AttributeSet; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -164,6 +165,7 @@ public class RatingBar extends AbsSeekBar { * * @attr ref android.R.styleable#RatingBar_isIndicator */ + @InspectableProperty(name = "isIndicator") public boolean isIndicator() { return !mIsUserSeekable; } @@ -190,6 +192,7 @@ public class RatingBar extends AbsSeekBar { * Returns the number of stars shown. * @return The number of stars shown. */ + @InspectableProperty public int getNumStars() { return mNumStars; } @@ -208,6 +211,7 @@ public class RatingBar extends AbsSeekBar { * * @return The current rating. */ + @InspectableProperty public float getRating() { return getProgress() / getProgressPerStar(); } @@ -234,6 +238,7 @@ public class RatingBar extends AbsSeekBar { * * @return The step size. */ + @InspectableProperty public float getStepSize() { return (float) getNumStars() / getMax(); } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 506d615fc077..556bfd19f942 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -34,6 +34,7 @@ import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.accessibility.AccessibilityEvent; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; @@ -289,6 +290,16 @@ public class RelativeLayout extends ViewGroup { } /** + * Get the id of the View to be ignored by gravity + * + * @attr ref android.R.styleable#RelativeLayout_ignoreGravity + */ + @InspectableProperty + public int getIgnoreGravity() { + return mIgnoreGravity; + } + + /** * Describes how the child views are positioned. * * @return the gravity. @@ -298,6 +309,7 @@ public class RelativeLayout extends ViewGroup { * * @attr ref android.R.styleable#RelativeLayout_gravity */ + @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY) public int getGravity() { return mGravity; } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 2dec4e87e662..8514b85cec00 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -206,13 +206,13 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public ApplicationInfo mApplication; /** * The resource ID of the layout file. (Added to the parcel) */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private final int mLayoutId; /** @@ -224,13 +224,13 @@ public class RemoteViews implements Parcelable, Filter { * An array of actions to perform on the view tree once it has been * inflated */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private ArrayList<Action> mActions; /** * Maps bitmaps to unique indicies to avoid Bitmap duplication. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private BitmapCache mBitmapCache; /** @@ -252,7 +252,7 @@ public class RemoteViews implements Parcelable, Filter { * RemoteViews. */ private RemoteViews mLandscape = null; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private RemoteViews mPortrait = null; @ApplyFlags @@ -430,7 +430,7 @@ public class RemoteViews implements Parcelable, Filter { // Do nothing } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int mergeBehavior() { return MERGE_REPLACE; } @@ -466,7 +466,7 @@ public class RemoteViews implements Parcelable, Filter { // Nothing to visit by default } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) int viewId; } @@ -499,7 +499,7 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void mergeRemoteViews(RemoteViews newRv) { if (newRv == null) return; // We first copy the new RemoteViews, as the process of merging modifies the way the actions @@ -690,7 +690,7 @@ public class RemoteViews implements Parcelable, Filter { return SET_PENDING_INTENT_TEMPLATE_TAG; } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) PendingIntent pendingIntentTemplate; } @@ -1138,7 +1138,7 @@ public class RemoteViews implements Parcelable, Filter { private static class BitmapCache { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) ArrayList<Bitmap> mBitmaps; int mBitmapMemory = -1; @@ -1190,9 +1190,9 @@ public class RemoteViews implements Parcelable, Filter { private class BitmapReflectionAction extends Action { int bitmapId; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) Bitmap bitmap; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) String methodName; BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) { @@ -1258,10 +1258,10 @@ public class RemoteViews implements Parcelable, Filter { static final int COLOR_STATE_LIST = 15; static final int ICON = 16; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) String methodName; int type; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) Object value; ReflectionAction(int viewId, String methodName, int type, Object value) { @@ -1554,7 +1554,7 @@ public class RemoteViews implements Parcelable, Filter { * ViewGroup methods that are related to adding Views. */ private class ViewGroupActionAdd extends Action { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private RemoteViews mNestedViews; private int mIndex; @@ -2469,7 +2469,7 @@ public class RemoteViews implements Parcelable, Filter { * Returns an estimate of the bitmap heap memory usage for this RemoteViews. */ /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public int estimateMemoryUsage() { return mBitmapCache.getBitmapMemory(); } @@ -2517,7 +2517,7 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void addView(int viewId, RemoteViews nestedView, int index) { addAction(new ViewGroupActionAdd(viewId, nestedView, index)); } @@ -2992,8 +2992,9 @@ public class RemoteViews implements Parcelable, Filter { * See {@link Adapter#getViewTypeCount()}. * * @hide + * @deprecated this appears to have no users outside of UnsupportedAppUsage? */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) { addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount)); } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 4658d7353355..fc4e9ec3caad 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -45,6 +45,7 @@ import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AnimationUtils; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -324,6 +325,7 @@ public class ScrollView extends FrameLayout { * * @attr ref android.R.styleable#ScrollView_fillViewport */ + @InspectableProperty public boolean isFillViewport() { return mFillViewport; } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 10e1dfb30a5a..af3b8c0afe08 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -62,6 +62,7 @@ import android.view.ViewConfiguration; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.view.inspector.InspectableProperty; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.TextView.OnEditorActionListener; @@ -563,6 +564,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { * * @return the query string */ + @InspectableProperty(hasAttributeId = false) public CharSequence getQuery() { return mSearchSrcTextView.getText(); } @@ -620,6 +622,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { * @return the displayed query hint text, or {@code null} if none set * @attr ref android.R.styleable#SearchView_queryHint */ + @InspectableProperty @Nullable public CharSequence getQueryHint() { final CharSequence hint; @@ -656,13 +659,25 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { * Returns the default iconified state of the search field. * @return * + * @deprecated use {@link #isIconifiedByDefault()} * @attr ref android.R.styleable#SearchView_iconifiedByDefault */ + @Deprecated public boolean isIconfiedByDefault() { return mIconifiedByDefault; } /** + * Returns the default iconified state of the search field. + * + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + */ + @InspectableProperty + public boolean isIconifiedByDefault() { + return mIconifiedByDefault; + } + + /** * Iconifies or expands the SearchView. Any query text is cleared when iconified. This is * a temporary state and does not override the default iconified state set by * {@link #setIconifiedByDefault(boolean)}. If the default state is iconified, then @@ -686,6 +701,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { * @return true if the SearchView is currently iconified, false if the search field is * fully visible. */ + @InspectableProperty(hasAttributeId = false) public boolean isIconified() { return mIconified; } @@ -780,6 +796,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { * * @attr ref android.R.styleable#SearchView_maxWidth */ + @InspectableProperty public int getMaxWidth() { return mMaxWidth; } diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 1705ba8c38e8..fb56d9739435 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -45,6 +45,7 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import android.widget.PopupWindow.OnDismissListener; import com.android.internal.R; @@ -360,6 +361,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { * * @attr ref android.R.styleable#Spinner_popupBackground */ + @InspectableProperty public Drawable getPopupBackground() { return mPopup.getBackground(); } @@ -392,6 +394,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { * * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset */ + @InspectableProperty public int getDropDownVerticalOffset() { return mPopup.getVerticalOffset(); } @@ -416,6 +419,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { * * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset */ + @InspectableProperty public int getDropDownHorizontalOffset() { return mPopup.getHorizontalOffset(); } @@ -452,6 +456,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { * * @attr ref android.R.styleable#Spinner_dropDownWidth */ + @InspectableProperty public int getDropDownWidth() { return mDropDownWidth; } @@ -491,6 +496,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { * * @return A {@link android.view.Gravity Gravity} value */ + @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY) public int getGravity() { return mGravity; } @@ -828,6 +834,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { /** * @return The prompt to display when the dialog is shown */ + @InspectableProperty public CharSequence getPrompt() { return mPopup.getHintText(); } diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index 79dc6708f9c3..af4f0202fd6a 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -52,6 +52,7 @@ import android.view.ViewConfiguration; import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -444,6 +445,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_switchPadding */ + @InspectableProperty public int getSwitchPadding() { return mSwitchPadding; } @@ -469,6 +471,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_switchMinWidth */ + @InspectableProperty public int getSwitchMinWidth() { return mSwitchMinWidth; } @@ -492,6 +495,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_thumbTextPadding */ + @InspectableProperty public int getThumbTextPadding() { return mThumbTextPadding; } @@ -532,6 +536,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_track */ + @InspectableProperty(name = "track") public Drawable getTrackDrawable() { return mTrackDrawable; } @@ -562,6 +567,7 @@ public class Switch extends CompoundButton { * @attr ref android.R.styleable#Switch_trackTint * @see #setTrackTintList(ColorStateList) */ + @InspectableProperty(name = "trackTint") @Nullable public ColorStateList getTrackTintList() { return mTrackTintList; @@ -591,6 +597,7 @@ public class Switch extends CompoundButton { * @attr ref android.R.styleable#Switch_trackTintMode * @see #setTrackTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getTrackTintMode() { return mTrackTintMode; @@ -655,6 +662,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_thumb */ + @InspectableProperty(name = "thumb") public Drawable getThumbDrawable() { return mThumbDrawable; } @@ -685,6 +693,7 @@ public class Switch extends CompoundButton { * @attr ref android.R.styleable#Switch_thumbTint * @see #setThumbTintList(ColorStateList) */ + @InspectableProperty(name = "thumbTint") @Nullable public ColorStateList getThumbTintList() { return mThumbTintList; @@ -714,6 +723,7 @@ public class Switch extends CompoundButton { * @attr ref android.R.styleable#Switch_thumbTintMode * @see #setThumbTintMode(PorterDuff.Mode) */ + @InspectableProperty @Nullable public PorterDuff.Mode getThumbTintMode() { return mThumbTintMode; @@ -758,6 +768,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_splitTrack */ + @InspectableProperty public boolean getSplitTrack() { return mSplitTrack; } @@ -767,6 +778,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_textOn */ + @InspectableProperty public CharSequence getTextOn() { return mTextOn; } @@ -786,6 +798,7 @@ public class Switch extends CompoundButton { * * @attr ref android.R.styleable#Switch_textOff */ + @InspectableProperty public CharSequence getTextOff() { return mTextOff; } @@ -817,6 +830,7 @@ public class Switch extends CompoundButton { * @return whether the on/off text should be displayed * @attr ref android.R.styleable#Switch_showText */ + @InspectableProperty public boolean getShowText() { return mShowText; } diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java index 4865808b3531..7f462cb3289b 100644 --- a/core/java/android/widget/TextClock.java +++ b/core/java/android/widget/TextClock.java @@ -39,6 +39,7 @@ import android.text.format.DateFormat; import android.util.AttributeSet; import android.view.RemotableViewMethod; import android.view.ViewHierarchyEncoder; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -285,6 +286,7 @@ public class TextClock extends TextView { * @see #setFormat12Hour(CharSequence) * @see #is24HourModeEnabled() */ + @InspectableProperty @ExportedProperty public CharSequence getFormat12Hour() { return mFormat12; @@ -344,6 +346,7 @@ public class TextClock extends TextView { * @see #setFormat24Hour(CharSequence) * @see #is24HourModeEnabled() */ + @InspectableProperty @ExportedProperty public CharSequence getFormat24Hour() { return mFormat24; @@ -435,6 +438,7 @@ public class TextClock extends TextView { * @see #setFormat24Hour(CharSequence) * @see #getFormat24Hour() */ + @InspectableProperty(hasAttributeId = false) public boolean is24HourModeEnabled() { if (mShowCurrentUserTime) { return DateFormat.is24HourFormat(getContext(), ActivityManager.getCurrentUser()); @@ -453,6 +457,7 @@ public class TextClock extends TextView { * @see java.util.TimeZone#getAvailableIDs() * @see #setTimeZone(String) */ + @InspectableProperty public String getTimeZone() { return mTimeZone; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8029cf0eb50e..d790c0cab886 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -172,6 +172,9 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; 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.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationContext; import android.view.textclassifier.TextClassificationManager; @@ -1889,6 +1892,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int) */ + @InspectableProperty(enumMapping = { + @EnumMap(name = "none", value = AUTO_SIZE_TEXT_TYPE_NONE), + @EnumMap(name = "uniform", value = AUTO_SIZE_TEXT_TYPE_UNIFORM) + }) @AutoSizeTextType public int getAutoSizeTextType() { return mAutoSizeTextType; @@ -1901,6 +1908,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) */ + @InspectableProperty public int getAutoSizeStepGranularity() { return Math.round(mAutoSizeStepGranularityInPx); } @@ -1914,6 +1922,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int) */ + @InspectableProperty public int getAutoSizeMinTextSize() { return Math.round(mAutoSizeMinTextSizeInPx); } @@ -1927,6 +1936,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int) */ + @InspectableProperty public int getAutoSizeMaxTextSize() { return Math.round(mAutoSizeMaxTextSizeInPx); } @@ -2271,6 +2281,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_text */ @ViewDebug.CapturedViewProperty + @InspectableProperty public CharSequence getText() { return mText; } @@ -2308,6 +2319,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * contain additional first-or last-line padding. * @return The height of one standard line in pixels. */ + @InspectableProperty public int getLineHeight() { return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd); } @@ -3231,6 +3243,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_drawablePadding */ + @InspectableProperty(name = "drawablePadding") public int getCompoundDrawablePadding() { final Drawables dr = mDrawables; return dr != null ? dr.mDrawablePadding : 0; @@ -3267,6 +3280,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_drawableTint * @see #setCompoundDrawableTintList(ColorStateList) */ + @InspectableProperty(name = "drawableTint") public ColorStateList getCompoundDrawableTintList() { return mDrawables != null ? mDrawables.mTintList : null; } @@ -3301,6 +3315,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_drawableTintMode * @see #setCompoundDrawableTintMode(PorterDuff.Mode) */ + @InspectableProperty(name = "drawableTintMode") public PorterDuff.Mode getCompoundDrawableTintMode() { return mDrawables != null ? mDrawables.mTintMode : null; } @@ -3481,6 +3496,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setFirstBaselineToTopHeight(int) * @attr ref android.R.styleable#TextView_firstBaselineToTopHeight */ + @InspectableProperty public int getFirstBaselineToTopHeight() { return getPaddingTop() - getPaint().getFontMetricsInt().top; } @@ -3491,17 +3507,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setLastBaselineToBottomHeight(int) * @attr ref android.R.styleable#TextView_lastBaselineToBottomHeight */ + @InspectableProperty public int getLastBaselineToBottomHeight() { return getPaddingBottom() + getPaint().getFontMetricsInt().bottom; } /** - * Gets the autolink mask of the text. See {@link - * android.text.util.Linkify#ALL Linkify.ALL} and peers for - * possible values. + * Gets the autolink mask of the text. + * + * See {@link Linkify#ALL} and peers for possible values. * * @attr ref android.R.styleable#TextView_autoLink */ + @InspectableProperty(name = "autoLink", flagMapping = { + @FlagMap(name = "web", target = Linkify.WEB_URLS), + @FlagMap(name = "email", target = Linkify.EMAIL_ADDRESSES), + @FlagMap(name = "phone", target = Linkify.PHONE_NUMBERS), + @FlagMap(name = "map", target = Linkify.MAP_ADDRESSES) + }) public final int getAutoLinkMask() { return mAutoLinkMask; } @@ -4150,6 +4173,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * @return the size (in pixels) of the default text size in this TextView. */ + @InspectableProperty @ViewDebug.ExportedProperty(category = "text") public float getTextSize() { return mTextPaint.getTextSize(); @@ -4243,6 +4267,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * This will usually be 1.0. * @return The horizontal scale factor. */ + @InspectableProperty public float getTextScaleX() { return mTextPaint.getTextScaleX(); } @@ -4303,6 +4328,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_typeface * @attr ref android.R.styleable#TextView_textStyle */ + @InspectableProperty public Typeface getTypeface() { return mTextPaint.getTypeface(); } @@ -4363,6 +4389,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_fallbackLineSpacing */ + @InspectableProperty public boolean isFallbackLineSpacing() { return mUseFallbackLineSpacing; } @@ -4376,6 +4403,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setElegantTextHeight(boolean) * @see Paint#setElegantTextHeight(boolean) */ + @InspectableProperty public boolean isElegantTextHeight() { return mTextPaint.isElegantTextHeight(); } @@ -4388,6 +4416,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setLetterSpacing(float) * @see Paint#setLetterSpacing */ + @InspectableProperty public float getLetterSpacing() { return mTextPaint.getLetterSpacing(); } @@ -4426,6 +4455,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setFontFeatureSettings(String) * @see Paint#setFontFeatureSettings(String) Paint.setFontFeatureSettings(String) */ + @InspectableProperty @Nullable public String getFontFeatureSettings() { return mTextPaint.getFontFeatureSettings(); @@ -4477,6 +4507,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_breakStrategy * @see #setBreakStrategy(int) */ + @InspectableProperty(enumMapping = { + @EnumMap(name = "simple", value = Layout.BREAK_STRATEGY_SIMPLE), + @EnumMap(name = "high_quality", value = Layout.BREAK_STRATEGY_HIGH_QUALITY), + @EnumMap(name = "balanced", value = Layout.BREAK_STRATEGY_BALANCED) + }) @Layout.BreakStrategy public int getBreakStrategy() { return mBreakStrategy; @@ -4523,6 +4558,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_hyphenationFrequency * @see #setHyphenationFrequency(int) */ + @InspectableProperty(enumMapping = { + @EnumMap(name = "none", value = Layout.HYPHENATION_FREQUENCY_NONE), + @EnumMap(name = "normal", value = Layout.HYPHENATION_FREQUENCY_NORMAL), + @EnumMap(name = "full", value = Layout.HYPHENATION_FREQUENCY_FULL) + }) @Layout.HyphenationFrequency public int getHyphenationFrequency() { return mHyphenationFrequency; @@ -4580,6 +4620,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @see #setJustificationMode(int) */ + @InspectableProperty(enumMapping = { + @EnumMap(name = "none", value = Layout.JUSTIFICATION_MODE_NONE), + @EnumMap(name = "inter_word", value = Layout.JUSTIFICATION_MODE_INTER_WORD) + }) public @Layout.JustificationMode int getJustificationMode() { return mJustificationMode; } @@ -4720,6 +4764,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColor */ + @InspectableProperty(name = "textColor") public final ColorStateList getTextColors() { return mTextColor; } @@ -4754,6 +4799,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColorHighlight */ + @InspectableProperty(name = "textColorHighlight") @ColorInt public int getHighlightColor() { return mHighlightColor; @@ -4819,6 +4865,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_shadowRadius */ + @InspectableProperty public float getShadowRadius() { return mShadowRadius; } @@ -4830,6 +4877,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_shadowDx */ + @InspectableProperty public float getShadowDx() { return mShadowDx; } @@ -4842,6 +4890,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_shadowDy */ + @InspectableProperty public float getShadowDy() { return mShadowDy; } @@ -4854,6 +4903,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_shadowColor */ + @InspectableProperty @ColorInt public int getShadowColor() { return mShadowColor; @@ -4901,6 +4951,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_linksClickable */ + @InspectableProperty public final boolean getLinksClickable() { return mLinksClickable; } @@ -4961,6 +5012,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColorHint */ + @InspectableProperty(name = "textColorHint") public final ColorStateList getHintTextColors() { return mHintTextColor; } @@ -5013,6 +5065,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColorLink */ + @InspectableProperty(name = "textColorLink") public final ColorStateList getLinkTextColors() { return mLinkTextColor; } @@ -5062,6 +5115,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see android.view.Gravity * @attr ref android.R.styleable#TextView_gravity */ + @InspectableProperty(valueType = InspectableProperty.ValueType.GRAVITY) public int getGravity() { return mGravity; } @@ -5118,6 +5172,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @attr ref android.R.styleable#TextView_scrollHorizontally * @see #setHorizontallyScrolling(boolean) */ + @InspectableProperty(name = "scrollHorizontally") public final boolean isHorizontallyScrollable() { return mHorizontallyScrolling; } @@ -5170,6 +5225,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_minLines */ + @InspectableProperty public int getMinLines() { return mMinMode == LINES ? mMinimum : -1; } @@ -5252,6 +5308,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_maxLines */ + @InspectableProperty public int getMaxLines() { return mMaxMode == LINES ? mMaximum : -1; } @@ -5291,6 +5348,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_maxHeight */ + @InspectableProperty public int getMaxHeight() { return mMaxMode == PIXELS ? mMaximum : -1; } @@ -5375,6 +5433,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_minEms */ + @InspectableProperty public int getMinEms() { return mMinWidthMode == EMS ? mMinWidth : -1; } @@ -5418,6 +5477,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_minWidth */ + @InspectableProperty public int getMinWidth() { return mMinWidthMode == PIXELS ? mMinWidth : -1; } @@ -5457,6 +5517,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_maxEms */ + @InspectableProperty public int getMaxEms() { return mMaxWidthMode == EMS ? mMaxWidth : -1; } @@ -5496,6 +5557,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_maxWidth */ + @InspectableProperty public int getMaxWidth() { return mMaxWidthMode == PIXELS ? mMaxWidth : -1; } @@ -5579,6 +5641,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_lineSpacingMultiplier */ + @InspectableProperty public float getLineSpacingMultiplier() { return mSpacingMult; } @@ -5593,6 +5656,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_lineSpacingExtra */ + @InspectableProperty public float getLineSpacingExtra() { return mSpacingAdd; } @@ -5877,6 +5941,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @see #setFreezesText */ + @InspectableProperty public boolean getFreezesText() { return mFreezesText; } @@ -6340,6 +6405,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_hint */ + @InspectableProperty @ViewDebug.CapturedViewProperty public CharSequence getHint() { return mHint; @@ -6351,6 +6417,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_singleLine */ + @InspectableProperty public boolean isSingleLine() { return mSingleLine; } @@ -6592,6 +6659,147 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setInputType(int) * @see android.text.InputType */ + @InspectableProperty(flagMapping = { + @FlagMap(name = "none", mask = 0xffffffff, target = InputType.TYPE_NULL), + @FlagMap( + name = "text", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL), + @FlagMap( + name = "textUri", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI), + @FlagMap( + name = "textEmailAddress", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS), + @FlagMap( + name = "textEmailSubject", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT), + @FlagMap( + name = "textShortMessage", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE), + @FlagMap( + name = "textLongMessage", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE), + @FlagMap( + name = "textPersonName", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PERSON_NAME), + @FlagMap( + name = "textPostalAddress", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS), + @FlagMap( + name = "textPassword", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD), + @FlagMap( + name = "textVisiblePassword", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD), + @FlagMap( + name = "textWebEditText", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT), + @FlagMap( + name = "textFilter", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER), + @FlagMap( + name = "textPhonetic", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC), + @FlagMap( + name = "textWebEmailAddress", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS), + @FlagMap( + name = "textWebPassword", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD), + @FlagMap( + name = "number", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL), + @FlagMap( + name = "numberPassword", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_NUMBER + | InputType.TYPE_NUMBER_VARIATION_PASSWORD), + @FlagMap( + name = "phone", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_PHONE), + @FlagMap( + name = "datetime", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_DATETIME + | InputType.TYPE_DATETIME_VARIATION_NORMAL), + @FlagMap( + name = "date", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_DATETIME + | InputType.TYPE_DATETIME_VARIATION_DATE), + @FlagMap( + name = "time", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION, + target = InputType.TYPE_CLASS_DATETIME + | InputType.TYPE_DATETIME_VARIATION_TIME), + @FlagMap( + name = "textCapCharacters", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS), + @FlagMap( + name = "textCapWords", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_WORDS), + @FlagMap( + name = "textCapSentences", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES), + @FlagMap( + name = "textAutoCorrect", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT), + @FlagMap( + name = "textAutoComplete", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE), + @FlagMap( + name = "textMultiLine", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE), + @FlagMap( + name = "textImeMultiLine", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE), + @FlagMap( + name = "textNoSuggestions", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS), + @FlagMap( + name = "numberSigned", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED), + @FlagMap( + name = "numberDecimal", + mask = InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_FLAGS, + target = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL), + }) public int getInputType() { return mEditor == null ? EditorInfo.TYPE_NULL : mEditor.mInputType; } @@ -6614,8 +6822,55 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Get the type of the Input Method Editor (IME). * @return the type of the IME * @see #setImeOptions(int) - * @see android.view.inputmethod.EditorInfo - */ + * @see EditorInfo + */ + @InspectableProperty(flagMapping = { + @FlagMap(name = "normal", mask = 0xffffffff, target = EditorInfo.IME_NULL), + @FlagMap( + name = "actionUnspecified", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_UNSPECIFIED), + @FlagMap( + name = "actionNone", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_NONE), + @FlagMap( + name = "actionGo", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_GO), + @FlagMap( + name = "actionSearch", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_SEARCH), + @FlagMap( + name = "actionSend", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_SEND), + @FlagMap( + name = "actionNext", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_NEXT), + @FlagMap( + name = "actionDone", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_DONE), + @FlagMap( + name = "actionPrevious", + mask = EditorInfo.IME_MASK_ACTION, + target = EditorInfo.IME_ACTION_PREVIOUS), + @FlagMap(name = "flagForceAscii", target = EditorInfo.IME_FLAG_FORCE_ASCII), + @FlagMap(name = "flagNavigateNext", target = EditorInfo.IME_FLAG_NAVIGATE_NEXT), + @FlagMap(name = "flagNavigatePrevious", target = EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS), + @FlagMap( + name = "flagNoAccessoryAction", + target = EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION), + @FlagMap(name = "flagNoEnterAction", target = EditorInfo.IME_FLAG_NO_ENTER_ACTION), + @FlagMap(name = "flagNoExtractUi", target = EditorInfo.IME_FLAG_NO_EXTRACT_UI), + @FlagMap(name = "flagNoFullscreen", target = EditorInfo.IME_FLAG_NO_FULLSCREEN), + @FlagMap( + name = "flagNoPersonalizedLearning", + target = EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING), + }) public int getImeOptions() { return mEditor != null && mEditor.mInputContentType != null ? mEditor.mInputContentType.imeOptions : EditorInfo.IME_NULL; @@ -6644,6 +6899,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setImeActionLabel * @see android.view.inputmethod.EditorInfo */ + @InspectableProperty public CharSequence getImeActionLabel() { return mEditor != null && mEditor.mInputContentType != null ? mEditor.mInputContentType.imeActionLabel : null; @@ -6655,6 +6911,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setImeActionLabel * @see android.view.inputmethod.EditorInfo */ + @InspectableProperty public int getImeActionId() { return mEditor != null && mEditor.mInputContentType != null ? mEditor.mInputContentType.imeActionId : 0; @@ -6777,6 +7034,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setPrivateImeOptions(String) * @see EditorInfo#privateImeOptions */ + @InspectableProperty public String getPrivateImeOptions() { return mEditor != null && mEditor.mInputContentType != null ? mEditor.mInputContentType.privateImeOptions : null; @@ -7385,6 +7643,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textIsSelectable */ + @InspectableProperty(name = "textIsSelectable") public boolean isTextSelectable() { return mEditor == null ? false : mEditor.mTextIsSelectable; } @@ -8924,6 +9183,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_includeFontPadding */ + @InspectableProperty public boolean getIncludeFontPadding() { return mIncludePad; } @@ -9870,6 +10130,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @see #setAllCaps(boolean) * @see #setTransformationMethod(TransformationMethod) */ + @InspectableProperty(name = "textAllCaps") public boolean isAllCaps() { final TransformationMethod method = getTransformationMethod(); return method != null && method instanceof AllCapsTransformationMethod; @@ -9979,6 +10240,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_marqueeRepeatLimit */ + @InspectableProperty public int getMarqueeRepeatLimit() { return mMarqueeRepeatLimit; } @@ -9987,6 +10249,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Returns where, if anywhere, words that are longer than the view * is wide should be ellipsized. */ + @InspectableProperty @ViewDebug.ExportedProperty public TextUtils.TruncateAt getEllipsize() { return mEllipsize; @@ -10038,6 +10301,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_cursorVisible */ + @InspectableProperty public boolean isCursorVisible() { // true is the default value return mEditor == null ? true : mEditor.mCursorVisible; diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index 6a5c8cc9fac2..b239ce638e68 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -35,6 +35,7 @@ import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; +import android.view.inspector.InspectableProperty; import com.android.internal.R; @@ -165,6 +166,10 @@ public class TimePicker extends FrameLayout { */ @TimePickerMode @TestApi + @InspectableProperty(name = "timePickerMode", enumMapping = { + @InspectableProperty.EnumMap(name = "clock", value = MODE_CLOCK), + @InspectableProperty.EnumMap(name = "spinner", value = MODE_SPINNER) + }) public int getMode() { return mMode; } @@ -185,6 +190,7 @@ public class TimePicker extends FrameLayout { * @return the currently selected hour, in the range (0-23) * @see #setHour(int) */ + @InspectableProperty(hasAttributeId = false) public int getHour() { return mDelegate.getHour(); } @@ -205,6 +211,7 @@ public class TimePicker extends FrameLayout { * @return the currently selected minute, in the range (0-59) * @see #setMinute(int) */ + @InspectableProperty(hasAttributeId = false) public int getMinute() { return mDelegate.getMinute(); } @@ -272,6 +279,7 @@ public class TimePicker extends FrameLayout { * {@code false} otherwise} * @see #setIs24HourView(Boolean) */ + @InspectableProperty(hasAttributeId = false, name = "24Hour") public boolean is24HourView() { return mDelegate.is24Hour(); } diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index c256d57a6af6..eef40e1f6e2e 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -341,10 +341,10 @@ public class Toast { // the proper ordering of these system-wide. // ======================================================================================= - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static INotificationManager sService; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) static private INotificationManager getService() { if (sService != null) { return sService; diff --git a/core/java/android/widget/ToggleButton.java b/core/java/android/widget/ToggleButton.java index 6a8449e73b7a..bba6da6b7b4c 100644 --- a/core/java/android/widget/ToggleButton.java +++ b/core/java/android/widget/ToggleButton.java @@ -21,6 +21,7 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; +import android.view.inspector.InspectableProperty; /** * Displays checked/unchecked states as a button @@ -87,6 +88,7 @@ public class ToggleButton extends CompoundButton { * * @return The text. */ + @InspectableProperty public CharSequence getTextOn() { return mTextOn; } @@ -105,6 +107,7 @@ public class ToggleButton extends CompoundButton { * * @return The text. */ + @InspectableProperty public CharSequence getTextOff() { return mTextOff; } @@ -118,6 +121,16 @@ public class ToggleButton extends CompoundButton { mTextOff = textOff; } + /** + * Returns the alpha value of the button when it is disabled + * + * @return the alpha value, 0.0-1.0 + */ + @InspectableProperty + public float getDisabledAlpha() { + return mDisabledAlpha; + } + @Override protected void onFinishInflate() { super.onFinishInflate(); diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index adb7f2f89320..a33c47d86673 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -45,6 +45,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.inspector.InspectableProperty; import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; @@ -383,6 +384,7 @@ public class Toolbar extends ViewGroup { * 0 if menus are inflated against the toolbar theme * @see #setPopupTheme(int) */ + @InspectableProperty public int getPopupTheme() { return mPopupTheme; } @@ -414,6 +416,7 @@ public class Toolbar extends ViewGroup { * @see #setTitleMarginStart(int) * @attr ref android.R.styleable#Toolbar_titleMarginStart */ + @InspectableProperty public int getTitleMarginStart() { return mTitleMarginStart; } @@ -436,6 +439,7 @@ public class Toolbar extends ViewGroup { * @see #setTitleMarginTop(int) * @attr ref android.R.styleable#Toolbar_titleMarginTop */ + @InspectableProperty public int getTitleMarginTop() { return mTitleMarginTop; } @@ -458,6 +462,7 @@ public class Toolbar extends ViewGroup { * @see #setTitleMarginEnd(int) * @attr ref android.R.styleable#Toolbar_titleMarginEnd */ + @InspectableProperty public int getTitleMarginEnd() { return mTitleMarginEnd; } @@ -480,6 +485,7 @@ public class Toolbar extends ViewGroup { * @see #setTitleMarginBottom(int) * @attr ref android.R.styleable#Toolbar_titleMarginBottom */ + @InspectableProperty public int getTitleMarginBottom() { return mTitleMarginBottom; } @@ -650,6 +656,7 @@ public class Toolbar extends ViewGroup { * @see #setLogo(int) * @see #setLogo(android.graphics.drawable.Drawable) */ + @InspectableProperty public Drawable getLogo() { return mLogoView != null ? mLogoView.getDrawable() : null; } @@ -688,6 +695,7 @@ public class Toolbar extends ViewGroup { * * @return A description of the logo */ + @InspectableProperty public CharSequence getLogoDescription() { return mLogoView != null ? mLogoView.getContentDescription() : null; } @@ -735,6 +743,7 @@ public class Toolbar extends ViewGroup { * * @return The current title. */ + @InspectableProperty public CharSequence getTitle() { return mTitleText; } @@ -791,6 +800,7 @@ public class Toolbar extends ViewGroup { * * @return The current subtitle */ + @InspectableProperty public CharSequence getSubtitle() { return mSubtitleText; } @@ -895,6 +905,7 @@ public class Toolbar extends ViewGroup { * * @attr ref android.R.styleable#Toolbar_navigationContentDescription */ + @InspectableProperty @Nullable public CharSequence getNavigationContentDescription() { return mNavButtonView != null ? mNavButtonView.getContentDescription() : null; @@ -987,6 +998,7 @@ public class Toolbar extends ViewGroup { * * @attr ref android.R.styleable#Toolbar_navigationIcon */ + @InspectableProperty @Nullable public Drawable getNavigationIcon() { return mNavButtonView != null ? mNavButtonView.getDrawable() : null; @@ -1024,6 +1036,7 @@ public class Toolbar extends ViewGroup { * * @attr ref android.R.styleable#Toolbar_collapseContentDescription */ + @InspectableProperty @Nullable public CharSequence getCollapseContentDescription() { return mCollapseButtonView != null ? mCollapseButtonView.getContentDescription() : null; @@ -1069,6 +1082,7 @@ public class Toolbar extends ViewGroup { * * @attr ref android.R.styleable#Toolbar_collapseIcon */ + @InspectableProperty @Nullable public Drawable getCollapseIcon() { return mCollapseButtonView != null ? mCollapseButtonView.getDrawable() : null; @@ -1234,6 +1248,7 @@ public class Toolbar extends ViewGroup { * @see #getContentInsetRight() * @attr ref android.R.styleable#Toolbar_contentInsetStart */ + @InspectableProperty public int getContentInsetStart() { return mContentInsets != null ? mContentInsets.getStart() : 0; } @@ -1254,6 +1269,7 @@ public class Toolbar extends ViewGroup { * @see #getContentInsetRight() * @attr ref android.R.styleable#Toolbar_contentInsetEnd */ + @InspectableProperty public int getContentInsetEnd() { return mContentInsets != null ? mContentInsets.getEnd() : 0; } @@ -1297,6 +1313,7 @@ public class Toolbar extends ViewGroup { * @see #getContentInsetRight() * @attr ref android.R.styleable#Toolbar_contentInsetLeft */ + @InspectableProperty public int getContentInsetLeft() { return mContentInsets != null ? mContentInsets.getLeft() : 0; } @@ -1317,6 +1334,7 @@ public class Toolbar extends ViewGroup { * @see #getContentInsetLeft() * @attr ref android.R.styleable#Toolbar_contentInsetRight */ + @InspectableProperty public int getContentInsetRight() { return mContentInsets != null ? mContentInsets.getRight() : 0; } @@ -1333,6 +1351,7 @@ public class Toolbar extends ViewGroup { * @see #setContentInsetStartWithNavigation(int) * @attr ref android.R.styleable#Toolbar_contentInsetStartWithNavigation */ + @InspectableProperty public int getContentInsetStartWithNavigation() { return mContentInsetStartWithNavigation != RtlSpacingHelper.UNDEFINED ? mContentInsetStartWithNavigation @@ -1376,6 +1395,7 @@ public class Toolbar extends ViewGroup { * @see #setContentInsetEndWithActions(int) * @attr ref android.R.styleable#Toolbar_contentInsetEndWithActions */ + @InspectableProperty public int getContentInsetEndWithActions() { return mContentInsetEndWithActions != RtlSpacingHelper.UNDEFINED ? mContentInsetEndWithActions diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java index 598a40779cd1..80ea363a6ad6 100644 --- a/core/java/android/widget/ViewAnimator.java +++ b/core/java/android/widget/ViewAnimator.java @@ -26,6 +26,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.view.inspector.InspectableProperty; /** * Base class for a {@link FrameLayout} container that will perform animations @@ -265,6 +266,7 @@ public class ViewAnimator extends FrameLayout { * @see #setInAnimation(android.view.animation.Animation) * @see #setInAnimation(android.content.Context, int) */ + @InspectableProperty public Animation getInAnimation() { return mInAnimation; } @@ -289,6 +291,7 @@ public class ViewAnimator extends FrameLayout { * @see #setOutAnimation(android.view.animation.Animation) * @see #setOutAnimation(android.content.Context, int) */ + @InspectableProperty public Animation getOutAnimation() { return mOutAnimation; } @@ -340,6 +343,7 @@ public class ViewAnimator extends FrameLayout { * * @see #setAnimateFirstView(boolean) */ + @InspectableProperty public boolean getAnimateFirstView() { return mAnimateFirstTime; } diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java index 5e72b2eee9ae..414b1369d23e 100644 --- a/core/java/android/widget/ViewFlipper.java +++ b/core/java/android/widget/ViewFlipper.java @@ -25,6 +25,7 @@ import android.content.res.TypedArray; import android.os.Message; import android.util.AttributeSet; import android.util.Log; +import android.view.inspector.InspectableProperty; import android.widget.RemoteViews.RemoteView; /** @@ -134,6 +135,16 @@ public class ViewFlipper extends ViewAnimator { } /** + * Get the delay before flipping to the next view. + * + * @return delay time in milliseconds + */ + @InspectableProperty + public int getFlipInterval() { + return mFlipInterval; + } + + /** * Start a timer to cycle through child views */ public void startFlipping() { @@ -191,6 +202,7 @@ public class ViewFlipper extends ViewAnimator { /** * Returns true if the child views are flipping. */ + @InspectableProperty(hasAttributeId = false) public boolean isFlipping() { return mStarted; } @@ -207,6 +219,7 @@ public class ViewFlipper extends ViewAnimator { * Returns true if this view automatically calls {@link #startFlipping()} * when it becomes attached to a window. */ + @InspectableProperty public boolean isAutoStart() { return mAutoStart; } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index cfe293925058..ee96ae985331 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -16,6 +16,9 @@ package com.android.internal.app; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; import android.app.Activity; import android.app.ActivityManager; import android.app.prediction.AppPredictionContext; @@ -27,6 +30,7 @@ import android.app.prediction.AppTargetId; import android.content.ClipData; import android.content.ClipboardManager; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -46,6 +50,7 @@ import android.database.DataSetObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.Path; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; @@ -93,11 +98,13 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.util.ImageUtils; import com.google.android.collect.Lists; import java.io.File; import java.io.IOException; +import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -174,6 +181,15 @@ public class ChooserActivity extends ResolverActivity { private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT = 3; private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED = 4; + @Retention(SOURCE) + @IntDef({CONTENT_PREVIEW_FILE, CONTENT_PREVIEW_IMAGE, CONTENT_PREVIEW_TEXT}) + private @interface ContentPreviewType { + } + + private static final int CONTENT_PREVIEW_IMAGE = 0; + private static final int CONTENT_PREVIEW_FILE = 1; + private static final int CONTENT_PREVIEW_TEXT = 2; + private final Handler mChooserHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -448,18 +464,35 @@ public class ChooserActivity extends ResolverActivity { return; } - ViewGroup contentPreviewLayout = findViewById(R.id.content_preview); String action = targetIntent.getAction(); if (!(Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action))) { - contentPreviewLayout.setVisibility(View.GONE); return; } - showDefaultContentPreview(contentPreviewLayout, targetIntent); + int previewType = findPreferredContentPreview(targetIntent, getContentResolver()); + displayContentPreview(previewType, targetIntent); + } + + private void displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent) { + switch (previewType) { + case CONTENT_PREVIEW_TEXT: + displayTextContentPreview(targetIntent); + break; + case CONTENT_PREVIEW_IMAGE: + displayImageContentPreview(targetIntent); + break; + case CONTENT_PREVIEW_FILE: + displayFileContentPreview(targetIntent); + break; + default: + Log.e(TAG, "Unexpected content preview type: " + previewType); + } } - private void showDefaultContentPreview(final ViewGroup parentLayout, - final Intent targetIntent) { + private void displayTextContentPreview(Intent targetIntent) { + ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_text_area); + contentPreviewLayout.setVisibility(View.VISIBLE); + CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (sharingText == null) { findViewById(R.id.content_preview_text_layout).setVisibility(View.GONE); @@ -498,6 +531,105 @@ public class ChooserActivity extends ResolverActivity { } } + private void displayImageContentPreview(Intent targetIntent) { + ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_image_area); + contentPreviewLayout.setVisibility(View.VISIBLE); + + String action = targetIntent.getAction(); + if (Intent.ACTION_SEND.equals(action)) { + Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); + loadUriIntoView(R.id.content_preview_image_1_large, uri); + } else { + ContentResolver resolver = getContentResolver(); + + List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + List<Uri> imageUris = new ArrayList<>(); + for (Uri uri : uris) { + if (isImageType(resolver.getType(uri))) { + imageUris.add(uri); + } + } + + if (imageUris.size() == 0) { + Log.i(TAG, "Attempted to display image preview area with zero" + + " available images detected in EXTRA_STREAM list"); + return; + } + + loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0)); + + if (imageUris.size() == 2) { + loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1)); + } else if (imageUris.size() > 2) { + loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1)); + RoundedRectImageView imageView = loadUriIntoView( + R.id.content_preview_image_3_small, imageUris.get(2)); + + if (imageUris.size() > 3) { + imageView.setExtraImageCount(imageUris.size() - 3); + } + } + } + } + + private void displayFileContentPreview(Intent targetIntent) { + // support coming + } + + private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri) { + RoundedRectImageView imageView = findViewById(imageResourceId); + imageView.setVisibility(View.VISIBLE); + Bitmap bmp = loadThumbnail(uri, new Size(200, 200)); + imageView.setImageBitmap(bmp); + + return imageView; + } + + @VisibleForTesting + protected boolean isImageType(String mimeType) { + return mimeType != null && mimeType.startsWith("image/"); + } + + @ContentPreviewType + private int findPreferredContentPreview(Uri uri, ContentResolver resolver) { + if (uri == null) { + return CONTENT_PREVIEW_TEXT; + } + + String mimeType = resolver.getType(uri); + return isImageType(mimeType) ? CONTENT_PREVIEW_IMAGE : CONTENT_PREVIEW_FILE; + } + + /** + * In {@link android.content.Intent#getType}, the app may specify a very general + * mime-type that broadly covers all data being shared, such as {@literal *}/* + * when sending an image and text. We therefore should inspect each item for the + * the preferred type, in order of IMAGE, FILE, TEXT. + */ + @ContentPreviewType + private int findPreferredContentPreview(Intent targetIntent, ContentResolver resolver) { + String action = targetIntent.getAction(); + if (Intent.ACTION_SEND.equals(action)) { + Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); + return findPreferredContentPreview(uri, resolver); + } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { + List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + if (uris == null || uris.isEmpty()) { + return CONTENT_PREVIEW_TEXT; + } + + for (Uri uri : uris) { + if (findPreferredContentPreview(uri, resolver) == CONTENT_PREVIEW_IMAGE) { + return CONTENT_PREVIEW_IMAGE; + } + } + + return CONTENT_PREVIEW_FILE; + } + + return CONTENT_PREVIEW_TEXT; + } + static SharedPreferences getPinnedSharedPrefs(Context context) { // The code below is because in the android:ui process, no one can hear you scream. // The package info in the context isn't initialized in the way it is for normal apps, @@ -1114,7 +1246,8 @@ public class ChooserActivity extends ResolverActivity { } try { - return getContentResolver().loadThumbnail(uri, size, null); + return ImageUtils.decodeSampledBitmapFromStream(getContentResolver(), + uri, size.getWidth(), size.getHeight()); } catch (IOException | NullPointerException ex) { Log.w(TAG, "Error loading preview thumbnail for uri: " + uri.toString(), ex); } @@ -2045,6 +2178,9 @@ public class ChooserActivity extends ResolverActivity { public static class RoundedRectImageView extends ImageView { private int mRadius = 0; private Path mPath = new Path(); + private Paint mOverlayPaint = new Paint(0); + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private String mExtraImageCount = null; public RoundedRectImageView(Context context) { super(context); @@ -2062,6 +2198,14 @@ public class ChooserActivity extends ResolverActivity { int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mRadius = context.getResources().getDimensionPixelSize(R.dimen.chooser_corner_radius); + + mOverlayPaint.setColor(0x99000000); + mOverlayPaint.setStyle(Paint.Style.FILL); + + mTextPaint.setColor(Color.WHITE); + mTextPaint.setTextSize(context.getResources() + .getDimensionPixelSize(R.dimen.chooser_preview_image_font_size)); + mTextPaint.setTextAlign(Paint.Align.CENTER); } private void updatePath(int width, int height) { @@ -2083,12 +2227,24 @@ public class ChooserActivity extends ResolverActivity { updatePath(getWidth(), getHeight()); } + /** + * Display an overlay with extra image count on 3rd image + */ + public void setExtraImageCount(int count) { + if (count > 0) { + this.mExtraImageCount = "+" + count; + } else { + this.mExtraImageCount = null; + } + } + @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); updatePath(width, height); } + @Override protected void onDraw(Canvas canvas) { if (mRadius != 0) { @@ -2096,6 +2252,16 @@ public class ChooserActivity extends ResolverActivity { } super.onDraw(canvas); + + if (mExtraImageCount != null) { + canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mOverlayPaint); + + int xPos = canvas.getWidth() / 2; + int yPos = (int) ((canvas.getHeight() / 2.0f) + - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)); + + canvas.drawText(mExtraImageCount, xPos, yPos, mTextPaint); + } } } } diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java index 5b699791ea77..aa4846f6059e 100644 --- a/core/java/com/android/internal/os/BinderInternal.java +++ b/core/java/com/android/internal/os/BinderInternal.java @@ -96,9 +96,10 @@ public class BinderInternal { * <p>The implementation should never execute a binder call since it is called during a * binder transaction. * + * @param untrustedWorkSourceUid The work source set by the caller. * @return the uid of the process to attribute the binder transaction to. */ - int resolveWorkSourceUid(); + int resolveWorkSourceUid(int untrustedWorkSourceUid); } /** diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java index 0f0eeddf9a47..b3d9ca7670b5 100644 --- a/core/java/com/android/internal/os/LooperStats.java +++ b/core/java/com/android/internal/os/LooperStats.java @@ -126,9 +126,11 @@ public class LooperStats implements Looper.Observer { } DispatchSession session = (DispatchSession) token; - Entry entry = findEntry(msg, /* allowCreateNew= */true); - synchronized (entry) { - entry.exceptionCount++; + Entry entry = findEntry(msg, /* allowCreateNew= */session != DispatchSession.NOT_SAMPLED); + if (entry != null) { + synchronized (entry) { + entry.exceptionCount++; + } } recycleSession(session); diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java index cd80d53a7546..429c6187dfe0 100644 --- a/core/java/com/android/internal/policy/DecorContext.java +++ b/core/java/com/android/internal/policy/DecorContext.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.view.ContextThemeWrapper; import android.view.WindowManager; import android.view.WindowManagerImpl; +import android.view.contentcapture.ContentCaptureManager; import java.lang.ref.WeakReference; @@ -36,6 +37,7 @@ class DecorContext extends ContextThemeWrapper { private PhoneWindow mPhoneWindow; private WindowManager mWindowManager; private Resources mActivityResources; + private ContentCaptureManager mContentCaptureManager; private WeakReference<Context> mActivityContext; @@ -60,6 +62,16 @@ class DecorContext extends ContextThemeWrapper { } return mWindowManager; } + if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) { + if (mContentCaptureManager == null) { + Context activityContext = mActivityContext.get(); + if (activityContext != null) { + mContentCaptureManager = (ContentCaptureManager) activityContext + .getSystemService(name); + } + } + return mContentCaptureManager; + } return super.getSystemService(name); } @@ -79,4 +91,9 @@ class DecorContext extends ContextThemeWrapper { public AssetManager getAssets() { return mActivityResources.getAssets(); } + + @Override + public boolean isContentCaptureSupported() { + return true; + } } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 9df37ada7701..bfb50848df26 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -69,8 +69,9 @@ interface IStatusBarService void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded, in int notificationLocation); void onNotificationDirectReplied(String key); void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount, - boolean generatedByAsssistant); - void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply, boolean generatedByAssistant, in int notificationLocation); + boolean generatedByAsssistant, boolean editBeforeSending); + void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply, + in int notificationLocation, boolean modifiedBeforeSending); void onNotificationSettingsViewed(String key); void setSystemUiVisibility(int displayId, int vis, int mask, String cause); diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 226b8db1540b..397df56a809c 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -690,4 +690,17 @@ public class ArrayUtils { } return result; } + + /** + * Returns the first element from the array for which + * condition {@code predicate} is true, or null if there is no such element + */ + public static @Nullable <T> T find(@Nullable T[] items, + @NonNull java.util.function.Predicate<T> predicate) { + if (isEmpty(items)) return null; + for (final T item : items) { + if (predicate.test(item)) return item; + } + return null; + } } diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java index f91b837410ba..78fdfe422712 100644 --- a/core/java/com/android/internal/util/CollectionUtils.java +++ b/core/java/com/android/internal/util/CollectionUtils.java @@ -335,6 +335,13 @@ public class CollectionUtils { } /** + * @return the first element if not empty/null, null otherwise + */ + public static @Nullable <T> T firstOrNull(@Nullable Collection<T> cur) { + return isEmpty(cur) ? null : cur.iterator().next(); + } + + /** * @return list of single given element if it's not null, empty list otherwise */ public static @NonNull <T> List<T> singletonOrEmpty(@Nullable T item) { diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java index 7d56e9e53b1c..195ae52ce977 100644 --- a/core/java/com/android/internal/util/ImageUtils.java +++ b/core/java/com/android/internal/util/ImageUtils.java @@ -16,14 +16,20 @@ package com.android.internal.util; +import android.content.ContentResolver; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; + +import java.io.IOException; +import java.io.InputStream; /** * Utility class for image analysis and processing. @@ -80,7 +86,7 @@ public class ImageUtils { width = height = COMPACT_BITMAP_SIZE; } - final int size = height*width; + final int size = height * width; ensureBufferSize(size); bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height); for (int i = 0; i < size; i++) { @@ -156,4 +162,55 @@ public class ImageUtils { return result; } + + /** + * @see https://developer.android.com/topic/performance/graphics/load-bitmap + */ + public static int calculateInSampleSize(BitmapFactory.Options options, + int reqWidth, int reqHeight) { + // Raw height and width of image + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((halfHeight / inSampleSize) >= reqHeight + && (halfWidth / inSampleSize) >= reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } + + /** + * Load a bitmap, and attempt to downscale to the required size, to save + * on memory. + * + * @see https://developer.android.com/topic/performance/graphics/load-bitmap + */ + public static Bitmap decodeSampledBitmapFromStream(ContentResolver resolver, + Uri uri, int reqWidth, int reqHeight) throws IOException { + + final BitmapFactory.Options options = new BitmapFactory.Options(); + try (InputStream is = resolver.openInputStream(uri)) { + // First decode with inJustDecodeBounds=true to check dimensions + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + } + + // need to do this twice as the InputStream is consumed in the first call, + // and not all InputStreams support marks + try (InputStream is = resolver.openInputStream(uri)) { + options.inJustDecodeBounds = false; + return BitmapFactory.decodeStream(is, null, options); + } + } } diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 0752efe562a9..cb18ca1fb7fe 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -34,9 +34,9 @@ interface IInputMethodManager { int untrustedDisplayId); // TODO: Use ParceledListSlice instead - List<InputMethodInfo> getInputMethodList(); + List<InputMethodInfo> getInputMethodList(int userId); // TODO: Use ParceledListSlice instead - List<InputMethodInfo> getEnabledInputMethodList(); + List<InputMethodInfo> getEnabledInputMethodList(int userId); List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId, boolean allowsImplicitlySelectedSubtypes); InputMethodSubtype getLastInputMethodSubtype(); diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl index 794238a3826e..664643cc9b4d 100644 --- a/core/java/com/android/internal/view/IInputMethodSession.aidl +++ b/core/java/com/android/internal/view/IInputMethodSession.aidl @@ -48,4 +48,6 @@ oneway interface IInputMethodSession { void finishSession(); void updateCursorAnchorInfo(in CursorAnchorInfo cursorAnchorInfo); + + void notifyImeHidden(); } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index e6d34600485c..64291de38130 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -26,6 +26,7 @@ import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; +import android.os.Build; import android.util.DisplayMetrics; import android.view.Display; import android.view.Gravity; @@ -107,10 +108,13 @@ public class MenuPopupHelper implements MenuHelper { * <p> * Changes take effect on the next call to show(). * + * This method should not be accessed directly outside the framework, please use + * {@link android.widget.PopupMenu#setForceShowIcon(boolean)} instead. + * * @param forceShowIcon {@code true} to force icons to be shown, or * {@code false} for icons to be optionally shown */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public void setForceShowIcon(boolean forceShowIcon) { mForceShowIcon = forceShowIcon; if (mPopup != null) { diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java index 7609b67e492b..498bc5a7d598 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -39,6 +39,7 @@ public class MediaNotificationView extends FrameLayout { private View mActions; private View mHeader; private View mMainColumn; + private View mMediaContent; private int mImagePushIn; public MediaNotificationView(Context context) { @@ -70,7 +71,7 @@ public class MediaNotificationView extends FrameLayout { (MarginLayoutParams) mRightIcon.getLayoutParams(); int imageEndMargin = layoutParams.getMarginEnd(); size -= imageEndMargin; - int fullHeight = getMeasuredHeight(); + int fullHeight = mMediaContent.getMeasuredHeight(); if (size > fullHeight) { size = fullHeight; } else if (size < fullHeight) { @@ -154,5 +155,6 @@ public class MediaNotificationView extends FrameLayout { mActions = findViewById(com.android.internal.R.id.media_actions); mHeader = findViewById(com.android.internal.R.id.notification_header); mMainColumn = findViewById(com.android.internal.R.id.notification_main_column); + mMediaContent = findViewById(com.android.internal.R.id.notification_media_content); } } diff --git a/core/java/com/android/server/backup/PermissionBackupHelper.java b/core/java/com/android/server/backup/PermissionBackupHelper.java index ff0e63da8289..c0ba18159639 100644 --- a/core/java/com/android/server/backup/PermissionBackupHelper.java +++ b/core/java/com/android/server/backup/PermissionBackupHelper.java @@ -19,7 +19,6 @@ package com.android.server.backup; import android.app.AppGlobals; import android.app.backup.BlobBackupHelper; import android.content.pm.IPackageManager; -import android.os.UserHandle; import android.util.Slog; public class PermissionBackupHelper extends BlobBackupHelper { @@ -32,8 +31,12 @@ public class PermissionBackupHelper extends BlobBackupHelper { // key under which the permission-grant state blob is committed to backup private static final String KEY_PERMISSIONS = "permissions"; - public PermissionBackupHelper() { + private final int mUserId; + + public PermissionBackupHelper(int userId) { super(STATE_VERSION, KEY_PERMISSIONS); + + mUserId = userId; } @Override @@ -45,7 +48,7 @@ public class PermissionBackupHelper extends BlobBackupHelper { try { switch (key) { case KEY_PERMISSIONS: - return pm.getPermissionGrantBackup(UserHandle.USER_SYSTEM); + return pm.getPermissionGrantBackup(mUserId); default: Slog.w(TAG, "Unexpected backup key " + key); @@ -65,7 +68,7 @@ public class PermissionBackupHelper extends BlobBackupHelper { try { switch (key) { case KEY_PERMISSIONS: - pm.restorePermissionGrants(payload, UserHandle.USER_SYSTEM); + pm.restorePermissionGrants(payload, mUserId); break; default: diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index 47e7a0e74563..8878421a8016 100644 --- a/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java @@ -19,7 +19,7 @@ package com.android.server.backup; import android.app.IWallpaperManager; import android.app.backup.BackupAgentHelper; import android.app.backup.BackupDataInput; -import android.app.backup.BackupDataOutput; +import android.app.backup.BackupHelper; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.app.backup.WallpaperBackupHelper; @@ -31,8 +31,11 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.util.Slog; +import com.google.android.collect.Sets; + import java.io.File; import java.io.IOException; +import java.util.Set; /** * Backup agent for various system-managed data. Wallpapers are now handled by a @@ -77,20 +80,25 @@ public class SystemBackupAgent extends BackupAgentHelper { // Use old keys to keep legacy data compatibility and avoid writing two wallpapers private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY; - private WallpaperBackupHelper mWallpaperHelper = null; + private static final Set<String> sEligibleForMultiUser = Sets.newArraySet( + PERMISSION_HELPER); + + private int mUserId = UserHandle.USER_SYSTEM; @Override - public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { + public void onCreate(UserHandle user) { + super.onCreate(user); + + mUserId = user.getIdentifier(); + addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this)); addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); - addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); + addHelper(PERMISSION_HELPER, new PermissionBackupHelper(mUserId)); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); addHelper(SLICES_HELPER, new SliceBackupHelper(this)); - super.onBackup(oldState, data, newState); } @Override @@ -103,26 +111,25 @@ public class SystemBackupAgent extends BackupAgentHelper { throws IOException { // Slot in a restore helper for the older wallpaper backup schema to support restore // from devices still generating data in that format. - mWallpaperHelper = new WallpaperBackupHelper(this, - new String[] { WALLPAPER_IMAGE_KEY} ); - addHelper(WALLPAPER_HELPER, mWallpaperHelper); + addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, + new String[] { WALLPAPER_IMAGE_KEY})); // On restore, we also support a long-ago wallpaper data schema "system_files" addHelper("system_files", new WallpaperBackupHelper(this, new String[] { WALLPAPER_IMAGE_KEY} )); - addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this)); - addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); - addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); - addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); - addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); - addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); - addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); - addHelper(SLICES_HELPER, new SliceBackupHelper(this)); - super.onRestore(data, appVersionCode, newState); } + @Override + public void addHelper(String keyPrefix, BackupHelper helper) { + if (mUserId != UserHandle.USER_SYSTEM && !sEligibleForMultiUser.contains(keyPrefix)) { + return; + } + + super.addHelper(keyPrefix, helper); + } + /** * Support for 'adb restore' of legacy archives */ diff --git a/core/jni/Android.bp b/core/jni/Android.bp index e7a1c49e7a99..345058bd4f6f 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -276,6 +276,7 @@ cc_library_shared { "libmediametrics", "libmeminfo", "libaudioclient", + "libaudiopolicy", "libjpeg", "libusbhost", "libharfbuzz_ng", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 49598bbb5ada..d69d416e8401 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -230,6 +230,11 @@ extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); +// Namespace for Android Runtime flags applied during boot time. +static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot"; +// Feature flag name for Garbage Collector type. +static const char* GCTYPE = "gctype"; + static AndroidRuntime* gCurRuntime = NULL; /* @@ -776,7 +781,9 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) } std::string gc_type_override = - server_configurable_flags::GetServerConfigurableFlag("runtime_native", "gctype", ""); + server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE, + GCTYPE, + /*default_value=*/ ""); std::string gc_type_override_temp; if (gc_type_override.empty()) { parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:"); diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 79bfa17bdd04..70e6604fddeb 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -507,9 +507,18 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, ninePatchChunk, ninePatchInsets, -1); } + // Speculative fix for b/112551574. It doesn't seem like |b| can be null. If it is, print some + // info that might be helpful to diagnose. + Bitmap* b = defaultAllocator.getStorageObjAndReset(); + if (!b) { + ALOGW("defaultAllocator has no storage object!"); + ALOGW("\tjavaBitmap: %s", (javaBitmap == nullptr ? "null" : "present")); + ALOGW("\tisHardware: %s", (isHardware ? "true" : "false")); + ALOGW("\twillScale: %s", (willScale ? "true" : "false")); + return nullptr; + } // now create the java bitmap - return bitmap::createBitmap(env, defaultAllocator.getStorageObjAndReset(), - bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1); + return bitmap::createBitmap(env, b, bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1); } static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage, diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 3b59321024fd..d80c071c3e26 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -670,6 +670,24 @@ static jlong android_os_Parcel_getBlobAshmemSize(jlong nativePtr) return 0; } +static jint android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr) +{ + Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); + if (parcel != NULL) { + return parcel->readCallingWorkSourceUid(); + } + return IPCThreadState::kUnsetWorkSource; +} + +static jboolean android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr, jint uid) +{ + Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); + if (parcel != NULL) { + return parcel->replaceCallingWorkSourceUid(uid); + } + return false; +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gParcelMethods[] = { @@ -740,6 +758,11 @@ static const JNINativeMethod gParcelMethods[] = { // @CriticalNative {"nativeGetBlobAshmemSize", "(J)J", (void*)android_os_Parcel_getBlobAshmemSize}, + + // @CriticalNative + {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid}, + // @CriticalNative + {"nativeReplaceCallingWorkSourceUid", "(JI)Z", (void*)android_os_Parcel_replaceCallingWorkSourceUid}, }; const char* const kParcelPathName = "android/os/Parcel"; diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp index 1dc68343047b..891330082f3e 100644 --- a/core/jni/android_util_XmlBlock.cpp +++ b/core/jni/android_util_XmlBlock.cpp @@ -81,12 +81,12 @@ static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobjec } ResXMLParser* st = new ResXMLParser(*osb); - st->setSourceResourceId(res_id); if (st == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return 0; } + st->setSourceResourceId(res_id); st->restart(); return reinterpret_cast<jlong>(st); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 840291da2ed6..c7b528c924dc 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4409,7 +4409,7 @@ {@link android.provider.Telephony.Intents#ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL} broadcast --> <permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|privileged" /> <!-- A subclass of {@link android.app.SmsAppService} must be protected with this permission. --> <permission android:name="android.permission.BIND_SMS_APP_SERVICE" diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index a24f920de732..f78466168e13 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -59,12 +59,84 @@ android:layout_centerHorizontal="true"/> </RelativeLayout> + <!-- The following 3 layouts are mutually exclusive. One of them will be + set VISIBLE programatically, when the optimal preview type can be + determined by inspecting the data being shared. This path was chosen + b/c inflating layouts in code had sizing problems with this widget. --> + + <!-- Layout Option 1: Supporting up to 3 images for preview --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="?attr/colorBackgroundFloating"> + <RelativeLayout + android:id="@+id/content_preview_image_area" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:paddingBottom="@dimen/chooser_view_spacing" + android:visibility="gone" + android:background="?attr/colorBackgroundFloating"> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_1_large" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="140dp" + android:layout_alignParentTop="true" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_2_large" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="140dp" + android:layout_alignParentTop="true" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_2_small" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="65dp" + android:layout_alignParentTop="true" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_3_small" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="65dp" + android:layout_below="@id/content_preview_image_2_small" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:layout_marginTop="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + </RelativeLayout> + </LinearLayout> + + <!-- Layout Option 2: Text preview, with optional title and thumbnail --> <LinearLayout - android:id="@+id/content_preview" + android:id="@+id/content_preview_text_area" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="@dimen/chooser_view_spacing" + android:visibility="gone" android:background="?attr/colorBackgroundFloating"> <LinearLayout @@ -108,15 +180,12 @@ <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" android:id="@+id/content_preview_thumbnail" - android:layout_width="80dp" - android:layout_height="80dp" - android:layout_marginRight="12dp" + android:layout_width="75dp" + android:layout_height="75dp" + android:layout_marginRight="16dp" android:adjustViewBounds="true" android:layout_gravity="center_vertical" android:gravity="center" - android:maxWidth="70dp" - android:maxHeight="70dp" - android:padding="5dp" android:scaleType="centerCrop"/> <TextView diff --git a/core/res/res/layout/notification_material_media_seekbar.xml b/core/res/res/layout/notification_material_media_seekbar.xml new file mode 100644 index 000000000000..1b691d68a201 --- /dev/null +++ b/core/res/res/layout/notification_material_media_seekbar.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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 + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/notification_media_progress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_alignParentBottom="true" + > + <SeekBar android:id="@+id/notification_media_progress_bar" + style="@style/Widget.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:maxHeight="3dp" + android:paddingTop="24dp" + android:paddingBottom="24dp" + android:layout_marginBottom="-24dp" + android:layout_marginTop="-12dp" + android:splitTrack="false" + /> + <FrameLayout + android:id="@+id/notification_media_progress_time" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginBottom="11dp" + > + + <!-- width is set to "match_parent" to avoid extra layout calls --> + <TextView android:id="@+id/notification_media_elapsed_time" + style="@style/Widget.DeviceDefault.Notification.Text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:gravity="left" + /> + + <TextView android:id="@+id/notification_media_total_time" + style="@style/Widget.DeviceDefault.Notification.Text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:gravity="right" + /> + </FrameLayout> +</LinearLayout>
\ No newline at end of file diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml index 56f7a593cc43..3267f726c69d 100644 --- a/core/res/res/layout/notification_template_material_big_media.xml +++ b/core/res/res/layout/notification_template_material_big_media.xml @@ -39,6 +39,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:id="@+id/notification_media_content" > <LinearLayout android:id="@+id/notification_main_column" @@ -84,5 +85,9 @@ android:id="@+id/media_seamless" /> </LinearLayout> + <ViewStub android:id="@+id/notification_media_seekbar_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> </LinearLayout> </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml index 01b0866f428c..64d91ad867f9 100644 --- a/core/res/res/layout/notification_template_material_media.xml +++ b/core/res/res/layout/notification_template_material_media.xml @@ -34,49 +34,61 @@ android:layout_width="match_parent" android:layout_height="@dimen/media_notification_header_height" /> <LinearLayout - android:id="@+id/notification_main_column" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_marginStart="@dimen/notification_content_margin_start" - android:layout_marginTop="@dimen/notification_content_margin_top" - android:tag="media" + android:orientation="vertical" + android:id="@+id/notification_media_content" > <LinearLayout - android:id="@+id/notification_content_container" + android:id="@+id/notification_main_column" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="fill_vertical" - android:layout_weight="1" - android:minHeight="@dimen/notification_min_content_height" - android:paddingBottom="@dimen/notification_content_margin" - android:orientation="vertical" - > - <include layout="@layout/notification_template_part_line1"/> - <include layout="@layout/notification_template_text"/> - </LinearLayout> - <LinearLayout - android:id="@+id/media_actions" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom|end" - android:layout_marginStart="10dp" - android:layout_marginBottom="@dimen/media_notification_actions_padding_bottom" - android:layoutDirection="ltr" android:orientation="horizontal" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginTop="@dimen/notification_content_margin_top" + android:layout_alignParentTop="true" + android:tag="media" > - <include - layout="@layout/notification_material_media_action" - android:id="@+id/action0" - /> - <include - layout="@layout/notification_material_media_action" - android:id="@+id/action1" - /> - <include - layout="@layout/notification_material_media_action" - android:id="@+id/action2" - /> + <LinearLayout + android:id="@+id/notification_content_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:layout_weight="1" + android:minHeight="@dimen/notification_min_content_height" + android:paddingBottom="@dimen/notification_content_margin" + android:orientation="vertical" + > + <include layout="@layout/notification_template_part_line1"/> + <include layout="@layout/notification_template_text"/> + </LinearLayout> + <LinearLayout + android:id="@+id/media_actions" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_marginStart="10dp" + android:layoutDirection="ltr" + android:orientation="horizontal" + > + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action0" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action1" + /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/action2" + /> + </LinearLayout> </LinearLayout> + <ViewStub android:id="@+id/notification_media_seekbar_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + /> </LinearLayout> </FrameLayout> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index df20f85d28b9..d65ef03e98e0 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1933,18 +1933,11 @@ the platform will search for an SMS app and use that (if there is one)--> <string name="default_sms_application" translatable="false">com.android.messaging</string> - <!-- Default web browser. This is the package name of the application that will - be the default browser when the device first boots. Afterwards the user - can select whatever browser app they wish to use as the default. - - If this string is empty or the specified package does not exist, then - the behavior will be as though no app was named as an explicit default. --> - <string name="default_browser" translatable="false"></string> - <!-- Default role holders. This will be an array of roles and package names of their default holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". --> <string-array name="config_defaultRoleHolders" translatable="false"> <item>android.app.role.SMS: com.android.messaging</item> + <item>android.app.role.DIALER: com.android.phone</item> </string-array> <!-- Enable/disable default bluetooth profiles: diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 38367fbf3f31..9f86f8416fb9 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -720,4 +720,5 @@ <dimen name="chooser_view_spacing">18dp</dimen> <dimen name="chooser_edge_margin_thin">16dp</dimen> <dimen name="chooser_edge_margin_normal">24dp</dimen> + <dimen name="chooser_preview_image_font_size">20sp</dimen> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c9098736fdc9..6d4b04c5e66a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -50,9 +50,14 @@ <java-symbol type="id" name="characterPicker" /> <java-symbol type="id" name="clearDefaultHint" /> <java-symbol type="id" name="contentPanel" /> - <java-symbol type="id" name="content_preview" /> + <java-symbol type="id" name="content_preview_image_area" /> + <java-symbol type="id" name="content_preview_image_1_large" /> + <java-symbol type="id" name="content_preview_image_2_large" /> + <java-symbol type="id" name="content_preview_image_2_small" /> + <java-symbol type="id" name="content_preview_image_3_small" /> <java-symbol type="id" name="content_preview_thumbnail" /> <java-symbol type="id" name="content_preview_text" /> + <java-symbol type="id" name="content_preview_text_area" /> <java-symbol type="id" name="content_preview_text_layout" /> <java-symbol type="id" name="content_preview_title" /> <java-symbol type="id" name="content_preview_title_layout" /> @@ -195,6 +200,12 @@ <java-symbol type="id" name="action3" /> <java-symbol type="id" name="action4" /> <java-symbol type="id" name="media_seamless" /> + <java-symbol type="id" name="notification_media_seekbar_container" /> + <java-symbol type="id" name="notification_media_content" /> + <java-symbol type="id" name="notification_media_progress" /> + <java-symbol type="id" name="notification_media_progress_bar" /> + <java-symbol type="id" name="notification_media_elapsed_time" /> + <java-symbol type="id" name="notification_media_total_time" /> <java-symbol type="id" name="big_picture" /> <java-symbol type="id" name="big_text" /> <java-symbol type="id" name="chronometer" /> @@ -1023,7 +1034,6 @@ <java-symbol type="string" name="sipAddressTypeOther" /> <java-symbol type="string" name="sipAddressTypeWork" /> <java-symbol type="string" name="default_sms_application" /> - <java-symbol type="string" name="default_browser" /> <java-symbol type="string" name="sms_control_message" /> <java-symbol type="string" name="sms_control_title" /> <java-symbol type="string" name="sms_control_no" /> @@ -1573,6 +1583,7 @@ <java-symbol type="layout" name="immersive_mode_cling" /> <java-symbol type="layout" name="user_switching_dialog" /> <java-symbol type="layout" name="common_tab_settings" /> + <java-symbol type="layout" name="notification_material_media_seekbar" /> <java-symbol type="anim" name="slide_in_child_bottom" /> <java-symbol type="anim" name="slide_in_right" /> @@ -2725,6 +2736,7 @@ <java-symbol type="dimen" name="chooser_view_spacing" /> <java-symbol type="dimen" name="chooser_edge_margin_thin" /> <java-symbol type="dimen" name="chooser_edge_margin_normal" /> + <java-symbol type="dimen" name="chooser_preview_image_font_size"/> <java-symbol type="layout" name="chooser_grid" /> <java-symbol type="layout" name="resolve_grid_item" /> <java-symbol type="id" name="day_picker_view_pager" /> diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index 6a8105088b88..40ebd44b9bd0 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -36,12 +36,11 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ frameworks-core-util-lib \ mockwebserver \ guava \ - androidx.test.runner \ + androidx.test.espresso.core \ androidx.test.ext.junit \ + androidx.test.runner \ androidx.test.rules \ - androidx.test.espresso.core \ mockito-target-minus-junit4 \ - espresso-core \ ub-uiautomator \ platform-test-annotations \ truth-prebuilt \ diff --git a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java index be1d44cec6a6..c71bc7395d4e 100644 --- a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java +++ b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java @@ -16,22 +16,28 @@ package android.animation; -import android.test.ActivityInstrumentationTestCase2; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import androidx.test.filters.LargeTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; +import org.junit.Rule; +import org.junit.Test; + import java.util.HashSet; import java.util.Set; @LargeTest -public class AnimatorInflaterTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { - Set<Integer> identityHashes = new HashSet<Integer>(); +public class AnimatorInflaterTest { + @Rule + public final ActivityTestRule<BasicAnimatorActivity> mActivityRule = + new ActivityTestRule<>(BasicAnimatorActivity.class); - public AnimatorInflaterTest() { - super(BasicAnimatorActivity.class); - } + private final Set<Integer> mIdentityHashes = new HashSet<>(); private void assertUnique(Object object) { assertUnique(object, ""); @@ -39,15 +45,16 @@ public class AnimatorInflaterTest extends ActivityInstrumentationTestCase2<Basic private void assertUnique(Object object, String msg) { final int code = System.identityHashCode(object); - assertTrue("object should be unique " + msg + ", obj:" + object, identityHashes.add(code)); - + assertTrue("object should be unique " + msg + ", obj:" + object, mIdentityHashes.add(code)); } + @Test public void testLoadStateListAnimator() { - StateListAnimator sla1 = AnimatorInflater.loadStateListAnimator(getActivity(), + final BasicAnimatorActivity activity = mActivityRule.getActivity(); + StateListAnimator sla1 = AnimatorInflater.loadStateListAnimator(activity, R.anim.test_state_anim); - sla1.setTarget(getActivity().mAnimatingButton); - StateListAnimator sla2 = AnimatorInflater.loadStateListAnimator(getActivity(), + sla1.setTarget(activity.mAnimatingButton); + StateListAnimator sla2 = AnimatorInflater.loadStateListAnimator(activity, R.anim.test_state_anim); assertNull(sla2.getTarget()); for (StateListAnimator sla : new StateListAnimator[]{sla1, sla2}) { diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java index 55837ba3926c..7a1de0c5d4fe 100644 --- a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java +++ b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java @@ -16,27 +16,38 @@ package android.animation; -import android.test.ActivityInstrumentationTestCase2; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + import android.view.View; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + import java.util.ArrayList; -public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { +@SmallTest +public class AnimatorSetActivityTest { + + @Rule + public final ActivityTestRule<AnimatorSetActivity> mActivityRule = + new ActivityTestRule<>(AnimatorSetActivity.class); private static final long POLL_INTERVAL = 100; // ms private AnimatorSetActivity mActivity; private ObjectAnimator a1,a2,a3; private ValueAnimator a4,a5; - public AnimatorSetActivityTest() { - super(AnimatorSetActivity.class); - } - static class MyListener implements Animator.AnimatorListener { boolean startIsCalled = false; boolean endIsCalled = false; @@ -63,10 +74,9 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An } } - @Override + @Before public void setUp() throws Exception { - super.setUp(); - mActivity = getActivity(); + mActivity = mActivityRule.getActivity(); View square1 = mActivity.findViewById(R.id.square1); View square2 = mActivity.findViewById(R.id.square2); @@ -78,7 +88,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An a5 = ValueAnimator.ofFloat(10f, 5f).setDuration(850); } - @Override + @After public void tearDown() throws Exception { mActivity = null; a1 = null; @@ -86,10 +96,9 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An a3 = null; a4 = null; a5 = null; - super.tearDown(); } - @SmallTest + @Test public void testGetChildAnimations() { AnimatorSet s1 = new AnimatorSet(); s1.playTogether(a1, a2, a3); @@ -129,7 +138,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An } } - @SmallTest + @Test public void testTotalDuration() { ArrayList<Animator> list = getAnimatorList(); @@ -192,7 +201,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An } - @SmallTest + @Test public void testGetDuration() { AnimatorSet s = new AnimatorSet(); assertTrue(s.getDuration() < 0); @@ -205,8 +214,8 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An } - @SmallTest @UiThreadTest + @Test public void testSetDuration() { AnimatorSet s = getSequentialSet(); assertTrue(s.getDuration() < 0); @@ -224,7 +233,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertEquals(duration, a5.getDuration()); } - @SmallTest + @Test public void testAddListener() throws InterruptedException { // Verify that the listener is added to the list of listeners in the AnimatorSet // and that newly added listener gets callback for lifecycle events of the animator @@ -241,13 +250,10 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertFalse(listener.endIsCalled); try { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - assertTrue(listener.startIsCalled); - assertFalse(listener.endIsCalled); - } + mActivityRule.runOnUiThread(() -> { + s.start(); + assertTrue(listener.startIsCalled); + assertFalse(listener.endIsCalled); }); } catch (Throwable throwable) { throwable.printStackTrace(); @@ -258,18 +264,13 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertTrue(listener.endIsCalled); } - @SmallTest + @Test public void testRemoveListener() throws Throwable { final AnimatorSet s = new AnimatorSet(); s.playTogether(a1, a2, a3, a4); MyListener listener = new MyListener(); s.addListener(listener); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - } - }); + mActivityRule.runOnUiThread(s::start); Thread.sleep(s.getTotalDuration() + 100); assertTrue(listener.startIsCalled); @@ -282,18 +283,13 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An listener.startIsCalled = false; listener.endIsCalled = false; - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - } - }); + mActivityRule.runOnUiThread(s::start); Thread.sleep(s.getTotalDuration() + 100); assertFalse(listener.startIsCalled); assertFalse(listener.endIsCalled); } - @SmallTest + @Test public void testEnd() throws Throwable { // End animator set final AnimatorSet s = new AnimatorSet(); @@ -301,37 +297,30 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An final MyListener listener = new MyListener(); s.addListener(listener); assertFalse(listener.endIsCalled); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - assertTrue(s.isStarted()); - assertTrue(listener.startIsCalled); - assertFalse(listener.endIsCalled); - } + mActivityRule.runOnUiThread(() -> { + s.start(); + assertTrue(s.isStarted()); + assertTrue(listener.startIsCalled); + assertFalse(listener.endIsCalled); }); Thread.sleep(a2.getTotalDuration()); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.end(); - assertTrue(listener.startIsCalled); - assertTrue(listener.endIsCalled); - assertFalse(s.isRunning()); - assertFalse(s.isStarted()); - - assertFalse(a1.isStarted()); - assertFalse(a2.isStarted()); - assertFalse(a3.isStarted()); - assertFalse(a4.isStarted()); - } + mActivityRule.runOnUiThread(() -> { + s.end(); + assertTrue(listener.startIsCalled); + assertTrue(listener.endIsCalled); + assertFalse(s.isRunning()); + assertFalse(s.isStarted()); + + assertFalse(a1.isStarted()); + assertFalse(a2.isStarted()); + assertFalse(a3.isStarted()); + assertFalse(a4.isStarted()); }); - } - @SmallTest + @Test public void testStart() throws Throwable { final AnimatorSet s = new AnimatorSet(); ArrayList<Animator> animators = getAnimatorList(); @@ -355,12 +344,9 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertFalse(l.endIsCalled); } - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - assertTrue(l.startIsCalled); - } + mActivityRule.runOnUiThread(() -> { + s.start(); + assertTrue(l.startIsCalled); }); long timeout = s.getTotalDuration() * 2; @@ -383,7 +369,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An } } - @SmallTest + @Test public void testCancel() throws Throwable { // Check whether cancel would trigger onAnimationCanceled and cancel all the unfinished // animations @@ -411,42 +397,33 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertFalse(l.endIsCalled); } - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - } - }); + mActivityRule.runOnUiThread(s::start); Thread.sleep(a1.getTotalDuration()); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - assertTrue(s.isStarted()); - ArrayList<Integer> runningAnimIds = new ArrayList<Integer>(); - for (int i = 0; i < animators.size(); i++) { - if (animators.get(i).isStarted()) { - runningAnimIds.add(i); - } + mActivityRule.runOnUiThread(() -> { + assertTrue(s.isStarted()); + ArrayList<Integer> runningAnimIds = new ArrayList<>(); + for (int i = 0; i < animators.size(); i++) { + if (animators.get(i).isStarted()) { + runningAnimIds.add(i); } - s.cancel(); - assertTrue(l.startIsCalled); - assertTrue(l.cancelIsCalled); - assertTrue(l.endIsCalled); - - for (int i = 0; i < listeners.size(); i++) { - assertTrue(listeners.get(i).startIsCalled); - if (runningAnimIds.contains(i)) { - assertTrue(listeners.get(i).cancelIsCalled); - } - assertTrue(listeners.get(i).endIsCalled); + } + s.cancel(); + assertTrue(l.startIsCalled); + assertTrue(l.cancelIsCalled); + assertTrue(l.endIsCalled); + + for (int i = 0; i < listeners.size(); i++) { + assertTrue(listeners.get(i).startIsCalled); + if (runningAnimIds.contains(i)) { + assertTrue(listeners.get(i).cancelIsCalled); } + assertTrue(listeners.get(i).endIsCalled); } }); - } - @SmallTest + @Test public void testIsRunning() throws Throwable { final AnimatorSet s = new AnimatorSet(); final long startDelay = 500; @@ -455,12 +432,7 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An s.setStartDelay(startDelay); MyListener listener = new MyListener(); s.addListener(listener); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s.start(); - } - }); + mActivityRule.runOnUiThread(s::start); while (!listener.endIsCalled) { boolean passedStartDelay = a1.isStarted() || a2.isStarted() || a3.isStarted() || @@ -471,35 +443,29 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An assertFalse(s.isRunning()); } - @SmallTest + @Test public void testPauseAndResume() throws Throwable { final AnimatorSet set = getSequentialSet(); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - // Calling pause before start should have no effect, per documentation - set.pause(); - set.start(); - assertFalse(set.isPaused()); - } + mActivityRule.runOnUiThread(() -> { + // Calling pause before start should have no effect, per documentation + set.pause(); + set.start(); + assertFalse(set.isPaused()); }); while (!a2.isStarted()) { Thread.sleep(50); } - runTestOnUiThread(new Runnable() { - @Override - public void run() { - assertFalse(set.isPaused()); - set.pause(); - assertTrue(set.isPaused()); - set.resume(); - assertFalse(set.isPaused()); - } + mActivityRule.runOnUiThread(() -> { + assertFalse(set.isPaused()); + set.pause(); + assertTrue(set.isPaused()); + set.resume(); + assertFalse(set.isPaused()); }); } - @SmallTest + @Test public void testClone() throws Throwable { // Set up an AnimatorSet and two clones, add one listener to each. When the clones animate, // listeners of both the clone and the animator being cloned should receive animation @@ -535,14 +501,11 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An // Start the animation, and make the first clone during its run and the second clone once // it ends. - runTestOnUiThread(new Runnable() { - @Override - public void run() { - assertFalse(l1.startIsCalled); - assertFalse(l1.endIsCalled); + mActivityRule.runOnUiThread(() -> { + assertFalse(l1.startIsCalled); + assertFalse(l1.endIsCalled); - s1.start(); - } + s1.start(); }); // Make the first clone, during the animation's run. @@ -552,20 +515,12 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An s2.addListener(l2); Thread.sleep(POLL_INTERVAL); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - s1.end(); - } - }); + mActivityRule.runOnUiThread(s1::end); Thread.sleep(POLL_INTERVAL); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - assertTrue(l1.startIsCalled); - assertTrue(l1.endIsCalled); - } + mActivityRule.runOnUiThread(() -> { + assertTrue(l1.startIsCalled); + assertTrue(l1.endIsCalled); }); Thread.sleep(POLL_INTERVAL); @@ -574,59 +529,49 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An final MyListener l3 = new MyListener(); s3.addListener(l3); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - // Checking the fields before animations start. - assertFalse(l2.startIsCalled); - assertFalse(l2.cancelIsCalled); - assertFalse(l2.endIsCalled); - assertFalse(l3.startIsCalled); - assertFalse(l3.cancelIsCalled); - assertFalse(l3.endIsCalled); - - s2.start(); - s3.start(); - } + mActivityRule.runOnUiThread(() -> { + // Checking the fields before animations start. + assertFalse(l2.startIsCalled); + assertFalse(l2.cancelIsCalled); + assertFalse(l2.endIsCalled); + assertFalse(l3.startIsCalled); + assertFalse(l3.cancelIsCalled); + assertFalse(l3.endIsCalled); + + s2.start(); + s3.start(); }); Thread.sleep(POLL_INTERVAL); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - // Make sure the listeners receive the callbacks - // At this time only onAnimationStart() should be called. - assertTrue(l2.startIsCalled); - assertTrue(l3.startIsCalled); - assertFalse(l2.endIsCalled); - assertFalse(l3.endIsCalled); - assertFalse(l2.cancelIsCalled); - assertFalse(l3.cancelIsCalled); - - s2.end(); - s3.cancel(); - } + mActivityRule.runOnUiThread(() -> { + // Make sure the listeners receive the callbacks + // At this time only onAnimationStart() should be called. + assertTrue(l2.startIsCalled); + assertTrue(l3.startIsCalled); + assertFalse(l2.endIsCalled); + assertFalse(l3.endIsCalled); + assertFalse(l2.cancelIsCalled); + assertFalse(l3.cancelIsCalled); + + s2.end(); + s3.cancel(); }); Thread.sleep(POLL_INTERVAL); - runTestOnUiThread(new Runnable() { - @Override - public void run() { - // Check that the new listeners for the new animations gets called for the events. - assertTrue(l2.startIsCalled); - assertFalse(l2.cancelIsCalled); - assertTrue(l2.endIsCalled); - assertTrue(l3.startIsCalled); - assertTrue(l3.cancelIsCalled); - assertTrue(l3.endIsCalled); - - // Check that the listener on the animation that was being clone receive the - // animation lifecycle events for the clones. - assertTrue(onlyContains(startedAnimators, s1, s2, s3)); - assertTrue(onlyContains(canceledAnimators, s3)); - assertTrue(onlyContains(endedAnimators, s1, s2, s3)); - } + mActivityRule.runOnUiThread(() -> { + // Check that the new listeners for the new animations gets called for the events. + assertTrue(l2.startIsCalled); + assertFalse(l2.cancelIsCalled); + assertTrue(l2.endIsCalled); + assertTrue(l3.startIsCalled); + assertTrue(l3.cancelIsCalled); + assertTrue(l3.endIsCalled); + + // Check that the listener on the animation that was being clone receive the + // animation lifecycle events for the clones. + assertTrue(onlyContains(startedAnimators, s1, s2, s3)); + assertTrue(onlyContains(canceledAnimators, s3)); + assertTrue(onlyContains(endedAnimators, s1, s2, s3)); }); - } /** @@ -663,5 +608,4 @@ public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<An list.add(a5); return list; } - } diff --git a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java index 4e90d1acf4a0..94c90aa531da 100644 --- a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java +++ b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java @@ -23,6 +23,8 @@ import androidx.test.filters.MediumTest; import com.android.frameworks.coretests.R; +import org.junit.Test; + import java.util.concurrent.TimeUnit; /** @@ -36,7 +38,7 @@ public class AnimatorSetEventsTest extends EventsTest { @Override public void setUp() throws Exception { - button = (Button) getActivity().findViewById(R.id.animatingButton); + button = mActivityRule.getActivity().findViewById(R.id.animatingButton); mAnimator = new AnimatorSet(); ((AnimatorSet)mAnimator).playSequentially(xAnim, yAnim); super.setUp(); @@ -53,23 +55,21 @@ public class AnimatorSetEventsTest extends EventsTest { * its children */ @MediumTest - public void testPlayingCancelDuringChildDelay() throws Exception { + @Test + public void testPlayingCancelDuringChildDelay() throws Throwable { yAnim.setStartDelay(500); final AnimatorSet animSet = new AnimatorSet(); animSet.playSequentially(xAnim, yAnim); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - animSet.addListener(mFutureListener); - mRunning = true; - animSet.start(); - handler.postDelayed(new Canceler(animSet, mFuture), ANIM_DURATION + 250); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + animSet.addListener(mFutureListener); + mRunning = true; + animSet.start(); + handler.postDelayed(new Canceler(animSet, mFuture), ANIM_DURATION + 250); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); diff --git a/core/tests/coretests/src/android/animation/AutoCancelTest.java b/core/tests/coretests/src/android/animation/AutoCancelTest.java index b3ec92cf1f0f..7df7336eb0b3 100644 --- a/core/tests/coretests/src/android/animation/AutoCancelTest.java +++ b/core/tests/coretests/src/android/animation/AutoCancelTest.java @@ -16,15 +16,24 @@ package android.animation; +import static org.junit.Assert.assertTrue; + import android.os.Handler; -import android.test.ActivityInstrumentationTestCase2; import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; + +import org.junit.Rule; +import org.junit.Test; import java.util.HashMap; import java.util.concurrent.TimeUnit; -public class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { +public class AutoCancelTest { + + @Rule + public final ActivityTestRule<BasicAnimatorActivity> mActivityRule = + new ActivityTestRule<>(BasicAnimatorActivity.class); boolean mAnimX1Canceled = false; boolean mAnimXY1Canceled = false; @@ -37,10 +46,6 @@ public class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimat HashMap<Animator, Boolean> mCanceledMap = new HashMap<Animator, Boolean>(); - public AutoCancelTest() { - super(BasicAnimatorActivity.class); - } - ObjectAnimator setupAnimator(long startDelay, String... properties) { ObjectAnimator returnVal; if (properties.length == 1) { @@ -58,8 +63,7 @@ public class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimat return returnVal; } - private void setupAnimators(long startDelay, boolean startLater, final FutureWaiter future) - throws Exception { + private void setupAnimators(long startDelay, boolean startLater, final FutureWaiter future) { // Animators to be auto-canceled final ObjectAnimator animX1 = setupAnimator(startDelay, "x"); final ObjectAnimator animY1 = setupAnimator(startDelay, "y"); @@ -123,64 +127,56 @@ public class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimat } @SmallTest - public void testAutoCancel() throws Exception { + @Test + public void testAutoCancel() throws Throwable { final FutureWaiter future = new FutureWaiter(); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setupAnimators(0, false, future); - } catch (Exception e) { - future.setException(e); - } + mActivityRule.runOnUiThread(() -> { + try { + setupAnimators(0, false, future); + } catch (Exception e) { + future.setException(e); } }); assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest - public void testAutoCancelDelayed() throws Exception { + @Test + public void testAutoCancelDelayed() throws Throwable { final FutureWaiter future = new FutureWaiter(); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setupAnimators(START_DELAY, false, future); - } catch (Exception e) { - future.setException(e); - } + mActivityRule.runOnUiThread(() -> { + try { + setupAnimators(START_DELAY, false, future); + } catch (Exception e) { + future.setException(e); } }); assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest - public void testAutoCancelTestLater() throws Exception { + @Test + public void testAutoCancelTestLater() throws Throwable { final FutureWaiter future = new FutureWaiter(); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setupAnimators(0, true, future); - } catch (Exception e) { - future.setException(e); - } + mActivityRule.runOnUiThread(() -> { + try { + setupAnimators(0, true, future); + } catch (Exception e) { + future.setException(e); } }); assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest - public void testAutoCancelDelayedTestLater() throws Exception { + @Test + public void testAutoCancelDelayedTestLater() throws Throwable { final FutureWaiter future = new FutureWaiter(); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - setupAnimators(START_DELAY, true, future); - } catch (Exception e) { - future.setException(e); - } + mActivityRule.runOnUiThread(() -> { + try { + setupAnimators(START_DELAY, true, future); + } catch (Exception e) { + future.setException(e); } }); assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS)); diff --git a/core/tests/coretests/src/android/animation/EventsTest.java b/core/tests/coretests/src/android/animation/EventsTest.java index ba7413a2a4f7..0c40a95f8bab 100644 --- a/core/tests/coretests/src/android/animation/EventsTest.java +++ b/core/tests/coretests/src/android/animation/EventsTest.java @@ -16,12 +16,20 @@ package android.animation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.annotation.CallSuper; import android.os.Handler; -import android.test.ActivityInstrumentationTestCase2; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -38,8 +46,11 @@ import java.util.concurrent.TimeoutException; * wait for some later event to occur before ending. These tests use a combination of an * AbstractFuture mechanism and a delayed action to release that Future later. */ -public abstract class EventsTest - extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { +public abstract class EventsTest { + + @Rule + public final ActivityTestRule<BasicAnimatorActivity> mActivityRule = + new ActivityTestRule<>(BasicAnimatorActivity.class); protected static final int ANIM_DURATION = 400; protected static final int ANIM_DELAY = 100; @@ -55,7 +66,6 @@ public abstract class EventsTest private boolean mCanceled; // tracks whether we've canceled the animator protected Animator.AnimatorListener mFutureListener; // mechanism for delaying end of the test protected FutureWaiter mFuture; // Mechanism for waiting for the UI test to complete - private Animator.AnimatorListener mListener; // Listener that handles/tests the events protected Animator mAnimator; // The animator used in the tests. Must be set in subclass // setup() method prior to calling the superclass setup() @@ -67,10 +77,12 @@ public abstract class EventsTest protected static class Canceler implements Runnable { Animator mAnim; FutureWaiter mFuture; + public Canceler(Animator anim, FutureWaiter future) { mAnim = anim; mFuture = future; } + @Override public void run() { try { @@ -79,7 +91,7 @@ public abstract class EventsTest mFuture.setException(new RuntimeException(e)); } } - }; + } /** * Timeout length, based on when the animation should reasonably be complete. @@ -95,10 +107,12 @@ public abstract class EventsTest static class Ender implements Runnable { Animator mAnim; FutureWaiter mFuture; + public Ender(Animator anim, FutureWaiter future) { mAnim = anim; mFuture = future; } + @Override public void run() { try { @@ -107,7 +121,7 @@ public abstract class EventsTest mFuture.setException(new RuntimeException(e)); } } - }; + } /** * Pauses the given animator. Used to delay pausing until some later time (after the @@ -116,10 +130,12 @@ public abstract class EventsTest static class Pauser implements Runnable { Animator mAnim; FutureWaiter mFuture; + public Pauser(Animator anim, FutureWaiter future) { mAnim = anim; mFuture = future; } + @Override public void run() { try { @@ -128,7 +144,7 @@ public abstract class EventsTest mFuture.setException(new RuntimeException(e)); } } - }; + } /** * Resumes the given animator. Used to delay resuming until some later time (after the @@ -137,10 +153,12 @@ public abstract class EventsTest static class Resumer implements Runnable { Animator mAnim; FutureWaiter mFuture; + public Resumer(Animator anim, FutureWaiter future) { mAnim = anim; mFuture = future; } + @Override public void run() { try { @@ -149,7 +167,7 @@ public abstract class EventsTest mFuture.setException(new RuntimeException(e)); } } - }; + } /** * Releases the given Future object when the listener's end() event is called. Specifically, @@ -171,28 +189,14 @@ public abstract class EventsTest public FutureReleaseListener(FutureWaiter future, long timeout) { mFuture = future; Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - mFuture.release(); - } - }, timeout); + handler.postDelayed(mFuture::release, timeout); } @Override public void onAnimationEnd(Animator animation) { Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - mFuture.release(); - } - }, FUTURE_RELEASE_DELAY); + handler.postDelayed(mFuture::release, FUTURE_RELEASE_DELAY); } - }; - - public EventsTest() { - super(BasicAnimatorActivity.class); } /** @@ -201,13 +205,12 @@ public abstract class EventsTest * and then call super.setup(), where further properties are set on that animator. * @throws Exception */ - @Override + @CallSuper + @Before public void setUp() throws Exception { - super.setUp(); - // mListener is the main testing mechanism of this file. The asserts of each test // are embedded in the listener callbacks that it implements. - mListener = new AnimatorListenerAdapter() { + final Animator.AnimatorListener listener = new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { // This should only be called on an animation that has not yet been started @@ -236,9 +239,8 @@ public abstract class EventsTest } }; - mAnimator.addListener(mListener); + mAnimator.addListener(listener); mAnimator.setDuration(ANIM_DURATION); - mFuture = new FutureWaiter(); mRunning = false; @@ -251,6 +253,7 @@ public abstract class EventsTest */ @UiThreadTest @SmallTest + @Test public void testCancel() throws Exception { mAnimator.cancel(); } @@ -260,6 +263,7 @@ public abstract class EventsTest */ @UiThreadTest @SmallTest + @Test public void testEnd() throws Exception { mRunning = true; // end() implicitly starts an unstarted animator mAnimator.end(); @@ -270,19 +274,17 @@ public abstract class EventsTest */ @UiThreadTest @SmallTest - public void testStartCancel() throws Exception { + @Test + public void testStartCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -293,19 +295,17 @@ public abstract class EventsTest */ @UiThreadTest @SmallTest - public void testStartEnd() throws Exception { + @Test + public void testStartEnd() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.end(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.end(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -315,20 +315,18 @@ public abstract class EventsTest * Same as testStartCancel, but with a startDelayed animator */ @SmallTest - public void testStartDelayedCancel() throws Exception { + @Test + public void testStartDelayedCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -338,20 +336,18 @@ public abstract class EventsTest * Same as testStartEnd, but with a startDelayed animator */ @SmallTest - public void testStartDelayedEnd() throws Exception { + @Test + public void testStartDelayedEnd() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.end(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.end(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -361,20 +357,18 @@ public abstract class EventsTest * Verify that canceling an animator that is playing does the right thing. */ @MediumTest - public void testPlayingCancel() throws Exception { + @Test + public void testPlayingCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -384,20 +378,18 @@ public abstract class EventsTest * Verify that ending an animator that is playing does the right thing. */ @MediumTest - public void testPlayingEnd() throws Exception { + @Test + public void testPlayingEnd() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -407,21 +399,19 @@ public abstract class EventsTest * Same as testPlayingCancel, but with a startDelayed animator */ @MediumTest - public void testPlayingDelayedCancel() throws Exception { + @Test + public void testPlayingDelayedCancel() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -431,21 +421,19 @@ public abstract class EventsTest * Same as testPlayingEnd, but with a startDelayed animator */ @MediumTest - public void testPlayingDelayedEnd() throws Exception { + @Test + public void testPlayingDelayedEnd() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -455,24 +443,21 @@ public abstract class EventsTest * Same as testPlayingDelayedCancel, but cancel during the startDelay period */ @MediumTest - public void testPlayingDelayedCancelMidDelay() throws Exception { + @Test + public void testPlayingDelayedCancelMidDelay() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - // Set the listener to automatically timeout after an uncanceled animation - // would have finished. This tests to make sure that we're not calling - // the listeners with cancel/end callbacks since they won't be called - // with the start event. - mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); - Handler handler = new Handler(); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DELAY); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + // Set the listener to automatically timeout after an uncanceled animation would + // have finished. This tests to make sure that we're not calling the listeners with + // cancel/end callbacks since they won't be called with the start event. + mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); + Handler handler = new Handler(); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DELAY); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout() + 100, TimeUnit.MILLISECONDS); @@ -482,24 +467,21 @@ public abstract class EventsTest * Same as testPlayingDelayedEnd, but end during the startDelay period */ @MediumTest - public void testPlayingDelayedEndMidDelay() throws Exception { + @Test + public void testPlayingDelayedEndMidDelay() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - // Set the listener to automatically timeout after an uncanceled animation - // would have finished. This tests to make sure that we're not calling - // the listeners with cancel/end callbacks since they won't be called - // with the start event. - mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); - Handler handler = new Handler(); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DELAY); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + // Set the listener to automatically timeout after an uncanceled animation would + // have finished. This tests to make sure that we're not calling the listeners with + // cancel/end callbacks since they won't be called with the start event. + mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); + Handler handler = new Handler(); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DELAY); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout() + 100, TimeUnit.MILLISECONDS); @@ -510,20 +492,18 @@ public abstract class EventsTest * does nothing. */ @MediumTest - public void testStartDoubleCancel() throws Exception { + @Test + public void testStartDoubleCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -534,21 +514,19 @@ public abstract class EventsTest * does nothing. */ @MediumTest - public void testStartDoubleEnd() throws Exception { + @Test + public void testStartDoubleEnd() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.end(); - mRunning = true; // end() implicitly starts an unstarted animator - mAnimator.end(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.end(); + mRunning = true; // end() implicitly starts an unstarted animator + mAnimator.end(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -558,21 +536,19 @@ public abstract class EventsTest * Same as testStartDoubleCancel, but with a startDelayed animator */ @MediumTest - public void testStartDelayedDoubleCancel() throws Exception { + @Test + public void testStartDelayedDoubleCancel() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -582,22 +558,20 @@ public abstract class EventsTest * Same as testStartDoubleEnd, but with a startDelayed animator */ @MediumTest - public void testStartDelayedDoubleEnd() throws Exception { + @Test + public void testStartDelayedDoubleEnd() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.end(); - mRunning = true; // end() implicitly starts an unstarted animator - mAnimator.end(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.end(); + mRunning = true; // end() implicitly starts an unstarted animator + mAnimator.end(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -608,22 +582,20 @@ public abstract class EventsTest * the appropriate timeout duration. */ @MediumTest - public void testPauseResume() throws Exception { + @Test + public void testPauseResume() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); - handler.postDelayed(new Resumer(mAnimator, mFuture), - ANIM_PAUSE_DELAY + ANIM_PAUSE_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); + handler.postDelayed(new Resumer(mAnimator, mFuture), + ANIM_PAUSE_DELAY + ANIM_PAUSE_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout() + ANIM_PAUSE_DURATION, TimeUnit.MILLISECONDS); @@ -634,23 +606,21 @@ public abstract class EventsTest * the appropriate timeout duration. */ @MediumTest - public void testPauseResumeDelayed() throws Exception { + @Test + public void testPauseResumeDelayed() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); - handler.postDelayed(new Resumer(mAnimator, mFuture), - ANIM_PAUSE_DELAY + ANIM_PAUSE_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); + handler.postDelayed(new Resumer(mAnimator, mFuture), + ANIM_PAUSE_DELAY + ANIM_PAUSE_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout() + ANIM_PAUSE_DURATION + ANIM_FULL_DURATION_SLOP, @@ -661,20 +631,18 @@ public abstract class EventsTest * Verify that pausing an animator without resuming it causes a timeout. */ @MediumTest - public void testPauseTimeout() throws Exception { + @Test + public void testPauseTimeout() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); try { @@ -689,21 +657,19 @@ public abstract class EventsTest * Verify that pausing a startDelayed animator without resuming it causes a timeout. */ @MediumTest - public void testPauseTimeoutDelayed() throws Exception { + @Test + public void testPauseTimeoutDelayed() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.addListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.addListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Pauser(mAnimator, mFuture), ANIM_PAUSE_DELAY); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); try { diff --git a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java index 53f94727f6d3..63ad061b2c6c 100644 --- a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java +++ b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java @@ -27,11 +27,10 @@ public class ObjectAnimatorEventsTest extends EventsTest { @Override public void setUp() throws Exception { - final BasicAnimatorActivity activity = getActivity(); - Button button = (Button) activity.findViewById(R.id.animatingButton); + final BasicAnimatorActivity activity = mActivityRule.getActivity(); + Button button = activity.findViewById(R.id.animatingButton); mAnimator = ObjectAnimator.ofFloat(button, "translationX", 0, 100); super.setUp(); } - } diff --git a/core/tests/coretests/src/android/animation/StateListAnimatorTest.java b/core/tests/coretests/src/android/animation/StateListAnimatorTest.java index e755b89f8551..12f1977c6d2f 100644 --- a/core/tests/coretests/src/android/animation/StateListAnimatorTest.java +++ b/core/tests/coretests/src/android/animation/StateListAnimatorTest.java @@ -16,41 +16,47 @@ package android.animation; -import android.test.ActivityInstrumentationTestCase2; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import android.util.StateSet; import android.view.View; import android.view.ViewGroup; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.LargeTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; +import org.junit.Rule; +import org.junit.Test; + import java.util.concurrent.atomic.AtomicInteger; @LargeTest -public class StateListAnimatorTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { +public class StateListAnimatorTest { - public StateListAnimatorTest() { - super(BasicAnimatorActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - } + @Rule + public final ActivityTestRule<BasicAnimatorActivity> mActivityRule = + new ActivityTestRule<>(BasicAnimatorActivity.class); + @Test public void testInflateFromAnimator() throws Exception { StateListAnimator stateListAnimator = AnimatorInflater - .loadStateListAnimator(getActivity(), R.anim.test_state_anim); + .loadStateListAnimator(mActivityRule.getActivity(), R.anim.test_state_anim); assertNotNull("A state list animator should be returned", stateListAnimator); assertEquals("State list animator should have three items", 3, stateListAnimator.getTuples().size()); } @UiThreadTest + @Test public void testAttachDetach() throws Exception { - View view = new View(getActivity()); + final BasicAnimatorActivity activity = mActivityRule.getActivity(); + View view = new View(activity); final AtomicInteger setStateCount = new AtomicInteger(0); StateListAnimator stateListAnimator = new StateListAnimator() { @Override @@ -62,7 +68,7 @@ public class StateListAnimatorTest extends ActivityInstrumentationTestCase2<Basi view.setStateListAnimator(stateListAnimator); assertNotNull("State list animator should have a reference to view even if it is detached", stateListAnimator.getTarget()); - ViewGroup viewGroup = (ViewGroup) getActivity().findViewById(android.R.id.content); + ViewGroup viewGroup = activity.findViewById(android.R.id.content); int preSetStateCount = setStateCount.get(); viewGroup.addView(view); assertTrue("When view is attached, state list drawable's setState should be called", @@ -82,9 +88,10 @@ public class StateListAnimatorTest extends ActivityInstrumentationTestCase2<Basi stateListAnimator2.getTarget()); } + @Test public void testStateListLoading() throws InterruptedException { StateListAnimator stateListAnimator = AnimatorInflater - .loadStateListAnimator(getActivity(), R.anim.test_state_anim); + .loadStateListAnimator(mActivityRule.getActivity(), R.anim.test_state_anim); assertNotNull("A state list animator should be returned", stateListAnimator); assertEquals("Steate list animator should have two items", 3, stateListAnimator.getTuples().size()); diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java index f6d71b88bd89..ba9aef828b8b 100644 --- a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java +++ b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java @@ -26,5 +26,4 @@ public class ValueAnimatorEventsTest extends EventsTest { mAnimator = ValueAnimator.ofFloat(0, 1); super.setUp(); } - } diff --git a/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java b/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java index 997af009a9b8..81cd4da4f425 100644 --- a/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java +++ b/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java @@ -16,17 +16,24 @@ package android.animation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import android.os.Handler; -import android.test.ActivityInstrumentationTestCase2; import android.view.ViewPropertyAnimator; import android.widget.Button; import androidx.test.annotation.UiThreadTest; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + import java.util.concurrent.TimeUnit; /** @@ -41,8 +48,11 @@ import java.util.concurrent.TimeUnit; * wait for some later event to occur before ending. These tests use a combination of an * AbstractFuture mechanism and a delayed action to release that Future later. */ -public abstract class ViewPropertyAnimatorTest - extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> { +public class ViewPropertyAnimatorTest { + + @Rule + public final ActivityTestRule<BasicAnimatorActivity> mActivityRule = + new ActivityTestRule<>(BasicAnimatorActivity.class); protected static final int ANIM_DURATION = 400; protected static final int ANIM_DELAY = 100; @@ -79,7 +89,7 @@ public abstract class ViewPropertyAnimatorTest mFuture.setException(new RuntimeException(e)); } } - }; + } /** * Timeout length, based on when the animation should reasonably be complete. @@ -108,28 +118,14 @@ public abstract class ViewPropertyAnimatorTest public FutureReleaseListener(FutureWaiter future, long timeout) { mFuture = future; Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - mFuture.release(); - } - }, timeout); + handler.postDelayed(mFuture::release, timeout); } @Override public void onAnimationEnd(Animator animation) { Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - mFuture.release(); - } - }, FUTURE_RELEASE_DELAY); + handler.postDelayed(mFuture::release, FUTURE_RELEASE_DELAY); } - }; - - public ViewPropertyAnimatorTest() { - super(BasicAnimatorActivity.class); } /** @@ -138,15 +134,13 @@ public abstract class ViewPropertyAnimatorTest * and then call super.setup(), where further properties are set on that animator. * @throws Exception */ - @Override + @Before public void setUp() throws Exception { - final BasicAnimatorActivity activity = getActivity(); - Button button = (Button) activity.findViewById(R.id.animatingButton); + final BasicAnimatorActivity activity = mActivityRule.getActivity(); + Button button = activity.findViewById(R.id.animatingButton); mAnimator = button.animate().x(100).y(100); - super.setUp(); - // mListener is the main testing mechanism of this file. The asserts of each test // are embedded in the listener callbacks that it implements. mListener = new AnimatorListenerAdapter() { @@ -195,6 +189,7 @@ public abstract class ViewPropertyAnimatorTest */ @UiThreadTest @SmallTest + @Test public void testCancel() throws Exception { mAnimator.cancel(); } @@ -204,19 +199,17 @@ public abstract class ViewPropertyAnimatorTest */ @UiThreadTest @SmallTest - public void testStartCancel() throws Exception { + @Test + public void testStartCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -226,20 +219,18 @@ public abstract class ViewPropertyAnimatorTest * Same as testStartCancel, but with a startDelayed animator */ @SmallTest - public void testStartDelayedCancel() throws Exception { + @Test + public void testStartDelayedCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -249,20 +240,18 @@ public abstract class ViewPropertyAnimatorTest * Verify that canceling an animator that is playing does the right thing. */ @MediumTest - public void testPlayingCancel() throws Exception { + @Test + public void testPlayingCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.setListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.setListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -272,21 +261,19 @@ public abstract class ViewPropertyAnimatorTest * Same as testPlayingCancel, but with a startDelayed animator */ @MediumTest - public void testPlayingDelayedCancel() throws Exception { + @Test + public void testPlayingDelayedCancel() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - Handler handler = new Handler(); - mAnimator.setListener(mFutureListener); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + Handler handler = new Handler(); + mAnimator.setListener(mFutureListener); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -296,24 +283,21 @@ public abstract class ViewPropertyAnimatorTest * Same as testPlayingDelayedCancel, but cancel during the startDelay period */ @MediumTest - public void testPlayingDelayedCancelMidDelay() throws Exception { + @Test + public void testPlayingDelayedCancelMidDelay() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - // Set the listener to automatically timeout after an uncanceled animation - // would have finished. This tests to make sure that we're not calling - // the listeners with cancel/end callbacks since they won't be called - // with the start event. - mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); - Handler handler = new Handler(); - mRunning = true; - mAnimator.start(); - handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DELAY); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + // Set the listener to automatically timeout after an uncanceled animation would + // have finished. This tests to make sure that we're not calling the listeners with + // cancel/end callbacks since they won't be called with the start event. + mFutureListener = new FutureReleaseListener(mFuture, getTimeout()); + Handler handler = new Handler(); + mRunning = true; + mAnimator.start(); + handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DELAY); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout() + 100, TimeUnit.MILLISECONDS); @@ -324,20 +308,18 @@ public abstract class ViewPropertyAnimatorTest * does nothing. */ @MediumTest - public void testStartDoubleCancel() throws Exception { + @Test + public void testStartDoubleCancel() throws Throwable { mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); @@ -347,24 +329,21 @@ public abstract class ViewPropertyAnimatorTest * Same as testStartDoubleCancel, but with a startDelayed animator */ @MediumTest - public void testStartDelayedDoubleCancel() throws Exception { + @Test + public void testStartDelayedDoubleCancel() throws Throwable { mAnimator.setStartDelay(ANIM_DELAY); mFutureListener = new FutureReleaseListener(mFuture); - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - try { - mRunning = true; - mAnimator.start(); - mAnimator.cancel(); - mAnimator.cancel(); - mFuture.release(); - } catch (junit.framework.AssertionFailedError e) { - mFuture.setException(new RuntimeException(e)); - } + mActivityRule.runOnUiThread(() -> { + try { + mRunning = true; + mAnimator.start(); + mAnimator.cancel(); + mAnimator.cancel(); + mFuture.release(); + } catch (junit.framework.AssertionFailedError e) { + mFuture.setException(new RuntimeException(e)); } }); mFuture.get(getTimeout(), TimeUnit.MILLISECONDS); } - } diff --git a/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java index 16be0b0a27c1..d8799cb182c8 100644 --- a/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java +++ b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java @@ -17,7 +17,7 @@ package android.hardware.hdmi; import static com.google.common.truth.Truth.assertThat; -import android.support.test.filters.SmallTest; +import androidx.test.filters.SmallTest; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceService.java b/core/tests/coretests/src/android/os/BinderWorkSourceService.java index 3bca5fbab486..46bd67da371d 100644 --- a/core/tests/coretests/src/android/os/BinderWorkSourceService.java +++ b/core/tests/coretests/src/android/os/BinderWorkSourceService.java @@ -38,11 +38,11 @@ public class BinderWorkSourceService extends Service { } public void setWorkSourceProvider(int uid) { - Binder.setWorkSourceProvider(() -> uid); + Binder.setWorkSourceProvider((x) -> uid); } public void clearWorkSourceProvider() { - Binder.setWorkSourceProvider(Binder::getCallingUid); + Binder.setWorkSourceProvider((x) -> Binder.getCallingUid()); } }; diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java index e16a3dbe4a26..b14c88f7341e 100644 --- a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java +++ b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java @@ -27,6 +27,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; +import androidx.test.filters.Suppress; import androidx.test.runner.AndroidJUnit4; import org.junit.After; @@ -97,6 +98,8 @@ public class BinderWorkSourceTest { public void tearDown() throws Exception { sContext.unbindService(mConnection); sContext.unbindService(mNestedConnection); + Binder.setProxyTransactListener(null); + ThreadLocalWorkSource.clear(); } @Test @@ -124,6 +127,28 @@ public class BinderWorkSourceTest { } @Test + public void setWorkSource_propagatedFromBinderProxyListener() throws Exception { + Binder.setProxyTransactListener(new Binder.PropagateWorkSourceTransactListener()); + Binder.clearCallingWorkSource(); + ThreadLocalWorkSource.setUid(UID); + assertEquals(UID, mService.getIncomingWorkSourceUid()); + } + + @Test + public void threadWorkSourceNotPropagated() throws Exception { + Binder.clearCallingWorkSource(); + ThreadLocalWorkSource.setUid(UID); + assertEquals(UID_NONE, mService.getIncomingWorkSourceUid()); + } + + @Test + public void setWorkSource_propagatedFromBinderProxyListener_unset() throws Exception { + Binder.setProxyTransactListener(new Binder.PropagateWorkSourceTransactListener()); + Binder.clearCallingWorkSource(); + assertEquals(UID_NONE, mService.getIncomingWorkSourceUid()); + } + + @Test public void restoreWorkSource() throws Exception { Binder.setCallingWorkSourceUid(UID); long token = Binder.clearCallingWorkSource(); @@ -158,18 +183,6 @@ public class BinderWorkSourceTest { } @Test - public void nestedSetWorkSouceNotPropagated() throws Exception { - Binder.setCallingWorkSourceUid(UID); - - int[] workSources = mNestedService.nestedCall(); - assertEquals(UID, workSources[0]); - // No UID propagated. - assertEquals(UID_NONE, workSources[1]); - // Initial work source restored. - assertEquals(UID, Binder.getCallingWorkSourceUid()); - } - - @Test public void workSourceProvider_default() throws Exception { Binder.clearCallingWorkSource(); mService.clearWorkSourceProvider(); @@ -177,6 +190,7 @@ public class BinderWorkSourceTest { } @Test + @Suppress // WorkSourceProvider is currently invoked only at the end of the binder call. public void workSourceProvider_customProvider() throws Exception { Binder.clearCallingWorkSource(); mService.clearWorkSourceProvider(); @@ -188,4 +202,16 @@ public class BinderWorkSourceTest { mService.clearWorkSourceProvider(); } } + + @Test + public void nestedSetWorkSouceNotPropagated() throws Exception { + Binder.setCallingWorkSourceUid(UID); + + int[] workSources = mNestedService.nestedCall(); + assertEquals(UID, workSources[0]); + // No UID propagated. + assertEquals(UID_NONE, workSources[1]); + // Initial work source restored. + assertEquals(UID, Binder.getCallingWorkSourceUid()); + } } diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java new file mode 100644 index 000000000000..0eba2edbb3c3 --- /dev/null +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 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.os; + +import static org.junit.Assert.assertEquals; + +import android.platform.test.annotations.Presubmit; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@RunWith(AndroidJUnit4.class) +public class ParcelTest { + private static final int WORK_SOURCE_1 = 1000; + private static final int WORK_SOURCE_2 = 1002; + private static final String INTERFACE_TOKEN_1 = "IBinder interface token"; + private static final String INTERFACE_TOKEN_2 = "Another IBinder interface token"; + + @Test + public void testCallingWorkSourceUidAfterWrite() { + Parcel p = Parcel.obtain(); + // Method does not throw if replaceCallingWorkSourceUid is called before requests headers + // are added. + assertEquals(false, p.replaceCallingWorkSourceUid(WORK_SOURCE_1)); + assertEquals(Binder.UNSET_WORKSOURCE, p.readCallingWorkSourceUid()); + + // WorkSource can be updated. + p.writeInterfaceToken(INTERFACE_TOKEN_1); + assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_1)); + assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid()); + + // WorkSource can be updated to unset value. + assertEquals(true, p.replaceCallingWorkSourceUid(Binder.UNSET_WORKSOURCE)); + assertEquals(Binder.UNSET_WORKSOURCE, p.readCallingWorkSourceUid()); + + p.recycle(); + } + + @Test + public void testCallingWorkSourceUidAfterEnforce() { + Parcel p = Parcel.obtain(); + // Write headers manually so that we do not invoke #writeInterfaceToken. + p.writeInt(1); // strict mode header + p.writeInt(WORK_SOURCE_1); // worksource header. + p.writeString(INTERFACE_TOKEN_1); // interface token. + p.setDataPosition(0); + + p.enforceInterface(INTERFACE_TOKEN_1); + assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid()); + + // WorkSource can be updated. + assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_1)); + assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid()); + + p.recycle(); + } + + @Test + public void testParcelWithMultipleHeaders() { + Parcel p = Parcel.obtain(); + Binder.setCallingWorkSourceUid(WORK_SOURCE_1); + p.writeInterfaceToken(INTERFACE_TOKEN_1); + Binder.setCallingWorkSourceUid(WORK_SOURCE_2); + p.writeInterfaceToken(INTERFACE_TOKEN_2); + p.setDataPosition(0); + + // WorkSource is from the first header. + p.enforceInterface(INTERFACE_TOKEN_1); + assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid()); + p.enforceInterface(INTERFACE_TOKEN_2); + assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid()); + + p.recycle(); + } +} diff --git a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java index d0719cbea86e..7855ef9c49ad 100644 --- a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java +++ b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java @@ -26,9 +26,6 @@ import android.app.Service; import android.app.UiAutomation; import android.graphics.Rect; import android.os.SystemClock; -import android.support.test.InstrumentationRegistry; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -36,6 +33,10 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityTestActivity; import android.view.accessibility.AccessibilityWindowInfo; +import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; + import com.android.compatibility.common.util.TestUtils; import com.android.frameworks.coretests.R; diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java index b07cb99f35c5..da81d176de8a 100644 --- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java @@ -24,6 +24,7 @@ import static junit.framework.Assert.assertTrue; import android.content.Context; import android.graphics.Insets; +import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.platform.test.annotations.Presubmit; @@ -80,7 +81,7 @@ public class ImeInsetsSourceConsumerTest { @Test public void testImeVisibility() { - final InsetsSourceControl ime = new InsetsSourceControl(TYPE_IME, mLeash); + final InsetsSourceControl ime = new InsetsSourceControl(TYPE_IME, mLeash, new Point()); mController.onControlsChanged(new InsetsSourceControl[] { ime }); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index 7cd3c44d9a4e..71ce02d859f5 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -19,13 +19,23 @@ package android.view; import static android.view.InsetsState.TYPE_NAVIGATION_BAR; import static android.view.InsetsState.TYPE_TOP_BAR; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.WindowInsets.Type.sideBars; +import static android.view.WindowInsets.Type.systemBars; +import static android.view.WindowInsets.Type.topBar; import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.graphics.Insets; import android.graphics.Matrix; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.platform.test.annotations.Presubmit; @@ -55,6 +65,7 @@ public class InsetsAnimationControlImplTest { private SurfaceSession mSession = new SurfaceSession(); private SurfaceControl mTopLeash; private SurfaceControl mNavLeash; + private InsetsState mInsetsState; @Mock Transaction mMockTransaction; @Mock InsetsController mMockController; @@ -63,6 +74,7 @@ public class InsetsAnimationControlImplTest { @Before public void setup() { + ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL; MockitoAnnotations.initMocks(this); mTopLeash = new SurfaceControl.Builder(mSession) .setName("testSurface") @@ -70,24 +82,25 @@ public class InsetsAnimationControlImplTest { mNavLeash = new SurfaceControl.Builder(mSession) .setName("testSurface") .build(); - InsetsState state = new InsetsState(); - state.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 500, 100)); - state.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500)); - InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, state, + mInsetsState = new InsetsState(); + mInsetsState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 500, 100)); + mInsetsState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500)); + InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, mInsetsState, () -> mMockTransaction, mMockController); - topConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mTopLeash)); + topConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mTopLeash, new Point(0, 0))); - InsetsSourceConsumer navConsumer = new InsetsSourceConsumer(TYPE_NAVIGATION_BAR, state, - () -> mMockTransaction, mMockController); + InsetsSourceConsumer navConsumer = new InsetsSourceConsumer(TYPE_NAVIGATION_BAR, + mInsetsState, () -> mMockTransaction, mMockController); navConsumer.hide(); - navConsumer.setControl(new InsetsSourceControl(TYPE_NAVIGATION_BAR, mNavLeash)); + navConsumer.setControl(new InsetsSourceControl(TYPE_NAVIGATION_BAR, mNavLeash, + new Point(400, 0))); SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); consumers.put(TYPE_TOP_BAR, topConsumer); consumers.put(TYPE_NAVIGATION_BAR, navConsumer); mController = new InsetsAnimationControlImpl(consumers, - new Rect(0, 0, 500, 500), state, mMockListener, WindowInsets.Type.systemBars(), - () -> mMockTransactionApplier, mock(InsetsController.class)); + new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(), + () -> mMockTransactionApplier, mMockController); } @Test @@ -95,7 +108,7 @@ public class InsetsAnimationControlImplTest { assertEquals(Insets.of(0, 100, 100, 0), mController.getShownStateInsets()); assertEquals(Insets.of(0, 0, 0, 0), mController.getHiddenStateInsets()); assertEquals(Insets.of(0, 100, 0, 0), mController.getCurrentInsets()); - assertEquals(WindowInsets.Type.systemBars(), mController.getTypes()); + assertEquals(systemBars(), mController.getTypes()); } @Test diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 8f2109676dfb..6dad6a22f7ea 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -27,6 +27,7 @@ import static junit.framework.Assert.assertTrue; import android.content.Context; import android.graphics.Insets; +import android.graphics.Point; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.WindowInsets.Type; @@ -74,11 +75,12 @@ public class InsetsControllerTest { Insets.of(10, 10, 10, 10), rect, rect, rect, rect), rect, rect); }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @Test public void testControlsChanged() { - InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash); + InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point()); mController.onControlsChanged(new InsetsSourceControl[] { control }); assertEquals(mLeash, mController.getSourceConsumer(TYPE_TOP_BAR).getControl().getLeash()); @@ -86,7 +88,7 @@ public class InsetsControllerTest { @Test public void testControlsRevoked() { - InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash); + InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point()); mController.onControlsChanged(new InsetsSourceControl[] { control }); mController.onControlsChanged(new InsetsSourceControl[0]); assertNull(mController.getSourceConsumer(TYPE_TOP_BAR).getControl()); @@ -94,22 +96,19 @@ public class InsetsControllerTest { @Test public void testAnimationEndState() { - final InsetsSourceControl navBar = new InsetsSourceControl(TYPE_NAVIGATION_BAR, mLeash); - final InsetsSourceControl topBar = new InsetsSourceControl(TYPE_TOP_BAR, mLeash); - final InsetsSourceControl ime = new InsetsSourceControl(TYPE_IME, mLeash); + InsetsSourceControl[] controls = prepareControls(); + InsetsSourceControl navBar = controls[0]; + InsetsSourceControl topBar = controls[1]; + InsetsSourceControl ime = controls[2]; - InsetsSourceControl[] controls = new InsetsSourceControl[3]; - controls[0] = navBar; - controls[1] = topBar; - controls[2] = ime; - mController.onControlsChanged(controls); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { mController.show(Type.all()); // quickly jump to final state by cancelling it. mController.cancelExistingAnimation(); assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible()); assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); - assertTrue(mController.getSourceConsumer(ime.getType()).isVisible()); + // no focused view, no IME. + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); mController.hide(Type.all()); mController.cancelExistingAnimation(); @@ -119,11 +118,175 @@ public class InsetsControllerTest { mController.show(Type.ime()); mController.cancelExistingAnimation(); + // no focused view, no IME. + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @Test + public void testApplyImeVisibility() { + final InsetsSourceControl ime = new InsetsSourceControl(TYPE_IME, mLeash, new Point()); + + InsetsSourceControl[] controls = new InsetsSourceControl[3]; + controls[0] = ime; + mController.onControlsChanged(controls); + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mController.applyImeVisibility(true); + mController.cancelExistingAnimation(); assertTrue(mController.getSourceConsumer(ime.getType()).isVisible()); + mController.applyImeVisibility(false); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } - mController.hide(Type.ime()); + @Test + public void testShowHideSelectively() { + InsetsSourceControl[] controls = prepareControls(); + InsetsSourceControl navBar = controls[0]; + InsetsSourceControl topBar = controls[1]; + InsetsSourceControl ime = controls[2]; + + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + int types = Type.sideBars() | Type.systemBars(); + // test show select types. + mController.show(types); mController.cancelExistingAnimation(); + assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + // test hide all + mController.hide(types); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @Test + public void testShowHideSingle() { + InsetsSourceControl[] controls = prepareControls(); + InsetsSourceControl navBar = controls[0]; + InsetsSourceControl topBar = controls[1]; + InsetsSourceControl ime = controls[2]; + + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + int types = Type.sideBars() | Type.systemBars(); + // test show select types. + mController.show(types); + mController.cancelExistingAnimation(); + assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + // test hide all + mController.hide(Type.all()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + // test single show + mController.show(Type.sideBars()); + mController.cancelExistingAnimation(); + assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + // test single hide + mController.hide(Type.sideBars()); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @Test + public void testShowHideMultiple() { + InsetsSourceControl[] controls = prepareControls(); + InsetsSourceControl navBar = controls[0]; + InsetsSourceControl topBar = controls[1]; + InsetsSourceControl ime = controls[2]; + + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + // start two animations and see if previous is cancelled and final state is reached. + mController.show(Type.sideBars()); + mController.show(Type.systemBars()); + mController.cancelExistingAnimation(); + assertTrue(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + mController.hide(Type.sideBars()); + mController.hide(Type.systemBars()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + int types = Type.sideBars() | Type.systemBars(); + // show two at a time and hide one by one. + mController.show(types); + mController.hide(Type.sideBars()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + mController.hide(Type.systemBars()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + @Test + public void testShowMultipleHideOneByOne() { + InsetsSourceControl[] controls = prepareControls(); + InsetsSourceControl navBar = controls[0]; + InsetsSourceControl topBar = controls[1]; + InsetsSourceControl ime = controls[2]; + + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + int types = Type.sideBars() | Type.systemBars(); + // show two at a time and hide one by one. + mController.show(types); + mController.hide(Type.sideBars()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertTrue(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + + mController.hide(Type.systemBars()); + mController.cancelExistingAnimation(); + assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); + assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + private InsetsSourceControl[] prepareControls() { + final InsetsSourceControl navBar = new InsetsSourceControl(TYPE_NAVIGATION_BAR, mLeash, + new Point()); + final InsetsSourceControl topBar = new InsetsSourceControl(TYPE_TOP_BAR, mLeash, + new Point()); + final InsetsSourceControl ime = new InsetsSourceControl(TYPE_IME, mLeash, new Point()); + + InsetsSourceControl[] controls = new InsetsSourceControl[3]; + controls[0] = navBar; + controls[1] = topBar; + controls[2] = ime; + mController.onControlsChanged(controls); + return controls; } } diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 82cd2131ab4e..66146c936dca 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import android.graphics.Point; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl.Transaction; @@ -56,7 +57,7 @@ public class InsetsSourceConsumerTest { .build(); mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(), () -> mMockTransaction, mMockController); - mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash)); + mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point())); } @Test @@ -78,7 +79,7 @@ public class InsetsSourceConsumerTest { reset(mMockTransaction); mConsumer.hide(); verifyZeroInteractions(mMockTransaction); - mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash)); + mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash, new Point())); verify(mMockTransaction).hide(eq(mLeash)); } } diff --git a/core/tests/coretests/src/android/view/PinchZoomAction.java b/core/tests/coretests/src/android/view/PinchZoomAction.java index bec9b557a40d..cfdec4dc831a 100644 --- a/core/tests/coretests/src/android/view/PinchZoomAction.java +++ b/core/tests/coretests/src/android/view/PinchZoomAction.java @@ -16,20 +16,21 @@ package android.view; -import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; import static com.google.common.base.Preconditions.checkNotNull; import static org.hamcrest.Matchers.allOf; import android.os.SystemClock; -import android.support.test.espresso.InjectEventSecurityException; -import android.support.test.espresso.PerformException; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.Swiper; -import android.support.test.espresso.util.HumanReadables; + +import androidx.test.espresso.InjectEventSecurityException; +import androidx.test.espresso.PerformException; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.Swiper; +import androidx.test.espresso.util.HumanReadables; import org.hamcrest.Matcher; diff --git a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java index 199013513bb3..f63a4548b478 100644 --- a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java +++ b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java @@ -16,48 +16,43 @@ package android.view; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.matcher.ViewMatchers.withId; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.content.Context; -import android.test.ActivityInstrumentationTestCase2; import android.util.DisplayMetrics; import android.widget.TextView; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; @LargeTest -public class ScaleGestureDetectorTest extends ActivityInstrumentationTestCase2<ScaleGesture> { - private ScaleGesture mScaleGestureActivity; +public class ScaleGestureDetectorTest { - public ScaleGestureDetectorTest() { - super("com.android.frameworks.coretests", ScaleGesture.class); - } + @Rule + public final ActivityTestRule<ScaleGesture> mActivityRule = + new ActivityTestRule<>(ScaleGesture.class); + private ScaleGesture mScaleGestureActivity; @Before public void setUp() throws Exception { - super.setUp(); - injectInstrumentation(InstrumentationRegistry.getInstrumentation()); - mScaleGestureActivity = getActivity(); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); + mScaleGestureActivity = mActivityRule.getActivity(); } @Test public void testScaleGestureDetector() { // No scaling should have occurred prior to performing pinch zoom action. final float initialScaleFactor = 1.0f; - assertEquals(initialScaleFactor, mScaleGestureActivity.getScaleFactor()); + assertEquals(initialScaleFactor, mScaleGestureActivity.getScaleFactor(), 0f); // Specify start and end coordinates, irrespective of device display size. final DisplayMetrics dm = new DisplayMetrics(); diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java index 71612e685920..34fdebfdf348 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java @@ -155,5 +155,10 @@ public class ContentCaptureSessionTest { void internalNotifyViewTextChanged(AutofillId id, CharSequence text) { throw new UnsupportedOperationException("should not have been called"); } + + @Override + public void internalNotifyViewHierarchyEvent(boolean started) { + throw new UnsupportedOperationException("should not have been called"); + } } } diff --git a/core/tests/coretests/src/android/widget/EditorCursorTest.java b/core/tests/coretests/src/android/widget/EditorCursorTest.java index e4f55df6f683..585c601b84c6 100644 --- a/core/tests/coretests/src/android/widget/EditorCursorTest.java +++ b/core/tests/coretests/src/android/widget/EditorCursorTest.java @@ -16,11 +16,12 @@ package android.widget; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnLeft; import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnRight; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; + import static junit.framework.Assert.fail; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java index 483270e1f9ab..f6e02bc1f48a 100644 --- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java +++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java @@ -16,15 +16,6 @@ package android.widget; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.Espresso.pressBack; -import static android.support.test.espresso.action.ViewActions.clearText; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.replaceText; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; import static android.widget.espresso.DragHandleUtils.onHandleView; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem; @@ -37,43 +28,55 @@ import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsP import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.Espresso.pressBack; +import static androidx.test.espresso.action.ViewActions.clearText; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import android.content.res.TypedArray; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.ViewAssertion; -import android.test.ActivityInstrumentationTestCase2; import android.text.Selection; import android.text.Spannable; import android.text.Spanned; import android.text.TextPaint; import android.text.style.SuggestionSpan; import android.text.style.TextAppearanceSpan; -import android.view.View; import androidx.test.filters.SmallTest; +import androidx.test.rule.ActivityTestRule; import com.android.frameworks.coretests.R; +import org.junit.Rule; +import org.junit.Test; + /** * SuggestionsPopupWindowTest tests. * * TODO: Add tests for when there are no suggestions */ -public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> { +@SmallTest +public class SuggestionsPopupWindowTest { - public SuggestionsPopupWindowTest() { - super(TextViewActivity.class); - } + @Rule + public final ActivityTestRule<TextViewActivity> mActivityRule = + new ActivityTestRule<>(TextViewActivity.class); - @Override - protected void setUp() throws Exception { - super.setUp(); - getActivity(); + private TextViewActivity getActivity() { + return mActivityRule.getActivity(); } private void setSuggestionSpan(SuggestionSpan span, int start, int end) { - final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + final TextView textView = getActivity().findViewById(R.id.textview); textView.post( () -> { final Spannable text = (Spannable) textView.getText(); @@ -83,7 +86,7 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 getInstrumentation().waitForIdleSync(); } - @SmallTest + @Test public void testOnTextContextMenuItem() { final String text = "abc def ghi"; @@ -94,14 +97,14 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION); setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); - final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + final TextView textView = getActivity().findViewById(R.id.textview); textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE)); getInstrumentation().waitForIdleSync(); assertSuggestionsPopupIsDisplayed(); } - @SmallTest + @Test public void testSelectionActionMode() { final String text = "abc def ghi"; @@ -123,7 +126,7 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 assertSuggestionsPopupIsDisplayed(); } - @SmallTest + @Test public void testInsertionActionMode() { final String text = "abc def ghi"; @@ -146,13 +149,13 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 } private void showSuggestionsPopup() { - final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + final TextView textView = getActivity().findViewById(R.id.textview); textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE)); getInstrumentation().waitForIdleSync(); assertSuggestionsPopupIsDisplayed(); } - @SmallTest + @Test public void testSuggestionItems() { final String text = "abc def ghi"; @@ -190,7 +193,7 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 onView(withId(R.id.textview)).check(matches(withText("abc ghi"))); } - @SmallTest + @Test public void testMisspelled() { final String text = "abc def ghi"; @@ -217,7 +220,7 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 // TODO: Check if add to dictionary dialog is displayed. } - @SmallTest + @Test public void testEasyCorrect() { final String text = "abc def ghi"; @@ -253,7 +256,7 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 getActivity().getString(com.android.internal.R.string.delete)); } - @SmallTest + @Test public void testTextAppearanceInSuggestionsPopup() { final String text = "abc def ghi"; @@ -302,53 +305,49 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 assertSuggestionsPopupContainsItem( getActivity().getString(com.android.internal.R.string.delete)); - onSuggestionsPopup().check(new ViewAssertion() { - @Override - public void check(View view, NoMatchingViewException e) { - final ListView listView = (ListView) view.findViewById( - com.android.internal.R.id.suggestionContainer); - assertNotNull(listView); - final int childNum = listView.getChildCount(); - assertEquals(singleWordCandidates.length + multiWordCandidates.length, - childNum); - - for (int j = 0; j < childNum; j++) { - final TextView suggestion = (TextView) listView.getChildAt(j); - assertNotNull(suggestion); - final Spanned spanned = (Spanned) suggestion.getText(); - assertNotNull(spanned); - - // Check that the suggestion item order is kept. - final String expectedText; - if (j < singleWordCandidates.length) { - expectedText = "abc " + singleWordCandidates[j] + " ghi"; - } else { - expectedText = multiWordCandidates[j - singleWordCandidates.length]; - } - assertEquals(expectedText, spanned.toString()); - - // Check that the text is highlighted with correct color and text size. - final TextAppearanceSpan[] taSpan = spanned.getSpans( - text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class); - assertEquals(1, taSpan.length); - TextPaint tp = new TextPaint(); - taSpan[0].updateDrawState(tp); - assertEquals(expectedHighlightTextColor, tp.getColor()); - assertEquals(expectedHighlightTextSize, tp.getTextSize()); - - // Check the correct part of the text is highlighted. - final int expectedStart; - final int expectedEnd; - if (j < singleWordCandidates.length) { - expectedStart = text.indexOf('d'); - expectedEnd = text.indexOf('f') + 1; - } else { - expectedStart = 0; - expectedEnd = text.length(); - } - assertEquals(expectedStart, spanned.getSpanStart(taSpan[0])); - assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0])); + onSuggestionsPopup().check((view, e) -> { + final ListView listView = view.findViewById( + com.android.internal.R.id.suggestionContainer); + assertNotNull(listView); + final int childNum = listView.getChildCount(); + assertEquals(singleWordCandidates.length + multiWordCandidates.length, childNum); + + for (int j = 0; j < childNum; j++) { + final TextView suggestion = (TextView) listView.getChildAt(j); + assertNotNull(suggestion); + final Spanned spanned = (Spanned) suggestion.getText(); + assertNotNull(spanned); + + // Check that the suggestion item order is kept. + final String expectedText; + if (j < singleWordCandidates.length) { + expectedText = "abc " + singleWordCandidates[j] + " ghi"; + } else { + expectedText = multiWordCandidates[j - singleWordCandidates.length]; + } + assertEquals(expectedText, spanned.toString()); + + // Check that the text is highlighted with correct color and text size. + final TextAppearanceSpan[] taSpan = spanned.getSpans( + text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class); + assertEquals(1, taSpan.length); + TextPaint tp = new TextPaint(); + taSpan[0].updateDrawState(tp); + assertEquals(expectedHighlightTextColor, tp.getColor()); + assertEquals(expectedHighlightTextSize, tp.getTextSize(), 0f); + + // Check the correct part of the text is highlighted. + final int expectedStart; + final int expectedEnd; + if (j < singleWordCandidates.length) { + expectedStart = text.indexOf('d'); + expectedEnd = text.indexOf('f') + 1; + } else { + expectedStart = 0; + expectedEnd = text.length(); } + assertEquals(expectedStart, spanned.getSpanStart(taSpan[0])); + assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0])); } }); pressBack(); diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java index 41fa08b7e0e2..b4116681e723 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java @@ -16,15 +16,6 @@ package android.widget; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.Espresso.pressBack; -import static android.support.test.espresso.action.ViewActions.replaceText; -import static android.support.test.espresso.action.ViewActions.typeText; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled; import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled; import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed; @@ -42,6 +33,15 @@ import static android.widget.espresso.TextViewActions.mouseTripleClickOnTextAtIn import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; import static android.widget.espresso.TextViewAssertions.hasSelection; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.Espresso.pressBack; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + import android.app.Activity; import android.view.MotionEvent; import android.view.textclassifier.TextClassificationManager; diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 9d93421b1783..267a9c8601da 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -16,15 +16,6 @@ package android.widget; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.longClick; -import static android.support.test.espresso.action.ViewActions.pressKey; -import static android.support.test.espresso.action.ViewActions.replaceText; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates; import static android.widget.espresso.DragHandleUtils.onHandleView; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; @@ -44,6 +35,16 @@ import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText; import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; import static android.widget.espresso.TextViewAssertions.hasSelection; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.longClick; +import static androidx.test.espresso.action.ViewActions.pressKey; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -60,7 +61,6 @@ import android.app.Activity; import android.app.Instrumentation; import android.content.ClipData; import android.content.ClipboardManager; -import android.support.test.espresso.action.EspressoKey; import android.support.test.uiautomator.UiDevice; import android.text.InputType; import android.text.Selection; @@ -79,6 +79,7 @@ import android.view.textclassifier.TextLinksParams; import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider; import androidx.test.InstrumentationRegistry; +import androidx.test.espresso.action.EspressoKey; import androidx.test.filters.MediumTest; import androidx.test.filters.Suppress; import androidx.test.rule.ActivityTestRule; diff --git a/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java b/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java index 02ee9be825be..0f8faa884e3e 100644 --- a/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java @@ -16,28 +16,29 @@ package android.widget.espresso; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; -import static android.support.test.espresso.matcher.ViewMatchers.hasFocus; -import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast; -import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; -import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; -import android.support.test.espresso.NoMatchingRootException; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.ViewInteraction; -import android.support.test.espresso.matcher.ViewMatchers; import android.view.View; import android.widget.MenuPopupWindow.MenuDropDownListView; +import androidx.test.espresso.NoMatchingRootException; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.matcher.ViewMatchers; + import com.android.internal.view.menu.ListMenuItemView; import org.hamcrest.Description; diff --git a/core/tests/coretests/src/android/widget/espresso/CustomViewActions.java b/core/tests/coretests/src/android/widget/espresso/CustomViewActions.java index daf9e78c9b4e..217553ec480f 100644 --- a/core/tests/coretests/src/android/widget/espresso/CustomViewActions.java +++ b/core/tests/coretests/src/android/widget/espresso/CustomViewActions.java @@ -16,15 +16,15 @@ package android.widget.espresso; -import static android.support.test.espresso.action.ViewActions.actionWithAssertions; +import static androidx.test.espresso.action.ViewActions.actionWithAssertions; import android.view.View; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.CoordinatesProvider; -import android.support.test.espresso.action.GeneralClickAction; -import android.support.test.espresso.action.Press; -import android.support.test.espresso.action.Tap; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.CoordinatesProvider; +import androidx.test.espresso.action.GeneralClickAction; +import androidx.test.espresso.action.Press; +import androidx.test.espresso.action.Tap; import com.android.internal.util.Preconditions; diff --git a/core/tests/coretests/src/android/widget/espresso/DragAction.java b/core/tests/coretests/src/android/widget/espresso/DragAction.java index b2c8e38141b8..afdc4d379e5e 100644 --- a/core/tests/coretests/src/android/widget/espresso/DragAction.java +++ b/core/tests/coretests/src/android/widget/espresso/DragAction.java @@ -16,27 +16,30 @@ package android.widget.espresso; -import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; + import static com.android.internal.util.Preconditions.checkNotNull; + import static org.hamcrest.Matchers.allOf; + import android.annotation.Nullable; import android.os.SystemClock; -import android.support.test.espresso.UiController; -import android.support.test.espresso.PerformException; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.CoordinatesProvider; -import android.support.test.espresso.action.MotionEvents; -import android.support.test.espresso.action.PrecisionDescriber; -import android.support.test.espresso.action.Swiper; -import android.support.test.espresso.util.HumanReadables; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; -import org.hamcrest.Matcher; +import androidx.test.espresso.PerformException; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.CoordinatesProvider; +import androidx.test.espresso.action.MotionEvents; +import androidx.test.espresso.action.PrecisionDescriber; +import androidx.test.espresso.action.Swiper; +import androidx.test.espresso.util.HumanReadables; +import org.hamcrest.Matcher; /** * Drags on a View using touch events.<br> diff --git a/core/tests/coretests/src/android/widget/espresso/DragHandleUtils.java b/core/tests/coretests/src/android/widget/espresso/DragHandleUtils.java index 1693e548f7bd..1b849b587b3e 100644 --- a/core/tests/coretests/src/android/widget/espresso/DragHandleUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/DragHandleUtils.java @@ -16,22 +16,23 @@ package android.widget.espresso; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.isPlatformPopup; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; -import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; import static org.hamcrest.Matchers.allOf; -import android.support.test.espresso.NoMatchingRootException; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.ViewInteraction; import android.widget.Editor; +import androidx.test.espresso.NoMatchingRootException; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewInteraction; + public final class DragHandleUtils { private DragHandleUtils() {} diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java index 0355f82506d7..d45d4b04af33 100644 --- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java @@ -16,30 +16,31 @@ package android.widget.espresso; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.isPlatformPopup; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.isRoot; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withTagValue; -import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isRoot; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; -import android.support.test.espresso.NoMatchingRootException; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.ViewInteraction; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import androidx.test.espresso.NoMatchingRootException; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.ViewInteraction; + import com.android.internal.widget.FloatingToolbar; import org.hamcrest.Description; diff --git a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java index b50d6f42b7be..f56af5a04dc3 100644 --- a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java +++ b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java @@ -16,18 +16,19 @@ package android.widget.espresso; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.CoordinatesProvider; -import android.support.test.espresso.action.MotionEvents; -import android.support.test.espresso.action.MotionEvents.DownResultHolder; -import android.support.test.espresso.action.Press; -import android.support.test.espresso.action.Tapper; import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.CoordinatesProvider; +import androidx.test.espresso.action.MotionEvents; +import androidx.test.espresso.action.MotionEvents.DownResultHolder; +import androidx.test.espresso.action.Press; +import androidx.test.espresso.action.Tapper; + import org.hamcrest.Matcher; /** diff --git a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java index 022be7603dc1..abee7369414b 100644 --- a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java +++ b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java @@ -18,16 +18,19 @@ package android.widget.espresso; import static com.android.internal.util.Preconditions.checkNotNull; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - import android.annotation.IntDef; -import android.support.test.espresso.InjectEventSecurityException; -import android.support.test.espresso.UiController; +import android.os.SystemClock; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; +import androidx.test.espresso.InjectEventSecurityException; +import androidx.test.espresso.UiController; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Iterator; + /** * Class to wrap an UiController to overwrite source of motion events to SOURCE_MOUSE. * Note that this doesn't change the tool type. @@ -71,6 +74,32 @@ public final class MouseUiController implements UiController { return mUiController.injectMotionEvent(event); } + /** + * Copied from latest {@link androidx.test.espresso.UiController}, since current + * {@link androidx.test.espresso.UiController#injectMotionEventSequence(Iterable)} seems not a + * default method. + */ + @Override + public boolean injectMotionEventSequence(Iterable<MotionEvent> events) + throws InjectEventSecurityException { + android.util.Log.w( + "UIC", + "Using default injectMotionEventSeq() - this may not inject a sequence properly. " + + "If wrapping UIController please override this method and delegate."); + Iterator<MotionEvent> mei = events.iterator(); + boolean success = true; + while (mei.hasNext()) { + MotionEvent me = mei.next(); + if (me.getEventTime() - SystemClock.uptimeMillis() > 10) { + // Because the loopMainThreadForAtLeast is overkill for waiting, intentially only + // call it with a smaller amount of milliseconds as best effort + loopMainThreadForAtLeast(10); + } + success &= injectMotionEvent(me); + } + return success; + } + @Override public boolean injectString(String str) throws InjectEventSecurityException { return mUiController.injectString(str); diff --git a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java index b5a96ae6c49a..32c02403204f 100644 --- a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java @@ -16,36 +16,40 @@ package android.widget.espresso; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import org.hamcrest.Matcher; - -import android.support.test.espresso.NoMatchingRootException; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.ViewInteraction; -import android.support.test.espresso.action.GeneralLocation; -import android.support.test.espresso.action.Press; -import android.support.test.espresso.action.Tap; import android.view.View; +import androidx.test.espresso.NoMatchingRootException; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.action.GeneralLocation; +import androidx.test.espresso.action.Press; +import androidx.test.espresso.action.Tap; + +import org.hamcrest.Matcher; + public final class SuggestionsPopupwindowUtils { private static final int id = com.android.internal.R.id.suggestionWindowContainer; private SuggestionsPopupwindowUtils() {}; public static ViewInteraction onSuggestionsPopup() { + getInstrumentation().waitForIdleSync(); return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id)))); } private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) { + getInstrumentation().waitForIdleSync(); return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id)))); } diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java index b4c547e1fbb7..83ce67bd96ad 100644 --- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java +++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java @@ -16,16 +16,9 @@ package android.widget.espresso; -import static android.support.test.espresso.action.ViewActions.actionWithAssertions; +import static androidx.test.espresso.action.ViewActions.actionWithAssertions; import android.graphics.Rect; -import android.support.test.espresso.PerformException; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.CoordinatesProvider; -import android.support.test.espresso.action.GeneralLocation; -import android.support.test.espresso.action.Press; -import android.support.test.espresso.action.Tap; -import android.support.test.espresso.util.HumanReadables; import android.text.Layout; import android.view.MotionEvent; import android.view.View; @@ -33,6 +26,14 @@ import android.widget.Editor; import android.widget.Editor.HandleView; import android.widget.TextView; +import androidx.test.espresso.PerformException; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.CoordinatesProvider; +import androidx.test.espresso.action.GeneralLocation; +import androidx.test.espresso.action.Press; +import androidx.test.espresso.action.Tap; +import androidx.test.espresso.util.HumanReadables; + /** * A collection of actions on a {@link android.widget.TextView}. */ diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java index 5ed69e06178b..d638da56a896 100644 --- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java +++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java @@ -16,7 +16,7 @@ package android.widget.espresso; -import static android.support.test.espresso.matcher.ViewMatchers.assertThat; +import static androidx.test.espresso.matcher.ViewMatchers.assertThat; import static com.android.internal.util.Preconditions.checkNotNull; @@ -26,14 +26,15 @@ import static org.hamcrest.number.IsCloseTo.closeTo; import android.annotation.IntDef; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.test.espresso.NoMatchingViewException; -import android.support.test.espresso.ViewAssertion; import android.text.Spanned; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.TextView; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewAssertion; + import junit.framework.AssertionFailedError; import org.hamcrest.Matcher; diff --git a/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java index 8bce1b09517b..1e6447df334f 100644 --- a/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java +++ b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java @@ -16,17 +16,18 @@ package android.widget.espresso; -import org.hamcrest.Matcher; - -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.support.test.espresso.action.CoordinatesProvider; -import android.support.test.espresso.action.GeneralClickAction; -import android.support.test.espresso.action.PrecisionDescriber; -import android.support.test.espresso.action.Tapper; import android.view.View; import android.view.ViewConfiguration; +import androidx.test.espresso.UiController; +import androidx.test.espresso.ViewAction; +import androidx.test.espresso.action.CoordinatesProvider; +import androidx.test.espresso.action.GeneralClickAction; +import androidx.test.espresso.action.PrecisionDescriber; +import androidx.test.espresso.action.Tapper; + +import org.hamcrest.Matcher; + public final class ViewClickAction implements ViewAction { private final GeneralClickAction mGeneralClickAction; diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index 6b9e69cdb853..b6f56ada445e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -421,6 +421,83 @@ public class ChooserActivityTest { assertThat("text/plain", is(clipDescription.getMimeType(0))); } + @Test + public void oneVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed()))); + } + + @Test + public void twoVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed()))); + } + + @Test + public void threeOrMoreVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + uris.add(uri); + uris.add(uri); + uris.add(uri); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed())); + } + private Intent createSendTextIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); @@ -441,6 +518,20 @@ public class ChooserActivityTest { return sendIntent; } + private Intent createSendImageIntentWithPreview(ArrayList<Uri> uris) { + Intent sendIntent = new Intent(); + + if (uris.size() > 1) { + sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE); + sendIntent.putExtra(Intent.EXTRA_STREAM, uris); + } else { + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); + } + + return sendIntent; + } + private Intent createViewTextIntent() { Intent viewIntent = new Intent(); viewIntent.setAction(Intent.ACTION_VIEW); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index 637d2eafc7af..ec8122fb2e47 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -85,6 +85,15 @@ public class ChooserWrapperActivity extends ChooserActivity { return super.loadThumbnail(uri, size); } + @Override + protected boolean isImageType(String mimeType) { + if (sOverrides.previewThumbnail != null) { + return true; + } + + return super.isImageType(mimeType); + } + /** * We cannot directly mock the activity created since instrumentation creates it. * <p> diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index fe2fb8530cf6..7430c7ab23fc 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -16,12 +16,12 @@ package com.android.internal.app; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.internal.app.ResolverWrapperActivity.sOverrides; diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java index 3ddd8aaeba2c..64b7c2cce946 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java @@ -22,8 +22,9 @@ import static org.junit.Assert.assertTrue; import android.os.Process; import android.os.SystemClock; -import android.support.test.filters.LargeTest; -import android.support.test.runner.AndroidJUnit4; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; import com.android.internal.os.KernelCpuThreadReader.ProcessCpuUsage; import com.android.internal.os.KernelCpuThreadReader.ThreadCpuUsage; diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java index 2c597b14c557..79b847754311 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -138,6 +138,26 @@ public final class LooperStatsTest { } @Test + public void testThrewException_notSampled() { + TestableLooperStats looperStats = new TestableLooperStats(2, 100); + + Object token = looperStats.messageDispatchStarting(); + looperStats.tickRealtime(10); + looperStats.tickThreadTime(10); + looperStats.messageDispatched(token, mHandlerFirst.obtainMessage(0)); + assertThat(looperStats.getEntries()).hasSize(1); + + // Will not be sampled so does not contribute to any entries. + Object token2 = looperStats.messageDispatchStarting(); + looperStats.tickRealtime(100); + looperStats.tickThreadTime(10); + looperStats.dispatchingThrewException( + token2, mHandlerSecond.obtainMessage(7), new ArithmeticException()); + assertThat(looperStats.getEntries()).hasSize(1); + assertThat(looperStats.getEntries().get(0).messageCount).isEqualTo(1); + } + + @Test public void testMultipleMessagesDispatched() { TestableLooperStats looperStats = new TestableLooperStats(2, 100); diff --git a/core/tests/coretests/src/com/android/internal/statusbar/NotificationVisibilityTest.java b/core/tests/coretests/src/com/android/internal/statusbar/NotificationVisibilityTest.java index b740eccfb794..22432a82c232 100644 --- a/core/tests/coretests/src/com/android/internal/statusbar/NotificationVisibilityTest.java +++ b/core/tests/coretests/src/com/android/internal/statusbar/NotificationVisibilityTest.java @@ -19,8 +19,8 @@ package com.android.internal.statusbar; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java index 28a8afe434e4..0a729a98a6a8 100644 --- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java @@ -181,6 +181,11 @@ public class HdmiAudioSystemClientTest { } @Override + public void sendVolumeKeyEvent( + final int deviceType, final int keyCode, final boolean isPressed) { + } + + @Override public void oneTouchPlay(final IHdmiControlCallback callback) { } diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 035ee108c6da..bb4765835890 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -58,6 +58,14 @@ prebuilt_etc { } prebuilt_etc { + name: "privapp_whitelist_com.android.dialer", + product_specific: true, + sub_dir: "permissions", + src: "com.android.dialer.xml", + filename_from_src: true, +} + +prebuilt_etc { name: "privapp_whitelist_com.android.launcher3", product_specific: true, sub_dir: "permissions", diff --git a/data/etc/com.android.dialer.xml b/data/etc/com.android.dialer.xml new file mode 100644 index 000000000000..ccdb21fa5040 --- /dev/null +++ b/data/etc/com.android.dialer.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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 + --> +<permissions> + <privapp-permissions package="com.android.dialer"> + <permission name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"/> + <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/> + <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/> + <permission name="android.permission.MODIFY_PHONE_STATE"/> + <permission name="android.permission.STATUS_BAR"/> + <permission name="android.permission.STOP_APP_SWITCHES"/> + <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/> + <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/> + </privapp-permissions> +</permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index bcac5fd63930..0f35918232b4 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -22,6 +22,7 @@ applications that come with the platform <permissions> <privapp-permissions package="android.ext.services"> <permission name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" /> + <permission name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" /> </privapp-permissions> <privapp-permissions package="com.android.apps.tag"> @@ -48,17 +49,6 @@ applications that come with the platform <permission name="android.permission.WRITE_MEDIA_STORAGE"/> </privapp-permissions> - <privapp-permissions package="com.android.dialer"> - <permission name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"/> - <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/> - <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/> - <permission name="android.permission.MODIFY_PHONE_STATE"/> - <permission name="android.permission.STATUS_BAR"/> - <permission name="android.permission.STOP_APP_SWITCHES"/> - <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/> - <permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/> - </privapp-permissions> - <privapp-permissions package="com.android.emergency"> <!-- Required to place emergency calls from emergency info screen. --> <permission name="android.permission.CALL_PRIVILEGED"/> @@ -300,6 +290,7 @@ applications that come with the platform <permission name="android.permission.MOUNT_FORMAT_FILESYSTEMS"/> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.MOVE_PACKAGE"/> + <permission name="android.permission.OBSERVE_APP_USAGE"/> <permission name="android.permission.PACKAGE_USAGE_STATS" /> <permission name="android.permission.POWER_SAVER" /> <permission name="android.permission.READ_FRAME_BUFFER"/> diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 080c5d5e8368..18f0cae4733c 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -25,6 +25,7 @@ import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; import android.content.res.ResourcesImpl; import android.hardware.HardwareBuffer; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; @@ -77,7 +78,7 @@ public final class Bitmap implements Parcelable { */ private boolean mRequestPremultiplied; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769491) private byte[] mNinePatchChunk; // may be null @UnsupportedAppUsage private NinePatch.InsetStruct mNinePatchInsets; // may be null diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index cb1f69c0ada3..d07088b93039 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -1019,9 +1019,8 @@ public class Typeface { /** * This method is used by supportlib-v27. - * TODO: Remove private API use in supportlib: http://b/72665240 */ - @UnsupportedAppUsage + @UnsupportedAppUsage(trackingBug = 123768395) private static Typeface createFromFamiliesWithDefault( android.graphics.FontFamily[] families, int weight, int italic) { return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic); diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index d0fe022616c5..15f53f286261 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -42,7 +42,13 @@ namespace uirenderer { namespace skiapipeline { SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread) - : SkiaPipeline(thread), mVkManager(thread.vulkanManager()) {} + : SkiaPipeline(thread), mVkManager(thread.vulkanManager()) { + thread.renderState().registerContextCallback(this); +} + +SkiaVulkanPipeline::~SkiaVulkanPipeline() { + mRenderThread.renderState().removeContextCallback(this); +} MakeCurrentResult SkiaVulkanPipeline::makeCurrent() { return MakeCurrentResult::AlreadyCurrent; @@ -53,6 +59,8 @@ Frame SkiaVulkanPipeline::getFrame() { "drawRenderNode called on a context with no surface!"); SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface); + LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, + "drawRenderNode called on a context with an invalid surface"); if (backBuffer == nullptr) { SkDebugf("failed to get backbuffer"); return Frame(-1, -1, 0); @@ -153,6 +161,13 @@ sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThr return nullptr; } +void SkiaVulkanPipeline::onContextDestroyed() { + if (mVkSurface) { + mVkManager.destroySurface(mVkSurface); + mVkSurface = nullptr; + } +} + } /* namespace skiapipeline */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h index 934307636913..2c24edddb7e0 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h @@ -19,14 +19,16 @@ #include "SkiaPipeline.h" #include "renderthread/VulkanManager.h" +#include "renderstate/RenderState.h" + namespace android { namespace uirenderer { namespace skiapipeline { -class SkiaVulkanPipeline : public SkiaPipeline { +class SkiaVulkanPipeline : public SkiaPipeline, public IGpuContextCallback { public: explicit SkiaVulkanPipeline(renderthread::RenderThread& thread); - virtual ~SkiaVulkanPipeline() {} + virtual ~SkiaVulkanPipeline(); renderthread::MakeCurrentResult makeCurrent() override; renderthread::Frame getFrame() override; @@ -49,6 +51,9 @@ public: static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread, SkBitmap& skBitmap); +protected: + void onContextDestroyed() override; + private: renderthread::VulkanManager& mVkManager; renderthread::VulkanSurface* mVkSurface = nullptr; diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp index 2f8d381f15f5..fe2d41ef630b 100644 --- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp @@ -43,7 +43,9 @@ VkFunctorDrawHandler::VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_ha , mImageInfo(image_info) {} VkFunctorDrawHandler::~VkFunctorDrawHandler() { - mFunctorHandle->postDrawVk(); + if (mDrawn) { + mFunctorHandle->postDrawVk(); + } } void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) { @@ -77,6 +79,7 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) { params.format = vulkan_info.fFormat; mFunctorHandle->drawVk(params); + mDrawn = true; vulkan_info.fDrawBounds->offset.x = mClip.fLeft; vulkan_info.fDrawBounds->offset.y = mClip.fTop; diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkFunctorDrawable.h index 1a53c8fd55db..d3f97773b91d 100644 --- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h +++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.h @@ -44,6 +44,8 @@ private: const SkMatrix mMatrix; const SkIRect mClip; const SkImageInfo mImageInfo; + + bool mDrawn = false; }; /** diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 6c04232ab7f5..6da80628be60 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -117,7 +117,6 @@ void CacheManager::configureContext(GrContextOptions* contextOptions, const void auto& cache = skiapipeline::ShaderCache::get(); cache.initShaderDiskCache(identity, size); contextOptions->fPersistentCache = &cache; - contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting; } void CacheManager::trimMemory(TrimMemoryMode mode) { diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 8bef35915c4d..3b37c83a6acc 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -203,11 +203,17 @@ void RenderThread::requireGlContext() { void RenderThread::destroyRenderingContext() { mFunctorManager.onContextDestroyed(); - if (mEglManager->hasEglContext()) { - setGrContext(nullptr); - mEglManager->destroy(); + if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { + if (mEglManager->hasEglContext()) { + setGrContext(nullptr); + mEglManager->destroy(); + } + } else { + if (vulkanManager().hasVkContext()) { + setGrContext(nullptr); + vulkanManager().destroy(); + } } - vulkanManager().destroy(); } void RenderThread::dumpGraphicsMemory(int fd) { diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 582d51e6af94..90397fddf618 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -89,7 +89,7 @@ void VulkanManager::destroy() { mPhysicalDeviceFeatures2 = {}; } -bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) { +void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) { VkResult err; constexpr VkApplicationInfo app_info = { @@ -107,15 +107,11 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe uint32_t extensionCount = 0; err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - if (VK_SUCCESS != err) { - return false; - } + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err); std::unique_ptr<VkExtensionProperties[]> extensions( new VkExtensionProperties[extensionCount]); err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.get()); - if (VK_SUCCESS != err) { - return false; - } + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err); bool hasKHRSurfaceExtension = false; bool hasKHRAndroidSurfaceExtension = false; for (uint32_t i = 0; i < extensionCount; ++i) { @@ -127,10 +123,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe hasKHRAndroidSurfaceExtension = true; } } - if (!hasKHRSurfaceExtension || !hasKHRAndroidSurfaceExtension) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(!hasKHRSurfaceExtension || !hasKHRAndroidSurfaceExtension); } const VkInstanceCreateInfo instance_create = { @@ -146,10 +139,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe GET_PROC(CreateInstance); err = mCreateInstance(&instance_create, nullptr, &mInstance); - if (err < 0) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(err < 0); GET_INST_PROC(DestroyInstance); GET_INST_PROC(EnumeratePhysicalDevices); @@ -166,39 +156,23 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe GET_INST_PROC(GetPhysicalDeviceSurfacePresentModesKHR); uint32_t gpuCount; - err = mEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr); - if (err) { - this->destroy(); - return false; - } - if (!gpuCount) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(mEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr)); + LOG_ALWAYS_FATAL_IF(!gpuCount); // Just returning the first physical device instead of getting the whole array. Since there // should only be one device on android. gpuCount = 1; err = mEnumeratePhysicalDevices(mInstance, &gpuCount, &mPhysicalDevice); // VK_INCOMPLETE is returned when the count we provide is less than the total device count. - if (err && VK_INCOMPLETE != err) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(err && VK_INCOMPLETE != err); VkPhysicalDeviceProperties physDeviceProperties; mGetPhysicalDeviceProperties(mPhysicalDevice, &physDeviceProperties); - if (physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0)); // query to get the initial queue props size uint32_t queueCount; mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr); - if (!queueCount) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(!queueCount); // now get the actual queue props std::unique_ptr<VkQueueFamilyProperties[]> queueProps(new VkQueueFamilyProperties[queueCount]); @@ -212,10 +186,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe break; } } - if (mGraphicsQueueIndex == queueCount) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(mGraphicsQueueIndex == queueCount); // All physical devices and queue families on Android must be capable of // presentation with any native window. So just use the first one. @@ -225,18 +196,12 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe uint32_t extensionCount = 0; err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount, nullptr); - if (VK_SUCCESS != err) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err); std::unique_ptr<VkExtensionProperties[]> extensions( new VkExtensionProperties[extensionCount]); err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount, extensions.get()); - if (VK_SUCCESS != err) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err); bool hasKHRSwapchainExtension = false; for (uint32_t i = 0; i < extensionCount; ++i) { mDeviceExtensions.push_back(extensions[i].extensionName); @@ -244,10 +209,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe hasKHRSwapchainExtension = true; } } - if (!hasKHRSwapchainExtension) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension); } auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) { @@ -259,10 +221,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(), mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data()); - if (!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)); memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2)); features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; @@ -332,11 +291,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe nullptr, // ppEnabledFeatures }; - err = mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice); - if (err) { - this->destroy(); - return false; - } + LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice)); GET_DEV_PROC(GetDeviceQueue); GET_DEV_PROC(DeviceWaitIdle); @@ -366,8 +321,6 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe GET_DEV_PROC(DestroyFence); GET_DEV_PROC(WaitForFences); GET_DEV_PROC(ResetFences); - - return true; } void VulkanManager::initialize() { @@ -381,7 +334,7 @@ void VulkanManager::initialize() { LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0)); GrVkExtensions extensions; - LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2)); + this->setupDevice(extensions, mPhysicalDeviceFeatures2); mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue); @@ -419,7 +372,7 @@ void VulkanManager::initialize() { if (!setupDummyCommandBuffer()) { this->destroy(); - return; + // Pass through will crash on next line. } LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE); @@ -520,6 +473,9 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { destroySurface(surface); *surfaceOut = createSurface(window, colorMode, colorSpace, colorType); surface = *surfaceOut; + if (!surface) { + return nullptr; + } } VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface); diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 6426fe2808b7..1fe6c65b35b8 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -151,7 +151,7 @@ private: // Sets up the VkInstance and VkDevice objects. Also fills out the passed in // VkPhysicalDeviceFeatures struct. - bool setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&); + void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&); void destroyBuffers(VulkanSurface* surface); diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index e795b8119760..1aeefb84129f 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -85,12 +85,12 @@ interface ILocationManager boolean stopGnssBatch(); boolean injectLocation(in Location location); - // --- deprecated --- List<String> getAllProviders(); List<String> getProviders(in Criteria criteria, boolean enabledOnly); String getBestProvider(in Criteria criteria, boolean enabledOnly); ProviderProperties getProviderProperties(String provider); - String getNetworkProviderPackage(); + boolean isProviderPackage(String packageName); + void setLocationControllerExtraPackage(String packageName); String getLocationControllerExtraPackage(); void setLocationControllerExtraPackageEnabled(boolean enabled); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 63b57d166f1f..c027fd499033 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -934,6 +934,7 @@ public class LocationManager { * @hide */ @SystemApi + @TestApi @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(LocationRequest request, LocationListener listener, Looper looper) { @@ -963,6 +964,7 @@ public class LocationManager { * @hide */ @SystemApi + @TestApi @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(LocationRequest request, PendingIntent intent) { checkPendingIntent(intent); @@ -1293,6 +1295,7 @@ public class LocationManager { * @hide */ @SystemApi + @TestApi @RequiresPermission(WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) { Settings.Secure.putIntForUser( @@ -2410,17 +2413,18 @@ public class LocationManager { } /** - * Return the package that implements the {@link #NETWORK_PROVIDER} functionality. + * Returns true if the given package name matches a location provider package, and false + * otherwise. * * @hide */ @SystemApi - public @Nullable String getNetworkProviderPackage() { + public boolean isProviderPackage(String packageName) { try { - return mService.getNetworkProviderPackage(); + return mService.isProviderPackage(packageName); } catch (RemoteException e) { e.rethrowFromSystemServer(); - return null; + return false; } } diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java index 0480eab580ac..0caa0c5b377a 100644 --- a/location/java/android/location/LocationRequest.java +++ b/location/java/android/location/LocationRequest.java @@ -19,6 +19,7 @@ package android.location; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -90,6 +91,7 @@ import android.util.TimeUtils; * @hide */ @SystemApi +@TestApi public final class LocationRequest implements Parcelable { /** * Used with {@link #setQuality} to request the most accurate locations available. diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl index b1b8f0c7c3f7..79166ae3a9b0 100644 --- a/location/java/com/android/internal/location/ILocationProviderManager.aidl +++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl @@ -26,6 +26,8 @@ import com.android.internal.location.ProviderProperties; */ interface ILocationProviderManager { + void onSetAdditionalProviderPackages(in List<String> packageNames); + void onSetEnabled(boolean enabled); void onSetProperties(in ProviderProperties properties); diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt index c7212183a37e..67d64965ac96 100644 --- a/location/lib/api/current.txt +++ b/location/lib/api/current.txt @@ -19,6 +19,7 @@ package com.android.location.provider { method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle); method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource); method public void reportLocation(android.location.Location); + method public void setAdditionalProviderPackages(java.util.List<java.lang.String>); method public void setEnabled(boolean); method public void setProperties(com.android.location.provider.ProviderPropertiesUnbundled); field public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation"; diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java index 5bcec92c4fba..7cd7207c26a0 100644 --- a/location/lib/java/com/android/location/provider/LocationProviderBase.java +++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java @@ -36,6 +36,8 @@ import com.android.internal.location.ProviderRequest; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; /** * Base class for location providers implemented as unbundled services. @@ -88,6 +90,7 @@ public abstract class LocationProviderBase { @Nullable private volatile ILocationProviderManager mManager; private volatile ProviderProperties mProperties; private volatile boolean mEnabled; + private final ArrayList<String> mAdditionalProviderPackages; public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) { mTag = tag; @@ -99,6 +102,7 @@ public abstract class LocationProviderBase { mManager = null; mProperties = properties.getProviderProperties(); mEnabled = true; + mAdditionalProviderPackages = new ArrayList<>(0); } public IBinder getBinder() { @@ -160,6 +164,29 @@ public abstract class LocationProviderBase { } /** + * Sets a list of additional packages that should be considered as part of this location + * provider for the purposes of generating locations. This should generally only be used when + * another package may issue location requests on behalf of this package in the course of + * providing location. This will inform location services to treat the other packages as + * location providers as well. + */ + public void setAdditionalProviderPackages(List<String> packageNames) { + synchronized (mBinder) { + mAdditionalProviderPackages.clear(); + mAdditionalProviderPackages.addAll(packageNames); + } + + ILocationProviderManager manager = mManager; + if (manager != null) { + try { + manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages); + } catch (RemoteException | RuntimeException e) { + Log.w(mTag, e); + } + } + } + + /** * Returns true if this provider has been set as enabled. This will be true unless explicitly * set otherwise. */ @@ -275,6 +302,9 @@ public abstract class LocationProviderBase { public void setLocationProviderManager(ILocationProviderManager manager) { synchronized (mBinder) { try { + if (!mAdditionalProviderPackages.isEmpty()) { + manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages); + } manager.onSetProperties(mProperties); manager.onSetEnabled(mEnabled); } catch (RemoteException e) { diff --git a/media/Android.bp b/media/Android.bp index 1aefebe0a378..141d415cbaf3 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -102,7 +102,8 @@ metalava_updatable_media_args = " --error UnhiddenSystemApi " + "--hide MissingPermission --hide BroadcastBehavior " + "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " + "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " + - "--hide HiddenTypedefConstant " + "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi " + + " --show-annotation android.annotation.TestApi " droidstubs { name: "updatable-media-stubs", @@ -110,8 +111,7 @@ droidstubs { ":updatable-media-srcs-without-aidls", ":framework-media-annotation-srcs", ], - args: metalava_updatable_media_args + " --show-annotation android.annotation.SystemApi " + - " --show-annotation android.annotation.TestApi ", + args: metalava_updatable_media_args, // Ideally, sdk_version here should be "current_system", but "current - 1" is used // to avoid dependency cycle with framework. sdk_version: "28", diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java index 925ca0dd8a7d..f7afa31e6173 100644 --- a/media/apex/java/android/media/MediaPlayer2.java +++ b/media/apex/java/android/media/MediaPlayer2.java @@ -86,6 +86,12 @@ import java.util.concurrent.atomic.AtomicLong; /** * MediaPlayer2 class can be used to control playback of audio/video files and streams. * + * <p> + * This API is not generally intended for third party application developers. + * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> + * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a> + * for consistent behavior across all devices. + * * <p>Topics covered here are: * <ol> * <li><a href="#PlayerStates">Player states</a> diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java index 1d763ced3ca0..0af47e8902a3 100644 --- a/media/java/android/media/AudioRecordingConfiguration.java +++ b/media/java/android/media/AudioRecordingConfiguration.java @@ -402,7 +402,7 @@ public final class AudioRecordingConfiguration implements Parcelable { && (mClientPortId == that.mClientPortId) && (mClientSilenced == that.mClientSilenced) && (mDeviceSource == that.mDeviceSource) - && (mClientEffects.equals(that.mClientEffects)) - && (mDeviceEffects.equals(that.mDeviceEffects))); + && (Arrays.equals(mClientEffects, that.mClientEffects)) + && (Arrays.equals(mDeviceEffects, that.mDeviceEffects))); } } diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java index 4f74ec911499..963b1d1504e2 100644 --- a/media/java/android/media/CamcorderProfile.java +++ b/media/java/android/media/CamcorderProfile.java @@ -97,9 +97,33 @@ public class CamcorderProfile */ public static final int QUALITY_2160P = 8; + /** + * Quality level corresponding to the VGA (640 x 480) resolution. + * @hide + */ + public static final int QUALITY_VGA = 9; + + /** + * Quality level corresponding to 4k-DCI (4096 x 2160) resolution. + * @hide + */ + public static final int QUALITY_4KDCI = 10; + + /** + * Quality level corresponding to QHD (2560 x 1440) resolution + * @hide + */ + public static final int QUALITY_QHD = 11; + + /** + * Quality level corresponding to 2K (2048 x 1080) resolution + * @hide + */ + public static final int QUALITY_2K = 12; + // Start and end of quality list private static final int QUALITY_LIST_START = QUALITY_LOW; - private static final int QUALITY_LIST_END = QUALITY_2160P; + private static final int QUALITY_LIST_END = QUALITY_2K; /** * Time lapse quality level corresponding to the lowest available resolution. @@ -146,9 +170,34 @@ public class CamcorderProfile */ public static final int QUALITY_TIME_LAPSE_2160P = 1008; + /** + * Time lapse quality level corresponding to the VGA (640 x 480) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_VGA = 1009; + + /** + * Time lapse quality level corresponding to the 4k-DCI (4096 x 2160) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_4KDCI = 1010; + + /** + * Time lapse quality level corresponding to the QHD (2560 x 1440) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_QHD = 1011; + + /** + * Time lapse quality level corresponding to the 2K (2048 x 1080) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_2K = 1012; + + // Start and end of timelapse quality list private static final int QUALITY_TIME_LAPSE_LIST_START = QUALITY_TIME_LAPSE_LOW; - private static final int QUALITY_TIME_LAPSE_LIST_END = QUALITY_TIME_LAPSE_2160P; + private static final int QUALITY_TIME_LAPSE_LIST_END = QUALITY_TIME_LAPSE_2K; /** * High speed ( >= 100fps) quality level corresponding to the lowest available resolution. @@ -204,9 +253,27 @@ public class CamcorderProfile */ public static final int QUALITY_HIGH_SPEED_2160P = 2005; + /** + * High speed ( >= 100fps) quality level corresponding to the CIF (352 x 288) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_CIF = 2006; + + /** + * High speed ( >= 100fps) quality level corresponding to the VGA (640 x 480) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_VGA = 2007; + + /** + * High speed ( >= 100fps) quality level corresponding to the 4K-DCI (4096 x 2160) + * @hide + */ + public static final int QUALITY_HIGH_SPEED_4KDCI = 2008; + // Start and end of high speed quality list private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW; - private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P; + private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_4KDCI; /** * Default recording duration in seconds before the session is terminated. diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index ce631a43327b..cf5711d73278 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -18,8 +18,12 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.cas.V1_0.*; +import android.hardware.cas.V1_0.HidlCasPluginDescriptor; +import android.hardware.cas.V1_1.ICas; +import android.hardware.cas.V1_1.ICasListener; +import android.hardware.cas.V1_1.IMediaCasService; import android.media.MediaCasException.*; +import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IHwBinder; @@ -128,6 +132,9 @@ public final class MediaCas implements AutoCloseable { private class EventHandler extends Handler { private static final int MSG_CAS_EVENT = 0; + private static final int MSG_CAS_SESSION_EVENT = 1; + private static final String SESSION_KEY = "sessionId"; + private static final String DATA_KEY = "data"; public EventHandler(Looper looper) { super(looper); @@ -138,6 +145,12 @@ public final class MediaCas implements AutoCloseable { if (msg.what == MSG_CAS_EVENT) { mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, toBytes((ArrayList<Byte>) msg.obj)); + } else if (msg.what == MSG_CAS_SESSION_EVENT) { + Bundle bundle = msg.getData(); + ArrayList<Byte> sessionId = toByteArray(bundle.getByteArray(SESSION_KEY)); + mListener.onSessionEvent(MediaCas.this, + createFromSessionId(sessionId), msg.arg1, msg.arg2, + bundle.getByteArray(DATA_KEY)); } } } @@ -149,6 +162,20 @@ public final class MediaCas implements AutoCloseable { mEventHandler.sendMessage(mEventHandler.obtainMessage( EventHandler.MSG_CAS_EVENT, event, arg, data)); } + @Override + public void onSessionEvent(@NonNull ArrayList<Byte> sessionId, + int event, int arg, @Nullable ArrayList<Byte> data) + throws RemoteException { + Message msg = mEventHandler.obtainMessage(); + msg.what = EventHandler.MSG_CAS_SESSION_EVENT; + msg.arg1 = event; + msg.arg2 = arg; + Bundle bundle = new Bundle(); + bundle.putByteArray(EventHandler.SESSION_KEY, toBytes(sessionId)); + bundle.putByteArray(EventHandler.DATA_KEY, toBytes(data)); + msg.setData(bundle); + mEventHandler.sendMessage(msg); + } }; /** @@ -222,6 +249,20 @@ public final class MediaCas implements AutoCloseable { } /** + * Query if an object equal current Session object. + * + * @param obj an object to compare to current Session object. + * + * @return Whether input object equal current Session object. + */ + public boolean equals(Object obj) { + if (obj instanceof Session) { + return mSessionId.equals(((Session) obj).mSessionId); + } + return false; + } + + /** * Set the private data for a session. * * @param data byte array of the private data. @@ -282,6 +323,30 @@ public final class MediaCas implements AutoCloseable { } /** + * Send a session event to a CA system. The format of the event is + * scheme-specific and is opaque to the framework. + * + * @param event an integer denoting a scheme-specific event to be sent. + * @param arg a scheme-specific integer argument for the event. + * @param data a byte array containing scheme-specific data for the event. + * + * @throws IllegalStateException if the MediaCas instance is not valid. + * @throws MediaCasException for CAS-specific errors. + * @throws MediaCasStateException for CAS-specific state exceptions. + */ + public void sendSessionEvent(int event, int arg, @Nullable byte[] data) + throws MediaCasException { + validateInternalStates(); + + try { + MediaCasException.throwExceptionIfNeeded( + mICas.sendSessionEvent(mSessionId, event, arg, toByteArray(data))); + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + } + + /** * Close the session. * * @throws IllegalStateException if the MediaCas instance is not valid. @@ -362,7 +427,7 @@ public final class MediaCas implements AutoCloseable { */ public MediaCas(int CA_system_id) throws UnsupportedCasException { try { - mICas = getService().createPlugin(CA_system_id, mBinder); + mICas = getService().createPluginExt(CA_system_id, mBinder); } catch(Exception e) { Log.e(TAG, "Failed to create plugin: " + e); mICas = null; @@ -388,13 +453,28 @@ public final class MediaCas implements AutoCloseable { /** * Notify the listener of a scheme-specific event from the CA system. * - * @param MediaCas the MediaCas object to receive this event. + * @param mediaCas the MediaCas object to receive this event. + * @param event an integer whose meaning is scheme-specific. + * @param arg an integer whose meaning is scheme-specific. + * @param data a byte array of data whose format and meaning are + * scheme-specific. + */ + void onEvent(@NonNull MediaCas mediaCas, int event, int arg, @Nullable byte[] data); + + /** + * Notify the listener of a scheme-specific session event from CA system. + * + * @param mediaCas the MediaCas object to receive this event. + * @param session session object which the event is for. * @param event an integer whose meaning is scheme-specific. * @param arg an integer whose meaning is scheme-specific. * @param data a byte array of data whose format and meaning are * scheme-specific. */ - void onEvent(MediaCas MediaCas, int event, int arg, @Nullable byte[] data); + default void onSessionEvent(@NonNull MediaCas mediaCas, @NonNull Session session, + int event, int arg, @Nullable byte[] data) { + Log.d(TAG, "Received MediaCas Session event"); + } } /** @@ -543,7 +623,7 @@ public final class MediaCas implements AutoCloseable { } } - /** + /** * Initiate a provisioning operation for a CA system. * * @param provisionString string containing information needed for the @@ -603,4 +683,4 @@ public final class MediaCas implements AutoCloseable { protected void finalize() { close(); } -}
\ No newline at end of file +} diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 0c3d6255f871..c6c2fdd00674 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -3373,6 +3373,8 @@ final public class MediaCodec { /** * Change a video encoder's target bitrate on the fly. The value is an * Integer object containing the new bitrate in bps. + * + * @see #setParameters(Bundle) */ public static final String PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate"; @@ -3384,12 +3386,43 @@ final public class MediaCodec { * input-side of the encoder in that case. * The value is an Integer object containing the value 1 to suspend * or the value 0 to resume. + * + * @see #setParameters(Bundle) */ public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames"; /** + * When {@link #PARAMETER_KEY_SUSPEND} is present, the client can also + * optionally use this key to specify the timestamp (in micro-second) + * at which the suspend/resume operation takes effect. + * + * Note that the specified timestamp must be greater than or equal to the + * timestamp of any previously queued suspend/resume operations. + * + * The value is a long int, indicating the timestamp to suspend/resume. + * + * @see #setParameters(Bundle) + */ + public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us"; + + /** + * Specify an offset (in micro-second) to be added on top of the timestamps + * onward. A typical use case is to apply an adjust to the timestamps after + * a period of pause by the user. + * + * This parameter can only be used on an encoder in "surface-input" mode. + * + * The value is a long int, indicating the timestamp offset to be applied. + * + * @see #setParameters(Bundle) + */ + public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us"; + + /** * Request that the encoder produce a sync frame "soon". * Provide an Integer with the value 0. + * + * @see #setParameters(Bundle) */ public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync"; diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index c82b5f6f12a1..4ca0216c80f2 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -463,6 +463,63 @@ public final class MediaFormat { = "repeat-previous-frame-after"; /** + * Instruct the video encoder in "surface-input" mode to drop excessive + * frames from the source, so that the input frame rate to the encoder + * does not exceed the specified fps. + * + * The associated value is a float, representing the max frame rate to + * feed the encoder at. + * + * @hide + */ + public static final String KEY_MAX_FPS_TO_ENCODER + = "max-fps-to-encoder"; + + /** + * Instruct the video encoder in "surface-input" mode to limit the gap of + * timestamp between any two adjacent frames fed to the encoder to the + * specified amount (in micro-second). + * + * The associated value is a long int. When positive, it represents the max + * timestamp gap between two adjacent frames fed to the encoder. When negative, + * the absolute value represents a fixed timestamp gap between any two adjacent + * frames fed to the encoder. Note that this will also apply even when the + * original timestamp goes backward in time. Under normal conditions, such frames + * would be dropped and not sent to the encoder. + * + * The output timestamp will be restored to the original timestamp and will + * not be affected. + * + * This is used in some special scenarios where input frames arrive sparingly + * but it's undesirable to allocate more bits to any single frame, or when it's + * important to ensure all frames are captured (rather than captured in the + * correct order). + * + * @hide + */ + public static final String KEY_MAX_PTS_GAP_TO_ENCODER + = "max-pts-gap-to-encoder"; + + /** + * If specified when configuring a video encoder that's in "surface-input" + * mode, it will instruct the encoder to put the surface source in suspended + * state when it's connected. No video frames will be accepted until a resume + * operation (see {@link MediaCodec#PARAMETER_KEY_SUSPEND}), optionally with + * timestamp specified via {@link MediaCodec#PARAMETER_KEY_SUSPEND_TIME}, is + * received. + * + * The value is an integer, with 1 indicating to create with the surface + * source suspended, or 0 otherwise. The default value is 0. + * + * If this key is not set or set to 0, the surface source will accept buffers + * as soon as it's connected to the encoder (although they may not be encoded + * immediately). This key can be used when the client wants to prepare the + * encoder session in advance, but do not want to accept buffers immediately. + */ + public static final String KEY_CREATE_INPUT_SURFACE_SUSPENDED + = "create-input-buffers-suspended"; + + /** * If specified when configuring a video decoder rendering to a surface, * causes the decoder to output "blank", i.e. black frames to the surface * when stopped to clear out any previously displayed contents. diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 5f513207bd5f..e08dab48ce39 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -26,7 +26,6 @@ #include <media/AudioTrack.h> #include "SoundPool.h" #include "SoundPoolThread.h" -#include <media/AudioPolicyHelper.h> #include <media/NdkMediaCodec.h> #include <media/NdkMediaExtractor.h> #include <media/NdkMediaFormat.h> @@ -746,7 +745,8 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV // initialize track size_t afFrameCount; uint32_t afSampleRate; - audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes()); + audio_stream_type_t streamType = + AudioSystem::attributesToStreamType(*mSoundPool->attributes()); if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { afFrameCount = kDefaultFrameCount; } diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 3156732ef02b..416ef42d21a7 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -499,7 +499,5 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, color.g = g; color.b = b; - transaction->setColor(surfaceControl, color) - .setColorAlpha(surfaceControl, alpha) - .setColorDataspace(surfaceControl, static_cast<ui::Dataspace>(dataspace)); + transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast<ui::Dataspace>(dataspace)); } diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index 1e38f262be3f..7b4e32b407ae 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -16,22 +16,18 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <color name="nav_bar_ripple_background_color">#40ffffff</color> - <color name="car_accent">#356FE5</color> <!-- colors for user switcher --> <color name="car_user_switcher_background_color">#000000</color> - <color name="car_user_switcher_name_text_color">@color/car_body1_light</color> + <color name="car_user_switcher_name_text_color">@*android:color/car_body1_light</color> <color name="car_user_switcher_add_user_background_color">#131313</color> - <color name="car_nav_icon_fill_color">@color/car_grey_50</color> + <color name="car_nav_icon_fill_color">@*android:color/car_grey_50</color> <!-- colors for seekbar --> <color name="car_seekbar_track_background">#131315</color> - <color name="car_seekbar_track_secondary_progress">@color/car_accent</color> + <color name="car_seekbar_track_secondary_progress">@*android:color/car_accent</color> <!-- colors for volume dialog tint --> - <color name="car_volume_dialog_tint">@color/car_tint_light</color> + <color name="car_volume_dialog_tint">@*android:color/car_tint</color> - <!-- System ui can't depend on car libs so redefine. --> - <color name="car_grey_50">#fffafafa</color> - - <color name="docked_divider_background">@color/car_grey_50</color> + <color name="docked_divider_background">@*android:color/car_grey_50</color> <color name="system_bar_background_opaque">#ff172026</color> <color name="status_bar_background_color">#33000000</color> @@ -46,10 +42,6 @@ <!-- The color of the ripples on the untinted notifications --> <color name="notification_ripple_untinted_color">@color/ripple_material_light</color> - <color name="car_teal_700">#ff00796b</color> - <color name="car_grey_300">#ffe0e0e0</color> - <color name="car_grey_900">#ff212121</color> - <color name="keyguard_button_text_color">@android:color/black</color> <color name="list_divider_color">@*android:color/car_list_divider_light</color> diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index e66a46249ff1..2dba1d5bc257 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -105,8 +105,6 @@ public class CarStatusBar extends StatusBar implements mHvacController.connectToCarService(); CarSystemUIFactory factory = SystemUIFactory.getInstance(); - mCarFacetButtonController = factory.getCarDependencyComponent() - .getCarFacetButtonController(); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned(); if (!mDeviceIsProvisioned) { @@ -137,7 +135,7 @@ public class CarStatusBar extends StatusBar implements /** * Remove all content from navbars and rebuild them. Used to allow for different nav bars - * before and after the device is provisioned + * before and after the device is provisioned. . Also for change of density and font size. */ private void restartNavBars() { // remove and reattach all hvac components such that we don't keep a reference to unused @@ -253,6 +251,9 @@ public class CarStatusBar extends StatusBar implements super.makeStatusBarView(); mHvacController = new HvacController(mContext); + CarSystemUIFactory factory = SystemUIFactory.getInstance(); + mCarFacetButtonController = factory.getCarDependencyComponent() + .getCarFacetButtonController(); mNotificationPanelBackground = getDefaultWallpaper(); mScrimController.setScrimBehindDrawable(mNotificationPanelBackground); @@ -589,6 +590,7 @@ public class CarStatusBar extends StatusBar implements @Override public void onDensityOrFontScaleChanged() { super.onDensityOrFontScaleChanged(); + restartNavBars(); // Need to update the background on density changed in case the change was due to night // mode. mNotificationPanelBackground = getDefaultWallpaper(); diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml index 7fb51b9496b9..fe6581b37330 100644 --- a/packages/ExtServices/AndroidManifest.xml +++ b/packages/ExtServices/AndroidManifest.xml @@ -24,6 +24,8 @@ <uses-permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" /> + <application android:label="@string/app_name" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true"> diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java index fe931fff1fde..b6b229c770b2 100644 --- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java +++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java @@ -105,6 +105,7 @@ public class Assistant extends NotificationAssistantService { protected AssistantSettings.Factory mSettingsFactory = AssistantSettings.FACTORY; @VisibleForTesting protected AssistantSettings mSettings; + private SmsHelper mSmsHelper; public Assistant() { } @@ -122,6 +123,18 @@ public class Assistant extends NotificationAssistantService { mAgingHelper = new AgingHelper(getContext(), mNotificationCategorizer, new AgingCallback()); + mSmsHelper = new SmsHelper(this); + mSmsHelper.initialize(); + } + + @Override + public void onDestroy() { + // This null check is only for the unit tests as ServiceTestCase.tearDown calls onDestroy + // without having first called onCreate. + if (mSmsHelper != null) { + mSmsHelper.destroy(); + } + super.onDestroy(); } private void loadFile() { @@ -214,7 +227,8 @@ public class Assistant extends NotificationAssistantService { if (!isForCurrentUser(sbn)) { return null; } - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry); return createEnqueuedNotificationAdjustment( entry, suggestions.actions, suggestions.replies); @@ -261,7 +275,7 @@ public class Assistant extends NotificationAssistantService { Ranking ranking = getRanking(sbn.getKey(), rankingMap); if (ranking != null && ranking.getChannel() != null) { NotificationEntry entry = new NotificationEntry(mPackageManager, - sbn, ranking.getChannel()); + sbn, ranking.getChannel(), mSmsHelper); String key = getKey( sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId()); ChannelImpressions ci = mkeyToImpressions.getOrDefault(key, diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java index ce2c409bd379..546bec21a542 100644 --- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java +++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java @@ -27,6 +27,7 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.Person; import android.app.RemoteInput; +import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -56,15 +57,17 @@ public class NotificationEntry { private boolean mSeen; private boolean mExpanded; private boolean mIsShowActionEventLogged; + private SmsHelper mSmsHelper; public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn, - NotificationChannel channel) { + NotificationChannel channel, SmsHelper smsHelper) { mSbn = sbn; mChannel = channel; mPackageManager = packageManager; mPreChannelsNotification = isPreChannelsNotification(); mAttributes = calculateAudioAttributes(); mImportance = calculateInitialImportance(); + mSmsHelper = smsHelper; } private boolean isPreChannelsNotification() { @@ -192,7 +195,16 @@ public class NotificationEntry { protected boolean involvesPeople() { return isMessaging() || hasStyle(Notification.InboxStyle.class) - || hasPerson(); + || hasPerson() + || isDefaultSmsApp(); + } + + private boolean isDefaultSmsApp() { + ComponentName defaultSmsApp = mSmsHelper.getDefaultSmsApplication(); + if (defaultSmsApp == null) { + return false; + } + return mSbn.getPackageName().equals(defaultSmsApp.getPackageName()); } protected boolean isMessaging() { diff --git a/packages/ExtServices/src/android/ext/services/notification/SmsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmsHelper.java new file mode 100644 index 000000000000..07be0b8e5aa9 --- /dev/null +++ b/packages/ExtServices/src/android/ext/services/notification/SmsHelper.java @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2019 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.ext.services.notification; + +import static android.provider.Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL; + +import android.annotation.Nullable; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.util.Log; + +import com.android.internal.telephony.SmsApplication; + +/** + * A helper class for storing and retrieving the default SMS application. + */ +public class SmsHelper { + private static final String TAG = "SmsHelper"; + + private final Context mContext; + private ComponentName mDefaultSmsApplication; + private BroadcastReceiver mBroadcastReceiver; + + SmsHelper(Context context) { + mContext = context.getApplicationContext(); + } + + void initialize() { + if (mBroadcastReceiver == null) { + mDefaultSmsApplication = SmsApplication.getDefaultSmsApplication(mContext, false); + mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL.equals(intent.getAction())) { + mDefaultSmsApplication = + SmsApplication.getDefaultSmsApplication(mContext, false); + } else { + Log.w(TAG, "Unknown broadcast received: " + intent.getAction()); + } + } + }; + mContext.registerReceiver( + mBroadcastReceiver, + new IntentFilter(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL)); + } + } + + void destroy() { + if (mBroadcastReceiver != null) { + mContext.unregisterReceiver(mBroadcastReceiver); + mBroadcastReceiver = null; + } + } + + @Nullable + public ComponentName getDefaultSmsApplication() { + return mDefaultSmsApplication; + } +} diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java index b023b364a19b..90018e5f8e6d 100644 --- a/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java +++ b/packages/ExtServices/tests/src/android/ext/services/notification/AgingHelperTest.java @@ -67,6 +67,8 @@ public class AgingHelperTest { private IPackageManager mPackageManager; @Mock private AgingHelper.Callback mCallback; + @Mock + private SmsHelper mSmsHelper; private AgingHelper mAgingHelper; @@ -99,7 +101,7 @@ public class AgingHelperTest { public void testNoSnoozingOnPost() { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); StatusBarNotification sbn = generateSbn(channel.getId()); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); mAgingHelper.onNotificationPosted(entry); @@ -110,7 +112,7 @@ public class AgingHelperTest { public void testPostResetsSnooze() { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); StatusBarNotification sbn = generateSbn(channel.getId()); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); mAgingHelper.onNotificationPosted(entry); @@ -121,7 +123,7 @@ public class AgingHelperTest { public void testSnoozingOnSeen() { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); StatusBarNotification sbn = generateSbn(channel.getId()); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); entry.setSeen(); when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE); @@ -134,7 +136,7 @@ public class AgingHelperTest { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); StatusBarNotification sbn = generateSbn(channel.getId()); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); when(mCategorizer.getCategory(entry)).thenReturn(NotificationCategorizer.CATEGORY_PEOPLE); mAgingHelper.onNotificationSeen(entry); diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java index 0a95b83bdbe3..f6328149b076 100644 --- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java +++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java @@ -85,6 +85,7 @@ public class AssistantTest extends ServiceTestCase<Assistant> { @Mock INotificationManager mNoMan; @Mock AtomicFile mFile; @Mock IPackageManager mPackageManager; + @Mock SmsHelper mSmsHelper; Assistant mAssistant; Application mApplication; @@ -467,7 +468,7 @@ public class AssistantTest extends ServiceTestCase<Assistant> { public void testAssistantNeverIncreasesImportanceWhenSuggestingSilent() throws Exception { StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "min notif!", null); Adjustment adjust = mAssistant.createEnqueuedNotificationAdjustment(new NotificationEntry( - mPackageManager, sbn, P1C3), new ArrayList<>(), new ArrayList<>()); + mPackageManager, sbn, P1C3, mSmsHelper), new ArrayList<>(), new ArrayList<>()); assertEquals(IMPORTANCE_MIN, adjust.getSignals().getInt(Adjustment.KEY_IMPORTANCE)); } } diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java index 9223c3dfe2bc..2d44e79d0f82 100644 --- a/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java +++ b/packages/ExtServices/tests/src/android/ext/services/notification/NotificationEntryTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.app.NotificationChannel; import android.app.Person; +import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.media.AudioAttributes; @@ -59,6 +60,10 @@ public class NotificationEntryTest { private IPackageManager mPackageManager; @Mock private ApplicationInfo mAppInfo; + @Mock + private SmsHelper mSmsHelper; + + private static final String DEFAULT_SMS_PACKAGE_NAME = "foo"; @Rule public final TestableContext mContext = @@ -73,6 +78,15 @@ public class NotificationEntryTest { UserHandle.SYSTEM, null, 0); } + private StatusBarNotification generateSbn(String channelId, String packageName) { + Notification n = new Notification.Builder(mContext, channelId) + .setContentTitle("foo") + .build(); + + return new StatusBarNotification(packageName, packageName, 0, "tag", mUid, mUid, n, + UserHandle.SYSTEM, null, 0); + } + private StatusBarNotification generateSbn(Notification n) { return new StatusBarNotification(mPkg, mPkg, 0, "tag", mUid, mUid, n, UserHandle.SYSTEM, null, 0); @@ -86,6 +100,8 @@ public class NotificationEntryTest { when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())) .thenReturn(mAppInfo); mAppInfo.targetSdkVersion = Build.VERSION_CODES.P; + when(mSmsHelper.getDefaultSmsApplication()) + .thenReturn(new ComponentName(DEFAULT_SMS_PACKAGE_NAME, "bar")); } @Test @@ -96,7 +112,7 @@ public class NotificationEntryTest { people.add(new Person.Builder().setKey("mailto:testing@android.com").build()); sbn.getNotification().extras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, people); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); assertTrue(entry.involvesPeople()); } @@ -104,7 +120,23 @@ public class NotificationEntryTest { public void testNotPerson() { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); StatusBarNotification sbn = generateSbn(channel.getId()); - NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); + assertFalse(entry.involvesPeople()); + } + + @Test + public void testHasPerson_matchesDefaultSmsApp() { + NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); + StatusBarNotification sbn = generateSbn(channel.getId(), DEFAULT_SMS_PACKAGE_NAME); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); + assertTrue(entry.involvesPeople()); + } + + @Test + public void testHasPerson_doesntMatchDefaultSmsApp() { + NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); + StatusBarNotification sbn = generateSbn(channel.getId(), "abc"); + NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper); assertFalse(entry.involvesPeople()); } @@ -115,7 +147,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setStyle(new Notification.InboxStyle()) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertTrue(entry.hasStyle(Notification.InboxStyle.class)); } @@ -126,7 +159,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setStyle(new Notification.MessagingStyle("")) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertTrue(entry.hasStyle(Notification.MessagingStyle.class)); } @@ -137,7 +171,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setStyle(new Notification.BigPictureStyle()) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertFalse(entry.hasStyle(Notification.InboxStyle.class)); assertFalse(entry.hasStyle(Notification.MessagingStyle.class)); } @@ -148,7 +183,7 @@ public class NotificationEntryTest { channel.setSound(null, new AudioAttributes.Builder().setUsage(USAGE_ALARM).build()); NotificationEntry entry = new NotificationEntry( - mPackageManager, generateSbn(channel.getId()), channel); + mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper); assertTrue(entry.isAudioAttributesUsage(USAGE_ALARM)); } @@ -157,7 +192,7 @@ public class NotificationEntryTest { public void testIsNotAudioAttributes() { NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH); NotificationEntry entry = new NotificationEntry( - mPackageManager, generateSbn(channel.getId()), channel); + mPackageManager, generateSbn(channel.getId()), channel, mSmsHelper); assertFalse(entry.isAudioAttributesUsage(USAGE_ALARM)); } @@ -169,7 +204,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setCategory(Notification.CATEGORY_EMAIL) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertTrue(entry.isCategory(Notification.CATEGORY_EMAIL)); assertFalse(entry.isCategory(Notification.CATEGORY_MESSAGE)); @@ -182,7 +218,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setFlag(FLAG_FOREGROUND_SERVICE, true) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertTrue(entry.isOngoing()); } @@ -194,7 +231,8 @@ public class NotificationEntryTest { Notification n = new Notification.Builder(mContext, channel.getId()) .setFlag(FLAG_CAN_COLORIZE, true) .build(); - NotificationEntry entry = new NotificationEntry(mPackageManager, generateSbn(n), channel); + NotificationEntry entry = + new NotificationEntry(mPackageManager, generateSbn(n), channel, mSmsHelper); assertFalse(entry.isOngoing()); } diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index 5a81f8bc6566..36ee81308e98 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -20,7 +20,7 @@ android_library { "SettingsLibLayoutPreference", "SettingsLibActionButtonsPreference", "SettingsLibEntityHeaderWidgets", - "SettingsLibBarChartPreference" + "SettingsLibBarChartPreference", ], // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES @@ -34,4 +34,18 @@ android_library { } -// For the test package. +// NOTE: Keep this module in sync with ./common.mk +java_defaults { + name: "SettingsLibDefaults", + static_libs: [ + "androidx.annotation_annotation", + "androidx.lifecycle_lifecycle-common", + "androidx.legacy_legacy-support-v4", + "androidx.lifecycle_lifecycle-runtime", + "androidx.recyclerview_recyclerview", + "androidx.preference_preference", + "androidx.appcompat_appcompat", + "androidx.legacy_legacy-preference-v14", + "SettingsLib", + ], +} diff --git a/packages/SettingsLib/common.mk b/packages/SettingsLib/common.mk index 834b83b49ada..8c309ff97370 100644 --- a/packages/SettingsLib/common.mk +++ b/packages/SettingsLib/common.mk @@ -12,6 +12,11 @@ # # include frameworks/base/packages/SettingsLib/common.mk # +# During the conversion to Soong bluprint files, the equivalent +# functionality is provided by adding +# defaults: ["SettingsLibDefaults"], +# to the corresponding module. +# NOTE: keep this file and ./Android.bp in sync. LOCAL_STATIC_JAVA_LIBRARIES += \ androidx.annotation_annotation \ diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 3e904a34959e..d6448336e402 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -218,9 +218,9 @@ <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">HD audio</string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the Hearing Aid profile. --> - <string name="bluetooth_profile_hearing_aid">Hearing Aid</string> + <string name="bluetooth_profile_hearing_aid">Hearing Aids</string> <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. --> - <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aid</string> + <string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aids</string> <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. --> <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string> @@ -260,7 +260,7 @@ will set the HID profile as preferred. --> <string name="bluetooth_hid_profile_summary_use_for">Use for input</string> <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. --> - <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aid</string> + <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aids</string> <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] --> <string name="bluetooth_pairing_accept">Pair</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java index 9451b3620418..ec8bb80bee13 100644 --- a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java @@ -420,7 +420,7 @@ public class AppRestrictionsHelper { List<InputMethodInfo> getInputMethodList() { InputMethodManager imm = (InputMethodManager) getContext().getSystemService( Context.INPUT_METHOD_SERVICE); - return imm.getInputMethodList(); + return imm.getInputMethodListAsUser(mUser.getIdentifier()); } } } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index c03268381367..e8c728d358ea 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -166,6 +166,7 @@ <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.SUSPEND_APPS" /> + <uses-permission android:name="android.permission.OBSERVE_APP_USAGE" /> <uses-permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND" /> <!-- Permission needed to wipe the device for Test Harness Mode --> <uses-permission android:name="android.permission.ENABLE_TEST_HARNESS_MODE" /> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 815ae9ac225c..866b46f732d8 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -631,6 +631,14 @@ android:exported="true"> </provider> + <!-- Provides list and realistic previews of clock faces for the picker app. --> + <provider + android:name="com.android.keyguard.clock.ClockOptionsProvider" + android:authorities="com.android.keyguard.clock" + android:exported="true" + android:grantUriPermissions="true"> + </provider> + <receiver android:name=".statusbar.KeyboardShortcutsReceiver"> <intent-filter> diff --git a/packages/SystemUI/docs/physics-animation-layout.md b/packages/SystemUI/docs/physics-animation-layout.md index a67b5e873b2e..300f63a3d285 100644 --- a/packages/SystemUI/docs/physics-animation-layout.md +++ b/packages/SystemUI/docs/physics-animation-layout.md @@ -26,7 +26,7 @@ Returns a SpringForce instance to use for animations of the given property. This ### Animation Control Methods  -Once the layout has used the controller’s configuration properties to build the animations, the controller can use them to actually run animations. This is done for two reasons - reacting to a view being added or removed, or responding to another class (such as a touch handler or broadcast receiver) requesting an animation. ```onChildAdded``` and ```onChildRemoved``` are called automatically by the layout, giving the controller the opportunity to animate the child in/out. Custom methods are called by anyone with access to the controller instance to do things like expand, collapse, or move the child views. +Once the layout has used the controller’s configuration properties to build the animations, the controller can use them to actually run animations. This is done for two reasons - reacting to a view being added or removed, or responding to another class (such as a touch handler or broadcast receiver) requesting an animation. ```onChildAdded```, ```onChildRemoved```, and ```setChildVisibility``` are called automatically by the layout, giving the controller the opportunity to animate the child in/out/visible/gone. Custom methods are called by anyone with access to the controller instance to do things like expand, collapse, or move the child views. In either case, the controller has access to the layout’s protected ```animateValueForChildAtIndex(ViewProperty property, int index, float value)``` method. This method is used to actually run an animation. diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png Binary files differnew file mode 100644 index 000000000000..67f072f54795 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png Binary files differnew file mode 100644 index 000000000000..8d0e6ed493e6 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png Binary files differnew file mode 100644 index 000000000000..035a4dffb026 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png Binary files differnew file mode 100644 index 000000000000..1ac01135c211 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png Binary files differnew file mode 100644 index 000000000000..63927bc4deaf --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png Binary files differnew file mode 100644 index 000000000000..83d714bfcb05 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png Binary files differnew file mode 100644 index 000000000000..a538149ca3d8 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png Binary files differnew file mode 100644 index 000000000000..2bfd655e37de --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_clock.xml index 21c64e9c7dbe..f4a73765acc1 100644 --- a/packages/SystemUI/res-keyguard/layout/type_clock.xml +++ b/packages/SystemUI/res-keyguard/layout/type_clock.xml @@ -24,32 +24,8 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" - > - <TextView - android:id="@+id/header" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="50dp" - style="@style/widget_big" - android:textColor="@color/typeClockAccentColor" - android:text="@string/type_clock_header" - android:textSize="40dp" - /> - <TextView - android:id="@+id/hour" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="50dp" - style="@style/widget_big" - android:textSize="40dp" - /> - <TextView - android:id="@+id/minute" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="50dp" - style="@style/widget_big" - android:textSize="40dp" - /> - </com.android.keyguard.clock.TypographicClock> + android:paddingLeft="50dp" + style="@style/widget_big" + android:textSize="40dp" + /> </com.android.keyguard.clock.ClockLayout> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 41acf82a4567..94481e7fe456 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -402,8 +402,25 @@ number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item> </plurals> - <!-- Header for typographic clock face. [CHAR LIMIT=8] --> - <string name="type_clock_header">It\u2019s</string> + <!-- Time displayed on typographic clock face, which displays the time in words. + Example: + + It's + Four + Twenty + Nine + + This string requires two arguments: the first in the hours of the time and + the second is the minutes of the time. The hours string is obtained from + string-array type_clock_hours below and the minutes string is obtained + from string-array type_clock_minutes below. + + [CHAR LIMIT=8] --> + <plurals name="type_clock_header"> + <item quantity="one"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item> + <item quantity="few"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item> + <item quantity="other"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item> + </plurals> <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=12] --> <string-array name="type_clock_hours"> @@ -485,4 +502,17 @@ number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. <item>Fifty\nNine</item> </string-array> + <!-- Title for default clock face that will appear in the picker app next to a preview image of + the clock face. [CHAR LIMIT=8] --> + <string name="clock_title_default" translatable="false">Default</string> + <!-- Title for Bubble clock face that will appear in the picker app next to a preview image of + the clock face. [CHAR LIMIT=8] --> + <string name="clock_title_bubble" translatable="false">Bubble</string> + <!-- Title for Stretch clock face that will appear in the picker app next to a preview image of + the clock face. [CHAR LIMIT=8] --> + <string name="clock_title_stretch" translatable="false">Stretch</string> + <!-- Title for Typographic clock face that will appear in the picker app next to a preview image of + the clock face. [CHAR LIMIT=8] --> + <string name="clock_title_type" translatable="false">Type</string> + </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 1060211cebf5..a5c8eafb8e8f 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -23,8 +23,9 @@ <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_height</dimen> <!-- Minimum swipe distance to catch the swipe gestures to invoke assist or switch tasks. --> <dimen name="navigation_bar_min_swipe_distance">48dp</dimen> - <!-- The distance from a side of device of the navigation bar to start an edge swipe --> - <dimen name="navigation_bar_edge_swipe_threshold">48dp</dimen> + <!-- The default distance from a side of the device to start an edge swipe from --> + <dimen name="navigation_bar_default_edge_width">48dp</dimen> + <dimen name="navigation_bar_default_edge_height">500dp</dimen> <!-- thickness (height) of the dead zone at the top of the navigation bar, reducing false presses on navbar buttons; approx 2mm --> @@ -83,6 +84,9 @@ <!-- Increased height of a small notification in the status bar --> <dimen name="notification_min_height_increased">146dp</dimen> + <!-- Increased height of a collapsed media notification in the status bar --> + <dimen name="notification_min_height_media">160dp</dimen> + <!-- Height of a small notification in the status bar which was used before android N --> <dimen name="notification_min_height_legacy">64dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 56d9bf4c5f8f..5365dcf72f11 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1829,6 +1829,9 @@ <!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] --> <string name="nav_bar">Navigation bar</string> + <!-- Label for navigation edge panel for gestures [CHAR LIMIT=60] --> + <string name="nav_bar_edge_panel" translatable="false">Navigation bar Edge Panel</string> + <!-- SysUI Tuner: Button that controls layout of navigation bar [CHAR LIMIT=60] --> <string name="nav_bar_layout">Layout</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java index a6b66e70c122..ea6fb48c67e7 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java @@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import android.app.ActivityOptions; import android.content.Context; @@ -31,11 +32,20 @@ import android.os.Handler; public abstract class ActivityOptionsCompat { /** - * @return ActivityOptions for starting a task in split screen. + * @return ActivityOptions for starting a task in split screen as the primary window. */ public static ActivityOptions makeSplitScreenOptions(boolean dockTopLeft) { + return makeSplitScreenOptions(dockTopLeft, true); + } + + /** + * @return ActivityOptions for starting a task in split screen. + */ + public static ActivityOptions makeSplitScreenOptions(boolean dockTopLeft, boolean isPrimary) { final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + options.setLaunchWindowingMode(isPrimary + ? WINDOWING_MODE_SPLIT_SCREEN_PRIMARY + : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); options.setSplitScreenCreateMode(dockTopLeft ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT); diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 2ce69650b65c..d5bd2b202803 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -21,12 +21,15 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; +import android.os.Handler; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.WirelessUtils; @@ -206,6 +209,7 @@ public class CarrierTextController { protected void updateCarrierText() { boolean allSimsMissing = true; boolean anySimReadyAndInService = false; + boolean missingSimsWithSubs = false; CharSequence displayText = null; List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); @@ -252,6 +256,7 @@ public class CarrierTextController { // described above. displayText = makeCarrierStringOnEmergencyCapable( getMissingSimMessage(), subs.get(0).getCarrierName()); + missingSimsWithSubs = true; } else { // We don't have a SubscriptionInfo to get the emergency calls only from. // Grab it from the old sticky broadcast if possible instead. We can use it @@ -288,12 +293,14 @@ public class CarrierTextController { displayText = getAirplaneModeMessage(); } + Handler handler = Dependency.get(Dependency.MAIN_HANDLER); + final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo( + displayText, + displayText.toString().split(mSeparator.toString()), + anySimReadyAndInService && !missingSimsWithSubs, + subsIds); if (mCarrierTextCallback != null) { - mCarrierTextCallback.updateCarrierInfo(new CarrierTextCallbackInfo( - displayText, - displayText.toString().split(mSeparator.toString()), - anySimReadyAndInService, - subsIds)); + handler.post(() -> mCarrierTextCallback.updateCarrierInfo(info)); } } @@ -487,7 +494,8 @@ public class CarrierTextController { public final boolean anySimReady; public final int[] subscriptionIds; - CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers, + @VisibleForTesting + public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers, boolean anySimReady, int[] subscriptionIds) { this.carrierText = carrierText; this.listOfCarriers = listOfCarriers; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index 64c5b1754fa8..261f391839b3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -264,7 +264,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView */ private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm, final boolean shouldIncludeAuxiliarySubtypes) { - final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList(); + final List<InputMethodInfo> enabledImis = + imm.getEnabledInputMethodListAsUser(KeyguardUpdateMonitor.getCurrentUser()); // Number of the filtered IMEs int filteredImisCount = 0; diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java new file mode 100644 index 000000000000..812f2156d5d9 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import android.graphics.Bitmap; + +import java.util.function.Supplier; + +/** + * Metadata about an available clock face. + */ +final class ClockInfo { + + private final String mName; + private final String mTitle; + private final String mId; + private final Supplier<Bitmap> mThumbnail; + private final Supplier<Bitmap> mPreview; + + private ClockInfo(String name, String title, String id, + Supplier<Bitmap> thumbnail, Supplier<Bitmap> preview) { + mName = name; + mTitle = title; + mId = id; + mThumbnail = thumbnail; + mPreview = preview; + } + + /** + * Gets the non-internationalized name for the clock face. + */ + String getName() { + return mName; + } + + /** + * Gets the name (title) of the clock face to be shown in the picker app. + */ + String getTitle() { + return mTitle; + } + + /** + * Gets the ID of the clock face, used by the picker to set the current selection. + */ + String getId() { + return mId; + } + + /** + * Gets a thumbnail image of the clock. + */ + Bitmap getThumbnail() { + return mThumbnail.get(); + } + + /** + * Gets a potentially realistic preview image of the clock face. + */ + Bitmap getPreview() { + return mPreview.get(); + } + + static Builder builder() { + return new Builder(); + } + + static class Builder { + private String mName; + private String mTitle; + private String mId; + private Supplier<Bitmap> mThumbnail; + private Supplier<Bitmap> mPreview; + + public ClockInfo build() { + return new ClockInfo(mName, mTitle, mId, mThumbnail, mPreview); + } + + public Builder setName(String name) { + mName = name; + return this; + } + + public Builder setTitle(String title) { + mTitle = title; + return this; + } + + public Builder setId(String id) { + mId = id; + return this; + } + + public Builder setThumbnail(Supplier<Bitmap> thumbnail) { + mThumbnail = thumbnail; + return this; + } + + public Builder setPreview(Supplier<Bitmap> preview) { + mPreview = preview; + return this; + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index 3217ca6f489c..95981427b642 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -17,12 +17,15 @@ package com.android.keyguard.clock; import android.content.ContentResolver; import android.content.Context; +import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.view.LayoutInflater; +import com.android.keyguard.R; import com.android.systemui.plugins.ClockPlugin; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.ExtensionController.Extension; @@ -45,6 +48,7 @@ public final class ClockManager { private final LayoutInflater mLayoutInflater; private final ContentResolver mContentResolver; + private final List<ClockInfo> mClockInfos = new ArrayList<>(); /** * Observe settings changes to know when to switch the clock face. */ @@ -76,6 +80,36 @@ public final class ClockManager { mExtensionController = extensionController; mLayoutInflater = LayoutInflater.from(context); mContentResolver = context.getContentResolver(); + + Resources res = context.getResources(); + mClockInfos.add(ClockInfo.builder() + .setName("default") + .setTitle(res.getString(R.string.clock_title_default)) + .setId("default") + .setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.default_thumbnail)) + .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.default_preview)) + .build()); + mClockInfos.add(ClockInfo.builder() + .setName("bubble") + .setTitle(res.getString(R.string.clock_title_bubble)) + .setId(BubbleClockController.class.getName()) + .setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_thumbnail)) + .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_preview)) + .build()); + mClockInfos.add(ClockInfo.builder() + .setName("stretch") + .setTitle(res.getString(R.string.clock_title_stretch)) + .setId(StretchAnalogClockController.class.getName()) + .setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_thumbnail)) + .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_preview)) + .build()); + mClockInfos.add(ClockInfo.builder() + .setName("type") + .setTitle(res.getString(R.string.clock_title_type)) + .setId(TypeClockController.class.getName()) + .setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.type_thumbnail)) + .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.type_preview)) + .build()); } /** @@ -101,6 +135,13 @@ public final class ClockManager { } } + /** + * Get information about available clock faces. + */ + List<ClockInfo> getClockInfos() { + return mClockInfos; + } + private void setClockPlugin(ClockPlugin plugin) { for (int i = 0; i < mListeners.size(); i++) { // It probably doesn't make sense to supply the same plugin instances to multiple diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java new file mode 100644 index 000000000000..5ef35be8df51 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockOptionsProvider.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.os.ParcelFileDescriptor.AutoCloseOutputStream; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.Dependency; + +import java.io.FileNotFoundException; +import java.util.List; +import java.util.function.Supplier; + +/** + * Exposes custom clock face options and provides realistic preview images. + * + * APIs: + * + * /list_options: List the available clock faces, which has the following columns + * name: name of the clock face + * title: title of the clock face + * id: value used to set the clock face + * thumbnail: uri of the thumbnail image, should be /thumbnail/{name} + * preview: uri of the preview image, should be /preview/{name} + * + * /thumbnail/{id}: Opens a file stream for the thumbnail image for clock face {id}. + * + * /preview/{id}: Opens a file stream for the preview image for clock face {id}. + */ +public final class ClockOptionsProvider extends ContentProvider { + + private static final String TAG = "ClockOptionsProvider"; + private static final String KEY_LIST_OPTIONS = "/list_options"; + private static final String KEY_PREVIEW = "preview"; + private static final String KEY_THUMBNAIL = "thumbnail"; + private static final String COLUMN_NAME = "name"; + private static final String COLUMN_TITLE = "title"; + private static final String COLUMN_ID = "id"; + private static final String COLUMN_THUMBNAIL = "thumbnail"; + private static final String COLUMN_PREVIEW = "preview"; + private static final String MIME_TYPE_PNG = "image/png"; + private static final String CONTENT_SCHEME = "content"; + private static final String AUTHORITY = "com.android.keyguard.clock"; + + private final Supplier<List<ClockInfo>> mClocksSupplier; + + public ClockOptionsProvider() { + this(() -> Dependency.get(ClockManager.class).getClockInfos()); + } + + @VisibleForTesting + ClockOptionsProvider(Supplier<List<ClockInfo>> clocksSupplier) { + mClocksSupplier = clocksSupplier; + } + + @Override + public boolean onCreate() { + return true; + } + + @Override + public String getType(Uri uri) { + List<String> segments = uri.getPathSegments(); + if (segments.size() > 0 && (KEY_PREVIEW.equals(segments.get(0)) + || KEY_THUMBNAIL.equals(segments.get(0)))) { + return MIME_TYPE_PNG; + } + return "vnd.android.cursor.dir/clock_faces"; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + if (!KEY_LIST_OPTIONS.equals(uri.getPath())) { + return null; + } + MatrixCursor cursor = new MatrixCursor(new String[] { + COLUMN_NAME, COLUMN_TITLE, COLUMN_ID, COLUMN_THUMBNAIL, COLUMN_PREVIEW}); + List<ClockInfo> clocks = mClocksSupplier.get(); + for (int i = 0; i < clocks.size(); i++) { + ClockInfo clock = clocks.get(i); + cursor.newRow() + .add(COLUMN_NAME, clock.getName()) + .add(COLUMN_TITLE, clock.getTitle()) + .add(COLUMN_ID, clock.getId()) + .add(COLUMN_THUMBNAIL, createThumbnailUri(clock)) + .add(COLUMN_PREVIEW, createPreviewUri(clock)); + } + return cursor; + } + + @Override + public Uri insert(Uri uri, ContentValues initialValues) { + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + List<String> segments = uri.getPathSegments(); + if (segments.size() != 2 || !(KEY_PREVIEW.equals(segments.get(0)) + || KEY_THUMBNAIL.equals(segments.get(0)))) { + throw new FileNotFoundException("Invalid preview url"); + } + String id = segments.get(1); + if (TextUtils.isEmpty(id)) { + throw new FileNotFoundException("Invalid preview url, missing id"); + } + ClockInfo clock = null; + List<ClockInfo> clocks = mClocksSupplier.get(); + for (int i = 0; i < clocks.size(); i++) { + if (id.equals(clocks.get(i).getId())) { + clock = clocks.get(i); + break; + } + } + if (clock == null) { + throw new FileNotFoundException("Invalid preview url, id not found"); + } + return openPipeHelper(uri, MIME_TYPE_PNG, null, KEY_PREVIEW.equals(segments.get(0)) + ? clock.getPreview() : clock.getThumbnail(), new MyWriter()); + } + + private Uri createThumbnailUri(ClockInfo clock) { + return new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(KEY_THUMBNAIL) + .appendPath(clock.getId()) + .build(); + } + + private Uri createPreviewUri(ClockInfo clock) { + return new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(KEY_PREVIEW) + .appendPath(clock.getId()) + .build(); + } + + private static class MyWriter implements ContentProvider.PipeDataWriter<Bitmap> { + @Override + public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType, + Bundle opts, Bitmap bitmap) { + try (AutoCloseOutputStream os = new AutoCloseOutputStream(output)) { + bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); + } catch (Exception e) { + Log.w(TAG, "fail to write to pipe", e); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java index 5f9da3ee33bb..8feae53159ac 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java @@ -17,9 +17,14 @@ package com.android.keyguard.clock; import android.content.Context; import android.content.res.Resources; +import android.text.Annotation; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannedString; +import android.text.TextUtils; import android.text.format.DateFormat; +import android.text.style.ForegroundColorSpan; import android.util.AttributeSet; -import android.widget.LinearLayout; import android.widget.TextView; import com.android.keyguard.R; @@ -31,13 +36,14 @@ import java.util.TimeZone; /** * Clock that presents the time in words. */ -public class TypographicClock extends LinearLayout { +public class TypographicClock extends TextView { + private static final String ANNOTATION_COLOR = "color"; + + private final Resources mResources; private final String[] mHours; private final String[] mMinutes; - private TextView mHeaderText; - private TextView mHourText; - private TextView mMinuteText; + private final int mAccentColor; private Calendar mTime; private String mDescFormat; private TimeZone mTimeZone; @@ -54,9 +60,10 @@ public class TypographicClock extends LinearLayout { super(context, attrs, defStyleAttr); mTime = Calendar.getInstance(); mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern(); - Resources res = context.getResources(); - mHours = res.getStringArray(R.array.type_clock_hours); - mMinutes = res.getStringArray(R.array.type_clock_minutes); + mResources = context.getResources(); + mHours = mResources.getStringArray(R.array.type_clock_hours); + mMinutes = mResources.getStringArray(R.array.type_clock_minutes); + mAccentColor = mResources.getColor(R.color.typeClockAccentColor, null); } /** @@ -65,11 +72,28 @@ public class TypographicClock extends LinearLayout { public void onTimeChanged() { mTime.setTimeInMillis(System.currentTimeMillis()); setContentDescription(DateFormat.format(mDescFormat, mTime)); - final int hour = mTime.get(Calendar.HOUR); - mHourText.setText(mHours[hour % 12]); - final int minute = mTime.get(Calendar.MINUTE); - mMinuteText.setText(mMinutes[minute % 60]); - invalidate(); + final int hour = mTime.get(Calendar.HOUR) % 12; + final int minute = mTime.get(Calendar.MINUTE) % 60; + + // Get the quantity based on the hour for languages like Portuguese and Czech. + SpannedString typeTemplate = (SpannedString) mResources.getQuantityText( + R.plurals.type_clock_header, hour); + + // Find the "color" annotation and set the foreground color to the accent color. + Annotation[] annotations = typeTemplate.getSpans(0, typeTemplate.length(), + Annotation.class); + SpannableString spanType = new SpannableString(typeTemplate); + for (int i = 0; i < annotations.length; i++) { + Annotation annotation = annotations[i]; + String key = annotation.getValue(); + if (ANNOTATION_COLOR.equals(key)) { + spanType.setSpan(new ForegroundColorSpan(mAccentColor), + spanType.getSpanStart(annotation), spanType.getSpanEnd(annotation), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + + setText(TextUtils.expandTemplate(spanType, mHours[hour], mMinutes[minute])); } /** @@ -82,25 +106,6 @@ public class TypographicClock extends LinearLayout { mTime.setTimeZone(timeZone); } - /** - * Set the color of the text used to display the time. - * - * This is necessary when the wallpaper shown behind the clock on the - * lock screen changes. - */ - public void setTextColor(int color) { - mHourText.setTextColor(color); - mMinuteText.setTextColor(color); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mHeaderText = findViewById(R.id.header); - mHourText = findViewById(R.id.hour); - mMinuteText = findViewById(R.id.minute); - } - @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 404f2e541ba2..9a9a52f40227 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -186,7 +186,12 @@ public class BubbleController { * Set a listener to be notified of bubble expand events. */ public void setExpandListener(BubbleExpandListener listener) { - mExpandListener = listener; + mExpandListener = ((isExpanding, key) -> { + if (listener != null) { + listener.onBubbleExpandChanged(isExpanding, key); + } + mStatusBarWindowController.setBubbleExpanded(isExpanding); + }); if (mStackView != null) { mStackView.setExpandListener(mExpandListener); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 4f870f6ceffc..164406494250 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -38,6 +38,12 @@ public class ExpandedAnimationController extends PhysicsAnimationLayout.PhysicsAnimationController { /** + * How much to translate the bubbles when they're animating in/out. This value is multiplied by + * the bubble size. + */ + private static final int ANIMATE_TRANSLATION_FACTOR = 4; + + /** * The stack position from which the bubbles were expanded. Saved in {@link #expandFromStack} * and used to return to stack form in {@link #collapseBackToStack}. */ @@ -125,7 +131,10 @@ public class ExpandedAnimationController Set<DynamicAnimation.ViewProperty> getAnimatedProperties() { return Sets.newHashSet( DynamicAnimation.TRANSLATION_X, - DynamicAnimation.TRANSLATION_Y); + DynamicAnimation.TRANSLATION_Y, + DynamicAnimation.SCALE_X, + DynamicAnimation.SCALE_Y, + DynamicAnimation.ALPHA); } @Override @@ -147,13 +156,55 @@ public class ExpandedAnimationController @Override void onChildAdded(View child, int index) { - // TODO: Animate the new bubble into the row, and push the other bubbles out of the way. - child.setTranslationY(getExpandedY()); + // Pop in from the top. + // TODO: Reverse this when bubbles are at the bottom. + child.setTranslationX(getXForChildAtIndex(index)); + child.setTranslationY(getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR); + mLayout.animateValueForChild(DynamicAnimation.TRANSLATION_Y, child, getExpandedY()); + + // Animate the remaining bubbles to the correct X position. + for (int i = index + 1; i < mLayout.getChildCount(); i++) { + mLayout.animateValueForChildAtIndex( + DynamicAnimation.TRANSLATION_X, i, getXForChildAtIndex(i)); + } + } + + @Override + void onChildRemoved(View child, int index, Runnable finishRemoval) { + // Bubble pops out to the top. + // TODO: Reverse this when bubbles are at the bottom. + mLayout.animateValueForChild( + DynamicAnimation.ALPHA, child, 0f, finishRemoval); + mLayout.animateValueForChild( + DynamicAnimation.TRANSLATION_Y, + child, + getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR); + + // Animate the remaining bubbles to the correct X position. + for (int i = index; i < mLayout.getChildCount(); i++) { + mLayout.animateValueForChildAtIndex( + DynamicAnimation.TRANSLATION_X, i, getXForChildAtIndex(i)); + } } @Override - void onChildToBeRemoved(View child, int index, Runnable actuallyRemove) { - // TODO: Animate the bubble out, and pull the other bubbles into its position. - actuallyRemove.run(); + protected void setChildVisibility(View child, int index, int visibility) { + if (visibility == View.VISIBLE) { + // Set alpha to 0 but then become visible immediately so the animation is visible. + child.setAlpha(0f); + child.setVisibility(View.VISIBLE); + } + + // Fade in. + mLayout.animateValueForChild( + DynamicAnimation.ALPHA, + child, + /* value */ visibility == View.GONE ? 0f : 1f, + () -> super.setChildVisibility(child, index, visibility)); + } + + /** Returns the appropriate X translation value for a bubble at the given index. */ + private float getXForChildAtIndex(int index) { + return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * index; } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java index e4e6bc913cfd..a4ddbf752316 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java @@ -92,14 +92,18 @@ public class PhysicsAnimationLayout extends FrameLayout { abstract void onChildAdded(View child, int index); /** - * Called when a child is to be removed from the layout. Controllers can use this - * opportunity to animate out the new view before calling the provided callback to actually - * remove it. + * Called with a child view that has been removed from the layout, from the given index. The + * passed view has been removed from the layout and added back as a transient view, which + * renders normally, but is not part of the normal view hierarchy and will not be considered + * by getChildAt() and getChildCount(). * - * Controllers should be careful to ensure that actuallyRemove is called on all code paths - * or child views will never be removed. + * The controller can perform animations on the child (either manually, or by using + * {@link #animateValueForChild}), and then call finishRemoval when complete. + * + * finishRemoval must be called by implementations of this method, or transient views will + * never be removed. */ - abstract void onChildToBeRemoved(View child, int index, Runnable actuallyRemove); + abstract void onChildRemoved(View child, int index, Runnable finishRemoval); protected PhysicsAnimationLayout mLayout; @@ -112,6 +116,15 @@ public class PhysicsAnimationLayout extends FrameLayout { protected PhysicsAnimationLayout getLayout() { return mLayout; } + + /** + * Sets the child's visibility when it moves beyond or within the limits set by a call to + * {@link PhysicsAnimationLayout#setMaxRenderedChildren}. This can be overridden to animate + * this transition. + */ + protected void setChildVisibility(View child, int index, int visibility) { + child.setVisibility(visibility); + } } /** @@ -236,7 +249,7 @@ public class PhysicsAnimationLayout extends FrameLayout { // Tell the controller to animate this view out, and call the callback when it's // finished. - mController.onChildToBeRemoved(view, index, () -> { + mController.onChildRemoved(view, index, () -> { // Done animating, remove the transient view. removeTransientView(view); @@ -457,11 +470,16 @@ public class PhysicsAnimationLayout extends FrameLayout { /** Hides children beyond the max rendering count. */ private void setChildrenVisibility() { for (int i = 0; i < getChildCount(); i++) { - getChildAt(i).setVisibility( - // Ignore views that are animating out when calculating whether to hide the - // view. That is, if we're supposed to render 5 views, but 4 are animating out - // and will soon be removed, render up to 9 views temporarily. - i < mMaxRenderedChildren ? View.VISIBLE : View.GONE); + final int targetVisibility = i < mMaxRenderedChildren ? View.VISIBLE : View.GONE; + final View targetView = getChildAt(i); + + if (targetView.getVisibility() != targetVisibility) { + if (mController != null) { + mController.setChildVisibility(targetView, i, targetVisibility); + } else { + targetView.setVisibility(targetVisibility); + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java index 23c6fd3c6a9b..0c089a75aece 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java @@ -316,10 +316,10 @@ public class StackAnimationController extends } @Override - void onChildToBeRemoved(View child, int index, Runnable actuallyRemove) { + void onChildRemoved(View child, int index, Runnable finishRemoval) { // Animate the child out, actually removing it once its alpha is zero. mLayout.animateValueForChild( - DynamicAnimation.ALPHA, child, 0f, actuallyRemove); + DynamicAnimation.ALPHA, child, 0f, finishRemoval); mLayout.animateValueForChild(DynamicAnimation.SCALE_X, child, ANIMATE_IN_STARTING_SCALE); mLayout.animateValueForChild(DynamicAnimation.SCALE_Y, child, ANIMATE_IN_STARTING_SCALE); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index e338a3406d7f..325018227692 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -71,7 +71,7 @@ public class DozeFactory { new DozeScreenState(wrappedService, handler, params, wakeLock), createDozeScreenBrightness(context, wrappedService, sensorManager, host, params, handler), - new DozeWallpaperState(context), + new DozeWallpaperState(context, machine), new DozeDockHandler(context, machine, host, config, handler, dockManager) }); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java index be504ef5eb9c..ca9f24fd236f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java @@ -37,17 +37,20 @@ public class DozeWallpaperState implements DozeMachine.Part { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final IWallpaperManager mWallpaperManagerService; - private boolean mIsAmbientMode; private final DozeParameters mDozeParameters; + private final DozeMachine mMachine; + private boolean mIsAmbientMode; - public DozeWallpaperState(Context context) { - this(IWallpaperManager.Stub.asInterface( + public DozeWallpaperState(Context context, DozeMachine machine) { + this(machine, IWallpaperManager.Stub.asInterface( ServiceManager.getService(Context.WALLPAPER_SERVICE)), DozeParameters.getInstance(context)); } @VisibleForTesting - DozeWallpaperState(IWallpaperManager wallpaperManagerService, DozeParameters parameters) { + DozeWallpaperState(DozeMachine machine, IWallpaperManager wallpaperManagerService, + DozeParameters parameters) { + mMachine = machine; mWallpaperManagerService = wallpaperManagerService; mDozeParameters = parameters; } @@ -61,10 +64,13 @@ public class DozeWallpaperState implements DozeMachine.Part { case DOZE_AOD_PAUSING: case DOZE_AOD_PAUSED: case DOZE_REQUEST_PULSE: - case DOZE_PULSING: case DOZE_PULSE_DONE: isAmbientMode = true; break; + case DOZE_PULSING: + isAmbientMode = + mMachine.getPulseReason() != DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN; + break; default: isAmbientMode = false; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index c0ed4b97eaff..b865ce8d261a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -54,6 +54,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.Utils; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.graph.SignalDrawable; +import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R.dimen; import com.android.systemui.plugins.ActivityStarter; @@ -134,6 +135,15 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mDeviceProvisionedController = deviceProvisionedController; } + @VisibleForTesting + public QSFooterImpl(Context context, AttributeSet attrs) { + this(context, attrs, + Dependency.get(ActivityStarter.class), + Dependency.get(UserInfoController.class), + Dependency.get(NetworkController.class), + Dependency.get(DeviceProvisionedController.class)); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -476,32 +486,62 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mInfos[0].visible && mInfos[1].visible ? View.VISIBLE : View.GONE); } + @VisibleForTesting + protected int getSlotIndex(int subscriptionId) { + return SubscriptionManager.getSlotIndex(subscriptionId); + } + @Override public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { if (info.anySimReady) { boolean[] slotSeen = new boolean[SIM_SLOTS]; - for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { - int slot = SubscriptionManager.getSlotIndex(info.subscriptionIds[i]); - mInfos[slot].visible = true; - slotSeen[slot] = true; - mCarrierTexts[slot].setText(info.listOfCarriers[i].toString().trim()); - mCarrierGroups[slot].setVisibility(View.VISIBLE); - } - for (int i = 0; i < SIM_SLOTS; i++) { - if (!slotSeen[i]) { + if (info.listOfCarriers.length == info.subscriptionIds.length) { + for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { + int slot = getSlotIndex(info.subscriptionIds[i]); + if (slot >= SIM_SLOTS) { + Log.w(TAG, "updateInfoCarrier - slot: " + slot); + continue; + } + if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, + "Invalid SIM slot index for subscription: " + + info.subscriptionIds[i]); + continue; + } + mInfos[slot].visible = true; + slotSeen[slot] = true; + mCarrierTexts[slot].setText(info.listOfCarriers[i].toString().trim()); + mCarrierGroups[slot].setVisibility(View.VISIBLE); + } + for (int i = 0; i < SIM_SLOTS; i++) { + if (!slotSeen[i]) { + mInfos[i].visible = false; + mCarrierGroups[i].setVisibility(View.GONE); + } + } + } else { + // If there are sims ready but there are not the same number of carrier names as + // subscription ids, just show the full text in the first slot + mInfos[0].visible = true; + mCarrierTexts[0].setText(info.carrierText); + mCarrierGroups[0].setVisibility(View.VISIBLE); + for (int i = 1; i < SIM_SLOTS; i++) { mInfos[i].visible = false; + mCarrierTexts[i].setText(""); mCarrierGroups[i].setVisibility(View.GONE); } } - handleUpdateState(); } else { mInfos[0].visible = false; - mInfos[1].visible = false; mCarrierTexts[0].setText(info.carrierText); mCarrierGroups[0].setVisibility(View.VISIBLE); - mCarrierGroups[1].setVisibility(View.GONE); - handleUpdateState(); + for (int i = 1; i < SIM_SLOTS; i++) { + mInfos[i].visible = false; + mCarrierTexts[i].setText(""); + mCarrierGroups[i].setVisibility(View.GONE); + } } + handleUpdateState(); } @Override @@ -510,9 +550,14 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming) { - int slotIndex = SubscriptionManager.getSlotIndex(subId); + int slotIndex = getSlotIndex(subId); if (slotIndex >= SIM_SLOTS) { - Log.e(TAG, "setMobileDataIndicators - slot: " + slotIndex); + Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); + return; + } + if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, "Invalid SIM slot index for subscription: " + subId); + return; } mInfos[slotIndex].visible = statusIcon.visible; mInfos[slotIndex].mobileSignalIconId = statusIcon.icon; @@ -539,7 +584,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, boolean roaming; } - /** * TextView that changes its ellipsize value with its visibility. */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 2d64ecd99c88..74e82b270aa0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -67,6 +67,7 @@ import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.privacy.OngoingPrivacyDialog; +import com.android.systemui.privacy.PrivacyDialogBuilder; import com.android.systemui.privacy.PrivacyItem; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.qs.QSDetail.Callback; @@ -534,10 +535,12 @@ public class QuickStatusBarHeader extends RelativeLayout implements mActivityStarter.postStartActivityDismissingKeyguard(new Intent( AlarmClock.ACTION_SHOW_ALARMS),0); } else if (v == mPrivacyChip) { + // Makes sure that the builder is grabbed as soon as the chip is pressed + PrivacyDialogBuilder builder = mPrivacyChip.getBuilder(); + if (builder.getAppsAndTypes().size() == 0) return; Handler mUiHandler = new Handler(Looper.getMainLooper()); mUiHandler.post(() -> { - Dialog mDialog = new OngoingPrivacyDialog(mContext, - mPrivacyChip.getBuilder()).createDialog(); + Dialog mDialog = new OngoingPrivacyDialog(mContext, builder).createDialog(); mDialog.getWindow().setType( WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); SystemUIDialog.setShowForAllUsers(mDialog, true); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 5f04e56f28a4..7fcd59f7c931 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -235,7 +235,7 @@ public class DndTile extends QSTileImpl<BooleanState> { state.label = getTileLabel(); state.secondaryLabel = TextUtils.emptyIfNull(ZenModeConfig.getDescription(mContext, zen != Global.ZEN_MODE_OFF, mController.getConfig(), false)); - state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on); + state.icon = ResourceIcon.get(R.drawable.ic_dnd); checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 31d16211f521..491f310cedf2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -54,6 +54,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.ShadeController; @@ -231,7 +232,8 @@ public class NotificationRemoteInputManager implements Dumpable { return false; } - return activateRemoteInput(view, inputs, input, pendingIntent); + return activateRemoteInput(view, inputs, input, pendingIntent, + null /* editedSuggestionInfo */); } }; @@ -291,6 +293,19 @@ public class NotificationRemoteInputManager implements Dumpable { } try { mBarService.onNotificationDirectReplied(entry.notification.getKey()); + if (entry.editedSuggestionInfo != null) { + boolean modifiedBeforeSending = + !TextUtils.equals(entry.remoteInputText, + entry.editedSuggestionInfo.originalText); + mBarService.onNotificationSmartReplySent( + entry.notification.getKey(), + entry.editedSuggestionInfo.index, + entry.editedSuggestionInfo.originalText, + NotificationLogger + .getNotificationLocation(entry) + .toMetricsEventEnum(), + modifiedBeforeSending); + } } catch (RemoteException e) { // Nothing to do, system going down } @@ -310,10 +325,12 @@ public class NotificationRemoteInputManager implements Dumpable { * @param inputs The remote inputs that need to be sent to the app. * @param input The remote input that needs to be activated. * @param pendingIntent The pending intent to be sent to the app. + * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or + * {@code null} if the user is not editing a smart reply. * @return Whether the {@link RemoteInput} was activated. */ public boolean activateRemoteInput(View view, RemoteInput[] inputs, RemoteInput input, - PendingIntent pendingIntent) { + PendingIntent pendingIntent, @Nullable EditedSuggestionInfo editedSuggestionInfo) { ViewParent p = view.getParent(); RemoteInputView riv = null; @@ -386,7 +403,7 @@ public class NotificationRemoteInputManager implements Dumpable { riv.setRevealParameters(cx, cy, r); riv.setPendingIntent(pendingIntent); - riv.setRemoteInput(inputs, input); + riv.setRemoteInput(inputs, input, editedSuggestionInfo); riv.focusAnimated(); return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java index 5a8f71d6627d..736b9ebea5c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java @@ -56,13 +56,12 @@ public class SmartReplyController { * Notifies StatusBarService a smart reply is sent. */ public void smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply, - boolean generatedByAssistant, int notificationLocation) { + int notificationLocation, boolean modifiedBeforeSending) { mCallback.onSmartReplySent(entry, reply); mSendingKeys.add(entry.key); try { - mBarService.onNotificationSmartReplySent( - entry.notification.getKey(), replyIndex, reply, generatedByAssistant, - notificationLocation); + mBarService.onNotificationSmartReplySent(entry.notification.getKey(), replyIndex, reply, + notificationLocation, modifiedBeforeSending); } catch (RemoteException e) { // Nothing to do, system going down } @@ -100,10 +99,10 @@ public class SmartReplyController { * Smart Replies and Actions have been added to the UI. */ public void smartSuggestionsAdded(final NotificationEntry entry, int replyCount, - int actionCount, boolean generatedByAssistant) { + int actionCount, boolean generatedByAssistant, boolean editBeforeSending) { try { - mBarService.onNotificationSmartSuggestionsAdded( - entry.notification.getKey(), replyCount, actionCount, generatedByAssistant); + mBarService.onNotificationSmartSuggestionsAdded(entry.notification.getKey(), replyCount, + actionCount, generatedByAssistant, editBeforeSending); } catch (RemoteException e) { // Nothing to do, system going down } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java index e1b231b96693..333239e77d1b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java @@ -268,7 +268,7 @@ public class ActivityLaunchAnimator { m.postTranslate(0, (float) (mParams.top - app.position.y)); mWindowCrop.set(mParams.left, 0, mParams.right, mParams.getHeight()); SurfaceParams params = new SurfaceParams(app.leash, 1f /* alpha */, m, mWindowCrop, - app.prefixOrderIndex, mCornerRadius); + app.prefixOrderIndex, mCornerRadius, true /* visible */); mSyncRtTransactionApplier.scheduleApply(params); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 5c620051b0bb..81d0e25782db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -47,6 +47,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * NotificationEntryManager is responsible for the adding, removing, and updating of notifications. @@ -64,6 +65,9 @@ public class NotificationEntryManager implements @VisibleForTesting protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>(); + private final Map<NotificationEntry, NotificationLifetimeExtender> mRetainedNotifications = + new ArrayMap<>(); + // Lazily retrieved dependencies private NotificationRemoteInputManager mRemoteInputManager; private NotificationRowBinder mNotificationRowBinder; @@ -89,6 +93,16 @@ public class NotificationEntryManager implements pw.println(entry.notification); } } + pw.println(" Lifetime-extended notifications:"); + if (mRetainedNotifications.isEmpty()) { + pw.println(" None"); + } else { + for (Map.Entry<NotificationEntry, NotificationLifetimeExtender> entry + : mRetainedNotifications.entrySet()) { + pw.println(" " + entry.getKey().notification + " retained by " + + entry.getValue().getClass().getName()); + } + } } public NotificationEntryManager(Context context) { @@ -244,7 +258,7 @@ public class NotificationEntryManager implements for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { if (extender.shouldExtendLifetime(entry)) { mLatestRankingMap = ranking; - extender.setShouldManageLifetime(entry, true /* shouldManage */); + extendLifetime(entry, extender); lifetimeExtended = true; break; } @@ -255,9 +269,7 @@ public class NotificationEntryManager implements // At this point, we are guaranteed the notification will be removed // Ensure any managers keeping the lifetime extended stop managing the entry - for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { - extender.setShouldManageLifetime(entry, false /* shouldManage */); - } + cancelLifetimeExtension(entry); if (entry.rowExists()) { entry.removeRow(); @@ -368,9 +380,7 @@ public class NotificationEntryManager implements // Notification is updated so it is essentially re-added and thus alive again. Don't need // to keep its lifetime extended. - for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { - extender.setShouldManageLifetime(entry, false /* shouldManage */); - } + cancelLifetimeExtension(entry); mNotificationData.update(entry, ranking, notification); @@ -464,4 +474,20 @@ public class NotificationEntryManager implements public Iterable<NotificationEntry> getPendingNotificationsIterator() { return mPendingNotifications.values(); } + + private void extendLifetime(NotificationEntry entry, NotificationLifetimeExtender extender) { + NotificationLifetimeExtender activeExtender = mRetainedNotifications.get(entry); + if (activeExtender != null && activeExtender != extender) { + activeExtender.setShouldManageLifetime(entry, false); + } + mRetainedNotifications.put(entry, extender); + extender.setShouldManageLifetime(entry, true); + } + + private void cancelLifetimeExtension(NotificationEntry entry) { + NotificationLifetimeExtender activeExtender = mRetainedNotifications.remove(entry); + if (activeExtender != null) { + activeExtender.setShouldManageLifetime(entry, false); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index db9fcc89f4a9..9f1693c71459 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -105,6 +105,14 @@ public final class NotificationEntry { /** Smart replies provided by the NotificationAssistantService. */ @NonNull public CharSequence[] systemGeneratedSmartReplies = new CharSequence[0]; + + /** + * If {@link android.app.RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is + * currently editing a choice (smart reply), then this field contains the information about the + * suggestion being edited. Otherwise <code>null</code>. + */ + public EditedSuggestionInfo editedSuggestionInfo; + @VisibleForTesting public int suppressedVisualEffects; public boolean suspended; @@ -746,4 +754,23 @@ public final class NotificationEntry { private static boolean isCategory(String category, Notification n) { return Objects.equals(n.category, category); } + + /** Information about a suggestion that is being edited. */ + public static class EditedSuggestionInfo { + + /** + * The value of the suggestion (before any user edits). + */ + public final CharSequence originalText; + + /** + * The index of the suggestion that is being edited. + */ + public final int index; + + public EditedSuggestionInfo(CharSequence originalText, int index) { + this.originalText = originalText; + this.index = index; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index bed2426021a1..b8e33a8e0d2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -90,6 +90,7 @@ import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag; +import com.android.systemui.statusbar.notification.row.wrapper.NotificationMediaTemplateViewWrapper; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.stack.AmbientState; import com.android.systemui.statusbar.notification.stack.AnimationProperties; @@ -144,6 +145,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private int mNotificationMinHeightBeforeP; private int mNotificationMinHeight; private int mNotificationMinHeightLarge; + private int mNotificationMinHeightMedia; private int mNotificationMaxHeight; private int mIncreasedPaddingBetweenElements; private int mNotificationLaunchHeight; @@ -652,8 +654,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N; boolean beforeP = mEntry.targetSdk < Build.VERSION_CODES.P; int minHeight; + + View expandedView = layout.getExpandedChild(); + boolean isMediaLayout = expandedView != null + && expandedView.findViewById(com.android.internal.R.id.media_actions) != null; + if (customView && beforeP && !mIsSummaryWithChildren) { minHeight = beforeN ? mNotificationMinHeightBeforeN : mNotificationMinHeightBeforeP; + } else if (isMediaLayout && !NotificationMediaTemplateViewWrapper.HIDE_COMPACT_SCRUBBER) { + minHeight = mNotificationMinHeightMedia; } else if (mUseIncreasedCollapsedHeight && layout == mPrivateLayout) { minHeight = mNotificationMinHeightLarge; } else { @@ -1642,6 +1651,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView R.dimen.notification_min_height); mNotificationMinHeightLarge = NotificationUtils.getFontScaledHeight(mContext, R.dimen.notification_min_height_increased); + mNotificationMinHeightMedia = NotificationUtils.getFontScaledHeight(mContext, + R.dimen.notification_min_height_media); mNotificationMaxHeight = NotificationUtils.getFontScaledHeight(mContext, R.dimen.notification_max_height); mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 878d533e91a6..80956159c20b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1509,8 +1509,13 @@ public class NotificationContentView extends FrameLayout { boolean fromAssistant = smartRepliesAndActions.smartReplies == null ? smartRepliesAndActions.smartActions.fromAssistant : smartRepliesAndActions.smartReplies.fromAssistant; + boolean editBeforeSending = smartRepliesAndActions.smartReplies != null + && mSmartReplyConstants.getEffectiveEditChoicesBeforeSending( + smartRepliesAndActions.smartReplies.remoteInput + .getEditChoicesBeforeSending()); + mSmartReplyController.smartSuggestionsAdded(entry, numSmartReplies, - numSmartActions, fromAssistant); + numSmartActions, fromAssistant, editBeforeSending); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 5a9a56865a5c..ddda3e50fc2c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -16,26 +16,222 @@ package com.android.systemui.statusbar.notification.row.wrapper; +import static com.android.systemui.Dependency.MAIN_HANDLER; + +import android.app.Notification; import android.content.Context; +import android.content.res.ColorStateList; +import android.media.MediaMetadata; +import android.media.session.MediaController; +import android.media.session.MediaSession; +import android.media.session.PlaybackState; +import android.os.Handler; +import android.text.format.DateUtils; +import android.util.Log; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewStub; +import android.widget.SeekBar; +import android.widget.TextView; +import com.android.internal.R; +import com.android.systemui.Dependency; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import java.util.Timer; +import java.util.TimerTask; + /** * Wraps a notification containing a media template */ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper { + private static final String TAG = "NotificationMediaTVW"; + private static final long PROGRESS_UPDATE_INTERVAL = 1000; // 1s + private static final String COMPACT_MEDIA_TAG = "media"; + private final Handler mHandler = Dependency.get(MAIN_HANDLER); + private Timer mSeekBarTimer; + private View mActions; + private SeekBar mSeekBar; + private TextView mSeekBarElapsedTime; + private TextView mSeekBarTotalTime; + private long mDuration = 0; + private MediaController mMediaController; + private View mSeekBarView; + private Context mContext; + + // TODO: implement as phenotype flag + public static final boolean HIDE_COMPACT_SCRUBBER = true; + + private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + if (mMediaController != null && canSeekMedia()) { + mMediaController.getTransportControls().seekTo(mSeekBar.getProgress()); + } + } + }; + + private MediaController.Callback mMediaCallback = new MediaController.Callback() { + @Override + public void onSessionDestroyed() { + clearTimer(); + mMediaController.unregisterCallback(this); + } + + @Override + public void onPlaybackStateChanged(PlaybackState state) { + if (state.getState() != PlaybackState.STATE_PLAYING) { + clearTimer(); + } else if (mSeekBarTimer == null) { + startTimer(); + } + } + }; + protected NotificationMediaTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { super(ctx, view, row); + mContext = ctx; } - View mActions; - private void resolveViews() { mActions = mView.findViewById(com.android.internal.R.id.media_actions); + + final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras + .getParcelable(Notification.EXTRA_MEDIA_SESSION); + + if (token == null || (COMPACT_MEDIA_TAG.equals(mView.getTag()) && HIDE_COMPACT_SCRUBBER)) { + if (mSeekBarView != null) { + mSeekBarView.setVisibility(View.GONE); + } + return; + } + + // Check for existing media controller and clean up / create as necessary + if (mMediaController == null || !mMediaController.getSessionToken().equals(token)) { + if (mMediaController != null) { + mMediaController.unregisterCallback(mMediaCallback); + } + mMediaController = new MediaController(mContext, token); + } + + if (mMediaController.getMetadata() != null) { + long duration = mMediaController.getMetadata().getLong( + MediaMetadata.METADATA_KEY_DURATION); + if (duration <= 0) { + // Don't include the seekbar if this is a livestream + Log.d(TAG, "removing seekbar"); + if (mSeekBarView != null) { + mSeekBarView.setVisibility(View.GONE); + } + return; + } else { + // Otherwise, make sure the seekbar is visible + if (mSeekBarView != null) { + mSeekBarView.setVisibility(View.VISIBLE); + } + } + } + + // Inflate the seekbar template + ViewStub stub = mView.findViewById(R.id.notification_media_seekbar_container); + if (stub instanceof ViewStub) { + LayoutInflater layoutInflater = LayoutInflater.from(stub.getContext()); + stub.setLayoutInflater(layoutInflater); + stub.setLayoutResource(R.layout.notification_material_media_seekbar); + mSeekBarView = stub.inflate(); + + mSeekBar = mSeekBarView.findViewById(R.id.notification_media_progress_bar); + mSeekBar.setOnSeekBarChangeListener(mSeekListener); + + mSeekBarElapsedTime = mSeekBarView.findViewById(R.id.notification_media_elapsed_time); + mSeekBarTotalTime = mSeekBarView.findViewById(R.id.notification_media_total_time); + + if (mSeekBarTimer == null) { + // Disable seeking if it is not supported for this media session + if (!canSeekMedia()) { + mSeekBar.getThumb().setAlpha(0); + mSeekBar.setEnabled(false); + } else { + mSeekBar.getThumb().setAlpha(255); + mSeekBar.setEnabled(true); + } + + startTimer(); + + mMediaController.registerCallback(mMediaCallback); + } + } + updateSeekBarTint(mSeekBarView); + } + + private void startTimer() { + clearTimer(); + mSeekBarTimer = new Timer(true /* isDaemon */); + mSeekBarTimer.schedule(new TimerTask() { + @Override + public void run() { + mHandler.post(mUpdatePlaybackUi); + } + }, 0, PROGRESS_UPDATE_INTERVAL); + } + + private void clearTimer() { + if (mSeekBarTimer != null) { + // TODO: also trigger this when the notification panel is collapsed + mSeekBarTimer.cancel(); + mSeekBarTimer.purge(); + mSeekBarTimer = null; + } + } + + private boolean canSeekMedia() { + if (mMediaController == null || mMediaController.getPlaybackState() == null) { + return false; + } + + long actions = mMediaController.getPlaybackState().getActions(); + return (actions == 0 || (actions & PlaybackState.ACTION_SEEK_TO) != 0); + } + + protected final Runnable mUpdatePlaybackUi = new Runnable() { + @Override + public void run() { + if (mMediaController != null && mMediaController.getMetadata() != null + && mSeekBar != null) { + long position = mMediaController.getPlaybackState().getPosition(); + long duration = mMediaController.getMetadata().getLong( + MediaMetadata.METADATA_KEY_DURATION); + + if (mDuration != duration) { + mDuration = duration; + mSeekBar.setMax((int) mDuration); + mSeekBarTotalTime.setText(millisecondsToTimeString(duration)); + } + mSeekBar.setProgress((int) position); + + mSeekBarElapsedTime.setText(millisecondsToTimeString(position)); + } else { + // We no longer have a media session / notification + clearTimer(); + } + } + }; + + private String millisecondsToTimeString(long milliseconds) { + long seconds = milliseconds / 1000; + String text = DateUtils.formatElapsedTime(seconds); + return text; } @Override @@ -46,6 +242,27 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi super.onContentUpdated(row); } + private void updateSeekBarTint(View seekBarContainer) { + if (seekBarContainer == null) { + return; + } + + if (this.getNotificationHeader() == null) { + return; + } + + int tintColor = getNotificationHeader().getOriginalIconColor(); + mSeekBarElapsedTime.setTextColor(tintColor); + mSeekBarTotalTime.setTextColor(tintColor); + + ColorStateList tintList = ColorStateList.valueOf(tintColor); + mSeekBar.setThumbTintList(tintList); + tintList = tintList.withAlpha(192); // 75% + mSeekBar.setProgressTintList(tintList); + tintList = tintList.withAlpha(128); // 50% + mSeekBar.setProgressBackgroundTintList(tintList); + } + @Override protected void updateTransformedTypes() { // This also clears the existing types diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java new file mode 100644 index 000000000000..dae4da7355c7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 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.statusbar.phone; + +import android.annotation.NonNull; +import android.content.Context; +import android.graphics.PixelFormat; +import android.view.View; +import android.view.WindowManager; + +import com.android.systemui.R; + +public class NavigationBarEdgePanel extends View { + private static final String TAG = "NavigationBarEdgePanel"; + + public static NavigationBarEdgePanel create(@NonNull Context context, int width, int height, + int gravity) { + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height, + WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, + WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSLUCENT); + lp.gravity = gravity; + lp.setTitle(TAG + context.getDisplayId()); + lp.accessibilityTitle = context.getString(R.string.nav_bar_edge_panel); + lp.windowAnimations = 0; + NavigationBarEdgePanel panel = new NavigationBarEdgePanel(context); + panel.setLayoutParams(lp); + return panel; + } + + private NavigationBarEdgePanel(Context context) { + super(context); + } + + public void setWindowFlag(int flags, boolean enable) { + WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams(); + if (lp == null || enable == ((lp.flags & flags) != 0)) { + return; + } + if (enable) { + lp.flags |= flags; + } else { + lp.flags &= ~flags; + } + updateLayout(lp); + } + + public void setDimensions(int width, int height) { + final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams(); + if (lp.width != width || lp.height != height) { + lp.width = width; + lp.height = height; + updateLayout(lp); + } + } + + private void updateLayout(WindowManager.LayoutParams lp) { + WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + wm.updateViewLayout(this, lp); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 02683c16d935..651670cbf2c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.phone; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON; @@ -35,6 +37,8 @@ import android.animation.PropertyValuesHolder; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.DrawableRes; +import android.annotation.IntDef; +import android.annotation.SuppressLint; import android.app.StatusBarManager; import android.content.Context; import android.content.res.Configuration; @@ -51,6 +55,7 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.view.Display; +import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -87,12 +92,21 @@ import com.android.systemui.statusbar.policy.KeyButtonDrawable; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> { final static boolean DEBUG = false; final static String TAG = "StatusBar/NavBarView"; + @Retention(RetentionPolicy.SOURCE) + @IntDef({WINDOW_TARGET_BOTTOM, WINDOW_TARGET_LEFT, WINDOW_TARGET_RIGHT}) + public @interface WindowTarget{} + public static final int WINDOW_TARGET_BOTTOM = 0; + public static final int WINDOW_TARGET_LEFT = 1; + public static final int WINDOW_TARGET_RIGHT = 2; + // slippery nav bar when everything is disabled, e.g. during setup final static boolean SLIPPERY_WHEN_DISABLED = true; @@ -109,6 +123,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav int mNavigationIconHints = 0; private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE; + private @WindowTarget int mWindowHitTarget = WINDOW_TARGET_BOTTOM; private Rect mHomeButtonBounds = new Rect(); private Rect mBackButtonBounds = new Rect(); private Rect mRecentsButtonBounds = new Rect(); @@ -160,6 +175,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private NavigationAssistantAction mAssistantAction; private NavigationNotificationPanelAction mNotificationPanelAction; + private NavigationBarEdgePanel mLeftEdgePanel; + private NavigationBarEdgePanel mRightEdgePanel; + /** * Helper that is responsible for showing the right toast when a disallowed activity operation * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in @@ -222,6 +240,18 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } }; + private final OnTouchListener mEdgePanelTouchListener = new OnTouchListener() { + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == ACTION_DOWN) { + mWindowHitTarget = v == mLeftEdgePanel ? WINDOW_TARGET_LEFT : WINDOW_TARGET_RIGHT; + mDownHitTarget = HIT_TARGET_NONE; + } + return mGestureHelper.onTouchEvent(event); + } + }; + private class H extends Handler { public void handleMessage(Message m) { switch (m.what) { @@ -297,6 +327,16 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mColorAdaptionController.end(); } } + + @Override + public void onEdgeSensitivityChanged(int width, int height) { + if (mLeftEdgePanel != null) { + mLeftEdgePanel.setDimensions(width, height); + } + if (mRightEdgePanel != null) { + mRightEdgePanel.setDimensions(width, height); + } + } }; public NavigationBarView(Context context, AttributeSet attrs) { @@ -433,6 +473,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav int x = (int) event.getX(); int y = (int) event.getY(); mDownHitTarget = HIT_TARGET_NONE; + mWindowHitTarget = WINDOW_TARGET_BOTTOM; if (deadZoneConsumed) { mDownHitTarget = HIT_TARGET_DEAD_ZONE; } else if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) { @@ -483,6 +524,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return mDownHitTarget; } + public @WindowTarget int getWindowTarget() { + return mWindowHitTarget; + } + public void abortCurrentGesture() { getHomeButton().abortCurrentGesture(); } @@ -837,24 +882,32 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } private void setSlippery(boolean slippery) { - boolean changed = false; + setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery); + } + + public void setWindowTouchable(boolean flag) { + setWindowFlag(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, !flag); + if (mLeftEdgePanel != null) { + mLeftEdgePanel.setWindowFlag(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, !flag); + } + if (mRightEdgePanel != null) { + mRightEdgePanel.setWindowFlag(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, !flag); + } + } + + private void setWindowFlag(int flags, boolean enable) { final ViewGroup navbarView = ((ViewGroup) getParent()); - final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView - .getLayoutParams(); - if (lp == null) { + WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView.getLayoutParams(); + if (lp == null || enable == ((lp.flags & flags) != 0)) { return; } - if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) { - lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY; - changed = true; - } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) { - lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY; - changed = true; - } - if (changed) { - WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE); - wm.updateViewLayout(navbarView, lp); + if (enable) { + lp.flags |= flags; + } else { + lp.flags &= ~flags; } + WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + wm.updateViewLayout(navbarView, lp); } public void setMenuVisibility(final boolean show) { @@ -1016,6 +1069,17 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } catch (RemoteException e) { Slog.e(TAG, "Failed to get nav bar position.", e); } + + // For landscape, hide the panel that would interfere with navigation bar layout + if (mLeftEdgePanel != null && mRightEdgePanel != null) { + mLeftEdgePanel.setVisibility(VISIBLE); + mRightEdgePanel.setVisibility(VISIBLE); + if (navBarPos == NAV_BAR_LEFT) { + mLeftEdgePanel.setVisibility(GONE); + } else if (navBarPos == NAV_BAR_RIGHT) { + mRightEdgePanel.setVisibility(GONE); + } + } mGestureHelper.setBarState(isRtl, navBarPos); } @@ -1142,6 +1206,21 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav NavGesture.class, false /* Only one */); setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled()); mColorAdaptionController.start(); + + if (mPrototypeController.isEnabled()) { + WindowManager wm = (WindowManager) getContext() + .getSystemService(Context.WINDOW_SERVICE); + int width = mPrototypeController.getEdgeSensitivityWidth(); + int height = mPrototypeController.getEdgeSensitivityHeight(); + mLeftEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height, + Gravity.START | Gravity.BOTTOM); + mRightEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height, + Gravity.END | Gravity.BOTTOM); + mLeftEdgePanel.setOnTouchListener(mEdgePanelTouchListener); + mRightEdgePanel.setOnTouchListener(mEdgePanelTouchListener); + wm.addView(mLeftEdgePanel, mLeftEdgePanel.getLayoutParams()); + wm.addView(mRightEdgePanel, mRightEdgePanel.getLayoutParams()); + } } @Override @@ -1157,6 +1236,17 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav for (int i = 0; i < mButtonDispatchers.size(); ++i) { mButtonDispatchers.valueAt(i).onDestroy(); } + + if (mPrototypeController.isEnabled()) { + WindowManager wm = (WindowManager) getContext() + .getSystemService(Context.WINDOW_SERVICE); + if (mLeftEdgePanel != null) { + wm.removeView(mLeftEdgePanel); + } + if (mRightEdgePanel != null) { + wm.removeView(mRightEdgePanel); + } + } } private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java index b4feb25fba7f..8421e23e97b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.annotation.IntDef; import android.content.Context; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; @@ -34,7 +35,12 @@ import java.lang.annotation.RetentionPolicy; public class NavigationPrototypeController extends ContentObserver { private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback"; private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome"; + private static final String PROTOTYPE_ENABLED = "prototype_enabled"; + private static final String EDGE_SENSITIVITY_HEIGHT_SETTING = + "quickstepcontroller_edge_height_sensitivity"; + public static final String EDGE_SENSITIVITY_WIDTH_SETTING = + "quickstepcontroller_edge_width_sensitivity"; private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map"; public static final String NAV_COLOR_ADAPT_ENABLE_SETTING = "navbar_color_adapt_enable"; @@ -79,6 +85,8 @@ public class NavigationPrototypeController extends ContentObserver { registerObserver(HIDE_HOME_BUTTON_SETTING); registerObserver(GESTURE_MATCH_SETTING); registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING); + registerObserver(EDGE_SENSITIVITY_WIDTH_SETTING); + registerObserver(EDGE_SENSITIVITY_HEIGHT_SETTING); } /** @@ -106,10 +114,26 @@ public class NavigationPrototypeController extends ContentObserver { } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) { mListener.onColorAdaptChanged( NavBarTintController.isEnabled(mContext)); + } else if (path.endsWith(EDGE_SENSITIVITY_WIDTH_SETTING) + || path.endsWith(EDGE_SENSITIVITY_HEIGHT_SETTING)) { + mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(), + getEdgeSensitivityHeight()); } } } + public int getEdgeSensitivityWidth() { + return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_WIDTH_SETTING, 0)); + } + + public int getEdgeSensitivityHeight() { + return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_HEIGHT_SETTING, 0)); + } + + public boolean isEnabled() { + return getGlobalBool(PROTOTYPE_ENABLED, false); + } + /** * Retrieve the action map to apply to the quick step controller * @return an action map @@ -144,15 +168,24 @@ public class NavigationPrototypeController extends ContentObserver { return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal ? 1 : 0) == 1; } + private int getGlobalInt(String name, int defaultVal) { + return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal); + } + private void registerObserver(String name) { mContext.getContentResolver() .registerContentObserver(Settings.Global.getUriFor(name), false, this); } + private static int convertDpToPixel(float dp) { + return (int) (dp * Resources.getSystem().getDisplayMetrics().density); + } + public interface OnPrototypeChangedListener { void onGestureRemap(@GestureAction int[] actions); void onBackButtonVisibilityChanged(boolean visible); void onHomeButtonVisibilityChanged(boolean visible); void onColorAdaptChanged(boolean enabled); + void onEdgeSensitivityChanged(int width, int height); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index d5d283c46b0a..84f1cef19b77 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -28,9 +28,12 @@ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; +import static com.android.systemui.statusbar.phone.NavigationBarView.WINDOW_TARGET_BOTTOM; +import static com.android.systemui.statusbar.phone.NavigationPrototypeController.EDGE_SENSITIVITY_WIDTH_SETTING; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; @@ -42,12 +45,9 @@ import android.util.Log; import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; +import android.view.ViewConfiguration; import android.view.ViewPropertyAnimator; -import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; - import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.R; @@ -72,6 +72,7 @@ public class QuickStepController implements GestureHelper { /** Experiment to swipe home button left to execute a back key press */ private static final String HIDE_BACK_BUTTON_PROP = "quickstepcontroller_hideback"; private static final String ENABLE_CLICK_THROUGH_NAV_PROP = "quickstepcontroller_clickthrough"; + private static final String GESTURE_REGION_THRESHOLD_SETTING = "gesture_region_threshold"; private static final long BACK_BUTTON_FADE_IN_ALPHA = 150; private static final long CLICK_THROUGH_TAP_DELAY = 70; private static final long CLICK_THROUGH_TAP_RESET_DELAY = 100; @@ -109,10 +110,10 @@ public class QuickStepController implements GestureHelper { private float mMaxDragLimit; private float mMinDragLimit; private float mDragDampeningFactor; - private float mEdgeSwipeThreshold; private boolean mClickThroughPressed; private float mClickThroughPressX; private float mClickThroughPressY; + private int mGestureRegionThreshold; private NavigationGestureAction mCurrentAction; private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES]; @@ -139,7 +140,7 @@ public class QuickStepController implements GestureHelper { }; private final Runnable mClickThroughResetTap = () -> { - setWindowTouchable(true); + mNavigationBarView.setWindowTouchable(true); mClickThroughPressed = false; }; @@ -210,7 +211,8 @@ public class QuickStepController implements GestureHelper { // The same down event was just sent on intercept and therefore can be ignored here final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN - && mOverviewEventSender.getProxy() != null; + && mOverviewEventSender.getProxy() != null + && mNavigationBarView.getWindowTarget() == WINDOW_TARGET_BOTTOM; return ignoreProxyDownEvent || handleTouchEvent(event); } @@ -268,12 +270,15 @@ public class QuickStepController implements GestureHelper { mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix); mAllowGestureDetection = true; mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed(); - mEdgeSwipeThreshold = mContext.getResources() - .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold); + final int defaultRegionThreshold = mContext.getResources() + .getDimensionPixelOffset(R.dimen.navigation_bar_default_edge_width); + mGestureRegionThreshold = convertDpToPixel(getIntGlobalSetting(mContext, + EDGE_SENSITIVITY_WIDTH_SETTING, defaultRegionThreshold)); break; } case MotionEvent.ACTION_MOVE: { - if (!mAllowGestureDetection) { + if (!mAllowGestureDetection + || mNavigationBarView.getWindowTarget() != WINDOW_TARGET_BOTTOM) { break; } int x = (int) event.getX(); @@ -330,18 +335,12 @@ public class QuickStepController implements GestureHelper { } else if (exceededSwipeHorizontalTouchSlop) { if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) { // Swiping left (rtl) gesture - int index = mGestureActions[ACTION_SWIPE_LEFT_FROM_EDGE_INDEX] != null - && isEdgeSwipeAlongNavBar(touchDownH, !mDragHPositive) - ? ACTION_SWIPE_LEFT_FROM_EDGE_INDEX : ACTION_SWIPE_LEFT_INDEX; - tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */, - event); + tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX], + true /* alignedWithNavBar */, event); } else { // Swiping right (ltr) gesture - int index = mGestureActions[ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX] != null - && isEdgeSwipeAlongNavBar(touchDownH, mDragHPositive) - ? ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX : ACTION_SWIPE_RIGHT_INDEX; - tryToStartGesture(mGestureActions[index], true /* alignedWithNavBar */, - event); + tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX], + true /* alignedWithNavBar */, event); } } } @@ -354,24 +353,34 @@ public class QuickStepController implements GestureHelper { case MotionEvent.ACTION_UP: if (mCurrentAction != null) { mCurrentAction.endGesture(); - } else if (action == MotionEvent.ACTION_UP - && getBoolGlobalSetting(mContext, ENABLE_CLICK_THROUGH_NAV_PROP) - && !mClickThroughPressed) { - // Enable click through functionality where no gesture has been detected and not - // passed the drag slop so inject a touch event at the same location - // after making the navigation bar window untouchable. After a some time, the - // navigation bar will be able to take input events again - float diffX = Math.abs(event.getX() - mTouchDownX); - float diffY = Math.abs(event.getY() - mTouchDownY); - - if ((diffX <= NavigationBarCompat.getQuickStepDragSlopPx() - && diffY <= NavigationBarCompat.getQuickStepDragSlopPx())) { - setWindowTouchable(false); - mClickThroughPressX = event.getRawX(); - mClickThroughPressY = event.getRawY(); - mClickThroughPressed = true; - mNavigationBarView.postDelayed(mClickThroughSendTap, - CLICK_THROUGH_TAP_DELAY); + } else if (action == MotionEvent.ACTION_UP) { + if (canTriggerEdgeSwipe(event)) { + int index = mNavigationBarView.getWindowTarget() == NAV_BAR_LEFT + ? ACTION_SWIPE_RIGHT_FROM_EDGE_INDEX + : ACTION_SWIPE_LEFT_FROM_EDGE_INDEX; + tryToStartGesture(mGestureActions[index], false /* alignedWithNavBar */, + event); + if (mCurrentAction != null) { + mCurrentAction.endGesture(); + } + } else if (getBoolGlobalSetting(mContext, ENABLE_CLICK_THROUGH_NAV_PROP) + && !mClickThroughPressed) { + // Enable click through functionality where no gesture has been detected and + // not passed the drag slop so inject a touch event at the same location + // after making the navigation bar window untouchable. After a some time, + // the navigation bar will be able to take input events again + float diffX = Math.abs(event.getX() - mTouchDownX); + float diffY = Math.abs(event.getY() - mTouchDownY); + + if ((diffX <= NavigationBarCompat.getQuickStepDragSlopPx() + && diffY <= NavigationBarCompat.getQuickStepDragSlopPx())) { + mNavigationBarView.setWindowTouchable(false); + mClickThroughPressX = event.getRawX(); + mClickThroughPressY = event.getRawY(); + mClickThroughPressed = true; + mNavigationBarView.postDelayed(mClickThroughSendTap, + CLICK_THROUGH_TAP_DELAY); + } } } @@ -403,30 +412,6 @@ public class QuickStepController implements GestureHelper { return mCurrentAction != null || deadZoneConsumed; } - private void setWindowTouchable(boolean flag) { - final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) - ((ViewGroup) mNavigationBarView.getParent()).getLayoutParams(); - if (flag) { - lp.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE; - } else { - lp.flags |= LayoutParams.FLAG_NOT_TOUCHABLE; - } - final WindowManager wm = (WindowManager) mNavigationBarView.getContext() - .getSystemService(Context.WINDOW_SERVICE); - wm.updateViewLayout((View) mNavigationBarView.getParent(), lp); - } - - private boolean isEdgeSwipeAlongNavBar(int touchDown, boolean dragPositiveDirection) { - // Detect edge swipe from side of 0 -> threshold - if (dragPositiveDirection) { - return touchDown < mEdgeSwipeThreshold; - } - // Detect edge swipe from side of size -> (size - threshold) - final int largeSide = isNavBarVertical() - ? mNavigationBarView.getHeight() : mNavigationBarView.getWidth(); - return touchDown > largeSide - mEdgeSwipeThreshold; - } - private void handleDragHitTarget(int position, int touchDown) { // Drag the hit target if gesture action requires it if (mHitTarget != null && (mGestureVerticalDragsButton || mGestureHorizontalDragsButton)) { @@ -448,6 +433,10 @@ public class QuickStepController implements GestureHelper { } private boolean shouldProxyEvents(int action) { + // Do not send events for side navigation bar panels + if (mNavigationBarView.getWindowTarget() != WINDOW_TARGET_BOTTOM) { + return false; + } final boolean actionValid = (mCurrentAction == null || !mCurrentAction.disableProxyEvents()); if (actionValid && !mIsInScreenPinning) { @@ -619,6 +608,32 @@ public class QuickStepController implements GestureHelper { } } + /** + * To trigger an edge swipe, the user must start from the left or right edges of certain height + * from the bottom then past the drag slope towards the center of the screen, followed by either + * a timed trigger for fast swipes or distance if held on the screen longer. + * For time, user must swipe up quickly before the Tap Timeout (typically 100ms) and for + * distance, the user can drag back to cancel if the touch up has not past the threshold. + * @param event Touch up event + * @return whether or not edge swipe gesture occurs + */ + private boolean canTriggerEdgeSwipe(MotionEvent event) { + if (mNavigationBarView.getWindowTarget() == WINDOW_TARGET_BOTTOM) { + return false; + } + int x = (int) event.getX(); + int y = (int) event.getY(); + int xDiff = Math.abs(x - mTouchDownX); + int yDiff = Math.abs(y - mTouchDownY); + final boolean exceededSwipeTouchSlop = xDiff > NavigationBarCompat.getQuickStepDragSlopPx() + && xDiff > yDiff; + if (exceededSwipeTouchSlop) { + long timeDiff = event.getEventTime() - event.getDownTime(); + return xDiff > mGestureRegionThreshold || timeDiff < ViewConfiguration.getTapTimeout(); + } + return false; + } + private boolean canPerformAnyAction() { for (NavigationGestureAction action: mGestureActions) { if (action != null && action.isEnabled()) { @@ -684,10 +699,18 @@ public class QuickStepController implements GestureHelper { return mNavBarPosition == NAV_BAR_LEFT || mNavBarPosition == NAV_BAR_RIGHT; } + private static int convertDpToPixel(float dp) { + return (int) (dp * Resources.getSystem().getDisplayMetrics().density); + } + static boolean getBoolGlobalSetting(Context context, String key) { return Settings.Global.getInt(context.getContentResolver(), key, 0) != 0; } + static int getIntGlobalSetting(Context context, String key, int defaultValue) { + return Settings.Global.getInt(context.getContentResolver(), key, defaultValue); + } + public static boolean shouldhideBackButton(Context context) { return getBoolGlobalSetting(context, HIDE_BACK_BUTTON_PROP); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java index 40f2392d2610..974de4b87ebc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSwitchAction.java @@ -22,7 +22,6 @@ import static com.android.systemui.recents.OverviewProxyService.TAG_OPS; import android.annotation.NonNull; import android.graphics.Rect; import android.os.RemoteException; -import android.provider.Settings; import android.util.Log; import android.view.MotionEvent; @@ -34,7 +33,6 @@ import com.android.systemui.shared.recents.utilities.Utilities; */ public class QuickSwitchAction extends NavigationGestureAction { private static final String TAG = "QuickSwitchAction"; - private static final String QUICKSWITCH_ENABLED_SETTING = "QUICK_SWITCH"; protected final Rect mDragOverRect = new Rect(); @@ -71,10 +69,6 @@ public class QuickSwitchAction extends NavigationGestureAction { @Override protected void onGestureStart(MotionEvent event) { - // Temporarily enable launcher to allow quick switch instead of quick scrub - Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(), - QUICKSWITCH_ENABLED_SETTING, 1 /* enabled */); - startQuickGesture(event); } @@ -105,10 +99,6 @@ public class QuickSwitchAction extends NavigationGestureAction { @Override protected void onGestureEnd() { endQuickGesture(true /* animate */); - - // Disable launcher to use quick switch instead of quick scrub - Settings.Global.putInt(mNavigationBarView.getContext().getContentResolver(), - QUICKSWITCH_ENABLED_SETTING, 0 /* disabled */); } protected void startQuickGesture(MotionEvent event) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index bf143c8940e5..ee1e3c09597f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -272,9 +272,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // AOD wallpapers should fade away after a while. // Docking pulses may take a long time, wallpapers should also fade away after a while. - if (mWallpaperSupportsAmbientMode && ( - mDozeParameters.getAlwaysOn() && mState == ScrimState.AOD - || mState == ScrimState.PULSING && mCallback != null)) { + if (mWallpaperSupportsAmbientMode && mDozeParameters.getAlwaysOn() + && mState == ScrimState.AOD) { if (!mWallpaperVisibilityTimedOut) { mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(), AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 11a2d32c9dd6..0f85c187ab7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -128,7 +128,8 @@ public enum ScrimState { public void prepare(ScrimState previousState) { mCurrentInFrontAlpha = 0f; if (mPulseReason == DozeLog.PULSE_REASON_NOTIFICATION - || mPulseReason == DozeLog.PULSE_REASON_DOCKING) { + || mPulseReason == DozeLog.PULSE_REASON_DOCKING + || mPulseReason == DozeLog.PULSE_REASON_INTENT) { mCurrentBehindAlpha = previousState.getBehindAlpha(); mCurrentBehindTint = Color.BLACK; } else { 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 ffaa236218fb..86e17f33fc77 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -202,7 +202,8 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat private void applyFocusableFlag(State state) { boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput) - || ENABLE_REMOTE_INPUT && state.remoteInputActive) { + || ENABLE_REMOTE_INPUT && state.remoteInputActive + || state.bubbleExpanded) { mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { @@ -486,6 +487,21 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat return mCurrentState.bubblesShowing; } + /** + * Sets if there is a bubble being expanded on the screen. + */ + public void setBubbleExpanded(boolean bubbleExpanded) { + mCurrentState.bubbleExpanded = bubbleExpanded; + apply(mCurrentState); + } + + /** + * The bubble is shown in expanded state for the status bar. + */ + public boolean getBubbleExpanded() { + return mCurrentState.bubbleExpanded; + } + public void setStateListener(OtherwisedCollapsedListener listener) { mListener = listener; } @@ -539,6 +555,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat boolean wallpaperSupportsAmbientMode; boolean notTouchable; boolean bubblesShowing; + boolean bubbleExpanded; /** * The {@link StatusBar} state from the status bar. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 7881df97df2a..1e090630efdb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.policy; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.Notification; import android.app.PendingIntent; @@ -59,6 +60,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; @@ -269,10 +271,24 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mPendingIntent = pendingIntent; } - public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput) { + /** + * Sets the remote input for this view. + * + * @param remoteInputs The remote inputs that need to be sent to the app. + * @param remoteInput The remote input that needs to be activated. + * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or + * {@code null} if the user is not editing a smart reply. + */ + public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput, + @Nullable EditedSuggestionInfo editedSuggestionInfo) { mRemoteInputs = remoteInputs; mRemoteInput = remoteInput; mEditText.setHint(mRemoteInput.getLabel()); + + mEntry.editedSuggestionInfo = editedSuggestionInfo; + if (editedSuggestionInfo != null) { + mEntry.remoteInputText = editedSuggestionInfo.originalText; + } } public void focusAnimated() { @@ -389,7 +405,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene public void stealFocusFrom(RemoteInputView other) { other.close(); setPendingIntent(other.mPendingIntent); - setRemoteInput(other.mRemoteInputs, other.mRemoteInput); + setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo); setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR); focus(); } @@ -429,7 +445,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene continue; } setPendingIntent(a.actionIntent); - setRemoteInput(inputs, input); + setRemoteInput(inputs, input, null /* editedSuggestionInfo*/); return true; } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 1d2d6f784620..45d215ef309c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; @@ -252,16 +253,17 @@ public class SmartReplyView extends ViewGroup { OnDismissAction action = () -> { if (mConstants.getEffectiveEditChoicesBeforeSending( smartReplies.remoteInput.getEditChoicesBeforeSending())) { - entry.remoteInputText = choice; + EditedSuggestionInfo editedSuggestionInfo = + new EditedSuggestionInfo(choice, replyIndex); mRemoteInputManager.activateRemoteInput(b, new RemoteInput[] { smartReplies.remoteInput }, smartReplies.remoteInput, - smartReplies.pendingIntent); + smartReplies.pendingIntent, editedSuggestionInfo); return false; } smartReplyController.smartReplySent(entry, replyIndex, b.getText(), - smartReplies.fromAssistant, - NotificationLogger.getNotificationLocation(entry).toMetricsEventEnum()); + NotificationLogger.getNotificationLocation(entry).toMetricsEventEnum(), + false /* modifiedBeforeSending */); Bundle results = new Bundle(); results.putString(smartReplies.remoteInput.getResultKey(), choice.toString()); Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java new file mode 100644 index 000000000000..d2b265401cc4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.verify; + +import android.graphics.Bitmap; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.function.Supplier; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public final class ClockInfoTest extends SysuiTestCase { + + @Mock + private Supplier<Bitmap> mMockSupplier; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetName() { + final String name = "name"; + ClockInfo info = ClockInfo.builder().setName(name).build(); + assertThat(info.getName()).isEqualTo(name); + } + + @Test + public void testGetTitle() { + final String title = "title"; + ClockInfo info = ClockInfo.builder().setTitle(title).build(); + assertThat(info.getTitle()).isEqualTo(title); + } + + @Test + public void testGetId() { + final String id = "id"; + ClockInfo info = ClockInfo.builder().setId(id).build(); + assertThat(info.getId()).isEqualTo(id); + } + + @Test + public void testGetThumbnail() { + ClockInfo info = ClockInfo.builder().setThumbnail(mMockSupplier).build(); + info.getThumbnail(); + verify(mMockSupplier).get(); + } + + @Test + public void testGetPreview() { + ClockInfo info = ClockInfo.builder().setPreview(mMockSupplier).build(); + info.getPreview(); + verify(mMockSupplier).get(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java new file mode 100644 index 000000000000..0cd6f9af8ffb --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.verify; + +import android.database.Cursor; +import android.graphics.Bitmap; +import android.net.Uri; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public final class ClockOptionsProviderTest extends SysuiTestCase { + + private static final String CONTENT_SCHEME = "content"; + private static final String AUTHORITY = "com.android.keyguard.clock"; + private static final String LIST_OPTIONS = "list_options"; + private static final String PREVIEW = "preview"; + private static final String THUMBNAIL = "thumbnail"; + private static final String MIME_TYPE_LIST_OPTIONS = "vnd.android.cursor.dir/clock_faces"; + private static final String MIME_TYPE_PNG = "image/png"; + private static final String NAME_COLUMN = "name"; + private static final String TITLE_COLUMN = "title"; + private static final String ID_COLUMN = "id"; + private static final String PREVIEW_COLUMN = "preview"; + private static final String THUMBNAIL_COLUMN = "thumbnail"; + + private ClockOptionsProvider mProvider; + private Supplier<List<ClockInfo>> mMockSupplier; + private List<ClockInfo> mClocks; + private Uri mListOptionsUri; + @Mock + private Supplier<Bitmap> mMockBitmapSupplier; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mClocks = new ArrayList<>(); + mProvider = new ClockOptionsProvider(() -> mClocks); + mListOptionsUri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(LIST_OPTIONS) + .build(); + } + + @Test + public void testGetType_listOptions() { + Uri uri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(LIST_OPTIONS) + .build(); + assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_LIST_OPTIONS); + } + + @Test + public void testGetType_preview() { + Uri uri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(PREVIEW) + .appendPath("id") + .build(); + assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_PNG); + } + + @Test + public void testGetType_thumbnail() { + Uri uri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(THUMBNAIL) + .appendPath("id") + .build(); + assertThat(mProvider.getType(uri)).isEqualTo(MIME_TYPE_PNG); + } + + @Test + public void testQuery_noClocks() { + Cursor cursor = mProvider.query(mListOptionsUri, null, null, null); + assertThat(cursor.getCount()).isEqualTo(0); + } + + @Test + public void testQuery_listOptions() { + mClocks.add(ClockInfo.builder() + .setName("name_a") + .setTitle("title_a") + .setId("id_a") + .build()); + mClocks.add(ClockInfo.builder() + .setName("name_b") + .setTitle("title_b") + .setId("id_b") + .build()); + Cursor cursor = mProvider.query(mListOptionsUri, null, null, null); + assertThat(cursor.getCount()).isEqualTo(2); + cursor.moveToFirst(); + assertThat(cursor.getString( + cursor.getColumnIndex(NAME_COLUMN))).isEqualTo("name_a"); + assertThat(cursor.getString( + cursor.getColumnIndex(TITLE_COLUMN))).isEqualTo("title_a"); + assertThat(cursor.getString( + cursor.getColumnIndex(ID_COLUMN))).isEqualTo("id_a"); + assertThat(cursor.getString( + cursor.getColumnIndex(PREVIEW_COLUMN))) + .isEqualTo("content://com.android.keyguard.clock/preview/id_a"); + assertThat(cursor.getString( + cursor.getColumnIndex(THUMBNAIL_COLUMN))) + .isEqualTo("content://com.android.keyguard.clock/thumbnail/id_a"); + cursor.moveToNext(); + assertThat(cursor.getString( + cursor.getColumnIndex(NAME_COLUMN))).isEqualTo("name_b"); + assertThat(cursor.getString( + cursor.getColumnIndex(TITLE_COLUMN))).isEqualTo("title_b"); + assertThat(cursor.getString( + cursor.getColumnIndex(ID_COLUMN))).isEqualTo("id_b"); + assertThat(cursor.getString( + cursor.getColumnIndex(PREVIEW_COLUMN))) + .isEqualTo("content://com.android.keyguard.clock/preview/id_b"); + assertThat(cursor.getString( + cursor.getColumnIndex(THUMBNAIL_COLUMN))) + .isEqualTo("content://com.android.keyguard.clock/thumbnail/id_b"); + } + + @Test + public void testOpenFile_preview() throws Exception { + mClocks.add(ClockInfo.builder() + .setId("id") + .setPreview(mMockBitmapSupplier) + .build()); + Uri uri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(PREVIEW) + .appendPath("id") + .build(); + mProvider.openFile(uri, "r").close(); + verify(mMockBitmapSupplier).get(); + } + + @Test + public void testOpenFile_thumbnail() throws Exception { + mClocks.add(ClockInfo.builder() + .setId("id") + .setThumbnail(mMockBitmapSupplier) + .build()); + Uri uri = new Uri.Builder() + .scheme(CONTENT_SCHEME) + .authority(AUTHORITY) + .appendPath(THUMBNAIL) + .appendPath("id") + .build(); + mProvider.openFile(uri, "r").close(); + verify(mMockBitmapSupplier).get(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index e32d48d2ab94..49b4641399f1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -168,12 +168,14 @@ public class BubbleControllerTest extends SysuiTestCase { // We should have bubbles & their notifs should show in the shade assertTrue(mBubbleController.hasBubbles()); assertTrue(mRow.getEntry().showInShadeWhenBubble()); + assertFalse(mStatusBarWindowController.getBubbleExpanded()); // Expand the stack BubbleStackView stackView = mBubbleController.getStackView(); stackView.expandStack(); assertTrue(mBubbleController.isStackExpanded()); verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key); + assertTrue(mStatusBarWindowController.getBubbleExpanded()); // Make sure it's no longer in the shade assertFalse(mRow.getEntry().showInShadeWhenBubble()); @@ -182,6 +184,7 @@ public class BubbleControllerTest extends SysuiTestCase { stackView.collapseStack(); verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key); assertFalse(mBubbleController.isStackExpanded()); + assertFalse(mStatusBarWindowController.getBubbleExpanded()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java index 1bb7ef4a657b..c0aac7ee8793 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java @@ -55,11 +55,12 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding); mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size); + + mExpansionPoint = new PointF(100, 100); } @Test public void testExpansionAndCollapse() throws InterruptedException { - mExpansionPoint = new PointF(100, 100); Runnable afterExpand = Mockito.mock(Runnable.class); mExpandedController.expandFromStack(mExpansionPoint, afterExpand); @@ -77,27 +78,48 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC Mockito.verify(afterExpand).run(); } + @Test + public void testOnChildRemoved() throws InterruptedException { + Runnable afterExpand = Mockito.mock(Runnable.class); + mExpandedController.expandFromStack(mExpansionPoint, afterExpand); + waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y); + testExpanded(); + + // Remove some views and see if the remaining child views still pass the expansion test. + mLayout.removeView(mViews.get(0)); + mLayout.removeView(mViews.get(3)); + waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y); + testExpanded(); + } + /** Check that children are in the correct positions for being stacked. */ private void testStackedAtPosition(float x, float y, int offsetMultiplier) { // Make sure the rest of the stack moved again, including the first bubble not moving, and // is stacked to the right now that we're on the right side of the screen. for (int i = 0; i < mLayout.getChildCount(); i++) { assertEquals(x + i * offsetMultiplier * mStackOffset, - mViews.get(i).getTranslationX(), 2f); - assertEquals(y, mViews.get(i).getTranslationY(), 2f); + mLayout.getChildAt(i).getTranslationX(), 2f); + assertEquals(y, mLayout.getChildAt(i).getTranslationY(), 2f); + + if (i < mMaxRenderedBubbles) { + assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f); + } } } /** Check that children are in the correct positions for being expanded. */ private void testExpanded() { - // Make sure the rest of the stack moved again, including the first bubble not moving, and - // is stacked to the right now that we're on the right side of the screen. - for (int i = 0; i < mLayout.getChildCount(); i++) { + // Check all the visible bubbles to see if they're in the right place. + for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) { assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)), - mViews.get(i).getTranslationX(), + mLayout.getChildAt(i).getTranslationX(), 2f); assertEquals(mBubblePadding + mCutoutInsetSize, - mViews.get(i).getTranslationY(), 2f); + mLayout.getChildAt(i).getTranslationY(), 2f); + + if (i < mMaxRenderedBubbles) { + assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f); + } } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java index 5be991f06586..c32140401fb2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; import android.os.SystemClock; import android.support.test.filters.SmallTest; @@ -100,9 +101,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { mTestableController.setRemoveImmediately(true); mLayout.removeView(mViews.get(1)); mLayout.removeView(mViews.get(2)); - Mockito.verify(mTestableController).onChildToBeRemoved( + Mockito.verify(mTestableController).onChildRemoved( eq(mViews.get(1)), eq(1), any()); - Mockito.verify(mTestableController).onChildToBeRemoved( + Mockito.verify(mTestableController).onChildRemoved( eq(mViews.get(2)), eq(1), any()); // Make sure we still get view added notifications after doing some removals. @@ -345,6 +346,24 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { assertTrue(mViews.get(0).getTranslationY() < 1000); } + @Test + public void testSetChildVisibility() throws InterruptedException { + mLayout.setController(mTestableController); + addOneMoreThanRenderLimitBubbles(); + + // The last view should have been set to GONE by the controller, since we added one more + // than the limit and it got pushed off. None of the first children should have been set + // VISIBLE, since they would have been animated in by onChildAdded. + Mockito.verify(mTestableController).setChildVisibility( + mViews.get(mViews.size() - 1), 5, View.GONE); + Mockito.verify(mTestableController, never()).setChildVisibility( + any(View.class), anyInt(), eq(View.VISIBLE)); + + // Remove the first view, which should cause the last view to become visible again. + mLayout.removeView(mViews.get(0)); + Mockito.verify(mTestableController).setChildVisibility( + mViews.get(mViews.size() - 1), 4, View.VISIBLE); + } /** Standard test of chained translation animations. */ private void testChainedTranslationAnimations() throws InterruptedException { @@ -440,10 +459,15 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase { void onChildAdded(View child, int index) {} @Override - void onChildToBeRemoved(View child, int index, Runnable actuallyRemove) { + void onChildRemoved(View child, int index, Runnable finishRemoval) { if (mRemoveImmediately) { - actuallyRemove.run(); + finishRemoval.run(); } } + + @Override + protected void setChildVisibility(View child, int index, int visibility) { + super.setChildVisibility(child, index, visibility); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java index ec2319d80194..9eb94f4aed72 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java @@ -44,11 +44,12 @@ public class DozeWallpaperStateTest extends SysuiTestCase { private DozeWallpaperState mDozeWallpaperState; @Mock IWallpaperManager mIWallpaperManager; @Mock DozeParameters mDozeParameters; + @Mock DozeMachine mMachine; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters); + mDozeWallpaperState = new DozeWallpaperState(mMachine, mIWallpaperManager, mDozeParameters); } @Test @@ -108,14 +109,28 @@ public class DozeWallpaperStateTest extends SysuiTestCase { } @Test - public void testTransitionTo_pulseIsAmbientMode() throws RemoteException { + public void testTransitionTo_notificationPulseIsAmbientMode() throws RemoteException { + when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_NOTIFICATION); mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE, DozeMachine.State.DOZE_PULSING); verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(0L)); } @Test + public void testTransitionTo_wakeFromPulseIsNotAmbientMode() throws RemoteException { + when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN); + mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, + DozeMachine.State.DOZE_REQUEST_PULSE); + reset(mIWallpaperManager); + + mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE, + DozeMachine.State.DOZE_PULSING); + verify(mIWallpaperManager).setInAmbientMode(eq(false), anyLong()); + } + + @Test public void testTransitionTo_animatesWhenWakingUpFromPulse() throws RemoteException { + when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_NOTIFICATION); mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE, DozeMachine.State.DOZE_PULSING); reset(mIWallpaperManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java index 850396299ae5..374a73c1d451 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java @@ -16,27 +16,35 @@ package com.android.systemui.qs; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.support.test.filters.SmallTest; +import android.telephony.SubscriptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; import android.view.View; +import com.android.keyguard.CarrierTextController.CarrierTextCallbackInfo; import com.android.systemui.R; import com.android.systemui.R.id; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; @RunWith(AndroidTestingRunner.class) @RunWithLooper @@ -68,4 +76,117 @@ public class QSFooterImplTest extends LeakCheckedTest { // Verify Settings wasn't launched. verify(mActivityStarter, never()).startActivity(any(), anyBoolean()); } + + @Test // throws no Exception + public void testUpdateCarrierText_sameLengts() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenAnswer( + new Answer<Integer>() { + @Override + public Integer answer(InvocationOnMock invocationOnMock) throws Throwable { + return invocationOnMock.getArgument(0); + } + }); + + // listOfCarriers length 1, subscriptionIds length 1, anySims false + CarrierTextCallbackInfo c1 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + false, + new int[]{0}); + spiedFooter.updateCarrierInfo(c1); + + // listOfCarriers length 1, subscriptionIds length 1, anySims true + CarrierTextCallbackInfo c2 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + true, + new int[]{0}); + spiedFooter.updateCarrierInfo(c2); + + // listOfCarriers length 2, subscriptionIds length 2, anySims false + CarrierTextCallbackInfo c3 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + false, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c3); + + // listOfCarriers length 2, subscriptionIds length 2, anySims true + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testUpdateCarrierText_differentLength() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenAnswer( + new Answer<Integer>() { + @Override + public Integer answer(InvocationOnMock invocationOnMock) throws Throwable { + return invocationOnMock.getArgument(0); + } + }); + + // listOfCarriers length 2, subscriptionIds length 1, anySims false + CarrierTextCallbackInfo c1 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + false, + new int[]{0}); + spiedFooter.updateCarrierInfo(c1); + + // listOfCarriers length 2, subscriptionIds length 1, anySims true + CarrierTextCallbackInfo c2 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0}); + spiedFooter.updateCarrierInfo(c2); + + // listOfCarriers length 1, subscriptionIds length 2, anySims false + CarrierTextCallbackInfo c3 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + false, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c3); + + // listOfCarriers length 1, subscriptionIds length 2, anySims true + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testUpdateCarrierText_invalidSim() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenReturn( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testSetMobileDataIndicators_invalidSim() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenReturn( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + spiedFooter.setMobileDataIndicators( + mock(NetworkController.IconState.class), + mock(NetworkController.IconState.class), + 0, 0, true, true, "", "", true, 0, true); + } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java index f34e1a6b01e7..31cd28019ea9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java @@ -98,8 +98,8 @@ public class SmartReplyControllerTest extends SysuiTestCase { @Test public void testSendSmartReply_updatesRemoteInput() { - mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, false, - MetricsEvent.LOCATION_UNKNOWN); + mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, + MetricsEvent.LOCATION_UNKNOWN, false /* modifiedBeforeSending */); // Sending smart reply should make calls to NotificationEntryManager // to update the notification with reply and spinner. @@ -109,48 +109,49 @@ public class SmartReplyControllerTest extends SysuiTestCase { @Test public void testSendSmartReply_logsToStatusBar() throws RemoteException { - mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, false, - MetricsEvent.LOCATION_UNKNOWN); + mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, + MetricsEvent.LOCATION_UNKNOWN, false /* modifiedBeforeSending */); // Check we log the result to the status bar service. verify(mIStatusBarService).onNotificationSmartReplySent(mSbn.getKey(), - TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, false, MetricsEvent.LOCATION_UNKNOWN); + TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, MetricsEvent.LOCATION_UNKNOWN, false); } @Test - public void testSendSmartReply_logsToStatusBar_generatedByAssistant() throws RemoteException { - mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, true, - MetricsEvent.LOCATION_UNKNOWN); + public void testSendSmartReply_logsToStatusBar_modifiedBeforeSending() throws RemoteException { + mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, + MetricsEvent.LOCATION_UNKNOWN, true /* modifiedBeforeSending */); // Check we log the result to the status bar service. verify(mIStatusBarService).onNotificationSmartReplySent(mSbn.getKey(), - TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, true, MetricsEvent.LOCATION_UNKNOWN); + TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, MetricsEvent.LOCATION_UNKNOWN, true); } @Test public void testShowSmartSuggestions_logsToStatusBar() throws RemoteException { final boolean generatedByAsssistant = true; + final boolean editBeforeSending = true; mSmartReplyController.smartSuggestionsAdded(mEntry, TEST_CHOICE_COUNT, TEST_ACTION_COUNT, - generatedByAsssistant); + generatedByAsssistant, editBeforeSending); // Check we log the result to the status bar service. verify(mIStatusBarService).onNotificationSmartSuggestionsAdded(mSbn.getKey(), - TEST_CHOICE_COUNT, TEST_ACTION_COUNT, generatedByAsssistant); + TEST_CHOICE_COUNT, TEST_ACTION_COUNT, generatedByAsssistant, editBeforeSending); } @Test public void testSendSmartReply_reportsSending() { - mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, false, - MetricsEvent.LOCATION_UNKNOWN); + mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, + MetricsEvent.LOCATION_UNKNOWN, false /* modifiedBeforeSending */); assertTrue(mSmartReplyController.isSendingSmartReply(mSbn.getKey())); } @Test public void testSendingSmartReply_afterRemove_shouldReturnFalse() { - mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, false, - MetricsEvent.LOCATION_UNKNOWN); + mSmartReplyController.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT, + MetricsEvent.LOCATION_UNKNOWN, false /* modifiedBeforeSending */); mSmartReplyController.stopSending(mEntry); assertFalse(mSmartReplyController.isSendingSmartReply(mSbn.getKey())); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 9ce6ae139998..a0b342071b07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -45,8 +45,11 @@ import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.util.ArraySet; import android.widget.FrameLayout; +import androidx.annotation.NonNull; + import com.android.internal.logging.MetricsLogger; import com.android.systemui.Dependency; import com.android.systemui.ForegroundServiceController; @@ -84,6 +87,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -348,28 +352,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase { } @Test - public void testRemoveNotification_blockedByLifetimeExtender() { - com.android.systemui.util.Assert.isNotMainThread(); - - NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class); - when(extender.shouldExtendLifetime(mEntry)).thenReturn(true); - - ArrayList<NotificationLifetimeExtender> extenders = mEntryManager.getLifetimeExtenders(); - extenders.clear(); - extenders.add(extender); - - mEntry.setRow(mRow); - mEntryManager.getNotificationData().add(mEntry); - - mEntryManager.removeNotification(mSbn.getKey(), mRankingMap); - - assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey())); - verify(extender).setShouldManageLifetime(mEntry, true /* shouldManage */); - verify(mEntryListener, never()).onEntryRemoved( - mEntry, null, false /* removedByUser */); - } - - @Test public void testRemoveNotification_onEntryRemoveNotFiredIfEntryDoesntExist() { com.android.systemui.util.Assert.isNotMainThread(); @@ -453,10 +435,142 @@ public class NotificationEntryManagerTest extends SysuiTestCase { assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title); } + @Test + public void testLifetimeExtenders_ifNotificationIsRetainedItIsntRemoved() { + // GIVEN an entry manager with a notification + mEntryManager.setRowBinder(mMockedRowBinder); + mEntryManager.getNotificationData().add(mEntry); + + // GIVEN a lifetime extender that always tries to extend lifetime + NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class); + when(extender.shouldExtendLifetime(mEntry)).thenReturn(true); + mEntryManager.addNotificationLifetimeExtender(extender); + + // WHEN the notification is removed + mEntryManager.removeNotification(mEntry.key, mRankingMap); + + // THEN the extender is asked to manage the lifetime + verify(extender).setShouldManageLifetime(mEntry, true); + // THEN the notification is retained + assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey())); + verify(mEntryListener, never()).onEntryRemoved(mEntry, null, false); + } + + @Test + public void testLifetimeExtenders_whenRetentionEndsNotificationIsRemoved() { + // GIVEN an entry manager with a notification whose life has been extended + mEntryManager.setRowBinder(mMockedRowBinder); + mEntryManager.getNotificationData().add(mEntry); + final FakeNotificationLifetimeExtender extender = new FakeNotificationLifetimeExtender(); + mEntryManager.addNotificationLifetimeExtender(extender); + mEntryManager.removeNotification(mEntry.key, mRankingMap); + assertTrue(extender.isManaging(mEntry.key)); + + // WHEN the extender finishes its extension + extender.setExtendLifetimes(false); + extender.getCallback().onSafeToRemove(mEntry.key); + + // THEN the notification is removed + assertNull(mEntryManager.getNotificationData().get(mSbn.getKey())); + verify(mEntryListener).onEntryRemoved(mEntry, null, false); + } + + @Test + public void testLifetimeExtenders_whenNotificationUpdatedRetainersAreCanceled() { + // GIVEN an entry manager with a notification whose life has been extended + mEntryManager.setRowBinder(mMockedRowBinder); + mEntryManager.getNotificationData().add(mEntry); + NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class); + when(extender.shouldExtendLifetime(mEntry)).thenReturn(true); + mEntryManager.addNotificationLifetimeExtender(extender); + mEntryManager.removeNotification(mEntry.key, mRankingMap); + + // WHEN the notification is updated + mEntryManager.updateNotification(mEntry.notification, mRankingMap); + + // THEN the lifetime extension is canceled + verify(extender).setShouldManageLifetime(mEntry, false); + } + + @Test + public void testLifetimeExtenders_whenNewExtenderTakesPrecedenceOldExtenderIsCanceled() { + // GIVEN an entry manager with a notification + mEntryManager.setRowBinder(mMockedRowBinder); + mEntryManager.getNotificationData().add(mEntry); + + // GIVEN two lifetime extenders, the first which never extends and the second which + // always extends + NotificationLifetimeExtender extender1 = mock(NotificationLifetimeExtender.class); + when(extender1.shouldExtendLifetime(mEntry)).thenReturn(false); + NotificationLifetimeExtender extender2 = mock(NotificationLifetimeExtender.class); + when(extender2.shouldExtendLifetime(mEntry)).thenReturn(true); + mEntryManager.addNotificationLifetimeExtender(extender1); + mEntryManager.addNotificationLifetimeExtender(extender2); + + // GIVEN a notification was lifetime-extended and extender2 is managing it + mEntryManager.removeNotification(mEntry.key, mRankingMap); + verify(extender1, never()).setShouldManageLifetime(mEntry, true); + verify(extender2).setShouldManageLifetime(mEntry, true); + + // WHEN the extender1 changes its mind and wants to extend the lifetime of the notif + when(extender1.shouldExtendLifetime(mEntry)).thenReturn(true); + mEntryManager.removeNotification(mEntry.key, mRankingMap); + + // THEN extender2 stops managing the notif and extender1 starts managing it + verify(extender1).setShouldManageLifetime(mEntry, true); + verify(extender2).setShouldManageLifetime(mEntry, false); + } + private Notification.Action createAction() { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), "action", PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build(); } + + private static class FakeNotificationLifetimeExtender implements NotificationLifetimeExtender { + private NotificationSafeToRemoveCallback mCallback; + private boolean mExtendLifetimes = true; + private Set<String> mManagedNotifs = new ArraySet<>(); + + @Override + public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) { + mCallback = callback; + } + + @Override + public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) { + return mExtendLifetimes; + } + + @Override + public void setShouldManageLifetime( + @NonNull NotificationEntry entry, + boolean shouldManage) { + final boolean hasEntry = mManagedNotifs.contains(entry.key); + if (shouldManage) { + if (hasEntry) { + throw new RuntimeException("Already managing this entry: " + entry.key); + } + mManagedNotifs.add(entry.key); + } else { + if (!hasEntry) { + throw new RuntimeException("Not managing this entry: " + entry.key); + } + mManagedNotifs.remove(entry.key); + } + } + + public void setExtendLifetimes(boolean extendLifetimes) { + mExtendLifetimes = extendLifetimes; + } + + public NotificationSafeToRemoveCallback getCallback() { + return mCallback; + } + + public boolean isManaging(String notificationKey) { + return mManagedNotifs.contains(notificationKey); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java index 382dde9ce043..dbf00a379c5f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java @@ -23,6 +23,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; +import static com.android.systemui.statusbar.phone.NavigationBarView.WINDOW_TARGET_BOTTOM; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -63,7 +64,6 @@ import org.mockito.MockitoAnnotations; public class QuickStepControllerTest extends SysuiTestCase { private static final int NAVBAR_WIDTH = 1000; private static final int NAVBAR_HEIGHT = 300; - private static final int EDGE_THRESHOLD = 100; private QuickStepController mController; private NavigationBarView mNavigationBarView; @@ -77,8 +77,6 @@ public class QuickStepControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); final ButtonDispatcher backButton = mock(ButtonDispatcher.class); mResources = mock(Resources.class); - doReturn(EDGE_THRESHOLD).when(mResources) - .getDimensionPixelSize(R.dimen.navigation_bar_edge_swipe_threshold); mProxyService = mock(OverviewProxyService.class); mProxy = mock(IOverviewProxy.Stub.class); @@ -95,6 +93,7 @@ public class QuickStepControllerTest extends SysuiTestCase { doReturn(true).when(mNavigationBarView).isNotificationsFullyCollapsed(); doReturn(true).when(mNavigationBarView).isQuickScrubEnabled(); doReturn(HIT_TARGET_NONE).when(mNavigationBarView).getDownHitTarget(); + doReturn(WINDOW_TARGET_BOTTOM).when(mNavigationBarView).getWindowTarget(); doReturn(backButton).when(mNavigationBarView).getBackButton(); doReturn(mResources).when(mNavigationBarView).getResources(); doReturn(mContext).when(mNavigationBarView).getContext(); @@ -196,10 +195,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // Swipe Up assertGestureTriggersAction(swipeUp, 1, 100, 5, 1); @@ -209,10 +206,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, 5, 1); // Swipe Right assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 5); - // Swipe Left from Edge - assertGestureTriggersAction(swipeLeftFromEdge, NAVBAR_WIDTH, 1, 5, 1); - // Swipe Right from Edge - assertGestureTriggersAction(swipeRightFromEdge, 0, 1, NAVBAR_WIDTH, 5); } @Test @@ -224,10 +217,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // In landscape mController.setBarState(false /* isRTL */, NAV_BAR_RIGHT); @@ -240,10 +231,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeUp, 100, 1, 5, 1); // Swipe Right assertGestureTriggersAction(swipeDown, 1, 1, 100, 5); - // Swipe Up from Edge - assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0); - // Swipe Down from Edge - assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH); } @Test @@ -256,10 +243,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // Swipe Up assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1); @@ -269,10 +254,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeDown, 100, 1, 5, 1); // Swipe Right assertGestureTriggersAction(swipeUp, 1, 1, 100, 5); - // Swipe Up from Edge - assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0); - // Swipe Down from Edge - assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH); } @Test @@ -286,10 +267,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // Swipe Up in RTL assertGestureTriggersAction(swipeUp, 1, 100, 5, 1); @@ -299,10 +278,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeRight, NAVBAR_WIDTH / 2, 1, 5, 1); // Swipe Right in RTL assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH / 2, 1, NAVBAR_WIDTH, 0); - // Swipe Left from Edge - assertGestureTriggersAction(swipeRightFromEdge, NAVBAR_WIDTH, 1, 5, 1); - // Swipe Right from Edge - assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, NAVBAR_WIDTH, 5); } @Test @@ -316,10 +291,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // Swipe Up assertGestureTriggersAction(swipeLeft, 1, NAVBAR_WIDTH / 2, 5, 1); @@ -329,10 +302,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeUp, 100, 1, 5, 1); // Swipe Right assertGestureTriggersAction(swipeDown, 1, 1, 100, 5); - // Swipe Up from Edge - assertGestureTriggersAction(swipeLeftFromEdge, 1, NAVBAR_WIDTH, 5, 0); - // Swipe Down from Edge - assertGestureTriggersAction(swipeRightFromEdge, 0, 1, 0, NAVBAR_WIDTH); } @Test @@ -346,10 +315,8 @@ public class QuickStepControllerTest extends SysuiTestCase { NavigationGestureAction swipeDown = mockAction(true); NavigationGestureAction swipeLeft = mockAction(true); NavigationGestureAction swipeRight = mockAction(true); - NavigationGestureAction swipeLeftFromEdge = mockAction(true); - NavigationGestureAction swipeRightFromEdge = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, swipeLeftFromEdge, - swipeRightFromEdge); + mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, + null /* leftEdgeSwipe */, null /* rightEdgeSwipe */); // Swipe Up assertGestureTriggersAction(swipeRight, 1, NAVBAR_WIDTH / 2, 5, 1); @@ -359,10 +326,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureTriggersAction(swipeDown, 100, 1, 5, 1); // Swipe Right assertGestureTriggersAction(swipeUp, 1, 1, 100, 5); - // Swipe Up from Edge - assertGestureTriggersAction(swipeRightFromEdge, 1, NAVBAR_WIDTH, 5, 0); - // Swipe Down from Edge - assertGestureTriggersAction(swipeLeftFromEdge, 0, 1, 0, NAVBAR_WIDTH); } @Test @@ -602,25 +565,6 @@ public class QuickStepControllerTest extends SysuiTestCase { assertGestureDragsHitTargetAllDirections(buttonView, true /* isRTL */, NAV_BAR_LEFT); } - @Test - public void testNoEdgeActionsTriggerNormalActions() { - doReturn(NAVBAR_WIDTH).when(mNavigationBarView).getWidth(); - doReturn(NAVBAR_HEIGHT).when(mNavigationBarView).getHeight(); - - NavigationGestureAction swipeUp = mockAction(true); - NavigationGestureAction swipeDown = mockAction(true); - NavigationGestureAction swipeLeft = mockAction(true); - NavigationGestureAction swipeRight = mockAction(true); - mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight, - null /* swipeLeftFromEdgeAction */, - null /* swipeLeftFromEdgeAction */); - - // Swipe Left from Edge - assertGestureTriggersAction(swipeLeft, NAVBAR_WIDTH, 1, 5, 1); - // Swipe Right from Edge - assertGestureTriggersAction(swipeRight, 0, 1, NAVBAR_WIDTH, 5); - } - private void assertGestureDragsHitTargetAllDirections(View buttonView, boolean isRTL, int navPos) { mController.setBarState(isRTL, navPos); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java index ed98c62502a4..568ff55f6d34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java @@ -96,7 +96,7 @@ public class RemoteInputViewTest extends SysuiTestCase { RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build(); view.setPendingIntent(pendingIntent); - view.setRemoteInput(new RemoteInput[]{input}, input); + view.setRemoteInput(new RemoteInput[]{input}, input, null /* editedSuggestionInfo */); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java index 55701225af71..6793ecaabdd7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java @@ -191,15 +191,7 @@ public class SmartReplyViewTest extends SysuiTestCase { setSmartReplies(TEST_CHOICES); mView.getChildAt(2).performClick(); verify(mLogger).smartReplySent(mEntry, 2, TEST_CHOICES[2], - false /* generatedByAsssitant */, MetricsEvent.LOCATION_UNKNOWN); - } - - @Test - public void testSendSmartReply_controllerCalled_generatedByAssistant() { - setSmartReplies(TEST_CHOICES, true); - mView.getChildAt(2).performClick(); - verify(mLogger).smartReplySent(mEntry, 2, TEST_CHOICES[2], - true /* generatedByAsssitant */, MetricsEvent.LOCATION_UNKNOWN); + MetricsEvent.LOCATION_UNKNOWN, false /* modifiedBeforeSending */); } @Test diff --git a/packages/overlays/IconPackCircularAndroidOverlay/Android.mk b/packages/overlays/IconPackCircularAndroidOverlay/Android.mk new file mode 100644 index 000000000000..60f525b65128 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/Android.mk @@ -0,0 +1,30 @@ +# +# Copyright 2019, 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. +# +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackCircularAndroid +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackCircularAndroidOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackCircularOverlay/AndroidManifest.xml b/packages/overlays/IconPackCircularAndroidOverlay/AndroidManifest.xml index 6f0124daa0c7..94056767ac4e 100644 --- a/packages/overlays/IconPackCircularOverlay/AndroidManifest.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/AndroidManifest.xml @@ -16,9 +16,9 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.theme.icon_pack.circular" + package="com.android.theme.icon_pack.circular.android" android:versionCode="1" android:versionName="1.0"> - <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack" android:priority="1"/> + <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack.android" android:priority="1"/> <application android:label="Circular" android:hasCode="false"/> </manifest> diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml new file mode 100644 index 000000000000..4d8c366fff53 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,18V11A9,9,0,0,0,3,11v7a2.93,2.93,0,0,0,2.88,3H8V13H4V11a8,8,0,0,1,16,0v2H16v8h2.12A2.93,2.93,0,0,0,21,18ZM7,14v6H5.88A1.92,1.92,0,0,1,4,18V14Zm13,4a1.92,1.92,0,0,1-1.88,2H17V14h3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml new file mode 100644 index 000000000000..ab6aec5bc416 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_expand_more.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.35,9.65a0.48 0.48 ,0,0,0-0.7,0L12,15.28,6.35,9.65a0.49 0.49 ,0,0,0-0.7 0.7 L12,16.7l6.35-6.35A0.48 0.48 ,0,0,0,18.35,9.65Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_info_outline_24.xml new file mode 100644 index 000000000000..0e108ca7924c --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_info_outline_24.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,11a0.5 0.5 ,0,0,0-0.5 0.5 v5a0.5 0.5 ,0,0,0,1,0v-5A0.5 0.5 ,0,0,0,12,11Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 7 C 12.4142135624 7 12.75 7.33578643763 12.75 7.75 C 12.75 8.16421356237 12.4142135624 8.5 12 8.5 C 11.5857864376 8.5 11.25 8.16421356237 11.25 7.75 C 11.25 7.33578643763 11.5857864376 7 12 7 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_invert_colors.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_invert_colors.xml new file mode 100644 index 000000000000..59e7838b9c67 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_invert_colors.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12.62,2.23A1,1,0,0,0,12,2a1.07,1.07,0,0,0-0.63 0.22 C9.48,3.75,4,8.5,4,14a7.89,7.89,0,0,0,8,8,8,8,0,0,0,8-8C20,8.5,14.5,3.73,12.62,2.23ZM12,21a6.92,6.92,0,0,1-7-7C5,9.16,9.89,4.71,12,3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..04a2c24ce45a --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,57 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19a2,2,0,0,0,2,2ZM2,19V6A1,1,0,0,1,3,5H21a1,1,0,0,1,1,1V19a1,1,0,0,1-1,1H3A1,1,0,0,1,2,19Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 8 L 10.5 8 Q 11 8 11 8.5 L 11 9.5 Q 11 10 10.5 10 L 9.5 10 Q 9 10 9 9.5 L 9 8.5 Q 9 8 9.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 8 L 6.5 8 Q 7 8 7 8.5 L 7 9.5 Q 7 10 6.5 10 L 5.5 10 Q 5 10 5 9.5 L 5 8.5 Q 5 8 5.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 8 L 14.5 8 Q 15 8 15 8.5 L 15 9.5 Q 15 10 14.5 10 L 13.5 10 Q 13 10 13 9.5 L 13 8.5 Q 13 8 13.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 12 L 10.5 12 Q 11 12 11 12.5 L 11 13.5 Q 11 14 10.5 14 L 9.5 14 Q 9 14 9 13.5 L 9 12.5 Q 9 12 9.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 12 L 6.5 12 Q 7 12 7 12.5 L 7 13.5 Q 7 14 6.5 14 L 5.5 14 Q 5 14 5 13.5 L 5 12.5 Q 5 12 5.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 12 L 14.5 12 Q 15 12 15 12.5 L 15 13.5 Q 15 14 14.5 14 L 13.5 14 Q 13 14 13 13.5 L 13 12.5 Q 13 12 13.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 8 L 18.5 8 Q 19 8 19 8.5 L 19 9.5 Q 19 10 18.5 10 L 17.5 10 Q 17 10 17 9.5 L 17 8.5 Q 17 8 17.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 12 L 18.5 12 Q 19 12 19 12.5 L 19 13.5 Q 19 14 18.5 14 L 17.5 14 Q 17 14 17 13.5 L 17 12.5 Q 17 12 17.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M8.5,17h7a0.5 0.5 ,0,0,0,0-1h-7a0.5 0.5 ,0,0,0,0,1Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml new file mode 100644 index 000000000000..f9b0f6cbccc6 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,21H7.18L20.41,7.77a2,2,0,0,0,0-2.83L19.06,3.59a2,2,0,0,0-2.83,0L3,16.82ZM16.94,4.3a1,1,0,0,1,1.41,0l1.36,1.35a1,1,0,0,1,0.29 0.7 ,1,1,0,0,1-0.3 0.71 l-2,2L15,6.26ZM4,17.23,14.26,7,17,9.74,6.77,20H4Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml new file mode 100644 index 000000000000..ac47a86abb6e --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,18.06a3.22,3.22,0,0,0-5.49-2.28L13.26,18A17.13,17.13,0,0,1,9.2,15.1,18.37,18.37,0,0,1,6,10.69L8.22,8.48A3.19,3.19,0,0,0,9,5.33,3.24,3.24,0,0,0,6,3H3.49s0,0,0,0L3.39,3l-0.1,0-0.07 0.05 -0.08 0.06 a0.35 0.35 ,0,0,0-0.05 0.08 A0.35 0.35 ,0,0,0,3,3.3a0.36 0.36 ,0,0,0,0,0.1 0.24 0.24,0,0,0,0,0.08v0H3a19.11,19.11,0,0,0,5.5,12.3,18.38,18.38,0,0,0,12,5.2h0a0.58 0.58 ,0,0,0,0.19,0,0.18 0.18 ,0,0,0,0.07-0.05l0.09-0.06,0-0.07a0.35 0.35 ,0,0,0,0.05-0.08 0.29 0.29,0,0,0,0-0.1s0-0.05,0-0.08h0ZM4.06,4H6A2.22,2.22,0,0,1,7.52,7.78l-2,2A18.05,18.05,0,0,1,4.06,4ZM14.21,18.5l2-2A2.22,2.22,0,0,1,20,18.06V20A17.64,17.64,0,0,1,14.21,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_night_display_on.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_night_display_on.xml new file mode 100644 index 000000000000..8ee7e2fc7666 --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_night_display_on.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M22.36,15.7a0.51 0.51 ,0,0,0-0.51-0.22,11.59,11.59,0,0,1-2.07 0.2 A11.5,11.5,0,0,1,8.31,4.17a10.91,10.91,0,0,1,0.2-2.08 0.51 0.51,0,0,0-0.22-0.51 0.5 0.5,0,0,0-0.55,0A10.57,10.57,0,1,0,22.36,16.25 0.5 0.5,0,0,0,22.36,15.7ZM13.55,20A9.59,9.59,0,0,1,7.36,3.12a9.34,9.34,0,0,0-0.05,1A12.46,12.46,0,0,0,20.82,16.63,9.49,9.49,0,0,1,13.55,20Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_location.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_location.xml new file mode 100644 index 000000000000..25535c7bfc3e --- /dev/null +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_location.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,21.5s7-5.34,7-11.25A7.13,7.13,0,0,0,12,3a7.13,7.13,0,0,0-7,7.25C5,16.16,12,21.5,12,21.5ZM12,4a6.13,6.13,0,0,1,6,6.25c0,4.37-4.37,8.54-6,10-1.63-1.4-6-5.57-6-9.95A6.13,6.13,0,0,1,12,4Z" /> + <path + android:fillColor="#000000" + android:pathData="M15,10a3,3,0,1,0-3,3A3,3,0,0,0,15,10Zm-5,0a2,2,0,1,1,2,2A2,2,0,0,1,10,10Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_0.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_0.xml index e1ca60d86d7a..b73fcb25d7f6 100644 --- a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_0.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_0.xml @@ -48,4 +48,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.08,5.08,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_1.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_1.xml index 06ac16dafef6..69b1bd8683f7 100644 --- a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_1.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_1.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -46,4 +45,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.08,5.08,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_2.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_2.xml index 844fabf3b994..353fccb53e57 100644 --- a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_2.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_2.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -43,4 +42,4 @@ <path android:fillColor="#000000" android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.07,5.07,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_3.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_3.xml index 3a010328dcef..a8bade5cef58 100644 --- a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_3.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_3.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -40,4 +39,4 @@ <path android:fillColor="#000000" android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.07,5.07,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_4.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_4.xml index 3512d44ad115..a4afffd6dbfd 100644 --- a/packages/overlays/IconPackCircularOverlay/res/drawable/ic_wifi_signal_4.xml +++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_wifi_signal_4.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -37,4 +36,4 @@ <path android:fillColor="#000000" android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.08,5.08,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSettingsOverlay/Android.mk b/packages/overlays/IconPackCircularSettingsOverlay/Android.mk new file mode 100644 index 000000000000..ad7324dec699 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright 2019, 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackCircularSettings +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackCircularSettingsOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackCircularSettingsOverlay/AndroidManifest.xml b/packages/overlays/IconPackCircularSettingsOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..c1a56985a4fd --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.circular.settings" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.settings" android:category="android.theme.customization.icon_pack.settings" android:priority="1"/> + <application android:label="Circular" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml new file mode 100644 index 000000000000..dbac48dfbf35 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml @@ -0,0 +1,54 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M6,4A2,2,0,0,0,6,8H7.5A0.5 0.5 ,0,0,0,8,7.5V6A2,2,0,0,0,6,4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,8h1.5a0.5 0.5 ,0,0,0,0.5-0.5V6a2,2,0,1,0-2,2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20,6a2,2,0,1,0-2,2h1.5a0.5 0.5 ,0,0,0,0.5-0.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M6,14H7.5a0.5 0.5 ,0,0,0,0.5-0.5V12a2,2,0,1,0-2,2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,14h1.5a0.5 0.5 ,0,0,0,0.5-0.5V12a2,2,0,1,0-2,2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20,12a2,2,0,1,0-2,2h1.5a0.5 0.5 ,0,0,0,0.5-0.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M6,20H7.5a0.5 0.5 ,0,0,0,0.5-0.5V18a2,2,0,1,0-2,2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,20h1.5a0.5 0.5 ,0,0,0,0.5-0.5V18a2,2,0,1,0-2,2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20,18a2,2,0,1,0-2,2h1.5a0.5 0.5 ,0,0,0,0.5-0.5Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml new file mode 100644 index 000000000000..a407bd6539f6 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M2,16.5A2.5,2.5,0,0,0,4.5,19h2a0.5 0.5 ,0,0,0,0-1h-2A1.5,1.5,0,0,1,3,16.5v-9A1.5,1.5,0,0,1,4.5,6h17a0.5 0.5 ,0,0,0,0-1H4.5A2.5,2.5,0,0,0,2,7.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M14,16a3,3,0,1,0-3,3A3,3,0,0,0,14,16ZM9,16a2,2,0,1,1,2,2A2,2,0,0,1,9,16Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M22,17V10a2,2,0,0,0-2-2H17a2,2,0,0,0-2,2v7a2,2,0,0,0,2,2h3A2,2,0,0,0,22,17Zm-6,0V10a1,1,0,0,1,1-1h3a1,1,0,0,1,1,1v7a1,1,0,0,1-1,1H17A1,1,0,0,1,16,17Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml new file mode 100644 index 000000000000..c9068478487f --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,22h0A10,10,0,0,0,22,12v0A10,10,0,1,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8.62,9.65a0.5 0.5 ,0,0,0,0.61-0.37,2.94,2.94,0,0,1,5-1.41A2.64,2.64,0,0,1,15,10a2.27,2.27,0,0,1-1,1.69l-0.44 0.26 a3.21,3.21,0,0,0-1.91,2.47A0.49 0.49 ,0,0,0,12,15h0.08a0.5 0.5 ,0,0,0,0.49-0.42A2.25,2.25,0,0,1,14,12.81l0.5-0.29A3.27,3.27,0,0,0,16,10.09,3.62,3.62,0,0,0,14.9,7.16a4,4,0,0,0-5.6,0A4.06,4.06,0,0,0,8.25,9.05 0.5 0.5,0,0,0,8.62,9.65Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 16.25 C 12.4142135624 16.25 12.75 16.5857864376 12.75 17 C 12.75 17.4142135624 12.4142135624 17.75 12 17.75 C 11.5857864376 17.75 11.25 17.4142135624 11.25 17 C 11.25 16.5857864376 11.5857864376 16.25 12 16.25 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml new file mode 100644 index 000000000000..f3419d4b8db5 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15,22a3,3,0,0,0,3-3V5a3,3,0,0,0-3-3H9A3,3,0,0,0,6,5V19a3,3,0,0,0,3,3ZM7,6H17V18H7ZM9,3h6a2,2,0,0,1,2,2H7A2,2,0,0,1,9,3ZM7,19H17a2,2,0,0,1-2,2H9A2,2,0,0,1,7,19Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,10.5a0.5 0.5 ,0,0,0-0.5 0.5 v4.5a0.5 0.5 ,0,0,0,1,0V11A0.5 0.5 ,0,0,0,12,10.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 8 C 12.4142135624 8 12.75 8.33578643763 12.75 8.75 C 12.75 9.16421356237 12.4142135624 9.5 12 9.5 C 11.5857864376 9.5 11.25 9.16421356237 11.25 8.75 C 11.25 8.33578643763 11.5857864376 8 12 8 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml new file mode 100644 index 000000000000..8a8ddec7501e --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml @@ -0,0 +1,42 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21,5.35A0.51 0.51 ,0,0,0,20.37,5,37.25,37.25,0,0,1,3.63,5,0.51 0.51 ,0,0,0,3,5.35 0.51 0.51,0,0,0,3.37,6,32.05,32.05,0,0,0,9,6.87V20a0.5 0.5 ,0,0,0,1,0V13.5h4V20a0.5 0.5 ,0,0,0,1,0V6.87A32.05,32.05,0,0,0,20.63,6,0.51 0.51 ,0,0,0,21,5.35Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 1 C 13.1045694997 1 14 1.89543050034 14 3 C 14 4.10456949966 13.1045694997 5 12 5 C 10.8954305003 5 10 4.10456949966 10 3 C 10 1.89543050034 10.8954305003 1 12 1 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml new file mode 100644 index 000000000000..01fc4b9a886b --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22Zm0-1a9,9,0,0,1-7-3.31,10.37,10.37,0,0,1,13.94,0A9,9,0,0,1,12,21ZM3,12a9,9,0,0,1,18,0,8.88,8.88,0,0,1-1.45,4.88,11.35,11.35,0,0,0-15.1,0A8.83,8.83,0,0,1,3,12Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15.5,9.5A3.5,3.5,0,1,0,12,13,3.5,3.5,0,0,0,15.5,9.5Zm-6,0A2.5,2.5,0,1,1,12,12,2.5,2.5,0,0,1,9.5,9.5Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml new file mode 100644 index 000000000000..b43923fec380 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M14,4a1,1,0,0,0-1-1H11a1,1,0,0,0-1,1H9A2,2,0,0,0,7,6V19a2,2,0,0,0,2,2h6a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml new file mode 100644 index 000000000000..580271b3da24 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M3.41,14.72A2,2,0,0,1,4,16.14V18a2,2,0,0,0,2,2H7.86a2,2,0,0,1,1.42 0.59 l1.31,1.31a2,2,0,0,0,2.82,0l1.31-1.31A2,2,0,0,1,16.14,20H18a2,2,0,0,0,2-2V16.14a2,2,0,0,1,0.59-1.42l1.31-1.31a2,2,0,0,0,0-2.82L20.59,9.28A2,2,0,0,1,20,7.86V6a2,2,0,0,0-2-2H16.14a2,2,0,0,1-1.42-0.59L13.41,2.1a2,2,0,0,0-2.82,0L9.28,3.41A2,2,0,0,1,7.86,4H6A2,2,0,0,0,4,6V7.86a2,2,0,0,1-0.59,1.42L2.1,10.59a2,2,0,0,0,0,2.82Zm-0.6-3.43L4.12,10A3,3,0,0,0,5,7.86V6A1,1,0,0,1,6,5H7.86A3,3,0,0,0,10,4.12l1.31-1.31a1,1,0,0,1,1.42,0L14,4.12A3,3,0,0,0,16.14,5H18a1,1,0,0,1,1,1V7.86A3,3,0,0,0,19.88,10l1.31,1.31a1,1,0,0,1,0,1.42L19.88,14A3,3,0,0,0,19,16.14V18a1,1,0,0,1-1,1H16.14a3,3,0,0,0-2.12 0.88 l-1.31,1.31a1,1,0,0,1-1.42,0L10,19.88A3,3,0,0,0,7.86,19H6a1,1,0,0,1-1-1V16.14A3,3,0,0,0,4.12,14L2.81,12.71a1,1,0,0,1,0-1.42Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M17,12a5,5,0,0,0-5-5V17A5,5,0,0,0,17,12Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml new file mode 100644 index 000000000000..37d5576ea9fc --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,21.5s7-5.34,7-11.25A7.13,7.13,0,0,0,12,3a7.13,7.13,0,0,0-7,7.25C5,16.16,12,21.5,12,21.5ZM12,4a6.13,6.13,0,0,1,6,6.25c0,4.37-4.37,8.54-6,10-1.63-1.4-6-5.57-6-9.95A6.13,6.13,0,0,1,12,4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15,10a3,3,0,1,0-3,3A3,3,0,0,0,15,10Zm-5,0a2,2,0,1,1,2,2A2,2,0,0,1,10,10Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml new file mode 100644 index 000000000000..32f9e533a29b --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,17a9.48,9.48,0,0,1-8.92-5.5A9.48,9.48,0,0,1,12,6a9.5,9.5,0,0,1,8.65,5h1.13A10.5,10.5,0,0,0,12,5,10.47,10.47,0,0,0,2,11.5,10.47,10.47,0,0,0,12,18a11.48,11.48,0,0,0,4-0.7V16.22A10.48,10.48,0,0,1,12,17Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,8a3.5,3.5,0,1,0,3.5,3.5A3.5,3.5,0,0,0,12,8Zm0,6a2.5,2.5,0,1,1,2.5-2.5A2.5,2.5,0,0,1,12,14Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M22,15V14a2,2,0,0,0-4,0v1a1,1,0,0,0-1,1v3a1,1,0,0,0,1,1h4a1,1,0,0,0,1-1V16A1,1,0,0,0,22,15Zm-3,0V14a1,1,0,0,1,2,0v1Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml new file mode 100644 index 000000000000..71d427ac0506 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,12a1.5,1.5,0,0,0-0.5,2.91V16.5a0.5 0.5 ,0,0,0,1,0V14.91A1.5,1.5,0,0,0,12,12Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23,5a4,4,0,0,0-8,0V8H6A1,1,0,0,0,5,9v9a3,3,0,0,0,3,3h8a3,3,0,0,0,3-3V9a1,1,0,0,0-1-1H16V5a3,3,0,0,1,6,0,0.5 0.5 ,0,0,0,1,0ZM18,9v9a2,2,0,0,1-2,2H8a2,2,0,0,1-2-2V9H18Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml new file mode 100644 index 000000000000..f4b29aef3693 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,11a0.5 0.5 ,0,0,0-0.5 0.5 v5a0.5 0.5 ,0,0,0,1,0v-5A0.5 0.5 ,0,0,0,12,11Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 7 C 12.4142135624 7 12.75 7.33578643763 12.75 7.75 C 12.75 8.16421356237 12.4142135624 8.5 12 8.5 C 11.5857864376 8.5 11.25 8.16421356237 11.25 7.75 C 11.25 7.33578643763 11.5857864376 7 12 7 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml new file mode 100644 index 000000000000..85abfff8c53b --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml @@ -0,0 +1,39 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M18.76,11.8a0.54 0.54 ,0,0,0,0.36-0.14 0.51 0.51,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.07,9.07,0,0,1,12.83,0A0.54 0.54 ,0,0,0,18.76,11.8Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M2.15,8.15a0.49 0.49 ,0,0,0,0.7 0.7 ,12.8,12.8,0,0,1,18.3,0,0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7A13.77,13.77,0,0,0,2.15,8.15Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15.93,14.64a0.49 0.49 ,0,0,0,0.35-0.15 0.5 0.5,0,0,0,0-0.71,6.08,6.08,0,0,0-8.58,0,0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.07,5.07,0,0,1,7.16,0A0.51 0.51 ,0,0,0,15.93,14.64Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml new file mode 100644 index 000000000000..ea7a97f7685d --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml @@ -0,0 +1,45 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M3,5V7A1,1,0,0,0,4,8H20a1,1,0,0,0,1-1V5a2,2,0,0,0-2-2H5A2,2,0,0,0,3,5ZM20,5V7H4V5A1,1,0,0,1,5,4H19A1,1,0,0,1,20,5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M3,19a1,1,0,0,0,1,1H20a1,1,0,0,0,1-1V17a2,2,0,0,0-2-2H5a2,2,0,0,0-2,2Zm1-2a1,1,0,0,1,1-1H19a1,1,0,0,1,1,1v2H4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M3,13a1,1,0,0,0,1,1H20a1,1,0,0,0,1-1V11a2,2,0,0,0-2-2H5a2,2,0,0,0-2,2Zm1-2a1,1,0,0,1,1-1H19a1,1,0,0,1,1,1v2H4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 6.01 4.75 C 6.42421356237 4.75 6.76 5.08578643763 6.76 5.5 C 6.76 5.91421356237 6.42421356237 6.25 6.01 6.25 C 5.59578643763 6.25 5.26 5.91421356237 5.26 5.5 C 5.26 5.08578643763 5.59578643763 4.75 6.01 4.75 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 6.01 10.75 C 6.42421356237 10.75 6.76 11.0857864376 6.76 11.5 C 6.76 11.9142135624 6.42421356237 12.25 6.01 12.25 C 5.59578643763 12.25 5.26 11.9142135624 5.26 11.5 C 5.26 11.0857864376 5.59578643763 10.75 6.01 10.75 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 6.01 16.75 C 6.42421356237 16.75 6.76 17.0857864376 6.76 17.5 C 6.76 17.9142135624 6.42421356237 18.25 6.01 18.25 C 5.59578643763 18.25 5.26 17.9142135624 5.26 17.5 C 5.26 17.0857864376 5.59578643763 16.75 6.01 16.75 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml new file mode 100644 index 000000000000..7ed248d7e8b1 --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13.79,13.79a0.5 0.5 ,0,0,0,0.21,1,0.54 0.54 ,0,0,0,0.21-0.05,2.92,2.92,0,0,0,0-5.39 0.49 0.49,0,0,0-0.66 0.24 0.5 0.5 ,0,0,0,0.24 0.67 ,1.93,1.93,0,0,1,0,3.58Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13.89,17.67a0.5 0.5 ,0,0,0,0.11,1l0.11,0a6.78,6.78,0,0,0,0-13.28 0.5 0.5,0,1,0-0.22,1,5.79,5.79,0,0,1,0,11.34Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M5,15H7l4.15,4.15a0.47 0.47 ,0,0,0,0.35 0.14 0.5 0.5 ,0,0,0,0.5-0.5V5.21a0.5 0.5 ,0,0,0-0.5-0.5 0.47 0.47,0,0,0-0.35 0.14 L7,9H5a2,2,0,0,0-2,2v2A2,2,0,0,0,5,15ZM4,11a1,1,0,0,1,1-1H7.41l0.3-0.29L11,6.41V17.59l-3.29-3.3L7.41,14H5a1,1,0,0,1-1-1Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_wifi_tethering.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_wifi_tethering.xml new file mode 100644 index 000000000000..10c15923215f --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_wifi_tethering.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 11 C 12.8284271247 11 13.5 11.6715728753 13.5 12.5 C 13.5 13.3284271247 12.8284271247 14 12 14 C 11.1715728753 14 10.5 13.3284271247 10.5 12.5 C 10.5 11.6715728753 11.1715728753 11 12 11 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15.18,16.39a0.51 0.51 ,0,0,0,0.71,0,5.5,5.5,0,0,0,0-7.78,5.52,5.52,0,0,0-7.78,0,5.5,5.5,0,0,0,0,7.78 0.5 0.5,0,0,0,0.35 0.15 0.51 0.51 ,0,0,0,0.36-0.15 0.51 0.51,0,0,0,0-0.71,4.5,4.5,0,1,1,6.36,0A0.51 0.51 ,0,0,0,15.18,16.39Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M18,19.22a0.49 0.49 ,0,0,0,0.35 0.14 0.5 0.5 ,0,0,0,0.36-0.14,9.5,9.5,0,1,0-13.44,0,0.51 0.51 ,0,0,0,0.71,0,0.5 0.5 ,0,0,0,0-0.71,8.5,8.5,0,0,1,12-12,8.5,8.5,0,0,1,0,12A0.5 0.5 ,0,0,0,18,19.22Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk b/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk new file mode 100644 index 000000000000..711063dbf6ad --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright 2019, 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackCircularSystemUI +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackCircularSystemUIOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/AndroidManifest.xml b/packages/overlays/IconPackCircularSystemUIOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..356b7e28395e --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.circular.systemui" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.systemui" android:category="android.theme.customization.icon_pack.systemui" android:priority="1"/> + <application android:label="Circular" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml new file mode 100644 index 000000000000..04ee7cd109a0 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M3.41,14.72A2,2,0,0,1,4,16.14V18a2,2,0,0,0,2,2H7.86a2,2,0,0,1,1.42 0.59 l1.31,1.31a2,2,0,0,0,2.82,0l1.31-1.31A2,2,0,0,1,16.14,20H18a2,2,0,0,0,2-2V16.14a2,2,0,0,1,0.59-1.42l1.31-1.31a2,2,0,0,0,0-2.82L20.59,9.28A2,2,0,0,1,20,7.86V6a2,2,0,0,0-2-2H16.14a2,2,0,0,1-1.42-0.59L13.41,2.1a2,2,0,0,0-2.82,0L9.28,3.41A2,2,0,0,1,7.86,4H6A2,2,0,0,0,4,6V7.86a2,2,0,0,1-0.59,1.42L2.1,10.59a2,2,0,0,0,0,2.82Zm-0.6-3.43L4.12,10A3,3,0,0,0,5,7.86V6A1,1,0,0,1,6,5H7.86A3,3,0,0,0,10,4.12l1.31-1.31a1,1,0,0,1,1.42,0L14,4.12A3,3,0,0,0,16.14,5H18a1,1,0,0,1,1,1V7.86A3,3,0,0,0,19.88,10l1.31,1.31a1,1,0,0,1,0,1.42L19.88,14A3,3,0,0,0,19,16.14V18a1,1,0,0,1-1,1H16.14a3,3,0,0,0-2.12 0.88 l-1.31,1.31a1,1,0,0,1-1.42,0L10,19.88A3,3,0,0,0,7.86,19H6a1,1,0,0,1-1-1V16.14A3,3,0,0,0,4.12,14L2.81,12.71a1,1,0,0,1,0-1.42Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M 12 7 C 14.7614237492 7 17 9.23857625085 17 12 C 17 14.7614237492 14.7614237492 17 12 17 C 9.23857625085 17 7 14.7614237492 7 12 C 7 9.23857625085 9.23857625085 7 12 7 Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml new file mode 100644 index 000000000000..d25350a9688f --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,7.5a0.5 0.5 ,0,0,0-0.5 0.5 v3.5H8a0.5 0.5 ,0,0,0,0,1h3.5V16a0.5 0.5 ,0,0,0,1,0V12.5H16a0.5 0.5 ,0,0,0,0-1H12.5V8A0.5 0.5 ,0,0,0,12,7.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M22,12a10,10,0,0,0-9-9.95v3A7,7,0,0,1,19,12a7.12,7.12,0,0,1-0.48,2.54h0l2.6,1.53A9.88,9.88,0,0,0,22,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.09,13.39a10,10,0,0,0,18,4.52l-2.6-1.53h0A7,7,0,1,1,11,5.08v-3A10,10,0,0,0,2.09,13.39Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_dnd.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_dnd.xml new file mode 100644 index 000000000000..3e32b3bd6664 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_dnd.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M7,12.5H17a0.5 0.5 ,0,0,0,0-1H7a0.5 0.5 ,0,0,0,0,1Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_drag_handle.xml new file mode 100644 index 000000000000..793b32fbd7e5 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_drag_handle.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.5,9H4.5a0.5 0.5 ,0,0,0,0,1h15a0.5 0.5 ,0,0,0,0-1Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.5,14H4.5a0.5 0.5 ,0,0,0,0,1h15a0.5 0.5 ,0,0,0,0-1Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset.xml new file mode 100644 index 000000000000..4d8c366fff53 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_headset.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,18V11A9,9,0,0,0,3,11v7a2.93,2.93,0,0,0,2.88,3H8V13H4V11a8,8,0,0,1,16,0v2H16v8h2.12A2.93,2.93,0,0,0,21,18ZM7,14v6H5.88A1.92,1.92,0,0,1,4,18V14Zm13,4a1.92,1.92,0,0,1-1.88,2H17V14h3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_hotspot.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_hotspot.xml new file mode 100644 index 000000000000..670449ac8574 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_hotspot.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 11 C 12.8284271247 11 13.5 11.6715728753 13.5 12.5 C 13.5 13.3284271247 12.8284271247 14 12 14 C 11.1715728753 14 10.5 13.3284271247 10.5 12.5 C 10.5 11.6715728753 11.1715728753 11 12 11 Z" /> + <path + android:fillColor="#000000" + android:pathData="M15.18,16.39a0.51 0.51 ,0,0,0,0.71,0,5.5,5.5,0,0,0,0-7.78,5.52,5.52,0,0,0-7.78,0,5.5,5.5,0,0,0,0,7.78 0.5 0.5,0,0,0,0.35 0.15 0.51 0.51 ,0,0,0,0.36-0.15 0.51 0.51,0,0,0,0-0.71,4.5,4.5,0,1,1,6.36,0A0.51 0.51 ,0,0,0,15.18,16.39Z" /> + <path + android:fillColor="#000000" + android:pathData="M18,19.22a0.49 0.49 ,0,0,0,0.35 0.14 0.5 0.5 ,0,0,0,0.36-0.14,9.5,9.5,0,1,0-13.44,0,0.51 0.51 ,0,0,0,0.71,0,0.5 0.5 ,0,0,0,0-0.71,8.5,8.5,0,0,1,12-12,8.5,8.5,0,0,1,0,12A0.5 0.5 ,0,0,0,18,19.22Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_info.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_info.xml new file mode 100644 index 000000000000..0e108ca7924c --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_info.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,11a0.5 0.5 ,0,0,0-0.5 0.5 v5a0.5 0.5 ,0,0,0,1,0v-5A0.5 0.5 ,0,0,0,12,11Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 7 C 12.4142135624 7 12.75 7.33578643763 12.75 7.75 C 12.75 8.16421356237 12.4142135624 8.5 12 8.5 C 11.5857864376 8.5 11.25 8.16421356237 11.25 7.75 C 11.25 7.33578643763 11.5857864376 7 12 7 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..04a2c24ce45a --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,57 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19a2,2,0,0,0,2,2ZM2,19V6A1,1,0,0,1,3,5H21a1,1,0,0,1,1,1V19a1,1,0,0,1-1,1H3A1,1,0,0,1,2,19Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 8 L 10.5 8 Q 11 8 11 8.5 L 11 9.5 Q 11 10 10.5 10 L 9.5 10 Q 9 10 9 9.5 L 9 8.5 Q 9 8 9.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 8 L 6.5 8 Q 7 8 7 8.5 L 7 9.5 Q 7 10 6.5 10 L 5.5 10 Q 5 10 5 9.5 L 5 8.5 Q 5 8 5.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 8 L 14.5 8 Q 15 8 15 8.5 L 15 9.5 Q 15 10 14.5 10 L 13.5 10 Q 13 10 13 9.5 L 13 8.5 Q 13 8 13.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 12 L 10.5 12 Q 11 12 11 12.5 L 11 13.5 Q 11 14 10.5 14 L 9.5 14 Q 9 14 9 13.5 L 9 12.5 Q 9 12 9.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 12 L 6.5 12 Q 7 12 7 12.5 L 7 13.5 Q 7 14 6.5 14 L 5.5 14 Q 5 14 5 13.5 L 5 12.5 Q 5 12 5.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 12 L 14.5 12 Q 15 12 15 12.5 L 15 13.5 Q 15 14 14.5 14 L 13.5 14 Q 13 14 13 13.5 L 13 12.5 Q 13 12 13.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 8 L 18.5 8 Q 19 8 19 8.5 L 19 9.5 Q 19 10 18.5 10 L 17.5 10 Q 17 10 17 9.5 L 17 8.5 Q 17 8 17.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 12 L 18.5 12 Q 19 12 19 12.5 L 19 13.5 Q 19 14 18.5 14 L 17.5 14 Q 17 14 17 13.5 L 17 12.5 Q 17 12 17.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M8.5,17h7a0.5 0.5 ,0,0,0,0-1h-7a0.5 0.5 ,0,0,0,0,1Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..2b9e3719961d --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,39 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2.5A1.5,1.5,0,0,0,10.5,4v0.2A6,6,0,0,0,6,10v5.5a0.5 0.5 ,0,0,1-0.5 0.5 A1.5,1.5,0,0,0,4,17.5v1a0.5 0.5 ,0,0,0,0.5 0.5 h15a0.5 0.5 ,0,0,0,0.5-0.5v-1A1.5,1.5,0,0,0,18.5,16a0.5 0.5 ,0,0,1-0.5-0.5V10a6,6,0,0,0-4.5-5.8V4A1.5,1.5,0,0,0,12,2.5ZM17,10v5.5A1.5,1.5,0,0,0,18.5,17a0.5 0.5 ,0,0,1,0.5 0.5 V18H5v-0.5a0.5 0.5 ,0,0,1,0.5-0.5A1.5,1.5,0,0,0,7,15.5V10a5,5,0,0,1,10,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M6,3.2a9.24,9.24,0,0,0-3.26,7.05 0.5 0.5,0,0,0,1,0A8.25,8.25,0,0,1,6.66,4,0.5 0.5 ,0,0,0,6,3.2Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.25,10.25A9.24,9.24,0,0,0,18,3.2a0.5 0.5 ,0,0,0-0.65 0.76 ,8.25,8.25,0,0,1,2.91,6.29 0.5 0.5,0,0,0,1,0Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_silence.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_silence.xml new file mode 100644 index 000000000000..838f75268d69 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_notifications_silence.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,5a5,5,0,0,1,5,5v5.17l3,3V17.5A1.5,1.5,0,0,0,18.5,16a0.5 0.5 ,0,0,1-0.5-0.5V10a6,6,0,0,0-4.5-5.8V4a1.5,1.5,0,0,0-3,0v0.2A6,6,0,0,0,7.68,5.85l0.71 0.71 A5,5,0,0,1,12,5Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.85,21.15l-18-18a0.48 0.48 ,0,0,0-0.7,0h0a0.48 0.48 ,0,0,0,0,0.7L6.33,8A6.06,6.06,0,0,0,6,10v5.5a0.5 0.5 ,0,0,1-0.5 0.5 A1.5,1.5,0,0,0,4,17.5v1a0.5 0.5 ,0,0,0,0.5 0.5 H17.29l2.86,2.85a0.48 0.48 ,0,0,0,0.7,0h0A0.48 0.48 ,0,0,0,20.85,21.15ZM5,18v-0.5a0.5 0.5 ,0,0,1,0.5-0.5A1.5,1.5,0,0,0,7,15.5V10a4.83,4.83,0,0,1,0.15-1.15L16.29,18Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml new file mode 100644 index 000000000000..f98e2b8b2a24 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.5,6a0.5 0.5 ,0,0,0-0.5 0.5 V11H7.5a0.5 0.5 ,0,0,0,0-1H4.76l5-4.65a2.49,2.49,0,0,1,3.48 0.05 l4.95,4.95a0.49 0.49 ,0,1,0,0.7-0.7L13.91,4.7A3.47,3.47,0,0,0,9,4.62L4,9.35V6.5A0.5 0.5 ,0,0,0,3.5,6Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.5,18a0.5 0.5 ,0,0,0,0.5-0.5V13H16.5a0.5 0.5 ,0,0,0,0,1h2.74l-5,4.65a2.49,2.49,0,0,1-3.48,0l-5-5a0.49 0.49 ,0,0,0-0.7 0.7 l4.94,5a3.47,3.47,0,0,0,4.87 0.08 l5-4.73V17.5A0.5 0.5 ,0,0,0,20.5,18Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml new file mode 100644 index 000000000000..10b1cbf68543 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.16,17.37a0.51 0.51 ,0,0,0,0.71,0,7.76,7.76,0,0,0,0-10.68 0.5 0.5,0,1,0-0.74 0.68 ,6.74,6.74,0,0,1,0,9.32A0.51 0.51 ,0,0,0,18.16,17.37Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.27,14.47a0.51 0.51 ,0,0,0,0.7,0,3.48,3.48,0,0,0,0-4.92l-0.72 0.7 a2.47,2.47,0,0,1,0,3.51A0.5 0.5 ,0,0,0,16.27,14.47Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.15,18.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L9,13.71V22h0.5a5.25,5.25,0,0,0,2.25-10A5.25,5.25,0,0,0,9.5,2H9v8.29L3.85,5.15a0.49 0.49 ,0,0,0-0.7 0.7 L9,11.71v0.58Zm10.63-1.4A4.26,4.26,0,0,1,10,21V12.53A4.26,4.26,0,0,1,13.78,16.75ZM10,3a4.25,4.25,0,0,1,0,8.44Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml new file mode 100644 index 000000000000..e8664f6807a0 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.78,7.25A5.27,5.27,0,0,0,11.5,2H11v8.29L5.85,5.15a0.49 0.49 ,0,0,0-0.7 0.7 L11,11.71v0.58L5.15,18.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L11,13.71V22h0.5a5.25,5.25,0,0,0,2.25-10A5.25,5.25,0,0,0,16.78,7.25Zm-1,9.5A4.26,4.26,0,0,1,12,21V12.53A4.26,4.26,0,0,1,15.78,16.75ZM12,11.47V3a4.25,4.25,0,0,1,0,8.44Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml new file mode 100644 index 000000000000..fc990d87f2fb --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.41,14.72A2,2,0,0,1,4,16.14V18a2,2,0,0,0,2,2H7.86a2,2,0,0,1,1.42 0.59 l1.31,1.31a2,2,0,0,0,2.82,0l1.31-1.31A2,2,0,0,1,16.14,20H18a2,2,0,0,0,2-2V16.14a2,2,0,0,1,0.59-1.42l1.31-1.31a2,2,0,0,0,0-2.82L20.59,9.28A2,2,0,0,1,20,7.86V6a2,2,0,0,0-2-2H16.14a2,2,0,0,1-1.42-0.59L13.41,2.1a2,2,0,0,0-2.82,0L9.28,3.41A2,2,0,0,1,7.86,4H6A2,2,0,0,0,4,6V7.86a2,2,0,0,1-0.59,1.42L2.1,10.59a2,2,0,0,0,0,2.82Zm-0.6-3.43L4.12,10A3,3,0,0,0,5,7.86V6A1,1,0,0,1,6,5H7.86A3,3,0,0,0,10,4.12l1.31-1.31a1,1,0,0,1,1.42,0L14,4.12A3,3,0,0,0,16.14,5H18a1,1,0,0,1,1,1V7.86A3,3,0,0,0,19.88,10l1.31,1.31a1,1,0,0,1,0,1.42L19.88,14A3,3,0,0,0,19,16.14V18a1,1,0,0,1-1,1H16.14a3,3,0,0,0-2.12 0.88 l-1.31,1.31a1,1,0,0,1-1.42,0L10,19.88A3,3,0,0,0,7.86,19H6a1,1,0,0,1-1-1V16.14A3,3,0,0,0,4.12,14L2.81,12.71a1,1,0,0,1,0-1.42Z" /> + <path + android:fillColor="#000000" + android:pathData="M10,14.61h4L14.85,17H17L13.11,7H10.87L7,17H9.15Zm1.92-5.44h0.11l1.29,3.71H10.63Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cancel.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cancel.xml new file mode 100644 index 000000000000..40de6093f372 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cancel.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,3a9,9,0,1,1-9,9A9,9,0,0,1,12,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.15,16.85a0.48 0.48 ,0,0,0,0.7,0L12,12.71l4.15,4.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L12.71,12l4.14-4.15a0.49 0.49 ,0,1,0-0.7-0.7L12,11.29,7.85,7.15a0.49 0.49 ,0,0,0-0.7 0.7 L11.29,12,7.15,16.15A0.48 0.48 ,0,0,0,7.15,16.85Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cast_on.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cast_on.xml new file mode 100644 index 000000000000..d12cf9ee85fd --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_cast_on.xml @@ -0,0 +1,42 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M22,17.5V6.5A2.5,2.5,0,0,0,19.5,4H4.5A2.5,2.5,0,0,0,2,6.5v2a0.5 0.5 ,0,0,0,1,0v-2A1.5,1.5,0,0,1,4.5,5h15A1.5,1.5,0,0,1,21,6.5v11A1.5,1.5,0,0,1,19.5,19h-6a0.5 0.5 ,0,0,0,0,1h6A2.5,2.5,0,0,0,22,17.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.21,19.61A1,1,0,0,0,3,20a1,1,0,0,0,0-2H3a1,1,0,0,0-0.79,1.61Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.5,12A7.5,7.5,0,0,1,10,19.5a0.5 0.5 ,0,0,0,1,0A8.51,8.51,0,0,0,2.5,11a0.5 0.5 ,0,0,0,0,1Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.5,16A3.5,3.5,0,0,1,6,19.5a0.5 0.5 ,0,0,0,1,0A4.51,4.51,0,0,0,2.5,15a0.5 0.5 ,0,0,0,0,1Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.5,15h-3a0.5 0.5 ,0,0,0,0,1h3A1.5,1.5,0,0,0,18,14.5v-5A1.5,1.5,0,0,0,16.5,8H6.5a0.5 0.5 ,0,0,0,0,1h10a0.5 0.5 ,0,0,1,0.5 0.5 v5A0.5 0.5 ,0,0,1,16.5,15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_no_sim.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_no_sim.xml new file mode 100644 index 000000000000..e17d646ce157 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_no_sim.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M10.41,4H17a1,1,0,0,1,1,1V16.17l1,1V5a2,2,0,0,0-2-2H10L7.42,5.58l0.7 0.71 Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.85,21.15l-18-18a0.48 0.48 ,0,0,0-0.7,0h0a0.48 0.48 ,0,0,0,0,0.7l3.5,3.5L5,8V19a2,2,0,0,0,2,2H17a2,2,0,0,0,1.55-0.75l1.6,1.6a0.48 0.48 ,0,0,0,0.7,0h0A0.48 0.48 ,0,0,0,20.85,21.15ZM17,20H7a1,1,0,0,1-1-1V8.41l0.35-0.35L17.83,19.53A1,1,0,0,1,17,20Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_vpn.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_vpn.xml new file mode 100644 index 000000000000..e5c1f4e830c3 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_vpn.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.5,9A2.5,2.5,0,1,0,10,11.5,2.5,2.5,0,0,0,7.5,9Zm0,4A1.5,1.5,0,1,1,9,11.5,1.5,1.5,0,0,1,7.5,13Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.5,9H12.39A5.5,5.5,0,0,0,2.12,10.32,5.58,5.58,0,0,0,3.23,15a5.49,5.49,0,0,0,9.16-1H15v1.5A1.5,1.5,0,0,0,16.5,17h2A1.5,1.5,0,0,0,20,15.5V14h1.5a0.5 0.5 ,0,0,0,0.5-0.5v-4A0.5 0.5 ,0,0,0,21.5,9ZM21,13H19.5a0.5 0.5 ,0,0,0-0.5 0.5 v2a0.5 0.5 ,0,0,1-0.5 0.5 h-2a0.5 0.5 ,0,0,1-0.5-0.5v-2a0.5 0.5 ,0,0,0-0.5-0.5H12.08a0.51 0.51 ,0,0,0-0.46 0.3 ,4.5,4.5,0,0,1-7.61,1,4.57,4.57,0,0,1-0.91-3.82A4.48,4.48,0,0,1,6.7,7.07,4.53,4.53,0,0,1,11.62,9.7a0.51 0.51 ,0,0,0,0.46 0.3 H21Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml new file mode 100644 index 000000000000..ad48771ee67a --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml @@ -0,0 +1,54 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.07,9.07,0,0,1,12.83,0,0.52 0.52 ,0,0,0,0.71,0,0.51 0.51 ,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.5,9a0.47 0.47 ,0,0,0,0.35-0.15 0.48 0.48,0,0,0,0-0.7,13.77,13.77,0,0,0-19.7,0,0.49 0.49 ,0,0,0,0.7 0.7 ,12.8,12.8,0,0,1,18.3,0A0.47 0.47 ,0,0,0,21.5,9Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.06,5.06,0,0,1,6.77-0.32,3.85,3.85,0,0,1,0.82-0.62A6.08,6.08,0,0,0,7.7,13.78Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.15,15.15a0.48 0.48 ,0,0,0,0,0.7L18.29,18l-2.14,2.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L19,18.71l2.15,2.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L19.71,18l2.14-2.15a0.49 0.49 ,0,1,0-0.7-0.7L19,17.29l-2.15-2.14A0.48 0.48 ,0,0,0,16.15,15.15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml new file mode 100644 index 000000000000..cc87827dbf3a --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml @@ -0,0 +1,51 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M5.58,11.66a9.07,9.07,0,0,1,12.83,0,0.52 0.52 ,0,0,0,0.71,0,0.51 0.51 ,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71A0.51 0.51 ,0,0,0,5.58,11.66Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M2.15,8.85a0.48 0.48 ,0,0,0,0.7,0,12.8,12.8,0,0,1,18.3,0,0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7,13.77,13.77,0,0,0-19.7,0A0.48 0.48 ,0,0,0,2.15,8.85Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.06,5.06,0,0,1,6.77-0.32,3.85,3.85,0,0,1,0.82-0.62A6.08,6.08,0,0,0,7.7,13.78Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.15,20.85a0.48 0.48 ,0,0,0,0.7,0L19,18.71l2.15,2.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L19.71,18l2.14-2.15a0.49 0.49 ,0,1,0-0.7-0.7L19,17.29l-2.15-2.14a0.49 0.49 ,0,0,0-0.7 0.7 L18.29,18l-2.14,2.15A0.48 0.48 ,0,0,0,16.15,20.85Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml new file mode 100644 index 000000000000..eceaa743284a --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml @@ -0,0 +1,48 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M18.41,11.66a0.52 0.52 ,0,0,0,0.71,0,0.51 0.51 ,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.07,9.07,0,0,1,12.83,0Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.5,9a0.47 0.47 ,0,0,0,0.35-0.15 0.48 0.48,0,0,0,0-0.7,13.77,13.77,0,0,0-19.7,0,0.49 0.49 ,0,0,0,0.7 0.7 ,12.8,12.8,0,0,1,18.3,0A0.47 0.47 ,0,0,0,21.5,9Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5.06,5.06,0,0,1,6.77-0.32,3.85,3.85,0,0,1,0.82-0.62A6.08,6.08,0,0,0,7.7,13.78Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.15,15.15a0.48 0.48 ,0,0,0,0,0.7L18.29,18l-2.14,2.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L19,18.71l2.15,2.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L19.71,18l2.14-2.15a0.49 0.49 ,0,1,0-0.7-0.7L19,17.29l-2.15-2.14A0.48 0.48 ,0,0,0,16.15,15.15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml new file mode 100644 index 000000000000..7640376dfe4a --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml @@ -0,0 +1,45 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.41,11.66a0.52 0.52 ,0,0,0,0.71,0,0.51 0.51 ,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.07,9.07,0,0,1,12.83,0Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M2.15,8.85a0.48 0.48 ,0,0,0,0.7,0,12.8,12.8,0,0,1,18.3,0,0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7,13.77,13.77,0,0,0-19.7,0A0.48 0.48 ,0,0,0,2.15,8.85Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,12A6.05,6.05,0,0,0,7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5,5,0,0,1,6.77-0.32,3.77,3.77,0,0,1,0.84-0.63A6,6,0,0,0,12,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.15,15.15a0.48 0.48 ,0,0,0,0,0.7L18.29,18l-2.14,2.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L19,18.71l2.15,2.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L19.71,18l2.14-2.15a0.49 0.49 ,0,1,0-0.7-0.7L19,17.29l-2.15-2.14A0.48 0.48 ,0,0,0,16.15,15.15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml new file mode 100644 index 000000000000..8213e1cfc4f5 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml @@ -0,0 +1,42 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.41,11.66a0.52 0.52 ,0,0,0,0.71,0,0.51 0.51 ,0,0,0,0-0.71A10.08,10.08,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.07,9.07,0,0,1,12.83,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.5,9a0.47 0.47 ,0,0,0,0.35-0.15 0.48 0.48,0,0,0,0-0.7,13.77,13.77,0,0,0-19.7,0,0.49 0.49 ,0,0,0,0.7 0.7 ,12.8,12.8,0,0,1,18.3,0A0.47 0.47 ,0,0,0,21.5,9Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,12A6.05,6.05,0,0,0,7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0,5,5,0,0,1,6.77-0.32,3.77,3.77,0,0,1,0.84-0.63A6,6,0,0,0,12,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.15,15.15a0.48 0.48 ,0,0,0,0,0.7L18.29,18l-2.14,2.15a0.48 0.48 ,0,0,0,0,0.7 0.48 0.48,0,0,0,0.7,0L19,18.71l2.15,2.14a0.48 0.48 ,0,0,0,0.7,0,0.48 0.48 ,0,0,0,0-0.7L19.71,18l2.14-2.15a0.49 0.49 ,0,1,0-0.7-0.7L19,17.29l-2.15-2.14A0.48 0.48 ,0,0,0,16.15,15.15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml new file mode 100644 index 000000000000..86c03c6da6ce --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml @@ -0,0 +1,57 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M 11.99 16.5 C 12.8184271247 16.5 13.49 17.1715728753 13.49 18 C 13.49 18.8284271247 12.8184271247 19.5 11.99 19.5 C 11.1615728753 19.5 10.49 18.8284271247 10.49 18 C 10.49 17.1715728753 11.1615728753 16.5 11.99 16.5 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M12,8A10,10,0,0,0,4.87,11a0.5 0.5 ,0,0,0,0,0.71 0.51 0.51,0,0,0,0.71,0,9.08,9.08,0,0,1,9.94-1.95A5.11,5.11,0,0,1,16.35,9,10,10,0,0,0,12,8Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.85,8.15a13.77,13.77,0,0,0-19.7,0,0.49 0.49 ,0,0,0,0.7 0.7 ,12.79,12.79,0,0,1,17.42-0.79A5.51,5.51,0,0,1,22,8.6 0.47 0.47,0,0,0,21.85,8.15Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.7,13.78a0.51 0.51 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.71,0A5.06,5.06,0,0,1,14,13.43a5.9,5.9,0,0,1,0.11-1A6.07,6.07,0,0,0,7.7,13.78Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.1,11.27a3.42,3.42,0,0,0-0.89,1.64 0.5 0.5,0,0,0,0.37 0.6 0.5 0.5 ,0,0,0,0.6-0.37A2.56,2.56,0,0,1,17.81,12a2.4,2.4,0,0,1,3.38,0,2.18,2.18,0,0,1,0.64,1.76A1.85,1.85,0,0,1,21,15.12a3.13,3.13,0,0,1-0.36 0.22 A2.8,2.8,0,0,0,19,17.5a0.51 0.51 ,0,0,0,0.41 0.58 h0.08a0.5 0.5 ,0,0,0,0.5-0.41,1.81,1.81,0,0,1,1.14-1.46l0.42-0.26a2.86,2.86,0,0,0,1.27-2.12,3.21,3.21,0,0,0-0.92-2.56A3.43,3.43,0,0,0,17.1,11.27Z" /> + <path + android:fillColor="#000000" + android:pathData="M 19.5 19.5 C 19.9142135624 19.5 20.25 19.8357864376 20.25 20.25 C 20.25 20.6642135624 19.9142135624 21 19.5 21 C 19.0857864376 21 18.75 20.6642135624 18.75 20.25 C 18.75 19.8357864376 19.0857864376 19.5 19.5 19.5 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_screenshot_delete.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_screenshot_delete.xml new file mode 100644 index 000000000000..174f36ed9771 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_screenshot_delete.xml @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M9,20h6a3,3,0,0,0,3-3V6h0.5a0.5 0.5 ,0,0,0,0-1H15L14,4H10L9,5H5.5a0.5 0.5 ,0,0,0,0,1H6V17A3,3,0,0,0,9,20ZM17,6V17a2,2,0,0,1-2,2H9a2,2,0,0,1-2-2V6Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,16a0.5 0.5 ,0,0,0,0.5-0.5v-7A0.5 0.5 ,0,0,0,14,8a0.5 0.5 ,0,0,0-0.5 0.5 v7A0.5 0.5 ,0,0,0,14,16Z" /> + <path + android:fillColor="#000000" + android:pathData="M10,16a0.5 0.5 ,0,0,0,0.5-0.5v-7a0.5 0.5 ,0,0,0-1,0v7A0.5 0.5 ,0,0,0,10,16Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_settings_16dp.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_settings_16dp.xml new file mode 100644 index 000000000000..33d172cd2517 --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_settings_16dp.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M5.31,19.26a1.6,1.6,0,0,0,0.53-0.09l1.8-0.7c0.26 0.16 0.52 0.31 0.79 0.45 l0.27,1.84A1.44,1.44,0,0,0,10.15,22h3.7a1.46,1.46,0,0,0,1.46-1.19l0.27-1.87c0.26-0.13 0.52 -0.28 0.78 -0.44l1.8 0.7 a1.47,1.47,0,0,0,0.54 0.1 A1.44,1.44,0,0,0,20,18.58l1.86-3.14a1.4,1.4,0,0,0-0.37-1.81l-1.52-1.17c0-0.14,0-0.29,0-0.45s0-0.3,0-0.44l1.52-1.17a1.41,1.41,0,0,0,0.36-1.83L20,5.47a1.46,1.46,0,0,0-1.29-0.73,1.69,1.69,0,0,0-0.53 0.09 l-1.8 0.7 c-0.26-0.16-0.52-0.31-0.79-0.45l-0.27-1.84A1.44,1.44,0,0,0,13.84,2h-3.7A1.45,1.45,0,0,0,8.7,3.22L8.43,5.08q-0.39 0.21 -0.78 0.45 L5.84,4.82a1.47,1.47,0,0,0-0.54-0.1,1.43,1.43,0,0,0-1.25 0.72 L2.2,8.55a1.37,1.37,0,0,0,0.37,1.83l1.52,1.17c0,0.14,0,0.3,0,0.45s0,0.3,0,0.44L2.56,13.61a1.42,1.42,0,0,0-0.36,1.83L4,18.53A1.46,1.46,0,0,0,5.31,19.26ZM3.16,14.4l1.53-1.16 0.43 -0.33,0-0.53c0-0.13,0-0.25,0-0.38s0-0.26,0-0.39l0-0.53-0.42-0.33L3.17,9.58a0.38 0.38 ,0,0,1-0.11-0.52L4.92,5.93a0.43 0.43 ,0,0,1,0.38-0.21 0.47 0.47,0,0,1,0.17,0l1.81 0.71 0.48 0.19 0.43-0.27A6.39,6.39,0,0,1,8.9,6l0.45-0.24 0.07 -0.5 0.27 -1.88A0.44 0.44 ,0,0,1,10.14,3h3.7a0.44 0.44 ,0,0,1,0.46 0.38 l0.27,1.85 0.08 0.51 0.46 0.24a5.3,5.3,0,0,1,0.7 0.4 l0.43 0.27 0.47-0.19,1.78-0.69a0.63 0.63 ,0,0,1,0.19,0,0.47 0.47 ,0,0,1,0.43 0.24 l1.83,3.08a0.42 0.42 ,0,0,1-0.1 0.55 l-1.52,1.16-0.42 0.33 ,0,0.53c0,0.13,0,0.25,0,0.38s0,0.26,0,0.39l0,0.53 0.42 0.33,1.51,1.15a0.42 0.42 ,0,0,1,0.13 0.52 l-1.87,3.16a0.43 0.43 ,0,0,1-0.39 0.21 0.57 0.57 ,0,0,1-0.18,0l-1.8-0.71-0.47-0.18-0.43 0.27 a7.46,7.46,0,0,1-0.71 0.41 l-0.45 0.24 -0.07 0.5 -0.27,1.86a0.47 0.47 ,0,0,1-0.47 0.34 h-3.7a0.44 0.44 ,0,0,1-0.46-0.38l-0.27-1.85-0.08-0.51L8.88,18a5.3,5.3,0,0,1-0.7-0.4l-0.43-0.27-0.47 0.19 -1.78 0.69 a0.58 0.58 ,0,0,1-0.19,0A0.48 0.48 ,0,0,1,4.89,18L3.08,15A0.42 0.42 ,0,0,1,3.16,14.4Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,15.91A3.92,3.92,0,1,0,8,12,4,4,0,0,0,12,15.91Zm0-6.83A2.92,2.92,0,1,1,9,12,3,3,0,0,1,12,9.08Z" /> +</vector> diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_airplane.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_airplane.xml new file mode 100644 index 000000000000..a5ef380c4a4d --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_airplane.xml @@ -0,0 +1,30 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.8,15l7.2-0.73v3.49L8,19.38a1.52,1.52,0,0,0-0.54,1.16v1a0.52 0.52 ,0,0,0,0.17 0.38 0.51 0.51 ,0,0,0,0.39 0.12 L12,21.5l3.94 0.5 H16a0.5 0.5 ,0,0,0,0.33-0.12 0.52 0.52,0,0,0,0.17-0.38v-1A1.52,1.52,0,0,0,16,19.38l-2-1.62V14.27l7.2 0.73 a0.51 0.51 ,0,0,0,0.55-0.5,3.49,3.49,0,0,0-2.15-3.23L14,8.94V3.5a2,2,0,0,0-4,0V8.94L4.4,11.27A3.49,3.49,0,0,0,2.25,14.5a0.51 0.51 ,0,0,0,0.55 0.5 Zm2-2.81,5.9-2.45A0.5 0.5 ,0,0,0,11,9.28V3.5a1,1,0,0,1,2,0V9.28a0.5 0.5 ,0,0,0,0.31 0.46 l5.9,2.45a2.51,2.51,0,0,1,1.48,1.75l-7.14-0.72a0.52 0.52 ,0,0,0-0.38 0.13 0.5 0.5 ,0,0,0-0.17 0.37 V18a0.53 0.53 ,0,0,0,0.18 0.39 l2.14,1.76a0.53 0.53 ,0,0,1,0.18 0.39 v0.39l-3.44-0.43h-0.12l-3.44 0.43 v-0.39a0.53 0.53 ,0,0,1,0.18-0.39l2.14-1.76A0.53 0.53 ,0,0,0,11,18V13.72a0.5 0.5 ,0,0,0-0.17-0.37 0.52 0.52,0,0,0-0.38-0.13l-7.14 0.72 A2.51,2.51,0,0,1,4.79,12.19Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_flashlight.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_flashlight.xml new file mode 100644 index 000000000000..15266910de6c --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_signal_flashlight.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M11,22h2a2,2,0,0,0,2-2V10a6.84,6.84,0,0,0,3-6V3H6V4a6.84,6.84,0,0,0,3,6V20A2,2,0,0,0,11,22ZM17,4a8.26,8.26,0,0,1-0.07,1H7.07A8.26,8.26,0,0,1,7,4ZM7.28,6h9.45a5.24,5.24,0,0,1-2.24,3.14L14,9.43V20a1,1,0,0,1-1,1H11a1,1,0,0,1-1-1V9.43l-0.49-0.29A5.25,5.25,0,0,1,7.28,6Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 13 C 12.5522847498 13 13 13.4477152502 13 14 C 13 14.5522847498 12.5522847498 15 12 15 C 11.4477152502 15 11 14.5522847498 11 14 C 11 13.4477152502 11.4477152502 13 12 13 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_swap_vert.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_swap_vert.xml new file mode 100644 index 000000000000..2f3ac2ed407e --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_swap_vert.xml @@ -0,0 +1,33 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.85,16.65a0.48 0.48 ,0,0,0-0.7,0L16,18.79V10.5a0.5 0.5 ,0,0,0-1,0v8.29l-2.15-2.14a0.49 0.49 ,0,0,0-0.7 0.7 l3.35,3.36,3.35-3.36A0.48 0.48 ,0,0,0,18.85,16.65Z" /> + <path + android:fillColor="#000000" + android:pathData="M11.85,6.64l-3-3h0L8.5,3.29l-0.35 0.35 h0l-3,3a0.5 0.5 ,0,0,0,0,0.71 0.5 0.5,0,0,0,0.7,0L8,5.2v8.3a0.5 0.5 ,0,0,0,1,0V5.2l2.15,2.15a0.48 0.48 ,0,0,0,0.7,0A0.5 0.5 ,0,0,0,11.85,6.64Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm.xml new file mode 100644 index 000000000000..c67e8970454e --- /dev/null +++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm.xml @@ -0,0 +1,39 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,4a9,9,0,1,0,9,9A9,9,0,0,0,12,4Zm0,17a8,8,0,1,1,8-8A8,8,0,0,1,12,21Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.51,2.71a2,2,0,0,0-1.36 0.71 0.5 0.5 ,0,0,0,0.76 0.64 ,1,1,0,0,1,1.41-0.12l1.53,1.29a1,1,0,0,1,0.35 0.68 ,1,1,0,0,1-0.23 0.73 0.49 0.49 ,0,0,0,0.06 0.7 0.51 0.51 ,0,0,0,0.32 0.12 0.5 0.5 ,0,0,0,0.39-0.18,2,2,0,0,0,0.46-1.46,2,2,0,0,0-0.7-1.35L19,3.18A1.92,1.92,0,0,0,17.51,2.71Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.65,7.46A0.51 0.51 ,0,0,0,4,7.34 0.49 0.49,0,0,0,4,6.64a1,1,0,0,1-0.23-0.73,1,1,0,0,1,0.35-0.68L5.68,3.94a1,1,0,0,1,0.73-0.23,1,1,0,0,1,0.68 0.35 0.5 0.5 ,0,1,0,0.76-0.64,2,2,0,0,0-1.36-0.71A1.92,1.92,0,0,0,5,3.18L3.5,4.47a2,2,0,0,0-0.7,1.35,2,2,0,0,0,0.46,1.46A0.5 0.5 ,0,0,0,3.65,7.46Z" /> + <path + android:fillColor="#000000" + android:pathData="M12.5,12.79V8a0.5 0.5 ,0,0,0-1,0v5.21l3.13,3.12a0.47 0.47 ,0,0,0,0.35 0.15 0.5 0.5 ,0,0,0,0.35-0.85Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackCircularOverlay/Android.mk b/packages/overlays/IconPackFilledAndroidOverlay/Android.mk index 010eb81a5cd3..e0db3a27cdbe 100644 --- a/packages/overlays/IconPackCircularOverlay/Android.mk +++ b/packages/overlays/IconPackFilledAndroidOverlay/Android.mk @@ -13,11 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # - LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_RRO_THEME := IconPackCircular +LOCAL_RRO_THEME := IconPackFilledAndroid LOCAL_CERTIFICATE := platform LOCAL_PRODUCT_MODULE := true @@ -25,7 +24,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_PACKAGE_NAME := IconPackCircularOverlay +LOCAL_PACKAGE_NAME := IconPackFilledAndroidOverlay LOCAL_SDK_VERSION := current include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackFilledOverlay/AndroidManifest.xml b/packages/overlays/IconPackFilledAndroidOverlay/AndroidManifest.xml index bf507cdb4346..6613407ea5b9 100644 --- a/packages/overlays/IconPackFilledOverlay/AndroidManifest.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/AndroidManifest.xml @@ -16,9 +16,9 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.theme.icon_pack.filled" + package="com.android.theme.icon_pack.filled.android" android:versionCode="1" android:versionName="1.0"> - <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack" android:priority="1"/> + <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack.android" android:priority="1"/> <application android:label="Filled" android:hasCode="false"/> </manifest> diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml new file mode 100644 index 000000000000..428d453955ff --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,18V11a9,9,0,0,0-9.6-9A9.21,9.21,0,0,0,3,11.31V17.2C3,19.66,4.34,21,6,21H8a1,1,0,0,0,1-1V14a1,1,0,0,0-1-1H5V11.29A7.19,7.19,0,0,1,11.79,4,7,7,0,0,1,19,11v2H16a1,1,0,0,0-1,1v6a1,1,0,0,0,1,1h2A3,3,0,0,0,21,18Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml new file mode 100644 index 000000000000..3ef7dd177d43 --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_expand_more.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.29,8.29a1,1,0,0,0-1.41,0L12,14.17,6.12,8.29A1,1,0,1,0,4.71,9.71l6.58,6.58a1,1,0,0,0,1.42,0l6.58-6.58A1,1,0,0,0,19.29,8.29Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_info_outline_24.xml new file mode 100644 index 000000000000..e39a2a0eb286 --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_info_outline_24.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M2,12A10,10,0,1,0,12,2,10,10,0,0,0,2,12Zm11,5.42a1,1,0,0,1-2,0V10.68a1,1,0,0,1,2,0ZM12,5.58a1.35,1.35,0,1,1-1.35,1.35A1.34,1.34,0,0,1,12,5.58Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_invert_colors.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_invert_colors.xml new file mode 100644 index 000000000000..0564c737c703 --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_invert_colors.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.44,7.71,12.7,3a1,1,0,0,0-1.41,0h0L6.56,7.71a8.21,8.21,0,0,0-0.62,11.1,8,8,0,0,0,12.12,0A8.21,8.21,0,0,0,17.44,7.71ZM12,19.59A6,6,0,0,1,7.76,9.35L12,5.1Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..8b9f5627a98b --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,55 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,21H21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19A2,2,0,0,0,3,21ZM3,6H21V19H3Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9 8 H 11 V 10 H 9 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5 8 H 7 V 10 H 5 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 8 16 H 16 V 17 H 8 V 16 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13 8 H 15 V 10 H 13 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9 12 H 11 V 14 H 9 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5 12 H 7 V 14 H 5 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13 12 H 15 V 14 H 13 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17 8 H 19 V 10 H 17 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17 12 H 19 V 14 H 17 V 12 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml new file mode 100644 index 000000000000..217845dd0249 --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.71,7a1,1,0,0,0,0-1.41h0L18.37,3.29a1,1,0,0,0-1.41,0h0L15.13,5.12l3.75,3.75Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,18.08V20.5a0.5 0.5 ,0,0,0,0.5 0.5 H5.92a2,2,0,0,0,1.41-0.59L17.81,9.94,14.06,6.19,3.59,16.66A2,2,0,0,0,3,18.08Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml new file mode 100644 index 000000000000..2eaa368f147e --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M9.78,7.06,9.13,3.8a1,1,0,0,0-1-0.8H4A1,1,0,0,0,3,4a17.92,17.92,0,0,0,2.43,8,18.08,18.08,0,0,0,6.5,6.5,17.92,17.92,0,0,0,8,2.43,1,1,0,0,0,1-1V15.82a1,1,0,0,0-0.8-1l-3.26-0.65a1,1,0,0,0-0.9 0.27 l-2.62,2.62a16.14,16.14,0,0,1-6.5-6.5L9.51,8A1,1,0,0,0,9.78,7.06Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_night_display_on.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_night_display_on.xml new file mode 100644 index 000000000000..f12beeca93ea --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_night_display_on.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.32,4.13a1,1,0,0,0-0.19-1.9A10,10,0,1,0,15,22a9.91,9.91,0,0,0,2.12-0.23,1,1,0,0,0,0.2-1.9,8.48,8.48,0,0,1,0-15.74Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_location.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_location.xml new file mode 100644 index 000000000000..1d107b9df3a5 --- /dev/null +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_signal_location.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2A7,7,0,0,0,5,9c0,4.17,4.42,9.92,6.24,12.11a1,1,0,0,0,1.53,0C14.58,18.92,19,13.17,19,9A7,7,0,0,0,12,2Zm0,9.5A2.5,2.5,0,1,1,14.5,9,2.5,2.5,0,0,1,12,11.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_0.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_0.xml index 7ff3d08b75af..0f7c5899a237 100644 --- a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_0.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_0.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -29,4 +28,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M23.66,8.11a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_1.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_1.xml index f83e6d512f8a..aa13b7e8f173 100644 --- a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_1.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_1.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -32,4 +31,4 @@ <path android:fillColor="#000000" android:pathData="M12.82,21.6l5.11-6.36a9,9,0,0,0-11.87,0l5.1,6.35A1.07,1.07,0,0,0,12.82,21.6Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_2.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_2.xml index 2bcaf2ae4591..b6d1b7229101 100644 --- a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_2.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_2.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -32,4 +31,4 @@ <path android:fillColor="#000000" android:pathData="M12.82,21.6l7-8.7a12,12,0,0,0-15.63,0l7,8.7A1.07,1.07,0,0,0,12.82,21.6Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_3.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_3.xml index 82b4c9d001ec..fe5718264029 100644 --- a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_3.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_3.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -32,4 +31,4 @@ <path android:fillColor="#000000" android:pathData="M12.82,21.6l8.25-10.26a14,14,0,0,0-18.14,0l8.23,10.26A1.07,1.07,0,0,0,12.82,21.6Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_4.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_4.xml index 45cf95fcc2c6..d8aa0c2f45e4 100644 --- a/packages/overlays/IconPackFilledOverlay/res/drawable/ic_wifi_signal_4.xml +++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_wifi_signal_4.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -26,4 +25,4 @@ <path android:fillColor="#000000" android:pathData="M12,3A20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L23.66,8.11a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/Android.mk b/packages/overlays/IconPackFilledSettingsOverlay/Android.mk index 075ed28fa1f7..0443560a573e 100644 --- a/packages/overlays/IconPackRoundedOverlay/Android.mk +++ b/packages/overlays/IconPackFilledSettingsOverlay/Android.mk @@ -13,10 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_RRO_THEME := IconPackRounded +LOCAL_RRO_THEME := IconPackFilledSettings LOCAL_CERTIFICATE := platform LOCAL_PRODUCT_MODULE := true @@ -24,7 +25,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_PACKAGE_NAME := IconPackRoundedOverlay +LOCAL_PACKAGE_NAME := IconPackFilledSettingsOverlay LOCAL_SDK_VERSION := current include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackFilledSettingsOverlay/AndroidManifest.xml b/packages/overlays/IconPackFilledSettingsOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..de81e21a8bca --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.filled.settings" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.settings" android:category="android.theme.customization.icon_pack.settings" android:priority="1"/> + <application android:label="Filled" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml new file mode 100644 index 000000000000..015e73e81180 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 4.5 4 L 7.5 4 Q 8 4 8 4.5 L 8 7.5 Q 8 8 7.5 8 L 4.5 8 Q 4 8 4 7.5 L 4 4.5 Q 4 4 4.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 10.5 4 L 13.5 4 Q 14 4 14 4.5 L 14 7.5 Q 14 8 13.5 8 L 10.5 8 Q 10 8 10 7.5 L 10 4.5 Q 10 4 10.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16.5 4 L 19.5 4 Q 20 4 20 4.5 L 20 7.5 Q 20 8 19.5 8 L 16.5 8 Q 16 8 16 7.5 L 16 4.5 Q 16 4 16.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 4.5 10 L 7.5 10 Q 8 10 8 10.5 L 8 13.5 Q 8 14 7.5 14 L 4.5 14 Q 4 14 4 13.5 L 4 10.5 Q 4 10 4.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 10.5 10 L 13.5 10 Q 14 10 14 10.5 L 14 13.5 Q 14 14 13.5 14 L 10.5 14 Q 10 14 10 13.5 L 10 10.5 Q 10 10 10.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16.5 10 L 19.5 10 Q 20 10 20 10.5 L 20 13.5 Q 20 14 19.5 14 L 16.5 14 Q 16 14 16 13.5 L 16 10.5 Q 16 10 16.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 4.5 16 L 7.5 16 Q 8 16 8 16.5 L 8 19.5 Q 8 20 7.5 20 L 4.5 20 Q 4 20 4 19.5 L 4 16.5 Q 4 16 4.5 16 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 10.5 16 L 13.5 16 Q 14 16 14 16.5 L 14 19.5 Q 14 20 13.5 20 L 10.5 20 Q 10 20 10 19.5 L 10 16.5 Q 10 16 10.5 16 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16.5 16 L 19.5 16 Q 20 16 20 16.5 L 20 19.5 Q 20 20 19.5 20 L 16.5 20 Q 16 20 16 19.5 L 16 16.5 Q 16 16 16.5 16 Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml new file mode 100644 index 000000000000..0b12655a23f4 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M3,20H6a1,1,0,0,0,0-2H3V6H20a1,1,0,0,0,0-2H3A2,2,0,0,0,1,6V18A2,2,0,0,0,3,20Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23,19V9a1.08,1.08,0,0,0-1-1H16a1.08,1.08,0,0,0-1,1V19a1.08,1.08,0,0,0,1,1h6A1.08,1.08,0,0,0,23,19Zm-2-1H17V10h4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M9,12v1.78a3,3,0,0,0,0,4.44V20h4V18.22a3,3,0,0,0,0-4.44V12Zm2,5.5A1.5,1.5,0,1,1,12.5,16,1.5,1.5,0,0,1,11,17.5Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml new file mode 100644 index 000000000000..097894d663e0 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm0,16.81a1.3,1.3,0,1,1,1.3-1.3A1.3,1.3,0,0,1,12,18.81Zm1.07-4.62a1,1,0,0,1-1.13 0.79 ,1,1,0,0,1-0.83-1.23c0.52-2.61,2.66-2.84,2.87-4.5a2,2,0,0,0-1.34-2.17,2,2,0,0,0-2.55,1.37,1,1,0,1,1-1.93-0.53A4,4,0,0,1,16,9.13C15.92,11.57,13.5,11.74,13.07,14.19Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml new file mode 100644 index 000000000000..80f3d1e707a9 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M7,1A2,2,0,0,0,5,3V21a2,2,0,0,0,2,2H17a2,2,0,0,0,2-2V3a2,2,0,0,0-2-2ZM17,19H7V5H17Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,11.62a1,1,0,0,0-1,0.9v3.59a1,1,0,0,0,2,0V12.52A1,1,0,0,0,12,11.62Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 7.06 C 12.6903559373 7.06 13.25 7.61964406271 13.25 8.31 C 13.25 9.00035593729 12.6903559373 9.56 12 9.56 C 11.3096440627 9.56 10.75 9.00035593729 10.75 8.31 C 10.75 7.61964406271 11.3096440627 7.06 12 7.06 Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml new file mode 100644 index 000000000000..9c8287bb3f8c --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20.76,5l0-0.06a1,1,0,0,0-1.2-0.72A35.66,35.66,0,0,1,12,5a35.66,35.66,0,0,1-7.54-0.76A1,1,0,0,0,3.26,5l0,0.06A1,1,0,0,0,4,6.24,37,37,0,0,0,9,7V19a1,1,0,0,0,2,0V14h2v5a1,1,0,0,0,2,0V7a37,37,0,0,0,5-0.76A1,1,0,0,0,20.76,5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml new file mode 100644 index 000000000000..ea418a8006d5 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM12,4a8,8,0,0,1,6.36,12.83c-1.43-1.74-4.9-2.33-6.36-2.33s-4.93 0.59 -6.36,2.33A8,8,0,0,1,12,4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 6 C 13.9329966244 6 15.5 7.56700337559 15.5 9.5 C 15.5 11.4329966244 13.9329966244 13 12 13 C 10.0670033756 13 8.5 11.4329966244 8.5 9.5 C 8.5 7.56700337559 10.0670033756 6 12 6 Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml new file mode 100644 index 000000000000..1c5df00d27ef --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M10,2V4H8.33A1.34,1.34,0,0,0,7,5.33V20.66A1.34,1.34,0,0,0,8.33,22h7.33A1.34,1.34,0,0,0,17,20.67V5.33A1.34,1.34,0,0,0,15.67,4H14V2Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml new file mode 100644 index 000000000000..02e15d2d0638 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M4,15.3V19a1,1,0,0,0,1,1H8.69l2.6,2.6a1,1,0,0,0,1.41,0L15.3,20H19a1,1,0,0,0,1-1V15.31l2.6-2.6a1,1,0,0,0,0-1.41L20,8.69V5a1,1,0,0,0-1-1H15.31l-2.6-2.6a1,1,0,0,0-1.41,0L8.69,4H5A1,1,0,0,0,4,5V8.69l-2.6,2.6a1,1,0,0,0,0,1.41ZM12,6a6,6,0,0,1,0,12Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml new file mode 100644 index 000000000000..818236b88a9a --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,2A7,7,0,0,0,5,9c0,4.17,4.42,9.92,6.24,12.11a1,1,0,0,0,1.53,0C14.58,18.92,19,13.17,19,9A7,7,0,0,0,12,2Zm0,9.5A2.5,2.5,0,1,1,14.5,9,2.5,2.5,0,0,1,12,11.5Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml new file mode 100644 index 000000000000..b0808822ee01 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,19a12,12,0,0,0,2-0.17v-2A10.13,10.13,0,0,1,12,17a9.77,9.77,0,0,1-8.82-5.5,9.82,9.82,0,0,1,17.64,0H23a11.82,11.82,0,0,0-22,0A11.83,11.83,0,0,0,12,19Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M16.5,11.5a4.55,4.55,0,1,0-2.38,3.95,5,5,0,0,1,2.31-3.22A4.4,4.4,0,0,0,16.5,11.5ZM12,14.2a2.7,2.7,0,1,1,2.7-2.7A2.7,2.7,0,0,1,12,14.2Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23,21V17a1.08,1.08,0,0,0-1-1v-0.5a2.5,2.5,0,0,0-5,0V16a1.08,1.08,0,0,0-1,1v4a1.08,1.08,0,0,0,1,1h5A1.08,1.08,0,0,0,23,21Zm-2.5-5h-2v-0.5a1,1,0,0,1,2,0Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml new file mode 100644 index 000000000000..39ac0d717d6b --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23,6a1,1,0,0,0,0.92-1.2A5,5,0,0,0,18.57,1a5.15,5.15,0,0,0-4.51,5.19V8H6a2,2,0,0,0-2,2V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2H16V6.12A3.18,3.18,0,0,1,18.44,3a3.1,3.1,0,0,1,3.62,2.27A1,1,0,0,0,23,6ZM12,17a2,2,0,1,1,2-2A2,2,0,0,1,12,17Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml new file mode 100644 index 000000000000..3c29998da5c4 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M2,12A10,10,0,1,0,12,2,10,10,0,0,0,2,12Zm11,5.42a1,1,0,0,1-2,0V10.68a1,1,0,0,1,2,0ZM12,5.58a1.35,1.35,0,1,1-1.35,1.35A1.34,1.34,0,0,1,12,5.58Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml new file mode 100644 index 000000000000..8fa846eeb345 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M11.29,19.29a1,1,0,0,0,1.42,0L14,18a1,1,0,0,0-0.22-1.58A3.92,3.92,0,0,0,12,16a4,4,0,0,0-1.77 0.41 A1,1,0,0,0,10,18Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M17.6,14.39l0.71-0.71a1,1,0,0,0-0.08-1.49,10,10,0,0,0-12.44,0,1,1,0,0,0-0.08,1.49l0.7 0.72 a1,1,0,0,0,1.32 0.08 A6.91,6.91,0,0,1,12,13a7,7,0,0,1,4.29,1.47A1,1,0,0,0,17.6,14.39Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21.83,10.16l0.71-0.71A1,1,0,0,0,22.48,8a15.79,15.79,0,0,0-20.92,0,1,1,0,0,0-0.07,1.47l0.71 0.71 a1,1,0,0,0,1.35 0.07 ,12.79,12.79,0,0,1,16.94,0A1,1,0,0,0,21.83,10.16Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml new file mode 100644 index 000000000000..82733b6e5128 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M4,14H20a2,2,0,0,0,0-4H4a2,2,0,0,0,0,4Zm1-3.1A1.1,1.1,0,1,1,3.9,12,1.1,1.1,0,0,1,5,10.9Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M4,8H20a2,2,0,0,0,0-4H4A2,2,0,0,0,4,8ZM5,4.9A1.1,1.1,0,1,1,3.9,6,1.1,1.1,0,0,1,5,4.9Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M4,20H20a2,2,0,0,0,0-4H4a2,2,0,0,0,0,4Zm1-3.1A1.1,1.1,0,1,1,3.9,18,1.1,1.1,0,0,1,5,16.9Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml new file mode 100644 index 000000000000..9587e54082e8 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M10.29,5.7,7,9H4a1,1,0,0,0-1,1v4a1,1,0,0,0,1,1H7l3.29,3.29A1,1,0,0,0,12,17.58V6.41A1,1,0,0,0,10.29,5.7Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M16.5,12A4.5,4.5,0,0,0,14,8V16A4.47,4.47,0,0,0,16.5,12Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M14,19.54a0.91 0.91 ,0,0,0,1.22 0.86 ,9,9,0,0,0,0-16.8A0.91 0.91 ,0,0,0,14,4.46v0.19a0.92 0.92 ,0,0,0,0.61 0.85 ,7,7,0,0,1,0,13,0.92 0.92 ,0,0,0-0.61 0.85 Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_wifi_tethering.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_wifi_tethering.xml new file mode 100644 index 000000000000..84c347b9f0ff --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_wifi_tethering.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15.46,16.46h0A1,1,0,0,0,17,16.35,5.9,5.9,0,0,0,18,13,6,6,0,1,0,7,16.35a1,1,0,0,0,1.51 0.11 h0a1,1,0,0,0,0.11-1.29A3.9,3.9,0,0,1,8,12.44a4,4,0,1,1,7.32,2.73A1,1,0,0,0,15.46,16.46Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M10.86,3.06A10,10,0,0,0,4.19,19.25a1,1,0,0,0,1.49 0.07 A1,1,0,0,0,5.75,18a8.05,8.05,0,0,1-1.59-6.61A8,8,0,0,1,20,13a7.89,7.89,0,0,1-1.77,5,1,1,0,0,0,0.08,1.31h0a1,1,0,0,0,1.49-0.07A9.9,9.9,0,0,0,22,13,10,10,0,0,0,10.86,3.06Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M10,13a2,2,0,1,0,2-2A2,2,0,0,0,10,13Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk b/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk new file mode 100644 index 000000000000..2506132e3058 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright 2019, 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackFilledSystemUI +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackFilledSystemUIOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/AndroidManifest.xml b/packages/overlays/IconPackFilledSystemUIOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..a1210c724341 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.filled.systemui" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.systemui" android:category="android.theme.customization.icon_pack.systemui" android:priority="1"/> + <application android:label="Filled" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml new file mode 100644 index 000000000000..fce6e94b5d67 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M4,15.3V19a1,1,0,0,0,1,1H8.69l2.6,2.6a1,1,0,0,0,1.41,0L15.3,20H19a1,1,0,0,0,1-1V15.31l2.6-2.6a1,1,0,0,0,0-1.41L20,8.69V5a1,1,0,0,0-1-1H15.31l-2.6-2.6a1,1,0,0,0-1.41,0L8.69,4H5A1,1,0,0,0,4,5V8.69l-2.6,2.6a1,1,0,0,0,0,1.41ZM12,7a5,5,0,1,1-5,5A5,5,0,0,1,12,7Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver_off.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver_off.xml new file mode 100644 index 000000000000..0949dc9d9d1b --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver_off.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,8a1,1,0,0,0-1,1v2H9a1,1,0,0,0,0,2h2v2a1,1,0,0,0,2,0V13h2a1,1,0,0,0,0-2H13V9A1,1,0,0,0,12,8Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.37,15.5A10.15,10.15,0,0,0,22,12a10,10,0,0,0-8.43-9.88 0.51 0.51,0,0,0-0.57 0.5 V4.15a0.49 0.49 ,0,0,0,0.41 0.48 ,7.5,7.5,0,0,1,5.7,9.75 0.49 0.49,0,0,0,0.21 0.59 l1.33 0.77 A0.51 0.51 ,0,0,0,21.37,15.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M10.43,2.12a10,10,0,1,0,9.36,16.13 0.5 0.5,0,0,0-0.15-0.74l-1.32-0.76a0.48 0.48 ,0,0,0-0.62 0.12 ,7.44,7.44,0,0,1-5.93,2.63,7.58,7.58,0,0,1-7.25-7.07,7.5,7.5,0,0,1,6.07-7.79A0.51 0.51 ,0,0,0,11,4.15V2.62A0.5 0.5 ,0,0,0,10.43,2.12Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_dnd.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_dnd.xml new file mode 100644 index 000000000000..e6086f3813c1 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_dnd.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22A10,10,0,1,0,2,12,10,10,0,0,0,12,22ZM8,11h8a1,1,0,0,1,0,2H8a1,1,0,0,1,0-2Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_drag_handle.xml new file mode 100644 index 000000000000..8f6db4925441 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_drag_handle.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,9H5a1,1,0,0,0,0,2H19a1,1,0,0,0,0-2Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,13H5a1,1,0,0,0,0,2H19a1,1,0,0,0,0-2Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset.xml new file mode 100644 index 000000000000..428d453955ff --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_headset.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,18V11a9,9,0,0,0-9.6-9A9.21,9.21,0,0,0,3,11.31V17.2C3,19.66,4.34,21,6,21H8a1,1,0,0,0,1-1V14a1,1,0,0,0-1-1H5V11.29A7.19,7.19,0,0,1,11.79,4,7,7,0,0,1,19,11v2H16a1,1,0,0,0-1,1v6a1,1,0,0,0,1,1h2A3,3,0,0,0,21,18Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_hotspot.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_hotspot.xml new file mode 100644 index 000000000000..00241f8e2132 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_hotspot.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M15.46,16.46h0A1,1,0,0,0,17,16.35,5.9,5.9,0,0,0,18,13,6,6,0,1,0,7,16.35a1,1,0,0,0,1.51 0.11 h0a1,1,0,0,0,0.11-1.29A3.9,3.9,0,0,1,8,12.44a4,4,0,1,1,7.32,2.73A1,1,0,0,0,15.46,16.46Z" /> + <path + android:fillColor="#000000" + android:pathData="M10.86,3.06A10,10,0,0,0,4.19,19.25a1,1,0,0,0,1.49 0.07 A1,1,0,0,0,5.75,18a8.05,8.05,0,0,1-1.59-6.61A8,8,0,0,1,20,13a7.89,7.89,0,0,1-1.77,5,1,1,0,0,0,0.08,1.31h0a1,1,0,0,0,1.49-0.07A9.9,9.9,0,0,0,22,13,10,10,0,0,0,10.86,3.06Z" /> + <path + android:fillColor="#000000" + android:pathData="M10,13a2,2,0,1,0,2-2A2,2,0,0,0,10,13Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_info.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_info.xml new file mode 100644 index 000000000000..e39a2a0eb286 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_info.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M2,12A10,10,0,1,0,12,2,10,10,0,0,0,2,12Zm11,5.42a1,1,0,0,1-2,0V10.68a1,1,0,0,1,2,0ZM12,5.58a1.35,1.35,0,1,1-1.35,1.35A1.34,1.34,0,0,1,12,5.58Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..8b9f5627a98b --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,55 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,21H21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19A2,2,0,0,0,3,21ZM3,6H21V19H3Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9 8 H 11 V 10 H 9 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5 8 H 7 V 10 H 5 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 8 16 H 16 V 17 H 8 V 16 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13 8 H 15 V 10 H 13 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9 12 H 11 V 14 H 9 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5 12 H 7 V 14 H 5 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13 12 H 15 V 14 H 13 V 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17 8 H 19 V 10 H 17 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17 12 H 19 V 14 H 17 V 12 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..7858b0533fb4 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M5.4,3.27A10.45,10.45,0,0,0,2.15,9.34a1,1,0,0,0,2,0.33A8.44,8.44,0,0,1,6.77,4.73a1,1,0,0,0,0-1.43A1,1,0,0,0,5.4,3.27Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.88,9.66a1,1,0,1,0,2-0.32A10.51,10.51,0,0,0,18.6,3.28a1,1,0,0,0-1.4,0,1,1,0,0,0,0,1.42A8.5,8.5,0,0,1,19.88,9.66Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2.5A1.5,1.5,0,0,0,10.5,4v0.68C7.63,5.36,6,7.92,6,11v5L3.85,18.15a0.5 0.5 ,0,0,0,0,0.71A0.48 0.48 ,0,0,0,4.2,19H19.8a0.49 0.49 ,0,0,0,0.35-0.85L18,16V11c0-3.07-1.64-5.64-4.5-6.32V4A1.5,1.5,0,0,0,12,2.5ZM16,11v6H8V11c0-2.48,1.51-4.5,4-4.5S16,8.52,16,11Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_silence.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_silence.xml new file mode 100644 index 000000000000..2cefe4b92b0e --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_notifications_silence.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.73,19.46l-0.6-0.6L5.54,4.26A0.9 0.9 ,0,1,0,4.27,5.53l2.4,2.4A7.35,7.35,0,0,0,6,11v5L3.85,18.15a0.5 0.5 ,0,0,0,0,0.71A0.48 0.48 ,0,0,0,4.2,19H17.73l1.73,1.73a0.9 0.9 ,0,0,0,1.27,0A0.88 0.88 ,0,0,0,20.73,19.46Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2.5A1.5,1.5,0,0,0,10.5,4v0.68a5.62,5.62,0,0,0-1.7 0.72 L18,14.6V11c0-3.07-1.64-5.64-4.5-6.32V4A1.5,1.5,0,0,0,12,2.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml new file mode 100644 index 000000000000..f823812ddf3f --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.41,11h2.83L11.05,2.78a1.62,1.62,0,0,0-2.29,0L4.27,7.31,2.85,5.89A0.5 0.5 ,0,0,0,2,6.25V10.5a0.5 0.5 ,0,0,0,0.5 0.5 H6.75a0.5 0.5 ,0,0,0,0.36-0.85L5.69,8.73,9.93,4.49Z" /> + <path + android:fillColor="#000000" + android:pathData="M22,13.51a0.5 0.5 ,0,0,0-0.5-0.5H17.25a0.5 0.5 ,0,0,0-0.36 0.85 l1.35,1.35-4.31,4.31L7.44,13H4.61l8.19,8.18a1.62,1.62,0,0,0,2.29,0l4.57-4.55,1.49,1.49a0.5 0.5 ,0,0,0,0.85-0.36Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml new file mode 100644 index 000000000000..f64bd309e204 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.67,16.42A0.84 0.84 ,0,0,0,20,16.19a9.83,9.83,0,0,0,1-4.3,10,10,0,0,0-0.91-4.12 0.85 0.85,0,0,0-1.39-0.23 0.87 0.87,0,0,0-0.17,1,8.71,8.71,0,0,1,0,7A0.84 0.84 ,0,0,0,18.67,16.42Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.48,18.56a1,1,0,0,0,1.47,0l4.05-4V21a1,1,0,0,0,1,1,1.07,1.07,0,0,0,0.71-0.27l0.05-0.05,4.46-4.46a1,1,0,0,0,0-1.48L11.51,12l3.75-3.73a1,1,0,0,0,0-1.48L10.79,2.32l0,0A1,1,0,0,0,9,3V9.49L5,5.43A1,1,0,0,0,3.48,6.9L8.57,12,3.48,17.09A1,1,0,0,0,3.48,18.56ZM11,5.38l2.15,2.15L11,9.68Zm0,8.94,2.15,2.15L11,18.62Z" /> + <path + android:fillColor="#000000" + android:pathData="M15,11.3a1,1,0,0,0,0,1.42l1.61,1.61A6.44,6.44,0,0,0,17,12a6.54,6.54,0,0,0-0.43-2.31Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml new file mode 100644 index 000000000000..b014083c5e3a --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.21,6.79l-4.5-4.5A1,1,0,0,0,11,3V9.59L7.2,5.78A1,1,0,0,0,5.79,7.2l4.8,4.8-4.8,4.8A1,1,0,0,0,7.2,18.22L11,14.41V21a1,1,0,0,0,0.62 0.92 A0.84 0.84 ,0,0,0,12,22a1,1,0,0,0,0.71-0.29l4.5-4.5a1,1,0,0,0,0-1.42L13.42,12l3.79-3.79A1,1,0,0,0,17.21,6.79ZM15.09,16.5,13,18.58V14.42ZM13,9.58V5.42L15.09,7.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml new file mode 100644 index 000000000000..f3b1c016c301 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M10,14.61h4L14.85,17H17L13.11,7H10.87L7,17H9.15Zm1.54-4.24 0.38 -1.2h0.11l0.38,1.2 0.91 ,2.51H10.63Z" /> + <path + android:fillColor="#000000" + android:pathData="M4,20H8.69L12,23.31,15.31,20H20V15.31L23.31,12,20,8.69V4H15.31L12,0.69,8.69,4H4V8.69L0.69,12,4,15.31Zm-0.48-8L6,9.52V6H9.52L12,3.52,14.48,6H18V9.52L20.48,12,18,14.48V18H14.48L12,20.48,9.52,18H6V14.48Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cancel.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cancel.xml new file mode 100644 index 000000000000..0403d818f758 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cancel.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm4.3,12.89a1,1,0,0,1,0,1.41,1,1,0,0,1-1.41,0h0L12,13.41,9.11,16.3A1,1,0,1,1,7.7,14.89L10.59,12,7.7,9.11A1,1,0,1,1,9.11,7.7L12,10.59,14.89,7.7A1,1,0,1,1,16.3,9.11L13.41,12Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cast_on.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cast_on.xml new file mode 100644 index 000000000000..0fd763b8d325 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_cast_on.xml @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M1.82,16.08a5,5,0,0,1,4.1,4.08,1,1,0,0,0,1,0.84,1,1,0,0,0,1-1.14,7,7,0,0,0-5.8-5.78,1,1,0,0,0-0.29,2Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,7H5V8.63A13,13,0,0,1,13.37,17H19Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,5H21V19H14v2h7a2,2,0,0,0,2-2V5a2,2,0,0,0-2-2H3A2,2,0,0,0,1,5V8H3Z" /> + <path + android:fillColor="#000000" + android:pathData="M1.85,12A9.06,9.06,0,0,1,10,20.12a1,1,0,0,0,1,0.88,1,1,0,0,0,1-1.1,11,11,0,0,0-9.87-9.85A1,1,0,0,0,1,11,1,1,0,0,0,1.85,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M2,21H4a3,3,0,0,0-3-3v2A1,1,0,0,0,2,21Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_no_sim.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_no_sim.xml new file mode 100644 index 000000000000..a488ee10a229 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_no_sim.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M17,3H10L7.66,5.34,19,16.68V5A2,2,0,0,0,17,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M20.73,22.23a0.9 0.9 ,0,0,0,0-1.27L4.28,4.51A0.88 0.88 ,0,0,0,3,4.5H3A0.9 0.9 ,0,0,0,3,5.78l2,2V19a2,2,0,0,0,2,2H17a2,2,0,0,0,1-0.26l1.49,1.49A0.9 0.9 ,0,0,0,20.73,22.23Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_vpn.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_vpn.xml new file mode 100644 index 000000000000..ee2677d6b4bc --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_vpn.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,10H12.65a6,6,0,1,0,0,4H16v2a2,2,0,0,0,4,0V14h1a2,2,0,0,0,0-4ZM7,14a2,2,0,1,1,2-2A2,2,0,0,1,7,14Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml new file mode 100644 index 000000000000..395b2e2f3fc4 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M23.43,6.57A20.54,20.54,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L14,20.13V12h6.54l3.12-3.89A1.06,1.06,0,0,0,23.43,6.57Z" /> + <path + android:fillColor="#000000" + android:pathData="M22.32,14.68a1,1,0,0,0-1.37,0l-1.44,1.44-1.45-1.45a1,1,0,0,0-1.37,0h0a1,1,0,0,0,0,1.37l1.45,1.45L16.68,19h0a1,1,0,0,0,0,1.37h0a1,1,0,0,0,1.37,0l1.45-1.45L21,20.32A1,1,0,0,0,22.32,19L20.87,17.5l1.45-1.45A1,1,0,0,0,22.32,14.68Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml new file mode 100644 index 000000000000..f24bb24fcc90 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M14,12h6.54l3.12-3.89a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L14,20.13Z" /> + <path + android:fillColor="#000000" + android:pathData="M22.71,15.67,20.88,17.5l1.83,1.83a1,1,0,0,1,0,1.38h0a1,1,0,0,1-1.38,0L19.5,18.88l-1.83,1.83a1,1,0,0,1-1.38,0h0a1,1,0,0,1,0-1.38l1.83-1.83-1.82-1.82a1,1,0,0,1,0-1.38h0a1,1,0,0,1,1.38,0L19.5,16.1l1.82-1.82a1,1,0,0,1,1.38,0h0A1,1,0,0,1,22.71,15.67Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml new file mode 100644 index 000000000000..4491abb53633 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M14,12h6.54l3.12-3.89a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L14,20.13Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20.13,12.82,21.6a1.07,1.07,0,0,1-1.66,0l-5.1-6.35A9,9,0,0,1,12,13a8.76,8.76,0,0,1,2,0.23Zm8.71-5.84h0a1,1,0,0,0-1.38,0l-1.82,1.82-1.82-1.82a1,1,0,0,0-1.38,0h0a1,1,0,0,0,0,1.38l1.82,1.82-1.83,1.83a1,1,0,0,0,0,1.38h0a1,1,0,0,0,1.38,0l1.83-1.83,1.83,1.83a1,1,0,0,0,1.38,0h0a1,1,0,0,0,0-1.38l-1.83-1.83,1.83-1.83A1,1,0,0,0,22.71,14.29Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml new file mode 100644 index 000000000000..cd4f78f5f9aa --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M14,12h6.54l3.12-3.89a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L14,20.13Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20.13,12.82,21.6a1.07,1.07,0,0,1-1.66,0l-7-8.7A12,12,0,0,1,18.62,12H14Zm8.71-5.84h0a1,1,0,0,0-1.38,0l-1.82,1.82-1.82-1.82a1,1,0,0,0-1.38,0h0a1,1,0,0,0,0,1.38l1.82,1.82-1.83,1.83a1,1,0,0,0,0,1.38h0a1,1,0,0,0,1.38,0l1.83-1.83,1.83,1.83a1,1,0,0,0,1.38,0h0a1,1,0,0,0,0-1.38l-1.83-1.83,1.83-1.83A1,1,0,0,0,22.71,14.29Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml new file mode 100644 index 000000000000..47ee8324ecba --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M14,12h6.54l3.12-3.89a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0L14,20.13Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20.13,12.82,21.6a1.07,1.07,0,0,1-1.66,0L2.93,11.35a14,14,0,0,1,18.14,0l-0.53 0.66 H14Zm8.71-5.84h0a1,1,0,0,0-1.38,0l-1.82,1.82-1.82-1.82a1,1,0,0,0-1.38,0h0a1,1,0,0,0,0,1.38l1.82,1.82-1.83,1.83a1,1,0,0,0,0,1.38h0a1,1,0,0,0,1.38,0l1.83-1.83,1.83,1.83a1,1,0,0,0,1.38,0h0a1,1,0,0,0,0-1.38l-1.83-1.83,1.83-1.83A1,1,0,0,0,22.71,14.29Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml new file mode 100644 index 000000000000..8bef29c5d69f --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M14.61,13a5,5,0,0,1,5-5A4.93,4.93,0,0,1,22.8,9.18l0.86-1.07a1.06,1.06,0,0,0-0.22-1.54A20.58,20.58,0,0,0,12,3,20.55,20.55,0,0,0,0.56,6.57,1.07,1.07,0,0,0,0.33,8.11L11.16,21.6a1.07,1.07,0,0,0,1.66,0l3.74-4.66A5,5,0,0,1,14.61,13Z" /> + <path + android:fillColor="#000000" + android:pathData="M20,22a1.1,1.1,0,1,0-1.1-1.1A1.1,1.1,0,0,0,20,22Z" /> + <path + android:fillColor="#000000" + android:pathData="M22.69,15.48a2.79,2.79,0,0,0,0.82-2,3.51,3.51,0,0,0-6.82-1.15 0.86 0.86,0,0,0,0.81,1.14 0.89 0.89,0,0,0,0.84-0.55,1.75,1.75,0,0,1,3.41 0.55 ,1.79,1.79,0,0,1-0.51,1.24l-1.09,1.1a3.21,3.21,0,0,0-1,2.12s0,0.05,0,0.08A0.89 0.89 ,0,0,0,20,19a0.87 0.87 ,0,0,0,0.87-0.77,2.85,2.85,0,0,1,1-1.95Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_screenshot_delete.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_screenshot_delete.xml new file mode 100644 index 000000000000..447d848755cf --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_screenshot_delete.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18,4H15.5l-0.71-0.71a1,1,0,0,0-0.7-0.29H9.9a1,1,0,0,0-0.7 0.29 L8.49,4H6A1,1,0,0,0,6,6H18a1,1,0,0,0,1-1A1,1,0,0,0,18,4Z" /> + <path + android:fillColor="#000000" + android:pathData="M18,19V7H6V19a2,2,0,0,0,2,2h8A2,2,0,0,0,18,19Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_settings_16dp.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_settings_16dp.xml new file mode 100644 index 000000000000..d292b13c8faf --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_settings_16dp.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.64,8.39,20,5.63a1.12,1.12,0,0,0-1.36-0.5L16.54,6A7.26,7.26,0,0,0,15,5.12l-0.27-2.2A1.1,1.1,0,0,0,13.59,2H10.41a1.1,1.1,0,0,0-1.11 0.92 L9,5.11A7.1,7.1,0,0,0,7.46,6L5.32,5.12A1.12,1.12,0,0,0,4,5.62L2.36,8.38A1.1,1.1,0,0,0,2.6,9.8l1.94,1.45a6.06,6.06,0,0,0,0,0.75,6.34,6.34,0,0,0,0,0.76L2.6,14.2a1.09,1.09,0,0,0-0.24,1.41L4,18.37a1.12,1.12,0,0,0,1.36 0.5 L7.46,18A7.26,7.26,0,0,0,9,18.88l0.27,2.19a1.1,1.1,0,0,0,1.11 0.93 h3.18a1.11,1.11,0,0,0,1.11-0.92L15,18.89A7.26,7.26,0,0,0,16.54,18l2.14 0.91 a1.12,1.12,0,0,0,1.36-0.5l1.6-2.76a1.1,1.1,0,0,0-0.24-1.42l-1.94-1.45a7.24,7.24,0,0,0,0-1.52L21.4,9.8A1.09,1.09,0,0,0,21.64,8.39ZM12,15.5A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" /> +</vector> diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_airplane.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_airplane.xml new file mode 100644 index 000000000000..999a9bf3cf45 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_airplane.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.15,15.8l7.35-2.3V19L8.9,20.2a1,1,0,0,0-0.4 0.8 v0.67a0.24 0.24 ,0,0,0,0.31 0.24 L12,21l3.19 0.91 a0.24 0.24 ,0,0,0,0.31-0.24V21a1,1,0,0,0-0.4-0.8L13.5,19V13.5l7.35,2.3a0.5 0.5 ,0,0,0,0.65-0.48v-0.49a1.5,1.5,0,0,0-0.7-1.27L13.5,9V3.5a1.5,1.5,0,0,0-3,0V9L3.2,13.56a1.5,1.5,0,0,0-0.7,1.27v0.49A0.5 0.5 ,0,0,0,3.15,15.8Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_flashlight.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_flashlight.xml new file mode 100644 index 000000000000..1ffb32b90144 --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_signal_flashlight.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M10,22h4a1,1,0,0,0,1-1V10a2,2,0,0,0,2-2V5.5H7V8a2,2,0,0,0,2,2V21A1,1,0,0,0,10,22Zm2-10a1.5,1.5,0,1,1-1.5,1.5A1.5,1.5,0,0,1,12,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M17,3a1,1,0,0,0-1-1H8A1,1,0,0,0,7,3V4H17Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_swap_vert.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_swap_vert.xml new file mode 100644 index 000000000000..43a01c63dbdc --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_swap_vert.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18,17H16V11a1,1,0,0,0-2,0v6H12a0.53 0.53 ,0,0,0-0.37 0.9 l2.95,2.94a0.53 0.53 ,0,0,0,0.75,0l3-2.94A0.52 0.52 ,0,0,0,18,17Z" /> + <path + android:fillColor="#000000" + android:pathData="M12.32,6.09l-3-2.95a0.52 0.52 ,0,0,0-0.74,0h0L5.68,6.09a0.53 0.53 ,0,0,0,0.37 0.9 H8v6a1,1,0,0,0,2,0V7H12A0.52 0.52 ,0,0,0,12.32,6.09Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm.xml new file mode 100644 index 000000000000..c300bed51aea --- /dev/null +++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.8,2.6A1,1,0,0,0,16.9,4L20,6.6a1,1,0,0,0,1.4-0.1,1,1,0,0,0-0.1-1.4L18.2,2.5A1,1,0,0,0,16.8,2.6Z" /> + <path + android:fillColor="#000000" + android:pathData="M4.1,6.6,7.1,4A1,1,0,1,0,5.8,2.5l-3,2.6a1,1,0,0,0-0.1,1.4A1,1,0,0,0,4.1,6.6Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,13a9,9,0,1,0,9-9A9,9,0,0,0,3,13Zm8-4.25a0.75 0.75 ,0,0,1,1.5,0v4.5l3.37,2a0.72 0.72 ,0,0,1,0.25,1,0.71 0.71 ,0,0,1-1,0.24L11,14Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledOverlay/Android.mk b/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk index 14bc1d6bf7a8..2937fb862618 100644 --- a/packages/overlays/IconPackFilledOverlay/Android.mk +++ b/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk @@ -16,7 +16,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_RRO_THEME := IconPackFilled +LOCAL_RRO_THEME := IconPackRoundedAndroid LOCAL_CERTIFICATE := platform LOCAL_PRODUCT_MODULE := true @@ -24,7 +24,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_PACKAGE_NAME := IconPackFilledOverlay +LOCAL_PACKAGE_NAME := IconPackRoundedAndroidOverlay LOCAL_SDK_VERSION := current include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackRoundedOverlay/AndroidManifest.xml b/packages/overlays/IconPackRoundedAndroidOverlay/AndroidManifest.xml index 801473375893..8da1948f0aa1 100644 --- a/packages/overlays/IconPackRoundedOverlay/AndroidManifest.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/AndroidManifest.xml @@ -16,9 +16,9 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.theme.icon_pack.rounded" + package="com.android.theme.icon_pack.rounded.android" android:versionCode="1" android:versionName="1.0"> - <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack" android:priority="1"/> + <overlay android:targetPackage="android" android:category="android.theme.customization.icon_pack.android" android:priority="1"/> <application android:label="Rounded" android:hasCode="false"/> </manifest> diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml new file mode 100644 index 000000000000..264e2122aa50 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_bt_headphones_a2dp.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.5,18V11.5C21.5,5.82,17.68,2,12,2S2.5,5.82,2.5,11.5V18a3,3,0,0,0,3,3H7a1.5,1.5,0,0,0,1.5-1.5V14A1.5,1.5,0,0,0,7,12.5H4v-1c0-4.86,3.14-8,8-8s8,3.14,8,8v1H17A1.5,1.5,0,0,0,15.5,14v5.5A1.5,1.5,0,0,0,17,21h1.5A3,3,0,0,0,21.5,18ZM7,19.5H5.5A1.5,1.5,0,0,1,4,18V14H7ZM20,18a1.5,1.5,0,0,1-1.5,1.5H17V14h3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml new file mode 100644 index 000000000000..407adacec5d1 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_expand_more.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.54,8.48a0.75 0.75 ,0,0,0-1.06,0L12,13.82,6.52,8.46a0.75 0.75 ,0,0,0-1.06,0,0.75 0.75 ,0,0,0,0,1.06l5.74,5.62a1.11,1.11,0,0,0,0.78 0.36 ,1.09,1.09,0,0,0,0.77-0.36l5.75-5.62A0.75 0.75 ,0,0,0,18.54,8.48Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_info_outline_24.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_info_outline_24.xml new file mode 100644 index 000000000000..642ac421fe99 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_info_outline_24.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.07,4.93A10,10,0,1,0,22,12,10,10,0,0,0,19.07,4.93ZM18,18a8.5,8.5,0,1,1,2.5-6A8.53,8.53,0,0,1,18,18Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,10a0.76 0.76 ,0,0,0-0.75 0.75 v5.5a0.75 0.75 ,0,0,0,1.5,0v-5.5A0.76 0.76 ,0,0,0,12,10Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_invert_colors.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_invert_colors.xml new file mode 100644 index 000000000000..173824be8a64 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_invert_colors.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12.62,2.23A1,1,0,0,0,12,2a1.07,1.07,0,0,0-0.63 0.22 C9.48,3.75,4,8.5,4,14a7.89,7.89,0,0,0,8,8,8,8,0,0,0,8-8C20,8.5,14.5,3.73,12.62,2.23ZM5.5,14c0-4.4,4.32-8.53,6.5-10.33V20.49A6.43,6.43,0,0,1,5.5,14Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..7897fa3a40a9 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,55 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,21H21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19A2,2,0,0,0,3,21ZM2.5,6A0.51 0.51 ,0,0,1,3,5.5H21a0.51 0.51 ,0,0,1,0.5 0.5 V19a0.51 0.51 ,0,0,1-0.5 0.5 H3a0.51 0.51 ,0,0,1-0.5-0.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 8 L 10.5 8 Q 11 8 11 8.5 L 11 9.5 Q 11 10 10.5 10 L 9.5 10 Q 9 10 9 9.5 L 9 8.5 Q 9 8 9.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 8 L 6.5 8 Q 7 8 7 8.5 L 7 9.5 Q 7 10 6.5 10 L 5.5 10 Q 5 10 5 9.5 L 5 8.5 Q 5 8 5.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M8.75,17.5h6.5a0.75 0.75 ,0,0,0,0-1.5H8.75a0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 8 L 14.5 8 Q 15 8 15 8.5 L 15 9.5 Q 15 10 14.5 10 L 13.5 10 Q 13 10 13 9.5 L 13 8.5 Q 13 8 13.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 12 L 10.5 12 Q 11 12 11 12.5 L 11 13.5 Q 11 14 10.5 14 L 9.5 14 Q 9 14 9 13.5 L 9 12.5 Q 9 12 9.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 12 L 6.5 12 Q 7 12 7 12.5 L 7 13.5 Q 7 14 6.5 14 L 5.5 14 Q 5 14 5 13.5 L 5 12.5 Q 5 12 5.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 12 L 14.5 12 Q 15 12 15 12.5 L 15 13.5 Q 15 14 14.5 14 L 13.5 14 Q 13 14 13 13.5 L 13 12.5 Q 13 12 13.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 8 L 18.5 8 Q 19 8 19 8.5 L 19 9.5 Q 19 10 18.5 10 L 17.5 10 Q 17 10 17 9.5 L 17 8.5 Q 17 8 17.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 12 L 18.5 12 Q 19 12 19 12.5 L 19 13.5 Q 19 14 18.5 14 L 17.5 14 Q 17 14 17 13.5 L 17 12.5 Q 17 12 17.5 12 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml new file mode 100644 index 000000000000..8532bdd29db5 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.35,21.15h0.07l3.88-0.6a1,1,0,0,0,0.56-0.28L21,7.07h0A0.75 0.75 ,0,0,0,21,6L18,3h0a0.73 0.73 ,0,0,0-0.52-0.21A0.74 0.74 ,0,0,0,17,3L15.51,4.45h0L14.44,5.5h0L3.73,16.14a1,1,0,0,0-0.28 0.56 l-0.6,3.88A0.51 0.51 ,0,0,0,3.35,21.15ZM17.5,4.59l1.95,1.94-0.93 0.93 L16.57,5.51ZM4.91,17.09,15.51,6.56l2,2L6.91,19.09l-2.37 0.37 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml new file mode 100644 index 000000000000..c62203dc893f --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,16.35A1.41,1.41,0,0,0,20,15l-2.42-0.73a1.43,1.43,0,0,0-1.41 0.34 l-2.95,2.87a16.48,16.48,0,0,1-3.74-2.7,17.33,17.33,0,0,1-3-4L9.36,7.94a1.42,1.42,0,0,0,0.37-1.36L9.07,4.12a1.43,1.43,0,0,0-1.37-1h-4a0.56 0.56 ,0,0,0-0.12,0,0.58 0.58 ,0,0,0-0.14,0,0.54 0.54 ,0,0,0-0.12 0.09 l-0.11 0.08 a0.94 0.94 ,0,0,0-0.09 0.12 l-0.07 0.12 ,0,0.15s0,0.08,0,0.12v0a18.53,18.53,0,0,0,5.42,12,18.25,18.25,0,0,0,11.79,5.07h0a0.72 0.72 ,0,0,0,0.29-0.06l0.08-0.05a0.53 0.53 ,0,0,0,0.15-0.11 0.31 0.31,0,0,0,0.07-0.09 0.67 0.67,0,0,0,0.09-0.14 0.53 0.53,0,0,0,0-0.12 0.37 0.37,0,0,0,0-0.15h0V16.35ZM8.3,6.88,5.81,9.33A17.23,17.23,0,0,1,4.58,4.58H7.64Zm8.83,8.82,2.37 0.72 v2.93a17.06,17.06,0,0,1-4.85-1.19Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_night_display_on.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_night_display_on.xml new file mode 100644 index 000000000000..96ce11c2b918 --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_night_display_on.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M22.63,16.12a0.75 0.75 ,0,0,0-0.76-0.32,12.23,12.23,0,0,1-2.12 0.2 A11.76,11.76,0,0,1,8,4.25a12.23,12.23,0,0,1,0.2-2.12 0.73 0.73,0,0,0-0.32-0.76 0.74 0.74,0,0,0-0.83,0A11.25,11.25,0,1,0,22.63,17,0.74 0.74 ,0,0,0,22.63,16.12ZM13.25,20.5A9.75,9.75,0,0,1,6.51,3.71c0,0.18,0,0.36,0,0.54A13.27,13.27,0,0,0,20.29,17.49,9.71,9.71,0,0,1,13.25,20.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_location.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_location.xml new file mode 100644 index 000000000000..eb94952fa24c --- /dev/null +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_signal_location.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M15,10a3,3,0,1,0-3,3A3,3,0,0,0,15,10Zm-4.5,0A1.5,1.5,0,1,1,12,11.5,1.5,1.5,0,0,1,10.5,10Z" /> + <path + android:fillColor="#000000" + android:pathData="M11.37,21.76A1,1,0,0,0,12,22a1,1,0,0,0,0.62-0.22C14.5,20.26,20,15.5,20,10a8,8,0,0,0-8-8,7.89,7.89,0,0,0-8,8C4,15.5,9.48,20.25,11.37,21.76ZM12,3.51A6.5,6.5,0,0,1,18.5,10c0,4.4-4.31,8.53-6.5,10.34C9.82,18.54,5.5,14.4,5.5,10A6.43,6.43,0,0,1,12,3.51Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_0.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_0.xml index 089974d97c21..96d04c3e8edd 100644 --- a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_0.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_0.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -47,4 +46,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_1.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_1.xml index e51879e4204b..b88732067ef4 100644 --- a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_1.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_1.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -44,4 +43,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M22.79,7.23A14.76,14.76,0,0,0,12,2.75,14.72,14.72,0,0,0,1.23,7.2a0.75 0.75 ,0,0,0,1.07,1,13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.75 0.75 ,0,0,0,1.07-1Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_2.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_2.xml index 77343af8e85f..af41245bcf14 100644 --- a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_2.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_2.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -41,4 +40,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M22.79,7.23A14.76,14.76,0,0,0,12,2.75,14.72,14.72,0,0,0,1.23,7.2a0.75 0.75 ,0,0,0,1.07,1,13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.75 0.75 ,0,0,0,1.07-1Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_3.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_3.xml index 0b89382fc49e..c13764395261 100644 --- a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_3.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_3.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -38,4 +37,4 @@ android:strokeAlpha="0.3" android:strokeWidth="1" android:pathData="M22.79,7.23A14.76,14.76,0,0,0,12,2.75,14.72,14.72,0,0,0,1.23,7.2a0.75 0.75 ,0,0,0,1.07,1,13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.75 0.75 ,0,0,0,1.07-1Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_4.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_4.xml index f02bc83b53e6..b8f2d78ba6b8 100644 --- a/packages/overlays/IconPackRoundedOverlay/res/drawable/ic_wifi_signal_4.xml +++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_wifi_signal_4.xml @@ -7,8 +7,7 @@ * 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 + * * 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 @@ -35,4 +34,4 @@ <path android:fillColor="#000000" android:pathData="M2.3,8.25a13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.73 0.73 ,0,0,0,1,0,0.75 0.75 ,0,0,0,0.05-1.06A14.76,14.76,0,0,0,12,2.75,14.76,14.76,0,0,0,1.22,7.2a0.77 0.77 ,0,0,0,0,1A0.75 0.75 ,0,0,0,2.3,8.25Z" /> -</vector> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk b/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk new file mode 100644 index 000000000000..44ac6dd939dd --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright 2019, 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackRoundedSettings +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackRoundedSettingsOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/AndroidManifest.xml b/packages/overlays/IconPackRoundedSettingsOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..df71e156490c --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.rounded.settings" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.settings" android:category="android.theme.customization.icon_pack.settings" android:priority="1"/> + <application android:label="Rounded" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml new file mode 100644 index 000000000000..62acfc66b5df --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.5 4 L 6.5 4 Q 8 4 8 5.5 L 8 6.5 Q 8 8 6.5 8 L 5.5 8 Q 4 8 4 6.5 L 4 5.5 Q 4 4 5.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 11.5 4 L 12.5 4 Q 14 4 14 5.5 L 14 6.5 Q 14 8 12.5 8 L 11.5 8 Q 10 8 10 6.5 L 10 5.5 Q 10 4 11.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 17.5 4 L 18.5 4 Q 20 4 20 5.5 L 20 6.5 Q 20 8 18.5 8 L 17.5 8 Q 16 8 16 6.5 L 16 5.5 Q 16 4 17.5 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.5 10 L 6.5 10 Q 8 10 8 11.5 L 8 12.5 Q 8 14 6.5 14 L 5.5 14 Q 4 14 4 12.5 L 4 11.5 Q 4 10 5.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 11.5 10 L 12.5 10 Q 14 10 14 11.5 L 14 12.5 Q 14 14 12.5 14 L 11.5 14 Q 10 14 10 12.5 L 10 11.5 Q 10 10 11.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 17.5 10 L 18.5 10 Q 20 10 20 11.5 L 20 12.5 Q 20 14 18.5 14 L 17.5 14 Q 16 14 16 12.5 L 16 11.5 Q 16 10 17.5 10 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.5 16 L 6.5 16 Q 8 16 8 17.5 L 8 18.5 Q 8 20 6.5 20 L 5.5 20 Q 4 20 4 18.5 L 4 17.5 Q 4 16 5.5 16 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 11.5 16 L 12.5 16 Q 14 16 14 17.5 L 14 18.5 Q 14 20 12.5 20 L 11.5 20 Q 10 20 10 18.5 L 10 17.5 Q 10 16 11.5 16 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 17.5 16 L 18.5 16 Q 20 16 20 17.5 L 20 18.5 Q 20 20 18.5 20 L 17.5 20 Q 16 20 16 18.5 L 16 17.5 Q 16 16 17.5 16 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml new file mode 100644 index 000000000000..be7f297a88e9 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M22,18V10a1.5,1.5,0,0,0-1.5-1.5h-4A1.5,1.5,0,0,0,15,10v8a1.5,1.5,0,0,0,1.5,1.5h4A1.5,1.5,0,0,0,22,18Zm-5.5-8h4v8h-4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13,17a2.5,2.5,0,1,0-2.5,2.5A2.5,2.5,0,0,0,13,17ZM9.5,17a1,1,0,1,1,1,1A1,1,0,0,1,9.5,17Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21.25,4H3.5A1.5,1.5,0,0,0,2,5.5V18a1.5,1.5,0,0,0,1.5,1.5H5.25a0.75 0.75 ,0,0,0,0-1.5H3.5V5.5H21.25a0.75 0.75 ,0,0,0,0-1.5Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml new file mode 100644 index 000000000000..e8c3e47f75ef --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,22h0A10,10,0,0,0,22,12v0A10,10,0,1,0,12,22ZM12,3.5A8.51,8.51,0,0,1,20.5,12h0.75l-0.75,0A8.49,8.49,0,0,1,12,20.5h0a8.5,8.5,0,0,1,0-17Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8.67,10a0.77 0.77 ,0,0,0,0.91-0.56,2.48,2.48,0,0,1,0.65-1.19,2.57,2.57,0,0,1,3.54,0A2.2,2.2,0,0,1,14.43,10a1.81,1.81,0,0,1-0.84,1.37c-0.13 0.09 -0.26 0.16 -0.4 0.24 a3.3,3.3,0,0,0-1.93,2.51 0.76 0.76,0,0,0,0.62 0.87 H12a0.75 0.75 ,0,0,0,0.74-0.62,1.84,1.84,0,0,1,1.19-1.46l0.49-0.29a3.32,3.32,0,0,0,1.5-2.48,3.71,3.71,0,0,0-1.09-3,4.1,4.1,0,0,0-5.66,0,4,4,0,0,0-1.05,1.9A0.75 0.75 ,0,0,0,8.67,10Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml new file mode 100644 index 000000000000..e5e57d4e4cb6 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8,1A3,3,0,0,0,5,4V20a3,3,0,0,0,3,3h8a3,3,0,0,0,3-3V4a3,3,0,0,0-3-3Zm8,20.5H8A1.5,1.5,0,0,1,6.5,20h11A1.5,1.5,0,0,1,16,21.5Zm1.5-3H6.5V5.5h11ZM17.5,4H6.5A1.5,1.5,0,0,1,8,2.5h8A1.5,1.5,0,0,1,17.5,4Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,11.25a0.76 0.76 ,0,0,0-0.75 0.75 v4a0.75 0.75 ,0,0,0,1.5,0V12A0.76 0.76 ,0,0,0,12,11.25Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml new file mode 100644 index 000000000000..1ac58b520590 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M14.25,2.5A2.25,2.25,0,1,0,12,4.75,2.25,2.25,0,0,0,14.25,2.5Zm-3,0a0.75 0.75 ,0,1,1,0.75 0.75 A0.76 0.76 ,0,0,1,11.25,2.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20.72,5.28a0.77 0.77 ,0,0,0-0.94-0.5,29.53,29.53,0,0,1-7.78,1,29.72,29.72,0,0,1-7.78-1,0.75 0.75 ,0,0,0-0.44,1.44A28.14,28.14,0,0,0,9,7.12V19a0.75 0.75 ,0,0,0,1.5,0V14h3v5A0.75 0.75 ,0,0,0,15,19V7.12a28.14,28.14,0,0,0,5.22-0.9A0.76 0.76 ,0,0,0,20.72,5.28Zm-7.22,2V12.5h-3V7.25Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml new file mode 100644 index 000000000000..90da97f76324 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M6.21,20.14l0.08 0.06 A10,10,0,0,0,12,22h0a10,10,0,0,0,5.76-1.84h0A10,10,0,0,0,22,12v0A10,10,0,1,0,6.21,20.14Zm5.8 0.36 h0a8.45,8.45,0,0,1-4.5-1.3V15.75A0.76 0.76 ,0,0,1,8.25,15h7.5a0.76 0.76 ,0,0,1,0.75 0.75 V19.2A8.39,8.39,0,0,1,12,20.5Zm0-17A8.51,8.51,0,0,1,20.5,12h0.75l-0.75,0A8.47,8.47,0,0,1,18,18V15.75a2.25,2.25,0,0,0-2.25-2.25H8.25A2.25,2.25,0,0,0,6,15.75V18A8.49,8.49,0,0,1,12,3.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,12h0A3,3,0,1,0,9,9H9A3,3,0,0,0,12,12ZM10.5,9A1.5,1.5,0,1,1,12,10.5h0A1.5,1.5,0,0,1,10.5,9Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml new file mode 100644 index 000000000000..3f3b95a942d2 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13,2.49H11a1,1,0,0,0-1,1V4H7A1,1,0,0,0,6,5V21a1,1,0,0,0,1,1H17a1,1,0,0,0,1-1V5a1,1,0,0,0-1-1H14V3.49A1,1,0,0,0,13,2.49Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml new file mode 100644 index 000000000000..54993e2b6ae8 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M19.5,12h0A7.5,7.5,0,1,0,12,19.5h0A7.49,7.49,0,0,0,19.5,12ZM12,18h0a6,6,0,1,1,6-6h0a6,6,0,0,1-6,6Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 1.5 C 12.4142135624 1.5 12.75 1.83578643763 12.75 2.25 C 12.75 2.66421356237 12.4142135624 3 12 3 C 11.5857864376 3 11.25 2.66421356237 11.25 2.25 C 11.25 1.83578643763 11.5857864376 1.5 12 1.5 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.1 4.35 C 5.51421356237 4.35 5.85 4.68578643763 5.85 5.1 C 5.85 5.51421356237 5.51421356237 5.85 5.1 5.85 C 4.68578643763 5.85 4.35 5.51421356237 4.35 5.1 C 4.35 4.68578643763 4.68578643763 4.35 5.1 4.35 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 2.25 11.25 C 2.66421356237 11.25 3 11.5857864376 3 12 C 3 12.4142135624 2.66421356237 12.75 2.25 12.75 C 1.83578643763 12.75 1.5 12.4142135624 1.5 12 C 1.5 11.5857864376 1.83578643763 11.25 2.25 11.25 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.1 18.15 C 5.51421356237 18.15 5.85 18.4857864376 5.85 18.9 C 5.85 19.3142135624 5.51421356237 19.65 5.1 19.65 C 4.68578643763 19.65 4.35 19.3142135624 4.35 18.9 C 4.35 18.4857864376 4.68578643763 18.15 5.1 18.15 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 21 C 12.4142135624 21 12.75 21.3357864376 12.75 21.75 C 12.75 22.1642135624 12.4142135624 22.5 12 22.5 C 11.5857864376 22.5 11.25 22.1642135624 11.25 21.75 C 11.25 21.3357864376 11.5857864376 21 12 21 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 18.9 18.15 C 19.3142135624 18.15 19.65 18.4857864376 19.65 18.9 C 19.65 19.3142135624 19.3142135624 19.65 18.9 19.65 C 18.4857864376 19.65 18.15 19.3142135624 18.15 18.9 C 18.15 18.4857864376 18.4857864376 18.15 18.9 18.15 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 21.75 11.25 C 22.1642135624 11.25 22.5 11.5857864376 22.5 12 C 22.5 12.4142135624 22.1642135624 12.75 21.75 12.75 C 21.3357864376 12.75 21 12.4142135624 21 12 C 21 11.5857864376 21.3357864376 11.25 21.75 11.25 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 18.9 4.35 C 19.3142135624 4.35 19.65 4.68578643763 19.65 5.1 C 19.65 5.51421356237 19.3142135624 5.85 18.9 5.85 C 18.4857864376 5.85 18.15 5.51421356237 18.15 5.1 C 18.15 4.68578643763 18.4857864376 4.35 18.9 4.35 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml new file mode 100644 index 000000000000..26aa3086ff06 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15,10a3,3,0,1,0-3,3A3,3,0,0,0,15,10Zm-4.5,0A1.5,1.5,0,1,1,12,11.5,1.5,1.5,0,0,1,10.5,10Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M11.37,21.76A1,1,0,0,0,12,22a1,1,0,0,0,0.62-0.22C14.5,20.26,20,15.5,20,10a8,8,0,0,0-8-8,7.89,7.89,0,0,0-8,8C4,15.5,9.48,20.25,11.37,21.76ZM12,3.51A6.5,6.5,0,0,1,18.5,10c0,4.4-4.31,8.53-6.5,10.34C9.82,18.54,5.5,14.4,5.5,10A6.43,6.43,0,0,1,12,3.51Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml new file mode 100644 index 000000000000..a6619bdcdb06 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,8a4,4,0,0,0,0,8,3.94,3.94,0,0,0,2.23-0.68,5.06,5.06,0,0,1,1.67-2.47A4,4,0,0,0,16,12,4,4,0,0,0,12,8Zm0,6.5A2.5,2.5,0,1,1,14.5,12,2.5,2.5,0,0,1,12,14.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M1.55,12.27C1.67,12.58,4.58,20,12,20a10.57,10.57,0,0,0,2-0.21V18.27a8.44,8.44,0,0,1-2,0.23c-5.72,0-8.37-5.22-8.94-6.5C3.63,10.75,6.33,5.5,12,5.5s8.38,5.22,9,6.5l-0.06 0.12 a4.84,4.84,0,0,1,1.28 0.8 c0.17-0.36 0.27 -0.6 0.29 -0.65a0.72 0.72 ,0,0,0,0-0.54C22.34,11.42,19.43,4,12,4S1.67,11.42,1.55,11.73A0.72 0.72 ,0,0,0,1.55,12.27Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21.25,16.5v-0.66a2.26,2.26,0,0,0-4.5,0v0.66H16V22h6V16.5Zm-3,0v-0.66c0-0.29 0.38 -0.59 0.75 -0.59s0.75 0.3 0.75 0.59 v0.66Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml new file mode 100644 index 000000000000..d769f4f5e8d4 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 13.5 C 12.8284271247 13.5 13.5 14.1715728753 13.5 15 C 13.5 15.8284271247 12.8284271247 16.5 12 16.5 C 11.1715728753 16.5 10.5 15.8284271247 10.5 15 C 10.5 14.1715728753 11.1715728753 13.5 12 13.5 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M18.51,3A2.32,2.32,0,0,1,21,5.15a0.79 0.79 ,0,0,0,0.76 0.74 0.75 0.75 ,0,0,0,0.74-0.77,3.8,3.8,0,0,0-4-3.66,3.83,3.83,0,0,0-4,3.68V8.5h-9A1.5,1.5,0,0,0,4,10V20a1.5,1.5,0,0,0,1.5,1.5h13A1.5,1.5,0,0,0,20,20V10a1.5,1.5,0,0,0-1.5-1.5H16V5.15A2.35,2.35,0,0,1,18.51,3Zm0,17H5.5V10h13Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml new file mode 100644 index 000000000000..ee990f92dc46 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M19.07,4.93A10,10,0,1,0,22,12,10,10,0,0,0,19.07,4.93ZM18,18a8.5,8.5,0,1,1,2.5-6A8.53,8.53,0,0,1,18,18Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,10a0.76 0.76 ,0,0,0-0.75 0.75 v5.5a0.75 0.75 ,0,0,0,1.5,0v-5.5A0.76 0.76 ,0,0,0,12,10Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml new file mode 100644 index 000000000000..ffd2c64a6909 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15.78,14.82a0.57 0.57 ,0,0,0,0.16 0.15 0.75 0.75 ,0,0,0,1-0.2 0.76 0.76,0,0,0-0.2-1,6.77,6.77,0,0,0-9.55,0,0.76 0.76 ,0,0,0,0,1,0.75 0.75 ,0,0,0,1.06,0h0a5.24,5.24,0,0,1,7.42,0A0.08 0.08 ,0,0,0,15.78,14.82Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M20,11.79a0.77 0.77 ,0,0,0,0-1.07h0a11.59,11.59,0,0,0-8-3.5,11.63,11.63,0,0,0-8,3.5 0.77 0.77,0,0,0,0,1.07 0.76 0.76,0,0,0,1.07,0,10.12,10.12,0,0,1,7-3,10.12,10.12,0,0,1,7,3A0.75 0.75 ,0,0,0,20,11.79Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M12,2.75A14.76,14.76,0,0,0,1.22,7.2a0.77 0.77 ,0,0,0,0,1,0.75 0.75 ,0,0,0,1.06,0,13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.73 0.73 ,0,0,0,1,0,0.75 0.75 ,0,0,0,0.05-1.06A14.76,14.76,0,0,0,12,2.75Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml new file mode 100644 index 000000000000..e6125db20e7a --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml @@ -0,0 +1,43 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21,2.75A0.76 0.76 ,0,0,0,20.25,2H3.75A0.76 0.76 ,0,0,0,3,2.75v4.5A0.76 0.76 ,0,0,0,3.75,8h16.5A0.76 0.76 ,0,0,0,21,7.25ZM19.5,6.5H4.5v-3h15Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.25 4.25 H 6.75 V 5.75 H 5.25 V 4.25 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21,9.75A0.76 0.76 ,0,0,0,20.25,9H3.75A0.76 0.76 ,0,0,0,3,9.75v4.5a0.76 0.76 ,0,0,0,0.75 0.75 h16.5a0.76 0.76 ,0,0,0,0.75-0.75ZM19.5,13.5H4.5v-3h15Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.25 11.25 H 6.75 V 12.75 H 5.25 V 11.25 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M21,21.25v-4.5a0.76 0.76 ,0,0,0-0.75-0.75H3.75a0.76 0.76 ,0,0,0-0.75 0.75 v4.5a0.76 0.76 ,0,0,0,0.75 0.75 h16.5A0.76 0.76 ,0,0,0,21,21.25Zm-1.5-0.75H4.5v-3h15Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 5.25 18.25 H 6.75 V 19.75 H 5.25 V 18.25 Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml new file mode 100644 index 000000000000..76d3e5f051c6 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M5.69,16l5,5a0.77 0.77 ,0,0,0,0.53 0.22 0.75 0.75 ,0,0,0,0.29-0.06A0.74 0.74 ,0,0,0,12,20.5V3.5A0.75 0.75 ,0,0,0,10.72,3l-5,5H3.49A1.52,1.52,0,0,0,2,9.5v5A1.5,1.5,0,0,0,3.5,16ZM3.5,9.5H6a0.75 0.75 ,0,0,0,0.53-0.22l4-4V18.69l-4-4A0.75 0.75 ,0,0,0,6,14.5H3.5Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13.52,20.64a0.77 0.77 ,0,0,0,0.73 0.56 0.63 0.63 ,0,0,0,0.19,0,9.48,9.48,0,0,0,0-18.34 0.75 0.75,0,0,0-0.92 0.53 0.76 0.76 ,0,0,0,0.54 0.92 ,8,8,0,0,1,0,15.44A0.76 0.76 ,0,0,0,13.52,20.64Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M13.85,15a0.76 0.76 ,0,0,0-0.24,1,0.78 0.78 ,0,0,0,0.64 0.35 0.83 0.83 ,0,0,0,0.4-0.11,5,5,0,0,0,1.6-6.88,5.2,5.2,0,0,0-1.6-1.6A0.75 0.75 ,0,1,0,13.85,9,3.33,3.33,0,0,1,15,10.16,3.47,3.47,0,0,1,13.85,15Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_wifi_tethering.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_wifi_tethering.xml new file mode 100644 index 000000000000..eadd300404a9 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_wifi_tethering.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 12 11 C 12.8284271247 11 13.5 11.6715728753 13.5 12.5 C 13.5 13.3284271247 12.8284271247 14 12 14 C 11.1715728753 14 10.5 13.3284271247 10.5 12.5 C 10.5 11.6715728753 11.1715728753 11 12 11 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M15,16.57a0.75 0.75 ,0,0,0,1.06,0,5.75,5.75,0,1,0-8.14,0,0.79 0.79 ,0,0,0,0.53 0.22 A0.75 0.75 ,0,0,0,9,16.57a0.74 0.74 ,0,0,0,0-1.06,4.25,4.25,0,1,1,6,0A0.75 0.75 ,0,0,0,15,16.57Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M18.36,19.61a0.71 0.71 ,0,0,0,0.53-0.22A9.74,9.74,0,0,0,5.11,5.61a9.73,9.73,0,0,0,0,13.78 0.74 0.74,0,0,0,1.06,0,0.75 0.75 ,0,0,0,0-1.06A8.24,8.24,0,0,1,17.83,6.67a8.23,8.23,0,0,1,0,11.66 0.75 0.75,0,0,0,0,1.06A0.74 0.74 ,0,0,0,18.36,19.61Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk new file mode 100644 index 000000000000..2d34a54fb4de --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright 2019, 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := IconPackRoundedSystemUI +LOCAL_CERTIFICATE := platform +LOCAL_PRODUCT_MODULE := true + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := IconPackRoundedSystemUIOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/AndroidManifest.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..01b121df37dd --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/AndroidManifest.xml @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon_pack.rounded.systemui" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="com.android.systemui" android:category="android.theme.customization.icon_pack.systemui" android:priority="1"/> + <application android:label="Rounded" android:hasCode="false"/> +</manifest> diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml new file mode 100644 index 000000000000..abfcfce79a9b --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M12,19.5h0A7.49,7.49,0,0,0,19.5,12h0A7.5,7.5,0,1,0,12,19.5ZM12,6a6,6,0,0,1,6,6h0a6,6,0,0,1-6,6h0A6,6,0,0,1,12,6Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M11.25 0.75 v1.5a0.75 0.75 ,0,0,0,1.5,0V0.75a0.75 0.75 ,0,0,0-1.5,0Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M4.58,3.51A0.76 0.76 ,0,0,0,3.51,4.58L4.57,5.64a0.79 0.79 ,0,0,0,1.07,0,0.77 0.77 ,0,0,0,0-1.07Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M3,12a0.76 0.76 ,0,0,0-0.75-0.75H0.75a0.75 0.75 ,0,0,0,0,1.5h1.5A0.76 0.76 ,0,0,0,3,12Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M3.51,20.49a0.76 0.76 ,0,0,0,1.07,0l1.06-1.06a0.76 0.76 ,0,1,0-1.07-1.07L3.51,19.42A0.77 0.77 ,0,0,0,3.51,20.49Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M11.25,21.75v1.5a0.75 0.75 ,0,0,0,1.5,0v-1.5a0.75 0.75 ,0,0,0-1.5,0Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M18.36,18.36a0.77 0.77 ,0,0,0,0,1.07l1.06,1.06a0.76 0.76 ,0,0,0,1.07,0,0.77 0.77 ,0,0,0,0-1.07l-1.06-1.06A0.77 0.77 ,0,0,0,18.36,18.36Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M23.25,11.25h-1.5a0.75 0.75 ,0,0,0,0,1.5h1.5a0.75 0.75 ,0,0,0,0-1.5Z" /> + <path + android:fillColor="?android:attr/colorControlActivated" + android:pathData="M19.42,3.51,18.36,4.57a0.77 0.77 ,0,0,0,0,1.07 0.79 0.79,0,0,0,1.07,0l1.06-1.06a0.76 0.76 ,0,0,0-1.07-1.07Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml new file mode 100644 index 000000000000..1158b2761a51 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M22,12a10,10,0,0,0-9-9.95v3A7,7,0,0,1,19,12a7.12,7.12,0,0,1-0.48,2.54h0l2.6,1.53A9.88,9.88,0,0,0,22,12Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.09,13.39a10,10,0,0,0,18,4.52l-2.6-1.53h0A7,7,0,1,1,11,5.08v-3A10,10,0,0,0,2.09,13.39Z" /> + <path + android:fillColor="#000000" + android:pathData="M11.25,8v3.25H8a0.75 0.75 ,0,0,0,0,1.5h3.25V16a0.75 0.75 ,0,0,0,1.5,0V12.75H16a0.75 0.75 ,0,0,0,0-1.5H12.75V8a0.75 0.75 ,0,0,0-1.5,0Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_dnd.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_dnd.xml new file mode 100644 index 000000000000..a9a32ee5bce4 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_dnd.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.25,12.75h9.5a0.75 0.75 ,0,0,0,0-1.5H7.25a0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,22h0A10,10,0,0,0,22,12v0A10,10,0,1,0,12,22ZM12,3.5A8.51,8.51,0,0,1,20.5,12h0.75l-0.75,0A8.49,8.49,0,0,1,12,20.5h0a8.5,8.5,0,0,1,0-17Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_drag_handle.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_drag_handle.xml new file mode 100644 index 000000000000..915597e170e6 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_drag_handle.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M4,10.5H20A0.75 0.75 ,0,0,0,20,9H4a0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M4,15H20a0.75 0.75 ,0,0,0,0-1.5H4A0.75 0.75 ,0,0,0,4,15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_headset.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_headset.xml new file mode 100644 index 000000000000..264e2122aa50 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_headset.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.5,18V11.5C21.5,5.82,17.68,2,12,2S2.5,5.82,2.5,11.5V18a3,3,0,0,0,3,3H7a1.5,1.5,0,0,0,1.5-1.5V14A1.5,1.5,0,0,0,7,12.5H4v-1c0-4.86,3.14-8,8-8s8,3.14,8,8v1H17A1.5,1.5,0,0,0,15.5,14v5.5A1.5,1.5,0,0,0,17,21h1.5A3,3,0,0,0,21.5,18ZM7,19.5H5.5A1.5,1.5,0,0,1,4,18V14H7ZM20,18a1.5,1.5,0,0,1-1.5,1.5H17V14h3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_hotspot.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_hotspot.xml new file mode 100644 index 000000000000..ae78a147afd6 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_hotspot.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 11 C 12.8284271247 11 13.5 11.6715728753 13.5 12.5 C 13.5 13.3284271247 12.8284271247 14 12 14 C 11.1715728753 14 10.5 13.3284271247 10.5 12.5 C 10.5 11.6715728753 11.1715728753 11 12 11 Z" /> + <path + android:fillColor="#000000" + android:pathData="M15,16.57a0.75 0.75 ,0,0,0,1.06,0,5.75,5.75,0,1,0-8.14,0,0.79 0.79 ,0,0,0,0.53 0.22 A0.75 0.75 ,0,0,0,9,16.57a0.74 0.74 ,0,0,0,0-1.06,4.25,4.25,0,1,1,6,0A0.75 0.75 ,0,0,0,15,16.57Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.36,19.61a0.71 0.71 ,0,0,0,0.53-0.22A9.74,9.74,0,0,0,5.11,5.61a9.73,9.73,0,0,0,0,13.78 0.74 0.74,0,0,0,1.06,0,0.75 0.75 ,0,0,0,0-1.06A8.24,8.24,0,0,1,17.83,6.67a8.23,8.23,0,0,1,0,11.66 0.75 0.75,0,0,0,0,1.06A0.74 0.74 ,0,0,0,18.36,19.61Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_info.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_info.xml new file mode 100644 index 000000000000..642ac421fe99 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_info.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.07,4.93A10,10,0,1,0,22,12,10,10,0,0,0,19.07,4.93ZM18,18a8.5,8.5,0,1,1,2.5-6A8.53,8.53,0,0,1,18,18Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,10a0.76 0.76 ,0,0,0-0.75 0.75 v5.5a0.75 0.75 ,0,0,0,1.5,0v-5.5A0.76 0.76 ,0,0,0,12,10Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 000000000000..7897fa3a40a9 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,55 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,21H21a2,2,0,0,0,2-2V6a2,2,0,0,0-2-2H3A2,2,0,0,0,1,6V19A2,2,0,0,0,3,21ZM2.5,6A0.51 0.51 ,0,0,1,3,5.5H21a0.51 0.51 ,0,0,1,0.5 0.5 V19a0.51 0.51 ,0,0,1-0.5 0.5 H3a0.51 0.51 ,0,0,1-0.5-0.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 8 L 10.5 8 Q 11 8 11 8.5 L 11 9.5 Q 11 10 10.5 10 L 9.5 10 Q 9 10 9 9.5 L 9 8.5 Q 9 8 9.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 8 L 6.5 8 Q 7 8 7 8.5 L 7 9.5 Q 7 10 6.5 10 L 5.5 10 Q 5 10 5 9.5 L 5 8.5 Q 5 8 5.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M8.75,17.5h6.5a0.75 0.75 ,0,0,0,0-1.5H8.75a0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 8 L 14.5 8 Q 15 8 15 8.5 L 15 9.5 Q 15 10 14.5 10 L 13.5 10 Q 13 10 13 9.5 L 13 8.5 Q 13 8 13.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9.5 12 L 10.5 12 Q 11 12 11 12.5 L 11 13.5 Q 11 14 10.5 14 L 9.5 14 Q 9 14 9 13.5 L 9 12.5 Q 9 12 9.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 5.5 12 L 6.5 12 Q 7 12 7 12.5 L 7 13.5 Q 7 14 6.5 14 L 5.5 14 Q 5 14 5 13.5 L 5 12.5 Q 5 12 5.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 12 L 14.5 12 Q 15 12 15 12.5 L 15 13.5 Q 15 14 14.5 14 L 13.5 14 Q 13 14 13 13.5 L 13 12.5 Q 13 12 13.5 12 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 8 L 18.5 8 Q 19 8 19 8.5 L 19 9.5 Q 19 10 18.5 10 L 17.5 10 Q 17 10 17 9.5 L 17 8.5 Q 17 8 17.5 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 17.5 12 L 18.5 12 Q 19 12 19 12.5 L 19 13.5 Q 19 14 18.5 14 L 17.5 14 Q 17 14 17 13.5 L 17 12.5 Q 17 12 17.5 12 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..74311e783e99 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2.5a1.25,1.25,0,0,0-1.25,1.25v0.78A6,6,0,0,0,6,10.4V17H4.75a0.75 0.75 ,0,0,0,0,1.5h14.5a0.75 0.75 ,0,0,0,0-1.5H18V10.4a6,6,0,0,0-4.75-5.87V3.75A1.25,1.25,0,0,0,12,2.5Zm4.5,7.9V17h-9V10.4a4.5,4.5,0,1,1,9,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M5.85,3A9.49,9.49,0,0,0,2.5,10.25a0.75 0.75 ,0,0,0,1.5,0,8,8,0,0,1,2.82-6.1A0.75 0.75 ,0,1,0,5.85,3Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.15,3a0.75 0.75 ,0,1,0-1,1.14A8,8,0,0,1,20,10.25a0.75 0.75 ,0,0,0,1.5,0A9.49,9.49,0,0,0,18.15,3Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_silence.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_silence.xml new file mode 100644 index 000000000000..a93c45b2cc68 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_notifications_silence.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M14,20H10a2,2,0,0,0,4,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,5.9a4.5,4.5,0,0,1,4.5,4.5v3.92l1.5,1.5V10.4a6,6,0,0,0-4.75-5.87V3.75a1.25,1.25,0,0,0-2.5,0v0.78A5.92,5.92,0,0,0,8.06,5.88L9.14,7A4.45,4.45,0,0,1,12,5.9Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,22A0.75 0.75 ,0,0,0,21,21L3,3A0.75 0.75 ,0,0,0,2,3H2A0.75 0.75 ,0,0,0,2,4L6.35,8.41a6,6,0,0,0-0.35,2V17H4.75a0.75 0.75 ,0,0,0,0,1.5H16.44L20,22A0.75 0.75 ,0,0,0,21,22ZM7.5,17V10.4a3.84,3.84,0,0,1,0.08-0.76L14.94,17Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml new file mode 100644 index 000000000000..fe7ecfd9d615 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_auto_rotate.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,6.81a0.75 0.75 ,0,0,0-0.75 0.75 v2.83a0.74 0.74 ,0,0,0,0.75 0.75 H5.8a0.75 0.75 ,0,1,0,0-1.5h-1l5.6-5.59,7.07,7.06a0.75 0.75 ,0,0,0,1.06-1.06l-7.6-7.6a0.75 0.75 ,0,0,0-1.06,0L3.72,8.62V7.56A0.76 0.76 ,0,0,0,3,6.81Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,12.85H18.21a0.75 0.75 ,0,0,0,0,1.5h1L13.59,20,6.52,12.89a0.75 0.75 ,0,0,0-1.06,0,0.74 0.74 ,0,0,0,0,1.06l7.6,7.6a0.75 0.75 ,0,0,0,1.06,0l6.17-6.17v1.06a0.75 0.75 ,0,1,0,1.5,0V13.6A0.76 0.76 ,0,0,0,21,12.85Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml new file mode 100644 index 000000000000..70282d4a2c13 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M4.47,17.78a0.75 0.75 ,0,0,0,1.06,0l4-4V21.5a0.74 0.74 ,0,0,0,0.46 0.69 0.75 0.75 ,0,0,0,0.29 0.06 0.77 0.77 ,0,0,0,0.53-0.22l4.75-4.75a0.75 0.75 ,0,0,0,0-1.06L11.31,12l4.22-4.22a0.75 0.75 ,0,0,0,0-1.06L10.78,2A0.75 0.75 ,0,0,0,10,1.81a0.74 0.74 ,0,0,0-0.46 0.69 v7.69l-4-4A0.75 0.75 ,0,0,0,4.47,7.28L9.19,12,4.47,16.72A0.75 0.75 ,0,0,0,4.47,17.78ZM11,4.31l2.94,2.94L11,10.19Zm0,9.5,2.94,2.94L11,19.69Z" /> + <path + android:fillColor="#000000" + android:pathData="M 16 11 C 16.5522847498 11 17 11.4477152502 17 12 C 17 12.5522847498 16.5522847498 13 16 13 C 15.4477152502 13 15 12.5522847498 15 12 C 15 11.4477152502 15.4477152502 11 16 11 Z" /> + <path + android:fillColor="#000000" + android:pathData="M18.55,16.37a0.74 0.74 ,0,0,0,0.45 0.15 0.77 0.77 ,0,0,0,0.6-0.3,7,7,0,0,0,0-8.42 0.76 0.76,0,0,0-1.05-0.15 0.75 0.75,0,0,0-0.15,1,5.53,5.53,0,0,1,0,6.62A0.75 0.75 ,0,0,0,18.55,16.37Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml new file mode 100644 index 000000000000..dfef14b226c2 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_on.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M17.53,6.72,12.78,2a0.75 0.75 ,0,0,0-1.28 0.53 v7.69l-4-4A0.75 0.75 ,0,0,0,6.47,7.28L11.19,12,6.47,16.72a0.75 0.75 ,0,0,0,1.06,1.06l4-4V21.5a0.74 0.74 ,0,0,0,0.46 0.69 0.74 0.74 ,0,0,0,0.82-0.16l4.75-4.75a0.75 0.75 ,0,0,0,0-1.06L13.31,12l4.22-4.22A0.75 0.75 ,0,0,0,17.53,6.72Zm-1.59,10L13,19.69V13.81ZM13,10.19V4.31l2.94,2.94Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml new file mode 100644 index 000000000000..9bf12749cca6 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_brightness_auto_on.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12.75,2.25V0.75a0.75 0.75 ,0,0,0-1.5,0v1.5a0.75 0.75 ,0,0,0,1.5,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M4.57,5.64a0.79 0.79 ,0,0,0,1.07,0,0.77 0.77 ,0,0,0,0-1.07L4.58,3.51A0.76 0.76 ,0,0,0,3.51,4.58Z" /> + <path + android:fillColor="#000000" + android:pathData="M0.75,12.75h1.5a0.75 0.75 ,0,0,0,0-1.5H0.75a0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.51,20.49a0.76 0.76 ,0,0,0,1.07,0l1.06-1.06a0.76 0.76 ,0,1,0-1.07-1.07L3.51,19.42A0.77 0.77 ,0,0,0,3.51,20.49Z" /> + <path + android:fillColor="#000000" + android:pathData="M11.25,21.75v1.5a0.75 0.75 ,0,0,0,1.5,0v-1.5a0.75 0.75 ,0,0,0-1.5,0Z" /> + <path + android:fillColor="#000000" + android:pathData="M20,20.71a0.79 0.79 ,0,0,0,0.53-0.22 0.77 0.77,0,0,0,0-1.07l-1.06-1.06a0.76 0.76 ,0,0,0-1.07,1.07l1.06,1.06A0.79 0.79 ,0,0,0,20,20.71Z" /> + <path + android:fillColor="#000000" + android:pathData="M23.25,11.25h-1.5a0.75 0.75 ,0,0,0,0,1.5h1.5a0.75 0.75 ,0,0,0,0-1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M19.42,3.51,18.36,4.57a0.77 0.77 ,0,0,0,0,1.07 0.79 0.79,0,0,0,1.07,0l1.06-1.06a0.76 0.76 ,0,0,0-1.07-1.07Z" /> + <path + android:fillColor="#000000" + android:pathData="M14.85,17H17L13.11,7H10.87L7,17H9.15L10,14.61h4Zm-4.22-4.12,1.31-3.71h0.11l1.29,3.71Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cancel.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cancel.xml new file mode 100644 index 000000000000..cc819a0d71c8 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cancel.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm0,18.5A8.5,8.5,0,1,1,20.5,12,8.51,8.51,0,0,1,12,20.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.6,7.4a0.75 0.75 ,0,0,0-1.06,0L12,10.94,8.46,7.4A0.75 0.75 ,0,0,0,7.4,8.46L10.94,12,7.4,15.54a0.75 0.75 ,0,0,0,0,1.06 0.79 0.79,0,0,0,0.53 0.22 0.75 0.75 ,0,0,0,0.53-0.22L12,13.06l3.54,3.54a0.75 0.75 ,0,0,0,0.53 0.22 0.79 0.79 ,0,0,0,0.53-0.22 0.75 0.75,0,0,0,0-1.06L13.06,12,16.6,8.46A0.75 0.75 ,0,0,0,16.6,7.4Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cast_on.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cast_on.xml new file mode 100644 index 000000000000..34ca21a76edc --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_cast_on.xml @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M22,18V5.5A1.5,1.5,0,0,0,20.5,4h-17A1.5,1.5,0,0,0,2,5.53V8.46a0.75 0.75 ,0,0,0,1.5,0v-3l17,0V18H13.15a0.75 0.75 ,0,1,0,0,1.5h7.38A1.5,1.5,0,0,0,22,18Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.25,19.5a1.25,1.25,0,0,0,0-2.5h0a1.25,1.25,0,0,0,0,2.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M2,11.25a0.76 0.76 ,0,0,0,0.75 0.75 A6.75,6.75,0,0,1,9.5,18.75a0.75 0.75 ,0,0,0,1.5,0A8.25,8.25,0,0,0,2.75,10.5 0.76 0.76,0,0,0,2,11.25Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.75,15.25a3.5,3.5,0,0,1,3.5,3.5 0.75 0.75,0,0,0,1.5,0,5,5,0,0,0-5-5,0.75 0.75 ,0,0,0,0,1.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M13.25,15a0.75 0.75 ,0,0,0,0,1.5h5a0.76 0.76 ,0,0,0,0.75-0.75v-8A0.76 0.76 ,0,0,0,18.25,7H5.75A0.76 0.76 ,0,0,0,5,7.75V8.5a0.75 0.75 ,0,0,0,1.5,0h11V15Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_no_sim.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_no_sim.xml new file mode 100644 index 000000000000..7020463cb3a9 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_no_sim.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M10.62,4.5H17a0.5 0.5 ,0,0,1,0.5 0.5 V15.32l1.5,1.5V5a2,2,0,0,0-2-2H10L7.59,5.41,8.65,6.47Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,21,3,3A0.75 0.75 ,0,0,0,2,3H2A0.75 0.75 ,0,0,0,2,4l3.5,3.5L5,8V19a2,2,0,0,0,2,2H17a2,2,0,0,0,1.38-0.56L20,22A0.75 0.75 ,0,0,0,21,22h0A0.75 0.75 ,0,0,0,21,21ZM17,19.5H7a0.5 0.5 ,0,0,1-0.5-0.5V8.62l0,0L17.32,19.38A0.53 0.53 ,0,0,1,17,19.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_vpn.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_vpn.xml new file mode 100644 index 000000000000..65c56f831462 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_vpn.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M21,9.5H11.37a5.25,5.25,0,1,0,0,5H14.5v1A1.5,1.5,0,0,0,16,17h2.5A1.5,1.5,0,0,0,20,15.5v-1h1A1.5,1.5,0,0,0,22.5,13V11A1.5,1.5,0,0,0,21,9.5ZM21,13H18.5v2.5H16V13H10.4l-0.19 0.46 A3.75,3.75,0,1,1,6.09,8.31a3.57,3.57,0,0,1,0.65-0.06,3.76,3.76,0,0,1,3.47,2.29l0.19 0.46 H21Z" /> + <path + android:fillColor="#000000" + android:pathData="M6.75,9.75A2.25,2.25,0,1,0,9,12,2.25,2.25,0,0,0,6.75,9.75Zm0,3A0.75 0.75 ,0,1,1,7.5,12,0.76 0.76 ,0,0,1,6.75,12.75Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml new file mode 100644 index 000000000000..ff02c59c1fe7 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_0.xml @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.7,8.3a0.83 0.83 ,0,0,0,1.05,0l0,0a0.73 0.73 ,0,0,0,0-1A14.51,14.51,0,0,0,12,2.8,14.77,14.77,0,0,0,1.25,7.25a0.76 0.76 ,0,0,0,0,1.05l0,0a0.72 0.72 ,0,0,0,1,0,13.34,13.34,0,0,1,9.7-4A13.16,13.16,0,0,1,21.7,8.3Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M19,11.8a0.74 0.74 ,0,0,0,1.05-1.05,11.43,11.43,0,0,0-8-3.5,11.36,11.36,0,0,0-8,3.5 0.74 0.74,0,0,0,1,1.05,9.93,9.93,0,0,1,7-3A10.15,10.15,0,0,1,19,11.8Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.25,13.75a0.76 0.76 ,0,0,0,0,1l0,0a0.73 0.73 ,0,0,0,1,0,5.28,5.28,0,0,1,6.2-0.9,3.87,3.87,0,0,1,1.57-0.78A6.73,6.73,0,0,0,7.25,13.75Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.92,16.08a0.74 0.74 ,0,0,0-1.06,0L19,17.94l-1.86-1.86a0.75 0.75 ,0,0,0-1.06,1.06L17.94,19l-1.86,1.86a0.74 0.74 ,0,0,0,0,1.06 0.73 0.73,0,0,0,0.53 0.22 0.74 0.74 ,0,0,0,0.53-0.22L19,20.06l1.86,1.86a0.74 0.74 ,0,0,0,0.53 0.22 0.73 0.73 ,0,0,0,0.53-0.22 0.74 0.74,0,0,0,0-1.06L20.06,19l1.86-1.86A0.74 0.74 ,0,0,0,21.92,16.08Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M13.5,18.5a1.5,1.5,0,0,0-0.5-1.11,1.5,1.5,0,1,0,0,2.22A1.5,1.5,0,0,0,13.5,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml new file mode 100644 index 000000000000..6a645a38c807 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_1.xml @@ -0,0 +1,49 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.23,13.71a0.75 0.75 ,0,0,0,1.06,1.06,5.23,5.23,0,0,1,6.22-0.88,4,4,0,0,1,1.57-0.78A6.75,6.75,0,0,0,7.23,13.71Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M19,11.77a0.75 0.75 ,0,0,0,1.06,0,0.77 0.77 ,0,0,0,0-1.07h0a11.59,11.59,0,0,0-8-3.5,11.63,11.63,0,0,0-8,3.5 0.75 0.75,0,0,0-0.1,1.06 0.74 0.74,0,0,0,1,0.1A0.38 0.38 ,0,0,0,5,11.77a10.12,10.12,0,0,1,7-3A10.1,10.1,0,0,1,19,11.77Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.72,8.27a0.75 0.75 ,0,0,0,1.07-1A14.76,14.76,0,0,0,12,2.75,14.76,14.76,0,0,0,1.22,7.2a0.76 0.76 ,0,0,0,0.05,1.06 0.76 0.76,0,0,0,1,0,13.25,13.25,0,0,1,9.7-4A13.27,13.27,0,0,1,21.72,8.27Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.92,16.08a0.74 0.74 ,0,0,0-1.06,0L19,17.94l-1.86-1.86a0.75 0.75 ,0,0,0-1.06,1.06L17.94,19l-1.86,1.86a0.74 0.74 ,0,0,0,0,1.06 0.73 0.73,0,0,0,0.53 0.22 0.74 0.74 ,0,0,0,0.53-0.22L19,20.06l1.86,1.86a0.74 0.74 ,0,0,0,0.53 0.22 0.73 0.73 ,0,0,0,0.53-0.22 0.74 0.74,0,0,0,0-1.06L20.06,19l1.86-1.86A0.74 0.74 ,0,0,0,21.92,16.08Z" /> + <path + android:fillColor="#000000" + android:pathData="M13.5,18.5a1.5,1.5,0,0,0-0.5-1.11,1.5,1.5,0,1,0,0,2.22A1.5,1.5,0,0,0,13.5,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml new file mode 100644 index 000000000000..b2207f9f7976 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_2.xml @@ -0,0 +1,46 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.23,13.71a0.75 0.75 ,0,0,0,1.06,1.06,5.23,5.23,0,0,1,6.22-0.88,4,4,0,0,1,1.57-0.78A6.75,6.75,0,0,0,7.23,13.71Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.72,8.27a0.75 0.75 ,0,0,0,1.07-1A14.76,14.76,0,0,0,12,2.75,14.76,14.76,0,0,0,1.22,7.2a0.76 0.76 ,0,0,0,0.05,1.06 0.76 0.76,0,0,0,1,0,13.25,13.25,0,0,1,9.7-4A13.27,13.27,0,0,1,21.72,8.27Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M19,11.77a0.75 0.75 ,0,0,0,1.06,0,0.77 0.77 ,0,0,0,0-1.07h0a11.59,11.59,0,0,0-8-3.5,11.63,11.63,0,0,0-8,3.5 0.75 0.75,0,0,0-0.1,1.06 0.74 0.74,0,0,0,1,0.1A0.38 0.38 ,0,0,0,5,11.77a10.12,10.12,0,0,1,7-3A10.1,10.1,0,0,1,19,11.77Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.92,16.08a0.74 0.74 ,0,0,0-1.06,0L19,17.94l-1.86-1.86a0.75 0.75 ,0,0,0-1.06,1.06L17.94,19l-1.86,1.86a0.74 0.74 ,0,0,0,0,1.06 0.73 0.73,0,0,0,0.53 0.22 0.74 0.74 ,0,0,0,0.53-0.22L19,20.06l1.86,1.86a0.74 0.74 ,0,0,0,0.53 0.22 0.73 0.73 ,0,0,0,0.53-0.22 0.74 0.74,0,0,0,0-1.06L20.06,19l1.86-1.86A0.74 0.74 ,0,0,0,21.92,16.08Z" /> + <path + android:fillColor="#000000" + android:pathData="M13.5,18.5a1.5,1.5,0,0,0-0.5-1.11,1.5,1.5,0,1,0,0,2.22A1.5,1.5,0,0,0,13.5,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml new file mode 100644 index 000000000000..6dd92a031963 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_3.xml @@ -0,0 +1,43 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.23,13.71a0.75 0.75 ,0,0,0,1.06,1.06,5.23,5.23,0,0,1,6.22-0.88,4,4,0,0,1,1.57-0.78A6.75,6.75,0,0,0,7.23,13.71Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.72,8.27a0.75 0.75 ,0,0,0,1.07-1A14.76,14.76,0,0,0,12,2.75,14.76,14.76,0,0,0,1.22,7.2a0.76 0.76 ,0,0,0,0.05,1.06 0.76 0.76,0,0,0,1,0,13.25,13.25,0,0,1,9.7-4A13.27,13.27,0,0,1,21.72,8.27Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,11.77a0.75 0.75 ,0,0,0,1.06,0,0.77 0.77 ,0,0,0,0-1.07h0a11.59,11.59,0,0,0-8-3.5,11.63,11.63,0,0,0-8,3.5 0.75 0.75,0,0,0-0.1,1.06 0.74 0.74,0,0,0,1,0.1A0.38 0.38 ,0,0,0,5,11.77a10.12,10.12,0,0,1,7-3A10.1,10.1,0,0,1,19,11.77Z" /> + <path + android:fillColor="#000000" + android:pathData="M21.92,16.08a0.74 0.74 ,0,0,0-1.06,0L19,17.94l-1.86-1.86a0.75 0.75 ,0,0,0-1.06,1.06L17.94,19l-1.86,1.86a0.74 0.74 ,0,0,0,0,1.06 0.73 0.73,0,0,0,0.53 0.22 0.74 0.74 ,0,0,0,0.53-0.22L19,20.06l1.86,1.86a0.74 0.74 ,0,0,0,0.53 0.22 0.73 0.73 ,0,0,0,0.53-0.22 0.74 0.74,0,0,0,0-1.06L20.06,19l1.86-1.86A0.74 0.74 ,0,0,0,21.92,16.08Z" /> + <path + android:fillColor="#000000" + android:pathData="M13.5,18.5a1.5,1.5,0,0,0-0.5-1.11,1.5,1.5,0,1,0,0,2.22A1.5,1.5,0,0,0,13.5,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml new file mode 100644 index 000000000000..13b00699346c --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_4.xml @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M7.23,13.71a0.75 0.75 ,0,0,0,1.06,1.06,5.23,5.23,0,0,1,6.22-0.88,4,4,0,0,1,1.57-0.78A6.75,6.75,0,0,0,7.23,13.71Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.3,8.25a13.25,13.25,0,0,1,9.7-4,13.27,13.27,0,0,1,9.72,4,0.75 0.75 ,0,0,0,1.07-1A14.76,14.76,0,0,0,12,2.75,14.76,14.76,0,0,0,1.22,7.2a0.76 0.76 ,0,0,0,0.05,1.06A0.76 0.76 ,0,0,0,2.3,8.25Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,11.77a0.75 0.75 ,0,0,0,1.06,0,0.77 0.77 ,0,0,0,0-1.07h0a11.59,11.59,0,0,0-8-3.5,11.63,11.63,0,0,0-8,3.5 0.75 0.75,0,0,0-0.1,1.06 0.74 0.74,0,0,0,1,0.1A0.38 0.38 ,0,0,0,5,11.77a10.12,10.12,0,0,1,7-3A10.1,10.1,0,0,1,19,11.77Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.08,16.08a0.74 0.74 ,0,0,0,0,1.06L17.94,19l-1.86,1.86a0.74 0.74 ,0,0,0,0,1.06 0.73 0.73,0,0,0,0.53 0.22 0.74 0.74 ,0,0,0,0.53-0.22L19,20.06l1.86,1.86a0.74 0.74 ,0,0,0,0.53 0.22 0.73 0.73 ,0,0,0,0.53-0.22 0.74 0.74,0,0,0,0-1.06L20.06,19l1.86-1.86a0.75 0.75 ,0,0,0-1.06-1.06L19,17.94l-1.86-1.86A0.74 0.74 ,0,0,0,16.08,16.08Z" /> + <path + android:fillColor="#000000" + android:pathData="M13.5,18.5a1.5,1.5,0,0,0-0.5-1.11,1.5,1.5,0,1,0,0,2.22A1.5,1.5,0,0,0,13.5,18.5Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml new file mode 100644 index 000000000000..c6607a77f146 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_wifi_disconnected.xml @@ -0,0 +1,55 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M21.7,8.3a0.83 0.83 ,0,0,0,1.05,0l0,0a0.73 0.73 ,0,0,0,0-1A14.51,14.51,0,0,0,12,2.8,14.77,14.77,0,0,0,1.25,7.25a0.76 0.76 ,0,0,0,0,1.05l0,0a0.72 0.72 ,0,0,0,1,0,13.34,13.34,0,0,1,9.7-4A13.16,13.16,0,0,1,21.7,8.3Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M12.05,7.25a11.36,11.36,0,0,0-8,3.5 0.74 0.74,0,0,0,1,1.05,9.93,9.93,0,0,1,7-3,9.94,9.94,0,0,1,3.25 0.64 ,5.58,5.58,0,0,1,1.56-1A11.38,11.38,0,0,0,12.05,7.25Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M7.25,13.75a0.76 0.76 ,0,0,0,0,1l0,0a0.73 0.73 ,0,0,0,1,0,5.26,5.26,0,0,1,5.2-1.3A5.48,5.48,0,0,1,13.72,12,6.73,6.73,0,0,0,7.25,13.75Z" /> + <path + android:fillColor="#000000" + android:fillAlpha="0.3" + android:strokeAlpha="0.3" + android:strokeWidth="1" + android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.42,11.09a3.66,3.66,0,0,0-1,1.76 0.73 0.73,0,0,0,0.56 0.9 0.74 0.74 ,0,0,0,0.9-0.56,2.23,2.23,0,0,1,0.56-1,2.14,2.14,0,0,1,3,0,2,2,0,0,1,0.57,1.57,1.61,1.61,0,0,1-0.72,1.2,3.13,3.13,0,0,1-0.34 0.21 ,3.07,3.07,0,0,0-1.76,2.34 0.75 0.75,0,0,0,0.62 0.86 H19a0.75 0.75 ,0,0,0,0.74-0.62,1.62,1.62,0,0,1,1-1.29c0.15-0.09 0.3 -0.17 0.44 -0.27a3.14,3.14,0,0,0,1.37-2.29,3.46,3.46,0,0,0-1-2.77A3.68,3.68,0,0,0,16.42,11.09Z" /> + <path + android:fillColor="#000000" + android:pathData="M 19 20 C 19.5522847498 20 20 20.4477152502 20 21 C 20 21.5522847498 19.5522847498 22 19 22 C 18.4477152502 22 18 21.5522847498 18 21 C 18 20.4477152502 18.4477152502 20 19 20 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_screenshot_delete.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_screenshot_delete.xml new file mode 100644 index 000000000000..9b424902d1e2 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_screenshot_delete.xml @@ -0,0 +1,34 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M8,21h8a3,3,0,0,0,3-3V5.5h1A0.75 0.75 ,0,0,0,20,4H15a1,1,0,0,0-1-1H10A1,1,0,0,0,9,4H4A0.75 0.75 ,0,0,0,4,5.5H5V18A3,3,0,0,0,8,21ZM9,5.5h8.5V18A1.5,1.5,0,0,1,16,19.5H8A1.5,1.5,0,0,1,6.5,18V5.5Z" /> + <path + android:fillColor="#000000" + android:pathData="M 13.5 8 H 15 V 17 H 13.5 V 8 Z" /> + <path + android:fillColor="#000000" + android:pathData="M 9 8 H 10.5 V 17 H 9 V 8 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_settings_16dp.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_settings_16dp.xml new file mode 100644 index 000000000000..4237323ca2f7 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_settings_16dp.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.2,15.53,4,18.7a1.46,1.46,0,0,0,1.28 0.75 ,1.61,1.61,0,0,0,0.53-0.1l1.8-0.72a9,9,0,0,0,0.79 0.46 L8.7,21a1.45,1.45,0,0,0,1.45,1.27h3.7A1.47,1.47,0,0,0,15.31,21l0.27-1.91c0.26-0.14 0.52 -0.29 0.78 -0.46l1.8 0.72 a1.47,1.47,0,0,0,0.54 0.1 A1.43,1.43,0,0,0,20,18.75l1.86-3.22a1.47,1.47,0,0,0-0.37-1.86l-1.52-1.19c0-0.15,0-0.3,0-0.46s0-0.31,0-0.46l1.52-1.19a1.47,1.47,0,0,0,0.36-1.88L20,5.31a1.46,1.46,0,0,0-1.29-0.75,1.71,1.71,0,0,0-0.53 0.1 l-1.8 0.72 a9,9,0,0,0-0.79-0.46L15.29,3a1.45,1.45,0,0,0-1.45-1.27h-3.7A1.46,1.46,0,0,0,8.7,3L8.43,4.92c-0.26 0.14 -0.52 0.29 -0.78 0.46 L5.84,4.65a1.47,1.47,0,0,0-0.54-0.1,1.42,1.42,0,0,0-1.25 0.73 L2.2,8.47a1.44,1.44,0,0,0,0.37,1.88l1.52,1.19c0,0.15,0,0.31,0,0.46s0,0.31,0,0.46L2.56,13.65A1.48,1.48,0,0,0,2.2,15.53ZM5,13.64l0.63-0.49,0-0.79c0-0.12,0-0.23,0-0.36s0-0.24,0-0.36l0-0.79L5,10.36,3.52,9.19,5.33,6.06l1.76 0.71 0.73 0.29 0.65-0.42a6.59,6.59,0,0,1,0.67-0.4l0.67-0.36 0.11 -0.75 0.26 -1.87h3.63l0.27,1.87 0.1 0.77 0.69 0.35a6,6,0,0,1,0.66 0.39 l0.65 0.42 0.73-0.29,1.76-0.71L20.5,9.21,19,10.38l-0.63 0.49 0.05 0.79 c0,0.12,0,0.23,0,0.36s0,0.24,0,0.36l-0.05 0.79 0.63 0.49 ,1.48,1.17L18.68,18l-1.76-0.7L16.19,17l-0.65 0.42 a6.59,6.59,0,0,1-0.67 0.4 l-0.67 0.36 -0.11 0.75 -0.26,1.84H10.18l-0.27-1.87-0.1-0.77-0.69-0.35a6,6,0,0,1-0.66-0.39L7.81,17l-0.73 0.29 L5.33,18,3.52,14.8Z" /> + <path + android:fillColor="#000000" + android:pathData="M12,16a4,4,0,1,0-4-4A4,4,0,0,0,12,16Zm0-6.5A2.5,2.5,0,1,1,9.5,12,2.5,2.5,0,0,1,12,9.5Z" /> +</vector> diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_airplane.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_airplane.xml new file mode 100644 index 000000000000..2d36a3986107 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_airplane.xml @@ -0,0 +1,28 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M2.52,16.17a1.25,1.25,0,0,0,1.11 0.19 L9.5,14.52v3.87L8,19.52a1.26,1.26,0,0,0-0.5,1v0.75a1.25,1.25,0,0,0,1.25,1.25h6.5a1.25,1.25,0,0,0,1.25-1.25v-0.75a1.26,1.26,0,0,0-0.5-1l-1.5-1.13V14.52l5.88,1.84a1.23,1.23,0,0,0,1.11-0.19,1.25,1.25,0,0,0,0.51-1V13.33a1.74,1.74,0,0,0-0.89-1.52L14.5,8.06V3.75a2.5,2.5,0,0,0-5,0V8.06L2.89,11.8A1.78,1.78,0,0,0,2,13.33v1.83A1.25,1.25,0,0,0,2.52,16.17Zm1.11-3.06L11,8.94V3.75a1,1,0,0,1,2,0V8.94l7.37,4.17a0.26 0.26 ,0,0,1,0.13 0.22 v1.49L13,12.48v6.66l2,1.5V21H9v-0.38l2-1.5V12.48L3.51,14.82V13.33A0.25 0.25 ,0,0,1,3.63,13.11Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_flashlight.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_flashlight.xml new file mode 100644 index 000000000000..3bde46fcb948 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_signal_flashlight.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M9,22h6a0.76 0.76 ,0,0,0,0.75-0.75V11.46l1.89-3.07A0.77 0.77 ,0,0,0,17.75,8V2.75A0.76 0.76 ,0,0,0,17,2H7a0.76 0.76 ,0,0,0-0.75 0.75 v5a0.77 0.77 ,0,0,0,0.11 0.39 l1.89,3.07v10A0.76 0.76 ,0,0,0,9,22ZM16.25,3.5V5H7.75V3.5Zm-8.5,4v-1h8.5V7.79l-1.89,3.07a0.77 0.77 ,0,0,0-0.11 0.39 V20.5H9.75V11a0.77 0.77 ,0,0,0-0.11-0.39Z" /> + <path + android:fillColor="#000000" + android:pathData="M 12 12.75 C 12.6903559373 12.75 13.25 13.3096440627 13.25 14 C 13.25 14.6903559373 12.6903559373 15.25 12 15.25 C 11.3096440627 15.25 10.75 14.6903559373 10.75 14 C 10.75 13.3096440627 11.3096440627 12.75 12 12.75 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_swap_vert.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_swap_vert.xml new file mode 100644 index 000000000000..297d8865d184 --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_swap_vert.xml @@ -0,0 +1,31 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M6,8,8.25,5.81V13a0.75 0.75 ,0,1,0,1.5,0V5.81L12,8A0.75 0.75 ,0,0,0,13,8,0.75 0.75 ,0,0,0,13,7l-3.5-3.5a0.75 0.75 ,0,0,0-1.06,0L5,7A0.75 0.75 ,0,1,0,6,8Z" /> + <path + android:fillColor="#000000" + android:pathData="M19,16A0.75 0.75 ,0,0,0,18,16l-2.22,2.22V11a0.75 0.75 ,0,0,0-1.5,0v7.21L12,16A0.75 0.75 ,0,1,0,11,17l3.5,3.5a0.75 0.75 ,0,0,0,1.06,0L19,17A0.75 0.75 ,0,0,0,19,16Z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm.xml new file mode 100644 index 000000000000..167d15f5181b --- /dev/null +++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm.xml @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright (c) 2019, 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. + */ +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" /> + <path + android:fillColor="#000000" + android:pathData="M14.43,16.52a0.76 0.76 ,0,0,0,0.54 0.23 0.79 0.79 ,0,0,0,0.53-0.22 0.75 0.75,0,0,0,0-1.06l-2.75-2.78V8a0.75 0.75 ,0,0,0-1.5,0v5a0.75 0.75 ,0,0,0,0.22 0.53 Z" /> + <path + android:fillColor="#000000" + android:pathData="M16.4,2.55a0.75 0.75 ,0,0,0,0.15,1.05l4,3a0.78 0.78 ,0,0,0,0.45 0.15 0.73 0.73 ,0,0,0,0.6-0.3 0.75 0.75,0,0,0-0.15-1l-4-3A0.75 0.75 ,0,0,0,16.4,2.55Z" /> + <path + android:fillColor="#000000" + android:pathData="M3,6.75a0.78 0.78 ,0,0,0,0.45-0.15l4-3a0.75 0.75 ,0,1,0-0.9-1.2l-4,3a0.75 0.75 ,0,0,0-0.15,1A0.73 0.73 ,0,0,0,3,6.75Z" /> + <path + android:fillColor="#000000" + android:pathData="M3.08,13A9,9,0,0,0,12,22h0a8.81,8.81,0,0,0,6.3-2.63A9,9,0,0,0,20.92,13v0A8.92,8.92,0,1,0,3.08,13ZM12,5.5A7.47,7.47,0,0,1,19.42,13h0.75l-0.75,0a7.47,7.47,0,0,1-2.18,5.29A7.33,7.33,0,0,1,12,20.5h0a7.5,7.5,0,0,1,0-15Z" /> +</vector>
\ No newline at end of file diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index 76bb24d81e21..eb8710d6759d 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -6936,6 +6936,19 @@ message MetricsEvent { // OS: Q ACTION_SET_NEW_PARENT_PROFILE_PASSWORD = 1646; + // Tagged data for SMART_REPLY_VISIBLE and SMART_REPLY_ACTION. + // Whether the smart reply was / is to be sent via direct reply because + // getEditChoicesBeforeSending was enabled. + // OS: Q + NOTIFICATION_SMART_REPLY_EDIT_BEFORE_SENDING = 1647; + + // Tagged data for SMART_REPLY_ACTION. + // Whether the smart reply was modified by the user via the direct reply field (implies that + // getEditChoicesBeforeSending was enabled). + // actions/replies. + // OS: Q + NOTIFICATION_SMART_REPLY_MODIFIED_BEFORE_SENDING = 1648; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java index 7ee304780530..593bb2c41587 100644 --- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java +++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java @@ -20,6 +20,7 @@ import static com.android.server.backup.BackupManagerService.MORE_DEBUG; import static com.android.server.backup.BackupManagerService.TAG; import static com.android.server.backup.UserBackupManagerService.PACKAGE_MANAGER_SENTINEL; import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE; +import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.annotation.Nullable; import android.app.AppGlobals; @@ -40,11 +41,18 @@ import com.android.internal.backup.IBackupTransport; import com.android.internal.util.ArrayUtils; import com.android.server.backup.transport.TransportClient; +import com.google.android.collect.Sets; + +import java.util.Set; + /** * Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ public class AppBackupUtils { private static final boolean DEBUG = false; + // Whitelist of system packages that are eligible for backup in non-system users. + private static final Set<String> systemPackagesWhitelistedForAllUsers = + Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME); /** * Returns whether app is eligible for backup. @@ -72,9 +80,9 @@ public class AppBackupUtils { // 2. they run as a system-level uid if (UserHandle.isCore(app.uid)) { - // and the backup is happening for non-system user - if (userId != UserHandle.USER_SYSTEM && !app.packageName.equals( - PACKAGE_MANAGER_SENTINEL)) { + // and the backup is happening for non-system user on a non-whitelisted package. + if (userId != UserHandle.USER_SYSTEM + && !systemPackagesWhitelistedForAllUsers.contains(app.packageName)) { return false; } diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index c8a27f165a99..7102b82d5e18 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -416,36 +416,5 @@ final class ContentCapturePerUserService // TODO(b/122595322): implement // TODO(b/119613670): log metrics } - - @Override - public void setActivityContentCaptureEnabled(ComponentName activity, boolean enabled) { - if (mMaster.verbose) { - Log.v(TAG, "setActivityContentCaptureEnabled(activity=" + activity + ", enabled=" - + enabled + ")"); - } - // TODO(b/122595322): implement - // TODO(b/119613670): log metrics - } - - @Override - public void setPackageContentCaptureEnabled(String packageName, boolean enabled) { - if (mMaster.verbose) { - Log.v(TAG, - "setPackageContentCaptureEnabled(packageName=" + packageName + ", enabled=" - + enabled + ")"); - } - // TODO(b/122595322): implement - // TODO(b/119613670): log metrics - } - - @Override - public void getContentCaptureDisabledActivities(IResultReceiver receiver) { - // TODO(b/122595322): implement - } - - @Override - public void getContentCaptureDisabledPackages(IResultReceiver receiver) { - // TODO(b/122595322): implement - } } } diff --git a/services/core/Android.bp b/services/core/Android.bp index f9de55466aeb..259aa50cdd2c 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -19,7 +19,6 @@ java_library_static { ":storaged_aidl", ":vold_aidl", ":gsiservice_aidl", - ":mediaupdateservice_aidl", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", ], diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index 8b7f321eb087..eafa0e2a6786 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -61,11 +61,11 @@ public class BinderCallsStatsService extends Binder { mAppIdWhitelist = new ArraySet<>(); } - public int resolveWorkSourceUid() { + public int resolveWorkSourceUid(int untrustedWorkSourceUid) { final int callingUid = getCallingUid(); final int appId = UserHandle.getAppId(callingUid); if (mAppIdWhitelist.contains(appId)) { - final int workSource = getCallingWorkSourceUid(); + final int workSource = untrustedWorkSourceUid; final boolean isWorkSourceSet = workSource != Binder.UNSET_WORKSOURCE; return isWorkSourceSet ? workSource : callingUid; } @@ -88,10 +88,6 @@ public class BinderCallsStatsService extends Binder { return Binder.getCallingUid(); } - protected int getCallingWorkSourceUid() { - return Binder.getCallingWorkSourceUid(); - } - private ArraySet<Integer> createAppidWhitelist(Context context) { // Use a local copy instead of mAppIdWhitelist to prevent concurrent read access. final ArraySet<Integer> whitelist = new ArraySet<>(); @@ -186,7 +182,7 @@ public class BinderCallsStatsService extends Binder { } else { Binder.setObserver(null); Binder.setProxyTransactListener(null); - Binder.setWorkSourceProvider(Binder::getCallingUid); + Binder.setWorkSourceProvider((x) -> Binder.getCallingUid()); } mEnabled = enabled; mBinderCallsStats.reset(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f80754380843..1cb2c4a2f5ee 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -60,7 +60,6 @@ import android.content.res.Configuration; import android.database.ContentObserver; import android.net.ConnectionInfo; import android.net.ConnectivityManager; -import android.net.ConnectivityManager.PacketKeepalive; import android.net.IConnectivityManager; import android.net.IIpConnectivityMetrics; import android.net.INetd; @@ -94,6 +93,7 @@ import android.net.NetworkWatchlistManager; import android.net.PrivateDnsConfigParcel; import android.net.ProxyInfo; import android.net.RouteInfo; +import android.net.SocketKeepalive; import android.net.UidRange; import android.net.Uri; import android.net.VpnService; @@ -2488,8 +2488,8 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.networkMisc.acceptUnvalidated = msg.arg1 == 1; break; } - case NetworkAgent.EVENT_PACKET_KEEPALIVE: { - mKeepaliveTracker.handleEventPacketKeepalive(nai, msg); + case NetworkAgent.EVENT_SOCKET_KEEPALIVE: { + mKeepaliveTracker.handleEventSocketKeepalive(nai, msg); break; } } @@ -2863,8 +2863,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // sending all CALLBACK_LOST messages (for requests, not listens) at the end // of rematchAllNetworksAndRequests notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST); - mKeepaliveTracker.handleStopAllKeepalives(nai, - ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); + mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK); for (String iface : nai.linkProperties.getAllInterfaceNames()) { // Disable wakeup packet monitoring for each interface. wakeupModifyInterface(iface, nai.networkCapabilities, false); @@ -3456,12 +3455,12 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } // Sent by KeepaliveTracker to process an app request on the state machine thread. - case NetworkAgent.CMD_START_PACKET_KEEPALIVE: { + case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: { mKeepaliveTracker.handleStartKeepalive(msg); break; } // Sent by KeepaliveTracker to process an app request on the state machine thread. - case NetworkAgent.CMD_STOP_PACKET_KEEPALIVE: { + case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: { NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj); int slot = msg.arg1; int reason = msg.arg2; @@ -6363,7 +6362,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.startNattKeepalive( getNetworkAgentInfoForNetwork(network), intervalSeconds, messenger, binder, - srcAddr, srcPort, dstAddr, ConnectivityManager.PacketKeepalive.NATT_PORT); + srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT); } @Override @@ -6380,7 +6379,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void stopKeepalive(Network network, int slot) { mHandler.sendMessage(mHandler.obtainMessage( - NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, slot, PacketKeepalive.SUCCESS, network)); + NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network)); } @Override diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 33c6dd24012a..5278bbbb4af2 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -92,6 +92,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.server.location.AbstractLocationProvider; import com.android.server.location.ActivityRecognitionProxy; +import com.android.server.location.CallerIdentity; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GeofenceProxy; @@ -113,6 +114,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -223,10 +225,10 @@ public class LocationManagerService extends ILocationManager.Stub { private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>(); @GuardedBy("mLock") - private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>(); + private final ArrayMap<IBinder, CallerIdentity> mGnssMeasurementsListeners = new ArrayMap<>(); @GuardedBy("mLock") - private final ArrayMap<IBinder, Identity> + private final ArrayMap<IBinder, CallerIdentity> mGnssNavigationMessageListeners = new ArrayMap<>(); // current active user on the device - other users are denied location data @@ -456,7 +458,7 @@ public class LocationManagerService extends ILocationManager.Stub { ArrayList<Receiver> deadReceivers = null; for (Receiver receiver : mReceivers.values()) { - if (receiver.mIdentity.mPackageName.equals(packageName)) { + if (receiver.mCallerIdentity.mPackageName.equals(packageName)) { if (deadReceivers == null) { deadReceivers = new ArrayList<>(); } @@ -479,7 +481,7 @@ public class LocationManagerService extends ILocationManager.Stub { for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { String provider = entry.getKey(); for (UpdateRecord record : entry.getValue()) { - if (record.mReceiver.mIdentity.mUid == uid + if (record.mReceiver.mCallerIdentity.mUid == uid && record.mIsForegroundUid != foreground) { if (D) { Log.d(TAG, "request from uid " + uid + " is now " @@ -487,7 +489,7 @@ public class LocationManagerService extends ILocationManager.Stub { } record.updateForeground(foreground); - if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) { + if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) { affectedProviders.add(provider); } } @@ -497,8 +499,8 @@ public class LocationManagerService extends ILocationManager.Stub { applyRequirementsLocked(provider); } - for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) { - Identity callerIdentity = entry.getValue(); + for (Entry<IBinder, CallerIdentity> entry : mGnssMeasurementsListeners.entrySet()) { + CallerIdentity callerIdentity = entry.getValue(); if (callerIdentity.mUid == uid) { if (D) { Log.d(TAG, "gnss measurements listener from uid " + uid @@ -507,7 +509,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (foreground || isThrottlingExemptLocked(entry.getValue())) { mGnssMeasurementsProvider.addListener( IGnssMeasurementsListener.Stub.asInterface(entry.getKey()), - callerIdentity.mUid, callerIdentity.mPackageName); + callerIdentity); } else { mGnssMeasurementsProvider.removeListener( IGnssMeasurementsListener.Stub.asInterface(entry.getKey())); @@ -515,8 +517,8 @@ public class LocationManagerService extends ILocationManager.Stub { } } - for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) { - Identity callerIdentity = entry.getValue(); + for (Entry<IBinder, CallerIdentity> entry : mGnssNavigationMessageListeners.entrySet()) { + CallerIdentity callerIdentity = entry.getValue(); if (callerIdentity.mUid == uid) { if (D) { Log.d(TAG, "gnss navigation message listener from uid " @@ -526,7 +528,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (foreground || isThrottlingExemptLocked(entry.getValue())) { mGnssNavigationMessageProvider.addListener( IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()), - callerIdentity.mUid, callerIdentity.mPackageName); + callerIdentity); } else { mGnssNavigationMessageProvider.removeListener( IGnssNavigationMessageListener.Stub.asInterface(entry.getKey())); @@ -668,7 +670,7 @@ public class LocationManagerService extends ILocationManager.Stub { // create a passive location provider, which is always enabled LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER); addProviderLocked(passiveProviderManager); - mPassiveProvider = new PassiveProvider(passiveProviderManager); + mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager); passiveProviderManager.attachLocked(mPassiveProvider); if (GnssLocationProvider.isSupported()) { @@ -804,7 +806,7 @@ public class LocationManagerService extends ILocationManager.Stub { Integer.parseInt(fragments[9]) /* accuracy */); LocationProvider testProviderManager = new LocationProvider(name); addProviderLocked(testProviderManager); - new MockProvider(testProviderManager, properties); + new MockProvider(mContext, testProviderManager, properties); } } @@ -835,18 +837,6 @@ public class LocationManagerService extends ILocationManager.Stub { onProviderAllowedChangedLocked(false); } - private static final class Identity { - final int mUid; - final int mPid; - final String mPackageName; - - Identity(int uid, int pid, String packageName) { - mUid = uid; - mPid = pid; - mPackageName = packageName; - } - } - private class LocationProvider implements AbstractLocationProvider.LocationProviderManager { private final String mName; @@ -906,15 +896,12 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - @Nullable - public String getPackageLocked() { + public List<String> getPackagesLocked() { if (mProvider == null) { - return null; - } else if (mProvider instanceof LocationProviderProxy) { - // safe to not clear binder context since this doesn't call into the actual provider - return ((LocationProviderProxy) mProvider).getConnectedPackageName(); + return Collections.emptyList(); } else { - return mContext.getPackageName(); + // safe to not clear binder context since this doesn't call into the real provider + return mProvider.getProviderPackages(); } } @@ -1234,7 +1221,7 @@ public class LocationManagerService extends ILocationManager.Stub { */ private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000; - final Identity mIdentity; + final CallerIdentity mCallerIdentity; private final int mAllowedResolutionLevel; // resolution level allowed to receiver private final ILocationListener mListener; @@ -1262,7 +1249,7 @@ public class LocationManagerService extends ILocationManager.Stub { mKey = intent; } mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid); - mIdentity = new Identity(uid, pid, packageName); + mCallerIdentity = new CallerIdentity(uid, pid, packageName); if (workSource != null && workSource.isEmpty()) { workSource = null; } @@ -1274,7 +1261,7 @@ public class LocationManagerService extends ILocationManager.Stub { // construct/configure wakelock mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); if (workSource == null) { - workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName); + workSource = new WorkSource(mCallerIdentity.mUid, mCallerIdentity.mPackageName); } mWakeLock.setWorkSource(workSource); @@ -1377,14 +1364,14 @@ public class LocationManagerService extends ILocationManager.Stub { int op) { if (!currentlyMonitoring) { if (allowMonitoring) { - return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName) - == AppOpsManager.MODE_ALLOWED; + return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid, + mCallerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED; } } else { if (!allowMonitoring - || mAppOps.noteOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName) - != AppOpsManager.MODE_ALLOWED) { - mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName); + || mAppOps.checkOpNoThrow(op, mCallerIdentity.mUid, + mCallerIdentity.mPackageName) != AppOpsManager.MODE_ALLOWED) { + mAppOps.finishOp(op, mCallerIdentity.mUid, mCallerIdentity.mPackageName); return false; } } @@ -1722,7 +1709,6 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @Override public void flushGnssBatch(String packageName) { mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, @@ -1918,7 +1904,7 @@ public class LocationManagerService extends ILocationManager.Stub { int allowedResolutionLevel) { int op = resolutionLevelToOp(allowedResolutionLevel); if (op >= 0) { - if (mAppOps.noteOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { + if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { return false; } } @@ -2014,7 +2000,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (records != null) { for (UpdateRecord record : records) { if (!isCurrentProfileLocked( - UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { + UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } @@ -2073,24 +2059,28 @@ public class LocationManagerService extends ILocationManager.Stub { providerRequest.lowPowerMode = true; for (UpdateRecord record : records) { if (!isCurrentProfileLocked( - UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { + UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } if (!checkLocationAccess( - record.mReceiver.mIdentity.mPid, - record.mReceiver.mIdentity.mUid, - record.mReceiver.mIdentity.mPackageName, + record.mReceiver.mCallerIdentity.mPid, + record.mReceiver.mCallerIdentity.mUid, + record.mReceiver.mCallerIdentity.mPackageName, record.mReceiver.mAllowedResolutionLevel)) { continue; } - if (!provider.isUseableLocked() && !isSettingsExemptLocked(record)) { - continue; + if (!provider.isUseableLocked()) { + if (isSettingsExemptLocked(record)) { + providerRequest.forceLocation = true; + } else { + continue; + } } LocationRequest locationRequest = record.mRealRequest; long interval = locationRequest.getInterval(); - if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) { + if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) { if (!record.mIsForegroundUid) { interval = Math.max(interval, backgroundThrottleInterval); } @@ -2120,7 +2110,7 @@ public class LocationManagerService extends ILocationManager.Stub { long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; for (UpdateRecord record : records) { if (isCurrentProfileLocked( - UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { + UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { LocationRequest locationRequest = record.mRequest; // Don't assign battery blame for update records whose @@ -2137,8 +2127,8 @@ public class LocationManagerService extends ILocationManager.Stub { // Assign blame to caller if there's no WorkSource associated with // the request or if it's invalid. worksource.add( - record.mReceiver.mIdentity.mUid, - record.mReceiver.mIdentity.mPackageName); + record.mReceiver.mCallerIdentity.mUid, + record.mReceiver.mCallerIdentity.mPackageName); } } } @@ -2175,19 +2165,17 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private boolean isThrottlingExemptLocked(Identity identity) { - if (identity.mUid == Process.SYSTEM_UID) { + private boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) { + if (callerIdentity.mUid == Process.SYSTEM_UID) { return true; } - if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) { + if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) { return true; } - for (LocationProvider provider : mProviders) { - if (identity.mPackageName.equals(provider.getPackageLocked())) { - return true; - } + if (isProviderPackage(callerIdentity.mPackageName)) { + return true; } return false; @@ -2199,14 +2187,13 @@ public class LocationManagerService extends ILocationManager.Stub { return false; } - if (mIgnoreSettingsPackageWhitelist.contains(record.mReceiver.mIdentity.mPackageName)) { + if (mIgnoreSettingsPackageWhitelist.contains( + record.mReceiver.mCallerIdentity.mPackageName)) { return true; } - for (LocationProvider provider : mProviders) { - if (record.mReceiver.mIdentity.mPackageName.equals(provider.getPackageLocked())) { - return true; - } + if (isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName)) { + return true; } return false; @@ -2230,7 +2217,7 @@ public class LocationManagerService extends ILocationManager.Stub { mRequest = request; mReceiver = receiver; mIsForegroundUid = isImportanceForeground( - mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName)); + mActivityManager.getPackageImportance(mReceiver.mCallerIdentity.mPackageName)); ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); if (records == null) { @@ -2243,7 +2230,7 @@ public class LocationManagerService extends ILocationManager.Stub { // Update statistics for historical location requests by package/provider mRequestStatistics.startRequesting( - mReceiver.mIdentity.mPackageName, provider, request.getInterval(), + mReceiver.mCallerIdentity.mPackageName, provider, request.getInterval(), mIsForegroundUid); } @@ -2253,14 +2240,14 @@ public class LocationManagerService extends ILocationManager.Stub { private void updateForeground(boolean isForeground) { mIsForegroundUid = isForeground; mRequestStatistics.updateForeground( - mReceiver.mIdentity.mPackageName, mProvider, isForeground); + mReceiver.mCallerIdentity.mPackageName, mProvider, isForeground); } /** * Method to be called when a record will no longer be used. */ private void disposeLocked(boolean removeReceiver) { - mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider); + mRequestStatistics.stopRequesting(mReceiver.mCallerIdentity.mPackageName, mProvider); // remove from mRecordsByProvider ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); @@ -2282,8 +2269,8 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public String toString() { - return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName - + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" + return "UpdateRecord[" + mProvider + " " + mReceiver.mCallerIdentity.mPackageName + + "(" + mReceiver.mCallerIdentity.mUid + (mIsForegroundUid ? " foreground" : " background") + ")" + " " + mRealRequest + " " + mReceiver.mWorkSource + "]"; @@ -2458,7 +2445,7 @@ public class LocationManagerService extends ILocationManager.Stub { Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + name + " " + request + " from " + packageName + "(" + uid + " " + (record.mIsForegroundUid ? "foreground" : "background") - + (isThrottlingExemptLocked(receiver.mIdentity) + + (isThrottlingExemptLocked(receiver.mCallerIdentity) ? " [whitelisted]" : "") + ")"); } @@ -2566,13 +2553,6 @@ public class LocationManagerService extends ILocationManager.Stub { return null; } - if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) { - if (D) { - Log.d(TAG, "not returning last loc for no op app: " - + packageName); - } - return null; - } // Figure out the provider. Either its explicitly request (deprecated API's), // or use the fused provider @@ -2582,8 +2562,8 @@ public class LocationManagerService extends ILocationManager.Stub { if (provider == null) return null; // only the current user or location providers may get location this way - if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isLocationProviderLocked( - uid)) { + if (!isCurrentProfileLocked(UserHandle.getUserId(uid)) && !isProviderPackage( + packageName)) { return null; } @@ -2616,16 +2596,27 @@ public class LocationManagerService extends ILocationManager.Stub { return null; } + Location lastLocation = null; if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { Location noGPSLocation = location.getExtraLocation( Location.EXTRA_NO_GPS_LOCATION); if (noGPSLocation != null) { - return new Location(mLocationFudger.getOrCreate(noGPSLocation)); + lastLocation = new Location(mLocationFudger.getOrCreate(noGPSLocation)); } } else { - return new Location(location); + lastLocation = new Location(location); + } + // Don't report location access if there is no last location to deliver. + if (lastLocation != null) { + if (!reportLocationAccessNoThrow( + pid, uid, packageName, allowedResolutionLevel)) { + if (D) { + Log.d(TAG, "not returning last loc for no op app: " + packageName); + } + lastLocation = null; + } } - return null; + return lastLocation; } finally { Binder.restoreCallingIdentity(identity); } @@ -2734,7 +2725,8 @@ public class LocationManagerService extends ILocationManager.Stub { // TODO(b/120449926): The GNSS status listeners should be handled similar to the GNSS // measurements listeners. - return mGnssStatusProvider.addListener(callback, Binder.getCallingUid(), packageName); + return mGnssStatusProvider.addListener(callback, new CallerIdentity(Binder.getCallingUid(), + Binder.getCallingPid(), packageName)); } @Override @@ -2750,8 +2742,8 @@ public class LocationManagerService extends ILocationManager.Stub { } synchronized (mLock) { - Identity callerIdentity - = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); + CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), + Binder.getCallingPid(), packageName); // TODO(b/120481270): Register for client death notification and update map. mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity); long identity = Binder.clearCallingIdentity(); @@ -2759,8 +2751,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (isThrottlingExemptLocked(callerIdentity) || isImportanceForeground( mActivityManager.getPackageImportance(packageName))) { - return mGnssMeasurementsProvider.addListener(listener, - callerIdentity.mUid, callerIdentity.mPackageName); + return mGnssMeasurementsProvider.addListener(listener, callerIdentity); } } finally { Binder.restoreCallingIdentity(identity); @@ -2815,8 +2806,8 @@ public class LocationManagerService extends ILocationManager.Stub { } synchronized (mLock) { - Identity callerIdentity - = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); + CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), + Binder.getCallingPid(), packageName); // TODO(b/120481270): Register for client death notification and update map. mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity); @@ -2825,8 +2816,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (isThrottlingExemptLocked(callerIdentity) || isImportanceForeground( mActivityManager.getPackageImportance(packageName))) { - return mGnssNavigationMessageProvider.addListener(listener, - callerIdentity.mUid, callerIdentity.mPackageName); + return mGnssNavigationMessageProvider.addListener(listener, callerIdentity); } } finally { Binder.restoreCallingIdentity(identity); @@ -2900,13 +2890,15 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public String getNetworkProviderPackage() { + public boolean isProviderPackage(String packageName) { synchronized (mLock) { - LocationProvider provider = getLocationProviderLocked(NETWORK_PROVIDER); - if (provider == null) { - return null; + for (LocationProvider provider : mProviders) { + if (provider.getPackagesLocked().contains(packageName)) { + return true; + } } - return provider.getPackageLocked(); + + return false; } } @@ -2988,28 +2980,6 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private boolean isLocationProviderLocked(int uid) { - if (uid == Process.SYSTEM_UID) { - return true; - } - - String[] packageNames = mPackageManager.getPackagesForUid(uid); - if (packageNames == null) { - return false; - } - for (LocationProvider provider : mProviders) { - String packageName = provider.getPackageLocked(); - if (packageName == null) { - continue; - } - if (ArrayUtils.contains(packageNames, packageName)) { - return true; - } - } - return false; - } - - @GuardedBy("mLock") private static boolean shouldBroadcastSafeLocked( Location loc, Location lastLoc, UpdateRecord record, long now) { // Always broadcast the first update @@ -3109,33 +3079,33 @@ public class LocationManagerService extends ILocationManager.Stub { continue; } - int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid); + int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid); if (!isCurrentProfileLocked(receiverUserId) - && !isLocationProviderLocked(receiver.mIdentity.mUid)) { + && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for background user " + receiverUserId + " (current user: " + mCurrentUserId + ", app: " + - receiver.mIdentity.mPackageName + ")"); + receiver.mCallerIdentity.mPackageName + ")"); } continue; } - if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) { + if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for blacklisted app: " + - receiver.mIdentity.mPackageName); + receiver.mCallerIdentity.mPackageName); } continue; } if (!reportLocationAccessNoThrow( - receiver.mIdentity.mPid, - receiver.mIdentity.mUid, - receiver.mIdentity.mPackageName, + receiver.mCallerIdentity.mPid, + receiver.mCallerIdentity.mUid, + receiver.mCallerIdentity.mPackageName, receiver.mAllowedResolutionLevel)) { if (D) { Log.d(TAG, "skipping loc update for no op app: " + - receiver.mIdentity.mPackageName); + receiver.mCallerIdentity.mPackageName); } continue; } @@ -3271,7 +3241,7 @@ public class LocationManagerService extends ILocationManager.Stub { // Mock Providers private boolean canCallerAccessMockLocation(String opPackageName) { - return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), + return mAppOps.checkOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), opPackageName) == AppOpsManager.MODE_ALLOWED; } @@ -3300,7 +3270,8 @@ public class LocationManagerService extends ILocationManager.Stub { MockLocationProvider mockProviderManager = new MockLocationProvider(name); addProviderLocked(mockProviderManager); - mockProviderManager.attachLocked(new MockProvider(mockProviderManager, properties)); + mockProviderManager.attachLocked( + new MockProvider(mContext, mockProviderManager, properties)); } finally { Binder.restoreCallingIdentity(identity); } @@ -3424,21 +3395,23 @@ public class LocationManagerService extends ILocationManager.Stub { } } pw.println(" Active GnssMeasurement Listeners:"); - for (Identity identity : mGnssMeasurementsListeners.values()) { - pw.println(" " + identity.mPid + " " + identity.mUid + " " - + identity.mPackageName + ": " + isThrottlingExemptLocked(identity)); + for (CallerIdentity callerIdentity : mGnssMeasurementsListeners.values()) { + pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " " + + callerIdentity.mPackageName + ": " + + isThrottlingExemptLocked(callerIdentity)); } pw.println(" Active GnssNavigationMessage Listeners:"); - for (Identity identity : mGnssNavigationMessageListeners.values()) { - pw.println(" " + identity.mPid + " " + identity.mUid + " " - + identity.mPackageName + ": " + isThrottlingExemptLocked(identity)); + for (CallerIdentity callerIdentity : mGnssNavigationMessageListeners.values()) { + pw.println(" " + callerIdentity.mPid + " " + callerIdentity.mUid + " " + + callerIdentity.mPackageName + ": " + + isThrottlingExemptLocked(callerIdentity)); } pw.println(" Overlay Provider Packages:"); for (LocationProvider provider : mProviders) { if (provider.mProvider instanceof LocationProviderProxy) { pw.println(" " + provider.getName() + ": " + ((LocationProviderProxy) provider.mProvider) - .getConnectedPackageName()); + .getProviderPackages()); } } pw.println(" Historical Records by Provider:"); diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java index 2f7929c962eb..9184128d466f 100644 --- a/services/core/java/com/android/server/LooperStatsService.java +++ b/services/core/java/com/android/server/LooperStatsService.java @@ -59,7 +59,8 @@ public class LooperStatsService extends Binder { private final Context mContext; private final LooperStats mStats; - private boolean mEnabled = DEFAULT_ENABLED; + // Default should be false so that the first call to #setEnabled installed the looper observer. + private boolean mEnabled = false; private LooperStatsService(Context context, LooperStats stats) { this.mContext = context; diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index e731f345b704..ddbb421c7f0a 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -80,6 +80,7 @@ class SettingsToPropertiesMapper { DeviceConfig.ActivityManagerNativeBoot.NAMESPACE, DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT, DeviceConfig.NAMESPACE_NETD_NATIVE, + DeviceConfig.RuntimeNativeBoot.NAMESPACE, DeviceConfig.RuntimeNative.NAMESPACE, }; diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING index c84b5c74c1e7..117174a6465e 100644 --- a/services/core/java/com/android/server/am/TEST_MAPPING +++ b/services/core/java/com/android/server/am/TEST_MAPPING @@ -1,17 +1,6 @@ { "presubmit": [ { - "name": "CtsActivityManagerDeviceSdk25TestCases", - "options": [ - { - "include-annotation": "android.platform.test.annotations.Presubmit" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] - }, - { "name": "CtsAppTestCases", "options": [ { @@ -38,20 +27,6 @@ "exclude-annotation": "androidx.test.filters.FlakyTest" } ] - }, - { - "name": "WmTests", - "options": [ - { - "include-filter": "com.android.server.am." - }, - { - "include-annotation": "android.platform.test.annotations.Presubmit" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] } ], "postsubmit": [ diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index deaa9313fadd..a3bae521a162 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -15,6 +15,9 @@ */ package com.android.server.audio; +import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED; +import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED; + import android.annotation.NonNull; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; @@ -43,7 +46,7 @@ import java.util.ArrayList; /** @hide */ /*package*/ final class AudioDeviceBroker { - private static final String TAG = "AudioDeviceBroker"; + private static final String TAG = "AS.AudioDeviceBroker"; private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s @@ -62,27 +65,27 @@ import java.util.ArrayList; private int mForcedUseForCommExt; // Manages all connected devices, only ever accessed on the message loop - //### or make it synchronized private final AudioDeviceInventory mDeviceInventory; // Manages notifications to BT service private final BtHelper mBtHelper; //------------------------------------------------------------------- + // we use a different lock than mDeviceStateLock so as not to create + // lock contention between enqueueing a message and handling them private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); + @GuardedBy("sLastDeviceConnectionMsgTimeLock") private static long sLastDeviceConnectMsgTime = 0; - private final Object mBluetoothA2dpEnabledLock = new Object(); + // General lock to be taken whenever the state of the audio devices is to be checked or changed + private final Object mDeviceStateLock = new Object(); + // Request to override default use of A2DP for media. - @GuardedBy("mBluetoothA2dpEnabledLock") + @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpEnabled; - // lock always taken synchronized on mConnectedDevices - /*package*/ final Object mA2dpAvrcpLock = new Object(); - // lock always taken synchronized on mConnectedDevices - /*package*/ final Object mHearingAidLock = new Object(); - // lock always taken when accessing AudioService.mSetModeDeathHandlers + // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 /*package*/ final Object mSetModeLock = new Object(); //------------------------------------------------------------------- @@ -109,13 +112,17 @@ import java.util.ArrayList; // All post* methods are asynchronous /*package*/ void onSystemReady() { - mBtHelper.onSystemReady(); + synchronized (mDeviceStateLock) { + mBtHelper.onSystemReady(); + } } /*package*/ void onAudioServerDied() { // Restore forced usage for communications and record - onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied"); - onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied"); + synchronized (mDeviceStateLock) { + onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied"); + onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied"); + } // restore devices sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); } @@ -130,7 +137,9 @@ import java.util.ArrayList; } /*package*/ void disconnectAllBluetoothProfiles() { - mBtHelper.disconnectAllBluetoothProfiles(); + synchronized (mDeviceStateLock) { + mBtHelper.disconnectAllBluetoothProfiles(); + } } /** @@ -140,11 +149,13 @@ import java.util.ArrayList; * @param intent */ /*package*/ void receiveBtEvent(@NonNull Intent intent) { - mBtHelper.receiveBtEvent(intent); + synchronized (mDeviceStateLock) { + mBtHelper.receiveBtEvent(intent); + } } /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { - synchronized (mBluetoothA2dpEnabledLock) { + synchronized (mDeviceStateLock) { if (mBluetoothA2dpEnabled == on) { return; } @@ -158,28 +169,34 @@ import java.util.ArrayList; } /*package*/ void setSpeakerphoneOn(boolean on, String eventSource) { - if (on) { - if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { - setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); + synchronized (mDeviceStateLock) { + if (on) { + if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { + setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); + } + mForcedUseForComm = AudioSystem.FORCE_SPEAKER; + } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { + mForcedUseForComm = AudioSystem.FORCE_NONE; } - mForcedUseForComm = AudioSystem.FORCE_SPEAKER; - } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { - mForcedUseForComm = AudioSystem.FORCE_NONE; - } - mForcedUseForCommExt = mForcedUseForComm; - setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); + mForcedUseForCommExt = mForcedUseForComm; + setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); + } } /*package*/ boolean isSpeakerphoneOn() { - return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); + synchronized (mDeviceStateLock) { + return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); + } } /*package*/ void setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state, String address, String name, String caller) { //TODO move logging here just like in setBluetooth* methods - mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller); + synchronized (mDeviceStateLock) { + mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller); + } } /*package*/ int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( @@ -192,22 +209,27 @@ import java.util.ArrayList; + " addr=" + device.getAddress() + " prof=" + profile + " supprNoisy=" + suppressNoisyIntent + " vol=" + a2dpVolume)).printLog(TAG)); - if (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, - new BtHelper.BluetoothA2dpDeviceInfo(device))) { - AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( - "A2DP connection state ignored")); - return 0; + synchronized (mDeviceStateLock) { + if (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, + new BtHelper.BluetoothA2dpDeviceInfo(device))) { + AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( + "A2DP connection state ignored")); + return 0; + } + return mDeviceInventory.setBluetoothA2dpDeviceConnectionState( + device, state, profile, suppressNoisyIntent, + AudioSystem.DEVICE_NONE, a2dpVolume); } - return mDeviceInventory.setBluetoothA2dpDeviceConnectionState( - device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume); } /*package*/ int handleBluetoothA2dpActiveDeviceChange( @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { - return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile, - suppressNoisyIntent, a2dpVolume); + synchronized (mDeviceStateLock) { + return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile, + suppressNoisyIntent, a2dpVolume); + } } /*package*/ int setBluetoothHearingAidDeviceConnectionState( @@ -218,57 +240,69 @@ import java.util.ArrayList; + " addr=" + device.getAddress() + " supprNoisy=" + suppressNoisyIntent + " src=" + eventSource)).printLog(TAG)); - return mDeviceInventory.setBluetoothHearingAidDeviceConnectionState( - device, state, suppressNoisyIntent, musicDevice); + synchronized (mDeviceStateLock) { + return mDeviceInventory.setBluetoothHearingAidDeviceConnectionState( + device, state, suppressNoisyIntent, musicDevice); + } } // never called by system components /*package*/ void setBluetoothScoOnByApp(boolean on) { - mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; + synchronized (mDeviceStateLock) { + mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; + } } /*package*/ boolean isBluetoothScoOnForApp() { - return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO; + synchronized (mDeviceStateLock) { + return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO; + } } /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { //Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); - if (on) { - // do not accept SCO ON if SCO audio is not connected - if (!mBtHelper.isBluetoothScoOn()) { - mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; - return; + synchronized (mDeviceStateLock) { + if (on) { + // do not accept SCO ON if SCO audio is not connected + if (!mBtHelper.isBluetoothScoOn()) { + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + return; + } + mForcedUseForComm = AudioSystem.FORCE_BT_SCO; + } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { + mForcedUseForComm = AudioSystem.FORCE_NONE; } - mForcedUseForComm = AudioSystem.FORCE_BT_SCO; - } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { - mForcedUseForComm = AudioSystem.FORCE_NONE; + mForcedUseForCommExt = mForcedUseForComm; + AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off")); + sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, + AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); + sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, + AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource); + // Un-mute ringtone stream volume + mAudioService.setUpdateRingerModeServiceInt(); } - mForcedUseForCommExt = mForcedUseForComm; - AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off")); - sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); - sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource); - // Un-mute ringtone stream volume - mAudioService.setUpdateRingerModeServiceInt(); } /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { - return mDeviceInventory.startWatchingRoutes(observer); + synchronized (mDeviceStateLock) { + return mDeviceInventory.startWatchingRoutes(observer); + } } /*package*/ AudioRoutesInfo getCurAudioRoutes() { - return mDeviceInventory.getCurAudioRoutes(); + synchronized (mDeviceStateLock) { + return mDeviceInventory.getCurAudioRoutes(); + } } /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { - synchronized (mA2dpAvrcpLock) { + synchronized (mDeviceStateLock) { return mBtHelper.isAvrcpAbsoluteVolumeSupported(); } } /*package*/ boolean isBluetoothA2dpOn() { - synchronized (mBluetoothA2dpEnabledLock) { + synchronized (mDeviceStateLock) { return mBluetoothA2dpEnabled; } } @@ -355,14 +389,12 @@ import java.util.ArrayList; sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); } - //###TODO unify with handleSetA2dpSinkConnectionState /*package*/ void postA2dpSinkConnection(int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE, state, btDeviceInfo, delay); } - //###TODO unify with handleSetA2dpSourceConnectionState /*package*/ void postA2dpSourceConnection(int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, @@ -395,7 +427,7 @@ import java.util.ArrayList; .append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(Binder.getCallingPid()).append(" src:").append(source).toString(); - synchronized (mBluetoothA2dpEnabledLock) { + synchronized (mDeviceStateLock) { mBluetoothA2dpEnabled = on; mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); onSetForceUse( @@ -407,25 +439,38 @@ import java.util.ArrayList; /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address, String deviceName) { - return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName); + synchronized (mDeviceStateLock) { + return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName); + } } /*package*/ void handleDisconnectA2dp() { - mDeviceInventory.disconnectA2dp(); + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectA2dp(); + } } /*package*/ void handleDisconnectA2dpSink() { - mDeviceInventory.disconnectA2dpSink(); + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectA2dpSink(); + } + } + + /*package*/ void handleDisconnectHearingAid() { + synchronized (mDeviceStateLock) { + mDeviceInventory.disconnectHearingAid(); + } } /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { - final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; - //### DOESN'T HONOR SYNC ON DEVICES -> make a synchronized version? - // might be ok here because called on BT thread? + sync happening in - // checkSendBecomingNoisyIntent - final int delay = mDeviceInventory.checkSendBecomingNoisyIntent( - AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState, - AudioSystem.DEVICE_NONE); + final int intState = (state == BluetoothA2dp.STATE_CONNECTED) + ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED; + final int delay; + synchronized (mDeviceStateLock) { + delay = mDeviceInventory.checkSendBecomingNoisyIntent( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState, + AudioSystem.DEVICE_NONE); + } final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress(); if (AudioService.DEBUG_DEVICES) { @@ -437,10 +482,6 @@ import java.util.ArrayList; state, btDeviceInfo, delay); } - /*package*/ void handleDisconnectHearingAid() { - mDeviceInventory.disconnectHearingAid(); - } - /*package*/ void handleSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; @@ -468,8 +509,6 @@ import java.util.ArrayList; sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo); } - //### - // must be called synchronized on mConnectedDevices /*package*/ boolean hasScheduledA2dpDockTimeout() { return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT); } @@ -486,19 +525,19 @@ import java.util.ArrayList; } /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { - synchronized (mA2dpAvrcpLock) { + synchronized (mDeviceStateLock) { mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); } } /*package*/ boolean getBluetoothA2dpEnabled() { - synchronized (mBluetoothA2dpEnabledLock) { + synchronized (mDeviceStateLock) { return mBluetoothA2dpEnabled; } } /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) { - synchronized (mA2dpAvrcpLock) { + synchronized (mDeviceStateLock) { return mBtHelper.getA2dpCodec(device); } } @@ -579,71 +618,97 @@ import java.util.ArrayList; public void handleMessage(Message msg) { switch (msg.what) { case MSG_RESTORE_DEVICES: - mDeviceInventory.onRestoreDevices(); - synchronized (mBluetoothA2dpEnabledLock) { + synchronized (mDeviceStateLock) { + mDeviceInventory.onRestoreDevices(); mBtHelper.onAudioServerDiedRestoreA2dp(); } break; case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: - mDeviceInventory.onSetWiredDeviceConnectionState( - (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); + synchronized (mDeviceStateLock) { + mDeviceInventory.onSetWiredDeviceConnectionState( + (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); + } break; case MSG_I_BROADCAST_BT_CONNECTION_STATE: - mBtHelper.onBroadcastScoConnectionState(msg.arg1); + synchronized (mDeviceStateLock) { + mBtHelper.onBroadcastScoConnectionState(msg.arg1); + } break; - case MSG_IIL_SET_FORCE_USE: // intented fall-through + case MSG_IIL_SET_FORCE_USE: // intended fall-through case MSG_IIL_SET_FORCE_BT_A2DP_USE: onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj); break; case MSG_REPORT_NEW_ROUTES: - mDeviceInventory.onReportNewRoutes(); + synchronized (mDeviceStateLock) { + mDeviceInventory.onReportNewRoutes(); + } break; case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: - mDeviceInventory.onSetA2dpSinkConnectionState( - (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); + synchronized (mDeviceStateLock) { + mDeviceInventory.onSetA2dpSinkConnectionState( + (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); + } break; case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: - mDeviceInventory.onSetA2dpSourceConnectionState( - (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); + synchronized (mDeviceStateLock) { + mDeviceInventory.onSetA2dpSourceConnectionState( + (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); + } break; case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: - mDeviceInventory.onSetHearingAidConnectionState( - (BluetoothDevice) msg.obj, msg.arg1); + synchronized (mDeviceStateLock) { + mDeviceInventory.onSetHearingAidConnectionState( + (BluetoothDevice) msg.obj, msg.arg1); + } break; case MSG_BT_HEADSET_CNCT_FAILED: - mBtHelper.resetBluetoothSco(); + synchronized (mDeviceStateLock) { + mBtHelper.resetBluetoothSco(); + } break; case MSG_IL_BTA2DP_DOCK_TIMEOUT: // msg.obj == address of BTA2DP device - mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); + synchronized (mDeviceStateLock) { + mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); + } break; case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: final int a2dpCodec; final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; - synchronized (mA2dpAvrcpLock) { + synchronized (mDeviceStateLock) { a2dpCodec = mBtHelper.getA2dpCodec(btDevice); + mDeviceInventory.onBluetoothA2dpDeviceConfigChange( + new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec)); } - mDeviceInventory.onBluetoothA2dpDeviceConfigChange( - new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec)); break; case MSG_BROADCAST_AUDIO_BECOMING_NOISY: onSendBecomingNoisyIntent(); break; case MSG_II_SET_HEARING_AID_VOLUME: - mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2); + synchronized (mDeviceStateLock) { + mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2); + } break; case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: - mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); + synchronized (mDeviceStateLock) { + mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); + } break; case MSG_I_DISCONNECT_BT_SCO: - mBtHelper.disconnectBluetoothSco(msg.arg1); + synchronized (mDeviceStateLock) { + mBtHelper.disconnectBluetoothSco(msg.arg1); + } break; case MSG_TOGGLE_HDMI: - mDeviceInventory.onToggleHdmi(); + synchronized (mDeviceStateLock) { + mDeviceInventory.onToggleHdmi(); + } break; case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: - mDeviceInventory.onBluetoothA2dpActiveDeviceChange( - (BtHelper.BluetoothA2dpDeviceInfo) msg.obj); + synchronized (mDeviceStateLock) { + mDeviceInventory.onBluetoothA2dpActiveDeviceChange( + (BtHelper.BluetoothA2dpDeviceInfo) msg.obj); + } break; default: Log.wtf(TAG, "Invalid message " + msg.what); diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 97649a741f62..11fdc8f05033 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -162,10 +162,7 @@ public final class AudioDeviceInventory { "A2DP sink connected: device addr=" + address + " state=" + state + " vol=" + a2dpVolume)); - final int a2dpCodec; - synchronized (mDeviceBroker.mA2dpAvrcpLock) { - a2dpCodec = btInfo.getCodec(); - } + final int a2dpCodec = btInfo.getCodec(); synchronized (mConnectedDevices) { final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, @@ -508,22 +505,20 @@ public final class AudioDeviceInventory { /*package*/ void disconnectA2dp() { synchronized (mConnectedDevices) { - synchronized (mDeviceBroker.mA2dpAvrcpLock) { - final ArraySet<String> toRemove = new ArraySet<>(); - // Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices - mConnectedDevices.values().forEach(deviceInfo -> { - if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) { - toRemove.add(deviceInfo.mDeviceAddress); - } - }); - if (toRemove.size() > 0) { - final int delay = checkSendBecomingNoisyIntentInt( - AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - 0, AudioSystem.DEVICE_NONE); - toRemove.stream().forEach(deviceAddress -> - makeA2dpDeviceUnavailableLater(deviceAddress, delay) - ); + final ArraySet<String> toRemove = new ArraySet<>(); + // Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices + mConnectedDevices.values().forEach(deviceInfo -> { + if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) { + toRemove.add(deviceInfo.mDeviceAddress); } + }); + if (toRemove.size() > 0) { + final int delay = checkSendBecomingNoisyIntentInt( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + AudioService.CONNECTION_STATE_DISCONNECTED, AudioSystem.DEVICE_NONE); + toRemove.stream().forEach(deviceAddress -> + makeA2dpDeviceUnavailableLater(deviceAddress, delay) + ); } } } @@ -543,22 +538,20 @@ public final class AudioDeviceInventory { /*package*/ void disconnectHearingAid() { synchronized (mConnectedDevices) { - synchronized (mDeviceBroker.mHearingAidLock) { - final ArraySet<String> toRemove = new ArraySet<>(); - // Disconnect ALL DEVICE_OUT_HEARING_AID devices - mConnectedDevices.values().forEach(deviceInfo -> { - if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) { - toRemove.add(deviceInfo.mDeviceAddress); - } - }); - if (toRemove.size() > 0) { - final int delay = checkSendBecomingNoisyIntentInt( - AudioSystem.DEVICE_OUT_HEARING_AID, 0, AudioSystem.DEVICE_NONE); - toRemove.stream().forEach(deviceAddress -> - // TODO delay not used? - makeHearingAidDeviceUnavailable(deviceAddress /*, delay*/) - ); + final ArraySet<String> toRemove = new ArraySet<>(); + // Disconnect ALL DEVICE_OUT_HEARING_AID devices + mConnectedDevices.values().forEach(deviceInfo -> { + if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) { + toRemove.add(deviceInfo.mDeviceAddress); } + }); + if (toRemove.size() > 0) { + final int delay = checkSendBecomingNoisyIntentInt( + AudioSystem.DEVICE_OUT_HEARING_AID, 0, AudioSystem.DEVICE_NONE); + toRemove.stream().forEach(deviceAddress -> + // TODO delay not used? + makeHearingAidDeviceUnavailable(deviceAddress /*, delay*/) + ); } } } @@ -566,7 +559,8 @@ public final class AudioDeviceInventory { // must be called before removing the device from mConnectedDevices // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying // from AudioSystem - /*package*/ int checkSendBecomingNoisyIntent(int device, int state, int musicDevice) { + /*package*/ int checkSendBecomingNoisyIntent(int device, + @AudioService.ConnectionState int state, int musicDevice) { synchronized (mConnectedDevices) { return checkSendBecomingNoisyIntentInt(device, state, musicDevice); } @@ -840,8 +834,9 @@ public final class AudioDeviceInventory { // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying // from AudioSystem @GuardedBy("mConnectedDevices") - private int checkSendBecomingNoisyIntentInt(int device, int state, int musicDevice) { - if (state != 0) { + private int checkSendBecomingNoisyIntentInt(int device, + @AudioService.ConnectionState int state, int musicDevice) { + if (state != AudioService.CONNECTION_STATE_DISCONNECTED) { return 0; } if ((device & mBecomingNoisyIntentDevices) == 0) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 9457fe3d84f1..de63d0ef8edf 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -786,7 +786,6 @@ public class AudioService extends IAudioService.Stub mPrescaleAbsoluteVolume[i] = preScale[i]; } } - } public void systemReady() { @@ -1711,7 +1710,7 @@ public class AudioService extends IAudioService.Stub Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index=" + newIndex + "stream=" + streamType); } - mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex); + mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10); } // Check if volume update should be send to Hearing Aid @@ -3821,7 +3820,6 @@ public class AudioService extends IAudioService.Stub private static void sendMsg(Handler handler, int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { - if (existingMsgPolicy == SENDMSG_REPLACE) { handler.removeMessages(msg); } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index bf325013c7da..b63af8a31cd9 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -16,6 +16,7 @@ package com.android.server.audio; import android.annotation.NonNull; +import android.annotation.Nullable; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; @@ -35,8 +36,6 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Log; -import com.android.internal.annotations.GuardedBy; - import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; @@ -57,21 +56,40 @@ public class BtHelper { } // List of clients having issued a SCO start request - private final ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>(); + private final @NonNull ArrayList<ScoClient> mScoClients = new ArrayList<ScoClient>(); // BluetoothHeadset API to control SCO connection - private BluetoothHeadset mBluetoothHeadset; + private @Nullable BluetoothHeadset mBluetoothHeadset; // Bluetooth headset device - private BluetoothDevice mBluetoothHeadsetDevice; + private @Nullable BluetoothDevice mBluetoothHeadsetDevice; + + private @Nullable BluetoothHearingAid mHearingAid; + + // Reference to BluetoothA2dp to query for AbsoluteVolume. + private @Nullable BluetoothA2dp mA2dp; + + // If absolute volume is supported in AVRCP device + private boolean mAvrcpAbsVolSupported = false; + + // Current connection state indicated by bluetooth headset + private int mScoConnectionState; // Indicate if SCO audio connection is currently active and if the initiator is // audio service (internal) or bluetooth headset (external) private int mScoAudioState; + + // Indicates the mode used for SCO audio connection. The mode is virtual call if the request + // originated from an app targeting an API version before JB MR2 and raw audio after that. + private int mScoAudioMode; + // SCO audio state is not active private static final int SCO_STATE_INACTIVE = 0; // SCO audio activation request waiting for headset service to connect private static final int SCO_STATE_ACTIVATE_REQ = 1; + // SCO audio state is active due to an action in BT handsfree (either voice recognition or + // in call audio) + private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; // SCO audio state is active or starting due to a request from AudioManager API private static final int SCO_STATE_ACTIVE_INTERNAL = 3; // SCO audio deactivation request waiting for headset service to connect @@ -79,39 +97,19 @@ public class BtHelper { // SCO audio deactivation in progress, waiting for Bluetooth audio intent private static final int SCO_STATE_DEACTIVATING = 5; - // SCO audio state is active due to an action in BT handsfree (either voice recognition or - // in call audio) - private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; - - // Indicates the mode used for SCO audio connection. The mode is virtual call if the request - // originated from an app targeting an API version before JB MR2 and raw audio after that. - private int mScoAudioMode; // SCO audio mode is undefined - /*package*/ static final int SCO_MODE_UNDEFINED = -1; + /*package*/ static final int SCO_MODE_UNDEFINED = -1; // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) /*package*/ static final int SCO_MODE_VIRTUAL_CALL = 0; // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) private static final int SCO_MODE_RAW = 1; // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition()) private static final int SCO_MODE_VR = 2; - + // max valid SCO audio mode values private static final int SCO_MODE_MAX = 2; - // Current connection state indicated by bluetooth headset - private int mScoConnectionState; - private static final int BT_HEARING_AID_GAIN_MIN = -128; - @GuardedBy("mDeviceBroker.mHearingAidLock") - private BluetoothHearingAid mHearingAid; - - // Reference to BluetoothA2dp to query for AbsoluteVolume. - @GuardedBy("mDeviceBroker.mA2dpAvrcpLock") - private BluetoothA2dp mA2dp; - // If absolute volume is supported in AVRCP device - @GuardedBy("mDeviceBroker.mA2dpAvrcpLock") - private boolean mAvrcpAbsVolSupported = false; - //---------------------------------------------------------------------- /*package*/ static class BluetoothA2dpDeviceInfo { private final @NonNull BluetoothDevice mBtDevice; @@ -144,7 +142,7 @@ public class BtHelper { //---------------------------------------------------------------------- // Interface for AudioDeviceBroker - /*package*/ void onSystemReady() { + /*package*/ synchronized void onSystemReady() { mScoConnectionState = android.media.AudioManager.SCO_AUDIO_STATE_ERROR; resetBluetoothSco(); getBluetoothHeadset(); @@ -165,45 +163,39 @@ public class BtHelper { } } - @GuardedBy("mBluetoothA2dpEnabledLock") - /*package*/ void onAudioServerDiedRestoreA2dp() { + /*package*/ synchronized void onAudioServerDiedRestoreA2dp() { final int forMed = mDeviceBroker.getBluetoothA2dpEnabled() ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP; mDeviceBroker.setForceUse_Async(AudioSystem.FOR_MEDIA, forMed, "onAudioServerDied()"); } - @GuardedBy("mA2dpAvrcpLock") - /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { + /*package*/ synchronized boolean isAvrcpAbsoluteVolumeSupported() { return (mA2dp != null && mAvrcpAbsVolSupported); } - @GuardedBy("mA2dpAvrcpLock") - /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { + /*package*/ synchronized void setAvrcpAbsoluteVolumeSupported(boolean supported) { mAvrcpAbsVolSupported = supported; } - /*package*/ void setAvrcpAbsoluteVolumeIndex(int index) { - synchronized (mDeviceBroker.mA2dpAvrcpLock) { - if (mA2dp == null) { - if (AudioService.DEBUG_VOL) { - Log.d(TAG, "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp"); - return; - } - } - if (!mAvrcpAbsVolSupported) { - return; - } + /*package*/ synchronized void setAvrcpAbsoluteVolumeIndex(int index) { + if (mA2dp == null) { if (AudioService.DEBUG_VOL) { - Log.i(TAG, "setAvrcpAbsoluteVolumeIndex index=" + index); + Log.d(TAG, "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp"); + return; } - AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent( - AudioServiceEvents.VolumeEvent.VOL_SET_AVRCP_VOL, index / 10)); - mA2dp.setAvrcpAbsoluteVolume(index / 10); } + if (!mAvrcpAbsVolSupported) { + return; + } + if (AudioService.DEBUG_VOL) { + Log.i(TAG, "setAvrcpAbsoluteVolumeIndex index=" + index); + } + AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent( + AudioServiceEvents.VolumeEvent.VOL_SET_AVRCP_VOL, index)); + mA2dp.setAvrcpAbsoluteVolume(index); } - @GuardedBy("mA2dpAvrcpLock") - /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) { + /*package*/ synchronized int getA2dpCodec(@NonNull BluetoothDevice device) { if (mA2dp == null) { return AudioSystem.AUDIO_FORMAT_DEFAULT; } @@ -218,7 +210,7 @@ public class BtHelper { return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType()); } - /*package*/ void receiveBtEvent(Intent intent) { + /*package*/ synchronized void receiveBtEvent(Intent intent) { final String action = intent.getAction(); if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) { BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); @@ -226,53 +218,51 @@ public class BtHelper { } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { boolean broadcast = false; int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; - synchronized (mScoClients) { - int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); - // broadcast intent if the connection was initated by AudioService - if (!mScoClients.isEmpty() - && (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL - || mScoAudioState == SCO_STATE_ACTIVATE_REQ - || mScoAudioState == SCO_STATE_DEACTIVATE_REQ - || mScoAudioState == SCO_STATE_DEACTIVATING)) { - broadcast = true; - } - switch (btState) { - case BluetoothHeadset.STATE_AUDIO_CONNECTED: - scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; - if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL - && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; - } - mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); - break; - case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); - scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; - // startBluetoothSco called after stopBluetoothSco - if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) { - if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null - && connectBluetoothScoAudioHelper(mBluetoothHeadset, - mBluetoothHeadsetDevice, mScoAudioMode)) { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - broadcast = false; - break; - } - } - // Tear down SCO if disconnected from external - clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL); - mScoAudioState = SCO_STATE_INACTIVE; - break; - case BluetoothHeadset.STATE_AUDIO_CONNECTING: - if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL - && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); + // broadcast intent if the connection was initated by AudioService + if (!mScoClients.isEmpty() + && (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL + || mScoAudioState == SCO_STATE_ACTIVATE_REQ + || mScoAudioState == SCO_STATE_DEACTIVATE_REQ + || mScoAudioState == SCO_STATE_DEACTIVATING)) { + broadcast = true; + } + switch (btState) { + case BluetoothHeadset.STATE_AUDIO_CONNECTED: + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL + && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); + break; + case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: + mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); + scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + // startBluetoothSco called after stopBluetoothSco + if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) { + if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null + && connectBluetoothScoAudioHelper(mBluetoothHeadset, + mBluetoothHeadsetDevice, mScoAudioMode)) { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + broadcast = false; + break; } - break; - default: - // do not broadcast CONNECTING or invalid state - broadcast = false; - break; - } + } + // Tear down SCO if disconnected from external + clearAllScoClients(0, mScoAudioState == SCO_STATE_ACTIVE_INTERNAL); + mScoAudioState = SCO_STATE_INACTIVE; + break; + case BluetoothHeadset.STATE_AUDIO_CONNECTING: + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL + && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + break; + default: + // do not broadcast CONNECTING or invalid state + broadcast = false; + break; } if (broadcast) { broadcastScoConnectionState(scoAudioState); @@ -289,15 +279,13 @@ public class BtHelper { * * @return false if SCO isn't connected */ - /*package*/ boolean isBluetoothScoOn() { - synchronized (mScoClients) { - if ((mBluetoothHeadset != null) - && (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) - != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { - Log.w(TAG, "isBluetoothScoOn(true) returning false because " - + mBluetoothHeadsetDevice + " is not in audio connected mode"); - return false; - } + /*package*/ synchronized boolean isBluetoothScoOn() { + if ((mBluetoothHeadset != null) + && (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { + Log.w(TAG, "isBluetoothScoOn(true) returning false because " + + mBluetoothHeadsetDevice + " is not in audio connected mode"); + return false; } return true; } @@ -308,17 +296,15 @@ public class BtHelper { * * @param exceptPid pid whose SCO connections through {@link AudioManager} should be kept */ - /*package*/ void disconnectBluetoothSco(int exceptPid) { - synchronized (mScoClients) { - checkScoAudioState(); - if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) { - return; - } - clearAllScoClients(exceptPid, true); + /*package*/ synchronized void disconnectBluetoothSco(int exceptPid) { + checkScoAudioState(); + if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL) { + return; } + clearAllScoClients(exceptPid, true); } - /*package*/ void startBluetoothScoForClient(IBinder cb, int scoAudioMode, + /*package*/ synchronized void startBluetoothScoForClient(IBinder cb, int scoAudioMode, @NonNull String eventSource) { ScoClient client = getScoClient(cb, true); // The calling identity must be cleared before calling ScoClient.incCount(). @@ -337,7 +323,8 @@ public class BtHelper { Binder.restoreCallingIdentity(ident); } - /*package*/ void stopBluetoothScoForClient(IBinder cb, @NonNull String eventSource) { + /*package*/ synchronized void stopBluetoothScoForClient(IBinder cb, + @NonNull String eventSource) { ScoClient client = getScoClient(cb, false); // The calling identity must be cleared before calling ScoClient.decCount(). // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs @@ -352,36 +339,29 @@ public class BtHelper { } - /*package*/ void setHearingAidVolume(int index, int streamType) { - synchronized (mDeviceBroker.mHearingAidLock) { - if (mHearingAid == null) { - if (AudioService.DEBUG_VOL) { - Log.i(TAG, "setHearingAidVolume: null mHearingAid"); - } - return; - } - //hearing aid expect volume value in range -128dB to 0dB - int gainDB = (int) AudioSystem.getStreamVolumeDB(streamType, index / 10, - AudioSystem.DEVICE_OUT_HEARING_AID); - if (gainDB < BT_HEARING_AID_GAIN_MIN) { - gainDB = BT_HEARING_AID_GAIN_MIN; - } + /*package*/ synchronized void setHearingAidVolume(int index, int streamType) { + if (mHearingAid == null) { if (AudioService.DEBUG_VOL) { - Log.i(TAG, "setHearingAidVolume: calling mHearingAid.setVolume idx=" - + index + " gain=" + gainDB); + Log.i(TAG, "setHearingAidVolume: null mHearingAid"); } - AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent( - AudioServiceEvents.VolumeEvent.VOL_SET_HEARING_AID_VOL, index, gainDB)); - mHearingAid.setVolume(gainDB); + return; } + //hearing aid expect volume value in range -128dB to 0dB + int gainDB = (int) AudioSystem.getStreamVolumeDB(streamType, index / 10, + AudioSystem.DEVICE_OUT_HEARING_AID); + if (gainDB < BT_HEARING_AID_GAIN_MIN) { + gainDB = BT_HEARING_AID_GAIN_MIN; + } + if (AudioService.DEBUG_VOL) { + Log.i(TAG, "setHearingAidVolume: calling mHearingAid.setVolume idx=" + + index + " gain=" + gainDB); + } + AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent( + AudioServiceEvents.VolumeEvent.VOL_SET_HEARING_AID_VOL, index, gainDB)); + mHearingAid.setVolume(gainDB); } - //---------------------------------------------------------------------- - private void broadcastScoConnectionState(int state) { - mDeviceBroker.broadcastScoConnectionState(state); - } - - /*package*/ void onBroadcastScoConnectionState(int state) { + /*package*/ synchronized void onBroadcastScoConnectionState(int state) { if (state == mScoConnectionState) { return; } @@ -393,6 +373,26 @@ public class BtHelper { mScoConnectionState = state; } + /*package*/ synchronized void disconnectAllBluetoothProfiles() { + mDeviceBroker.handleDisconnectA2dp(); + mDeviceBroker.handleDisconnectA2dpSink(); + disconnectHeadset(); + mDeviceBroker.handleDisconnectHearingAid(); + } + + /*package*/ synchronized void resetBluetoothSco() { + clearAllScoClients(0, false); + mScoAudioState = SCO_STATE_INACTIVE; + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + AudioSystem.setParameters("A2dpSuspended=false"); + mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco"); + } + + //---------------------------------------------------------------------- + private void broadcastScoConnectionState(int state) { + mDeviceBroker.broadcastScoConnectionState(state); + } + private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) { if (btDevice == null) { return true; @@ -437,25 +437,23 @@ public class BtHelper { } private void setBtScoActiveDevice(BluetoothDevice btDevice) { - synchronized (mScoClients) { - Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice); - final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice; - if (Objects.equals(btDevice, previousActiveDevice)) { - return; - } - if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) { - Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device " - + previousActiveDevice); - } - if (!handleBtScoActiveDeviceChange(btDevice, true)) { - Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice); - // set mBluetoothHeadsetDevice to null when failing to add new device - btDevice = null; - } - mBluetoothHeadsetDevice = btDevice; - if (mBluetoothHeadsetDevice == null) { - resetBluetoothSco(); - } + Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice); + final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice; + if (Objects.equals(btDevice, previousActiveDevice)) { + return; + } + if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) { + Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device " + + previousActiveDevice); + } + if (!handleBtScoActiveDeviceChange(btDevice, true)) { + Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice); + // set mBluetoothHeadsetDevice to null when failing to add new device + btDevice = null; + } + mBluetoothHeadsetDevice = btDevice; + if (mBluetoothHeadsetDevice == null) { + resetBluetoothSco(); } } @@ -466,7 +464,7 @@ public class BtHelper { List<BluetoothDevice> deviceList; switch(profile) { case BluetoothProfile.A2DP: - synchronized (mDeviceBroker.mA2dpAvrcpLock) { + synchronized (BtHelper.this) { mA2dp = (BluetoothA2dp) proxy; deviceList = mA2dp.getConnectedDevices(); if (deviceList.size() > 0) { @@ -495,7 +493,7 @@ public class BtHelper { break; case BluetoothProfile.HEADSET: - synchronized (mScoClients) { + synchronized (BtHelper.this) { // Discard timeout message mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService(); mBluetoothHeadset = (BluetoothHeadset) proxy; @@ -536,17 +534,19 @@ public class BtHelper { break; case BluetoothProfile.HEARING_AID: - mHearingAid = (BluetoothHearingAid) proxy; - deviceList = mHearingAid.getConnectedDevices(); - if (deviceList.size() > 0) { - btDevice = deviceList.get(0); - final @BluetoothProfile.BtProfileState int state = - mHearingAid.getConnectionState(btDevice); - mDeviceBroker.setBluetoothHearingAidDeviceConnectionState( - btDevice, state, - /*suppressNoisyIntent*/ false, - /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE, - /*eventSource*/ "mBluetoothProfileServiceListener"); + synchronized (BtHelper.this) { + mHearingAid = (BluetoothHearingAid) proxy; + deviceList = mHearingAid.getConnectedDevices(); + if (deviceList.size() > 0) { + btDevice = deviceList.get(0); + final @BluetoothProfile.BtProfileState int state = + mHearingAid.getConnectionState(btDevice); + mDeviceBroker.setBluetoothHearingAidDeviceConnectionState( + btDevice, state, + /*suppressNoisyIntent*/ false, + /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE, + /*eventSource*/ "mBluetoothProfileServiceListener"); + } } break; @@ -579,18 +579,9 @@ public class BtHelper { } }; - void disconnectAllBluetoothProfiles() { - mDeviceBroker.handleDisconnectA2dp(); - mDeviceBroker.handleDisconnectA2dpSink(); - disconnectHeadset(); - mDeviceBroker.handleDisconnectHearingAid(); - } - private void disconnectHeadset() { - synchronized (mScoClients) { - setBtScoActiveDevice(null); - mBluetoothHeadset = null; - } + setBtScoActiveDevice(null); + mBluetoothHeadset = null; } //---------------------------------------------------------------------- @@ -605,8 +596,12 @@ public class BtHelper { mStartcount = 0; } + @Override public void binderDied() { - synchronized (mScoClients) { + // this is the only place the implementation of ScoClient needs to be synchronized + // on the instance, as all other methods are directly or indirectly called from + // package-private methods, which are synchronized + synchronized (BtHelper.this) { Log.w(TAG, "SCO client died"); int index = mScoClients.indexOf(this); if (index < 0) { @@ -618,77 +613,69 @@ public class BtHelper { } } - public void incCount(int scoAudioMode) { - synchronized (mScoClients) { - requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); - if (mStartcount == 0) { - try { - mCb.linkToDeath(this, 0); - } catch (RemoteException e) { - // client has already died! - Log.w(TAG, "ScoClient incCount() could not link to " - + mCb + " binder death"); - } + void incCount(int scoAudioMode) { + requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); + if (mStartcount == 0) { + try { + mCb.linkToDeath(this, 0); + } catch (RemoteException e) { + // client has already died! + Log.w(TAG, "ScoClient incCount() could not link to " + + mCb + " binder death"); } - mStartcount++; } + mStartcount++; } - public void decCount() { - synchronized (mScoClients) { + void decCount() { + if (mStartcount == 0) { + Log.w(TAG, "ScoClient.decCount() already 0"); + } else { + mStartcount--; if (mStartcount == 0) { - Log.w(TAG, "ScoClient.decCount() already 0"); - } else { - mStartcount--; - if (mStartcount == 0) { - try { - mCb.unlinkToDeath(this, 0); - } catch (NoSuchElementException e) { - Log.w(TAG, "decCount() going to 0 but not registered to binder"); - } - } - requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); - } - } - } - - public void clearCount(boolean stopSco) { - synchronized (mScoClients) { - if (mStartcount != 0) { try { mCb.unlinkToDeath(this, 0); } catch (NoSuchElementException e) { - Log.w(TAG, "clearCount() mStartcount: " - + mStartcount + " != 0 but not registered to binder"); + Log.w(TAG, "decCount() going to 0 but not registered to binder"); } } - mStartcount = 0; - if (stopSco) { - requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); + requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); + } + } + + void clearCount(boolean stopSco) { + if (mStartcount != 0) { + try { + mCb.unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + Log.w(TAG, "clearCount() mStartcount: " + + mStartcount + " != 0 but not registered to binder"); } } + mStartcount = 0; + if (stopSco) { + requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); + } } - public int getCount() { + int getCount() { return mStartcount; } - public IBinder getBinder() { + IBinder getBinder() { return mCb; } - public int getPid() { + int getPid() { return mCreatorPid; } - public int totalCount() { - synchronized (mScoClients) { - int count = 0; - for (ScoClient mScoClient : mScoClients) { - count += mScoClient.getCount(); - } - return count; + private int totalCount() { + int count = 0; + for (ScoClient mScoClient : mScoClients) { + count += mScoClient.getCount(); } + return count; } private void requestScoState(int state, int scoAudioMode) { @@ -705,6 +692,7 @@ public class BtHelper { broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); // Accept SCO audio activation only in NORMAL audio mode or if the mode is // currently controlled by the same client process. + // TODO do not sync that way, see b/123769055 synchronized (mDeviceBroker.mSetModeLock) { int modeOwnerPid = mDeviceBroker.getSetModeDeathHandlers().isEmpty() ? 0 : mDeviceBroker.getSetModeDeathHandlers().get(0).getPid(); @@ -857,61 +845,44 @@ public class BtHelper { } } - /*package*/ void resetBluetoothSco() { - synchronized (mScoClients) { - clearAllScoClients(0, false); - mScoAudioState = SCO_STATE_INACTIVE; - broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - } - AudioSystem.setParameters("A2dpSuspended=false"); - mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco"); - } - - private void checkScoAudioState() { - synchronized (mScoClients) { - if (mBluetoothHeadset != null - && mBluetoothHeadsetDevice != null - && mScoAudioState == SCO_STATE_INACTIVE - && mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) - != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; - } + if (mBluetoothHeadset != null + && mBluetoothHeadsetDevice != null + && mScoAudioState == SCO_STATE_INACTIVE + && mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; } } private ScoClient getScoClient(IBinder cb, boolean create) { - synchronized (mScoClients) { - for (ScoClient existingClient : mScoClients) { - if (existingClient.getBinder() == cb) { - return existingClient; - } + for (ScoClient existingClient : mScoClients) { + if (existingClient.getBinder() == cb) { + return existingClient; } - if (create) { - ScoClient newClient = new ScoClient(cb); - mScoClients.add(newClient); - return newClient; - } - return null; } + if (create) { + ScoClient newClient = new ScoClient(cb); + mScoClients.add(newClient); + return newClient; + } + return null; } private void clearAllScoClients(int exceptPid, boolean stopSco) { - synchronized (mScoClients) { - ScoClient savedClient = null; - for (ScoClient cl : mScoClients) { - if (cl.getPid() != exceptPid) { - cl.clearCount(stopSco); - } else { - savedClient = cl; - } - } - mScoClients.clear(); - if (savedClient != null) { - mScoClients.add(savedClient); + ScoClient savedClient = null; + for (ScoClient cl : mScoClients) { + if (cl.getPid() != exceptPid) { + cl.clearCount(stopSco); + } else { + savedClient = cl; } } + mScoClients.clear(); + if (savedClient != null) { + mScoClients.add(savedClient); + } } private boolean getBluetoothHeadset() { diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 1559ba8ba883..07e28f9fb543 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -16,26 +16,27 @@ package com.android.server.connectivity; -// TODO: Clean up imports and remove references of PacketKeepalive constants. - -import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_INTERVAL; -import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS; -import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK; -import static android.net.ConnectivityManager.PacketKeepalive.MIN_INTERVAL; -import static android.net.ConnectivityManager.PacketKeepalive.NATT_PORT; -import static android.net.ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; -import static android.net.ConnectivityManager.PacketKeepalive.SUCCESS; -import static android.net.NetworkAgent.CMD_START_PACKET_KEEPALIVE; -import static android.net.NetworkAgent.CMD_STOP_PACKET_KEEPALIVE; -import static android.net.NetworkAgent.EVENT_PACKET_KEEPALIVE; +import static android.net.NattSocketKeepalive.NATT_PORT; +import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE; +import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE; +import static android.net.NetworkAgent.EVENT_SOCKET_KEEPALIVE; +import static android.net.SocketKeepalive.BINDER_DIED; +import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL; +import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; +import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK; import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET; +import static android.net.SocketKeepalive.MAX_INTERVAL_SEC; +import static android.net.SocketKeepalive.MIN_INTERVAL_SEC; +import static android.net.SocketKeepalive.NO_KEEPALIVE; +import static android.net.SocketKeepalive.SUCCESS; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.ConnectivityManager.PacketKeepalive; import android.net.KeepalivePacketData; +import android.net.NattKeepalivePacketData; import android.net.NetworkAgent; import android.net.NetworkUtils; +import android.net.SocketKeepalive.InvalidPacketException; import android.net.util.IpUtils; import android.os.Binder; import android.os.Handler; @@ -60,7 +61,7 @@ import java.util.ArrayList; import java.util.HashMap; /** - * Manages packet keepalive requests. + * Manages socket keepalive requests. * * Provides methods to stop and start keepalive requests, and keeps track of keepalives across all * networks. This class is tightly coupled to ConnectivityService. It is not thread-safe and its @@ -83,13 +84,13 @@ public class KeepaliveTracker { } /** - * Tracks information about a packet keepalive. + * Tracks information about a socket keepalive. * * All information about this keepalive is known at construction time except the slot number, * which is only returned when the hardware has successfully started the keepalive. */ class KeepaliveInfo implements IBinder.DeathRecipient { - // Bookkeping data. + // Bookkeeping data. private final Messenger mMessenger; private final IBinder mBinder; private final int mUid; @@ -98,7 +99,7 @@ public class KeepaliveTracker { /** Keepalive slot. A small integer that identifies this keepalive among the ones handled * by this network. */ - private int mSlot = PacketKeepalive.NO_KEEPALIVE; + private int mSlot = NO_KEEPALIVE; // Packet data. private final KeepalivePacketData mPacket; @@ -144,7 +145,7 @@ public class KeepaliveTracker { .toString(); } - /** Sends a message back to the application via its PacketKeepalive.Callback. */ + /** Sends a message back to the application via its SocketKeepalive.Callback. */ void notifyMessenger(int slot, int err) { KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err); } @@ -153,8 +154,8 @@ public class KeepaliveTracker { public void binderDied() { // Not called from ConnectivityService handler thread, so send it a message. mConnectivityServiceHandler.obtainMessage( - NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, - mSlot, PacketKeepalive.BINDER_DIED, mNai.network).sendToTarget(); + NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, + mSlot, BINDER_DIED, mNai.network).sendToTarget(); } void unlinkDeathRecipient() { @@ -181,7 +182,10 @@ public class KeepaliveTracker { } private int checkInterval() { - return mInterval >= MIN_INTERVAL ? SUCCESS : ERROR_INVALID_INTERVAL; + if (mInterval < MIN_INTERVAL_SEC || mInterval > MAX_INTERVAL_SEC) { + return ERROR_INVALID_INTERVAL; + } + return SUCCESS; } private int isValid() { @@ -198,7 +202,7 @@ public class KeepaliveTracker { int error = isValid(); if (error == SUCCESS) { Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name()); - mNai.asyncChannel.sendMessage(CMD_START_PACKET_KEEPALIVE, slot, mInterval, mPacket); + mNai.asyncChannel.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket); } else { handleStopKeepalive(mNai, mSlot, error); return; @@ -214,7 +218,7 @@ public class KeepaliveTracker { } if (isStarted) { Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name()); - mNai.asyncChannel.sendMessage(CMD_STOP_PACKET_KEEPALIVE, mSlot); + mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot); } // TODO: at the moment we unconditionally return failure here. In cases where the // NetworkAgent is alive, should we ask it to reply, so it can return failure? @@ -225,7 +229,7 @@ public class KeepaliveTracker { void notifyMessenger(Messenger messenger, int slot, int err) { Message message = Message.obtain(); - message.what = EVENT_PACKET_KEEPALIVE; + message.what = EVENT_SOCKET_KEEPALIVE; message.arg1 = slot; message.arg2 = err; message.obj = null; @@ -310,7 +314,7 @@ public class KeepaliveTracker { } /** Handle keepalive events from lower layer. */ - public void handleEventPacketKeepalive(@NonNull NetworkAgentInfo nai, + public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai, @NonNull Message message) { int slot = message.arg1; int reason = message.arg2; @@ -369,16 +373,16 @@ public class KeepaliveTracker { KeepalivePacketData packet; try { - packet = KeepalivePacketData.nattKeepalivePacket( + packet = NattKeepalivePacketData.nattKeepalivePacket( srcAddress, srcPort, dstAddress, NATT_PORT); - } catch (KeepalivePacketData.InvalidPacketException e) { + } catch (InvalidPacketException e) { notifyMessenger(messenger, NO_KEEPALIVE, e.error); return; } KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds); Log.d(TAG, "Created keepalive: " + ki.toString()); mConnectivityServiceHandler.obtainMessage( - NetworkAgent.CMD_START_PACKET_KEEPALIVE, ki).sendToTarget(); + CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget(); } /** @@ -432,7 +436,7 @@ public class KeepaliveTracker { } public void dump(IndentingPrintWriter pw) { - pw.println("Packet keepalives:"); + pw.println("Socket keepalives:"); pw.increaseIndent(); for (NetworkAgentInfo nai : mKeepalives.keySet()) { pw.println(nai.name()); diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java index 591ce8dd2bae..b3a1a06eedc2 100644 --- a/services/core/java/com/android/server/display/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/ColorDisplayService.java @@ -23,6 +23,7 @@ import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL; import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED; + import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE; import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION; @@ -65,10 +66,9 @@ import android.provider.Settings.System; import android.util.MathUtils; import android.util.Slog; import android.view.SurfaceControl; +import android.view.SurfaceControl.DisplayPrimaries; import android.view.accessibility.AccessibilityManager; import android.view.animation.AnimationUtils; -import android.view.SurfaceControl; -import android.view.SurfaceControl.DisplayPrimaries; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -79,6 +79,7 @@ import com.android.server.SystemService; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -145,6 +146,7 @@ public final class ColorDisplayService extends SystemService { private float[] mCurrentColorTemperatureXYZ; private boolean mSetUp = false; private float[] mMatrixDisplayWhiteBalance = new float[16]; + private Boolean mIsAvailable; @Override public void setUp(Context context, boolean needsLinear) { @@ -255,6 +257,14 @@ public final class ColorDisplayService extends SystemService { return LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE; } + @Override + public boolean isAvailable(Context context) { + if (mIsAvailable == null) { + mIsAvailable = ColorDisplayManager.isDisplayWhiteBalanceAvailable(context); + } + return mIsAvailable; + } + /** * Format a given matrix into a string. * @@ -280,9 +290,7 @@ public final class ColorDisplayService extends SystemService { @Override public void dump(PrintWriter pw) { synchronized (mLock) { - pw.println("ColorDisplayService"); pw.println(" mSetUp = " + mSetUp); - if (!mSetUp) { return; } @@ -402,6 +410,11 @@ public final class ColorDisplayService extends SystemService { public int getLevel() { return LEVEL_COLOR_MATRIX_SATURATION; } + + @Override + public boolean isAvailable(Context context) { + return ColorDisplayManager.isColorTransformAccelerated(context); + } }; /** @@ -623,7 +636,7 @@ public final class ColorDisplayService extends SystemService { // existing activated state. This ensures consistency of tint across the color mode change. onDisplayColorModeChanged(mNightDisplayController.getColorMode()); - if (ColorDisplayManager.isNightDisplayAvailable(getContext())) { + if (mNightDisplayTintController.isAvailable(getContext())) { // Reset the activated state. mNightDisplayTintController.setActivated(null); @@ -641,7 +654,7 @@ public final class ColorDisplayService extends SystemService { } } - if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) { + if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { // Prepare the display white balance transform matrix. mDisplayWhiteBalanceTintController.setUp(getContext(), true /* needsLinear */); @@ -658,7 +671,7 @@ public final class ColorDisplayService extends SystemService { mNightDisplayController = null; } - if (ColorDisplayManager.isNightDisplayAvailable(getContext())) { + if (mNightDisplayTintController.isAvailable(getContext())) { if (mNightDisplayAutoMode != null) { mNightDisplayAutoMode.onStop(); mNightDisplayAutoMode = null; @@ -666,7 +679,7 @@ public final class ColorDisplayService extends SystemService { mNightDisplayTintController.endAnimator(); } - if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) { + if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { mDisplayWhiteBalanceTintController.endAnimator(); } } @@ -714,9 +727,11 @@ public final class ColorDisplayService extends SystemService { mNightDisplayTintController.cancelAnimator(); mDisplayWhiteBalanceTintController.cancelAnimator(); - mNightDisplayTintController - .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode)); - mNightDisplayTintController.setMatrix(getNightDisplayColorTemperatureSetting()); + if (mNightDisplayTintController.isAvailable(getContext())) { + mNightDisplayTintController + .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode)); + mNightDisplayTintController.setMatrix(getNightDisplayColorTemperatureSetting()); + } updateDisplayWhiteBalanceStatus(); @@ -1064,13 +1079,32 @@ public final class ColorDisplayService extends SystemService { private void dumpInternal(PrintWriter pw) { pw.println("COLOR DISPLAY MANAGER dumpsys (color_display)"); + pw.println("Night Display:"); - if (ColorDisplayManager.isNightDisplayAvailable(getContext())) { + if (mNightDisplayTintController.isAvailable(getContext())) { pw.println(" Activated: " + mNightDisplayTintController.isActivated()); + pw.println(" Color temp: " + mNightDisplayTintController.getColorTemperature()); } else { pw.println(" Not available"); } + + pw.println("Global saturation:"); + if (mGlobalSaturationTintController.isAvailable(getContext())) { + pw.println(" Activated: " + mGlobalSaturationTintController.isActivated()); + } else { + pw.println(" Not available"); + } + mAppSaturationController.dump(pw); + + pw.println("Display white balance:"); + if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { + pw.println(" Activated: " + mDisplayWhiteBalanceTintController.isActivated()); + } else { + pw.println(" Not available"); + } + + pw.println("Color mode: " + getColorModeInternal()); } private boolean isNightDisplayActivatedSetting() { @@ -1368,12 +1402,19 @@ public final class ColorDisplayService extends SystemService { * Get the color transform level to apply the matrix. */ public abstract int getLevel(); + + /** + * Returns whether or not this transform type is available on this device. + */ + public abstract boolean isAvailable(Context context); } private final class NightDisplayTintController extends TintController { - private float[] mMatrix = new float[16]; + private final float[] mMatrix = new float[16]; private final float[] mColorTempCoefficients = new float[9]; + + private Boolean mIsAvailable; private Integer mColorTemp; /** @@ -1446,13 +1487,21 @@ public final class ColorDisplayService extends SystemService { return LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; } + @Override + public boolean isAvailable(Context context) { + if (mIsAvailable == null) { + mIsAvailable = ColorDisplayManager.isNightDisplayAvailable(context); + } + return mIsAvailable; + } + void onActivated(boolean activated) { Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display"); if (mNightDisplayAutoMode != null) { mNightDisplayAutoMode.onActivated(activated); } - if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) { + if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { updateDisplayWhiteBalanceStatus(); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java index adc1cd7fc1d3..2c0cacdd26e5 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java @@ -450,6 +450,20 @@ final class HdmiCecKeycode { } /** + * Returns {@code true} if given Android keycode is volume control related, + * otherwise {@code false}. + */ + static boolean isVolumeKeycode(int androidKeycode) { + int cecKeyCode = HdmiCecKeycode.androidKeyToCecKey(androidKeycode)[0]; + return isSupportedKeycode(androidKeycode) + && (cecKeyCode == CEC_KEYCODE_VOLUME_UP + || cecKeyCode == CEC_KEYCODE_VOLUME_DOWN + || cecKeyCode == CEC_KEYCODE_MUTE + || cecKeyCode == CEC_KEYCODE_MUTE_FUNCTION + || cecKeyCode == CEC_KEYCODE_RESTORE_VOLUME_FUNCTION); + } + + /** * Returns CEC keycode to control audio mute status. * * @param muting {@code true} if audio is being muted diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 414f6bbfb995..78b091e436ac 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -1016,6 +1016,40 @@ abstract class HdmiCecLocalDevice { } /** + * Send a volume key event to other CEC device. The logical address of target device will be + * given by {@link #findAudioReceiverAddress()}. + * + * @param keyCode key code defined in {@link android.view.KeyEvent} + * @param isPressed {@code true} for key down event + * @see #findAudioReceiverAddress() + */ + @ServiceThreadOnly + protected void sendVolumeKeyEvent(int keyCode, boolean isPressed) { + assertRunOnServiceThread(); + if (!HdmiCecKeycode.isVolumeKeycode(keyCode)) { + Slog.w(TAG, "Not a volume key: " + keyCode); + return; + } + List<SendKeyAction> action = getActions(SendKeyAction.class); + int logicalAddress = findAudioReceiverAddress(); + if (logicalAddress == Constants.ADDR_INVALID || logicalAddress == mAddress) { + // Don't send key event to invalid device or itself. + Slog.w( + TAG, + "Discard volume key event: " + + keyCode + + ", pressed:" + + isPressed + + ", receiverAddr=" + + logicalAddress); + } else if (!action.isEmpty()) { + action.get(0).processKeyEvent(keyCode, isPressed); + } else if (isPressed) { + addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode)); + } + } + + /** * Returns the logical address of the device which will receive key events via {@link * #sendKeyEvent}. * @@ -1026,6 +1060,17 @@ abstract class HdmiCecLocalDevice { return Constants.ADDR_INVALID; } + /** + * Returns the logical address of the audio receiver device which will receive volume key events + * via {@link#sendVolumeKeyEvent}. + * + * @see #sendVolumeKeyEvent(int, boolean) + */ + protected int findAudioReceiverAddress() { + Slog.w(TAG, "findAudioReceiverAddress is not implemented"); + return Constants.ADDR_INVALID; + } + @ServiceThreadOnly void invokeCallback(IHdmiControlCallback callback, int result) { assertRunOnServiceThread(); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 1ba0c52ce875..67109867c074 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -68,11 +68,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { private static final String TAG = "HdmiCecLocalDeviceAudioSystem"; - // Whether System audio mode is activated or not. - // This becomes true only when all system audio sequences are finished. - @GuardedBy("mLock") - private boolean mSystemAudioActivated; - // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; @@ -271,7 +266,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { synchronized (mLock) { mService.writeStringSystemProperty( Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, - mSystemAudioActivated ? "true" : "false"); + isSystemAudioActivated() ? "true" : "false"); } terminateSystemAudioMode(); } @@ -786,7 +781,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { int maxVolume = mService.getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC); int minVolume = mService.getAudioManager().getStreamMinVolume(AudioManager.STREAM_MUSIC); int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume); - HdmiLogger.debug("Reporting volume %i (%i-%i) as CEC volume %i", volume, + HdmiLogger.debug("Reporting volume %d (%d-%d) as CEC volume %d", volume, minVolume, maxVolume, scaledVolume); mService.sendCecCommand( @@ -814,7 +809,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } HdmiLogger.debug( "System Audio Mode change[old:%b new:%b]", - mSystemAudioActivated, newSystemAudioMode); + isSystemAudioActivated(), newSystemAudioMode); // Wake up device if System Audio Control is turned on if (newSystemAudioMode) { mService.wakeUp(); @@ -854,8 +849,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } updateAudioManagerForSystemAudio(newSystemAudioMode); synchronized (mLock) { - if (mSystemAudioActivated != newSystemAudioMode) { - mSystemAudioActivated = newSystemAudioMode; + if (isSystemAudioActivated() != newSystemAudioMode) { + mService.setSystemAudioActivated(newSystemAudioMode); mService.announceSystemAudioModeChange(newSystemAudioMode); } } @@ -946,9 +941,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } protected boolean isSystemAudioActivated() { - synchronized (mLock) { - return mSystemAudioActivated; - } + return mService.isSystemAudioActivated(); } protected void terminateSystemAudioMode() { @@ -1215,7 +1208,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { protected void dump(IndentingPrintWriter pw) { pw.println("HdmiCecLocalDeviceAudioSystem:"); pw.increaseIndent(); - pw.println("mSystemAudioActivated: " + mSystemAudioActivated); pw.println("isRoutingFeatureEnabled " + isRoutingControlFeatureEnabled()); pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); pw.println("mTvSystemAudioModeSupport: " + mTvSystemAudioModeSupport); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index ef7d24159009..20933db803b9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -19,6 +19,7 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemProperties; @@ -30,6 +31,7 @@ import com.android.internal.app.LocalePicker; import com.android.internal.app.LocalePicker.LocaleInfo; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; +import com.android.server.hdmi.HdmiControlService.SendMessageCallback; import java.io.UnsupportedEncodingException; import java.util.List; @@ -85,6 +87,22 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { mAddress, mService.getPhysicalAddress(), mDeviceType)); mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( mAddress, mService.getVendorId())); + if (mService.audioSystem() == null) { + // If current device is not a functional audio system device, + // send message to potential audio system device in the system to get the system + // audio mode status. If no response, set to false. + mService.sendCecCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus( + mAddress, Constants.ADDR_AUDIO_SYSTEM), new SendMessageCallback() { + @Override + public void onSendCompleted(int error) { + if (error != SendMessageResult.SUCCESS) { + HdmiLogger.debug( + "AVR did not respond to <Give System Audio Mode Status>"); + mService.setSystemAudioActivated(false); + } + } + }); + } startQueuedActions(); } @@ -275,11 +293,50 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } @Override + protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { + // System Audio Mode only turns on/off when Audio System broadcasts on/off message. + // For device with type 4 and 5, it can set system audio mode on/off + // when there is another audio system device connected into the system first. + if (message.getDestination() != Constants.ADDR_BROADCAST + || message.getSource() != Constants.ADDR_AUDIO_SYSTEM + || mService.audioSystem() != null) { + return true; + } + boolean setSystemAudioModeOn = HdmiUtils.parseCommandParamSystemAudioStatus(message); + if (mService.isSystemAudioActivated() != setSystemAudioModeOn) { + mService.setSystemAudioActivated(setSystemAudioModeOn); + } + return true; + } + + @Override + protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { + // Only directly addressed System Audio Mode Status message can change internal + // system audio mode status. + if (message.getDestination() == mAddress + && message.getSource() == Constants.ADDR_AUDIO_SYSTEM) { + boolean setSystemAudioModeOn = HdmiUtils.parseCommandParamSystemAudioStatus(message); + if (mService.isSystemAudioActivated() != setSystemAudioModeOn) { + mService.setSystemAudioActivated(setSystemAudioModeOn); + } + } + return true; + } + + @Override protected int findKeyReceiverAddress() { return Constants.ADDR_TV; } @Override + protected int findAudioReceiverAddress() { + if (mService.isSystemAudioActivated()) { + return Constants.ADDR_AUDIO_SYSTEM; + } + return Constants.ADDR_TV; + } + + @Override @ServiceThreadOnly protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) { super.disableDevice(initiatedByCec, callback); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index a8c435086e8e..8a7051f0e736 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -77,11 +77,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // True by default for all the ARC-enabled ports. private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray(); - // Whether System audio mode is activated or not. - // This becomes true only when all system audio sequences are finished. - @GuardedBy("mLock") - private boolean mSystemAudioActivated = false; - // Whether the System Audio Control feature is enabled or not. True by default. @GuardedBy("mLock") private boolean mSystemAudioControlFeatureEnabled; @@ -829,11 +824,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { + "because the System Audio Control feature is disabled."); return; } - HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on); + HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", + mService.isSystemAudioActivated(), on); updateAudioManagerForSystemAudio(on); synchronized (mLock) { - if (mSystemAudioActivated != on) { - mSystemAudioActivated = on; + if (mService.isSystemAudioActivated() != on) { + mService.setSystemAudioActivated(on); mService.announceSystemAudioModeChange(on); } startArcAction(on); @@ -849,9 +845,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!hasSystemAudioDevice()) { return false; } - synchronized (mLock) { - return mSystemAudioActivated; - } + return mService.isSystemAudioActivated(); } @ServiceThreadOnly @@ -1904,7 +1898,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { super.dump(pw); pw.println("mArcEstablished: " + mArcEstablished); pw.println("mArcFeatureEnabled: " + mArcFeatureEnabled); - pw.println("mSystemAudioActivated: " + mSystemAudioActivated); pw.println("mSystemAudioMute: " + mSystemAudioMute); pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled); pw.println("mAutoDeviceOff: " + mAutoDeviceOff); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index c5eccdf57e73..7376ed2b0679 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -147,6 +147,10 @@ public class HdmiControlService extends SystemService { @GuardedBy("mLock") protected final ActiveSource mActiveSource = new ActiveSource(); + // Whether System Audio Mode is activated or not. + @GuardedBy("mLock") + private boolean mSystemAudioActivated = false; + private static final boolean isHdmiCecNeverClaimPlaybackLogicAddr = SystemProperties.getBoolean( Constants.PROPERTY_HDMI_CEC_NEVER_CLAIM_PLAYBACK_LOGICAL_ADDRESS, false); @@ -1533,7 +1537,7 @@ public class HdmiControlService extends SystemService { if (mCecController != null) { HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(deviceType); if (localDevice == null) { - Slog.w(TAG, "Local device not available"); + Slog.w(TAG, "Local device not available to send key event."); return; } localDevice.sendKeyEvent(keyCode, isPressed); @@ -1543,6 +1547,28 @@ public class HdmiControlService extends SystemService { } @Override + public void sendVolumeKeyEvent( + final int deviceType, final int keyCode, final boolean isPressed) { + enforceAccessPermission(); + runOnServiceThread(new Runnable() { + @Override + public void run() { + if (mCecController == null) { + Slog.w(TAG, "CEC controller not available to send volume key event."); + return; + } + HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(deviceType); + if (localDevice == null) { + Slog.w(TAG, "Local device " + deviceType + + " not available to send volume key event."); + return; + } + localDevice.sendVolumeKeyEvent(keyCode, isPressed); + } + }); + } + + @Override public void oneTouchPlay(final IHdmiControlCallback callback) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @@ -2010,6 +2036,7 @@ public class HdmiControlService extends SystemService { pw.increaseIndent(); pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled); pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled); + pw.println("mSystemAudioActivated: " + isSystemAudioActivated()); pw.decreaseIndent(); pw.println("mMhlController: "); @@ -2636,6 +2663,18 @@ public class HdmiControlService extends SystemService { } } + boolean isSystemAudioActivated() { + synchronized (mLock) { + return mSystemAudioActivated; + } + } + + void setSystemAudioActivated(boolean on) { + synchronized (mLock) { + mSystemAudioActivated = on; + } + } + @ServiceThreadOnly void setCecOption(int key, boolean value) { assertRunOnServiceThread(); diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java index 40d2583691c6..5ad7fab888fd 100644 --- a/services/core/java/com/android/server/hdmi/SendKeyAction.java +++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java @@ -17,8 +17,10 @@ package com.android.server.hdmi; import static com.android.server.hdmi.HdmiConfig.IRT_MS; +import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; import android.view.KeyEvent; +import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Feature action that transmits remote control key command (User Control Press/ @@ -146,8 +148,26 @@ final class SendKeyAction extends HdmiCecFeatureAction { if (cecKeycodeAndParams == null) { return; } - sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), - mTargetAddress, cecKeycodeAndParams)); + // Devices that are not directly connected with audio system device can't detect if the + // audio system device is still plugged in. Framework checks if the volume key forwarding is + // successful or not every time to make sure the System Audio Mode status is still updated. + if (mTargetAddress == Constants.ADDR_AUDIO_SYSTEM + && localDevice().mAddress != Constants.ADDR_TV) { + sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), + mTargetAddress, cecKeycodeAndParams), new SendMessageCallback() { + @Override + public void onSendCompleted(int error) { + if (error != SendMessageResult.SUCCESS) { + HdmiLogger.debug( + "AVR did not respond to <User Control Pressed>"); + localDevice().mService.setSystemAudioActivated(false); + } + } + }); + } else { + sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), + mTargetAddress, cecKeycodeAndParams)); + } } private void sendKeyUp() { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index d20508a5e704..144f2b6b143f 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -1627,10 +1627,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public List<InputMethodInfo> getInputMethodList() { - final int callingUserId = UserHandle.getCallingUserId(); + public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + } synchronized (mMethodMap) { - final int[] resolvedUserIds = InputMethodUtils.resolveUserId(callingUserId, + final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId, mSettings.getCurrentUserId(), null); if (resolvedUserIds.length != 1) { return Collections.emptyList(); @@ -1645,10 +1647,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public List<InputMethodInfo> getEnabledInputMethodList() { - final int callingUserId = UserHandle.getCallingUserId(); + public List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + } synchronized (mMethodMap) { - final int[] resolvedUserIds = InputMethodUtils.resolveUserId(callingUserId, + final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId, mSettings.getCurrentUserId(), null); if (resolvedUserIds.length != 1) { return Collections.emptyList(); @@ -4697,7 +4701,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSettings.getCurrentUserId(), mContext.getBasePackageName()); nextIme = mSettings.getSelectedInputMethod(); - nextEnabledImes = getEnabledInputMethodList(); + nextEnabledImes = mSettings.getEnabledInputMethodListLocked(); final PrintWriter pr = shellCommand.getOutPrintWriter(); pr.println("Reset current and enabled IMEs"); pr.println("Newly selected IME:"); diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 3222143fc89f..500c388ec99e 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -16,6 +16,7 @@ package com.android.server.inputmethod; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -1195,6 +1196,7 @@ public final class MultiClientInputMethodManagerService { * Takes care of IPCs exposed to the IME client. */ private static final class ApiCallbacks extends IInputMethodManager.Stub { + private final Context mContext; private final UserDataMap mUserDataMap; private final UserToInputMethodInfoMap mInputMethodInfoMap; private final AppOpsManager mAppOpsManager; @@ -1202,6 +1204,7 @@ public final class MultiClientInputMethodManagerService { ApiCallbacks(Context context, UserDataMap userDataMap, UserToInputMethodInfoMap inputMethodInfoMap) { + mContext = context; mUserDataMap = userDataMap; mInputMethodInfoMap = inputMethodInfoMap; mAppOpsManager = context.getSystemService(AppOpsManager.class); @@ -1233,14 +1236,20 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override - public List<InputMethodInfo> getInputMethodList() { - return mInputMethodInfoMap.getAsList(UserHandle.getUserId(Binder.getCallingUid())); + public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, null); + } + return mInputMethodInfoMap.getAsList(userId); } @BinderThread @Override - public List<InputMethodInfo> getEnabledInputMethodList() { - return mInputMethodInfoMap.getAsList(UserHandle.getUserId(Binder.getCallingUid())); + public List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) { + if (UserHandle.getCallingUserId() != userId) { + mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, null); + } + return mInputMethodInfoMap.getAsList(userId); } @BinderThread diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index cefe583fc5d1..19d10ecfb34d 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -509,7 +509,7 @@ public class JobSchedulerService extends com.android.server.SystemService private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f; private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f; private static final boolean DEFAULT_USE_HEARTBEATS = false; - private static final boolean DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true; + private static final boolean DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false; private static final long DEFAULT_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS = 10 * 60 * 1000L; // 10 minutes private static final long DEFAULT_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS = diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java index b3f101848692..0edd17b1f777 100644 --- a/services/core/java/com/android/server/location/AbstractLocationProvider.java +++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.content.Context; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -26,6 +27,7 @@ import com.android.internal.location.ProviderRequest; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Collections; import java.util.List; /** @@ -65,9 +67,12 @@ public abstract class AbstractLocationProvider { void onReportLocation(List<Location> locations); } + protected final Context mContext; private final LocationProviderManager mLocationProviderManager; - protected AbstractLocationProvider(LocationProviderManager locationProviderManager) { + protected AbstractLocationProvider( + Context context, LocationProviderManager locationProviderManager) { + mContext = context; mLocationProviderManager = locationProviderManager; } @@ -101,6 +106,11 @@ public abstract class AbstractLocationProvider { mLocationProviderManager.onSetProperties(properties); } + /** Returns list of packages currently associated with this provider. */ + public List<String> getProviderPackages() { + return Collections.singletonList(mContext.getPackageName()); + } + /** * Called when the location service delivers a new request for fulfillment to the provider. * Replaces any previous requests completely. diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java new file mode 100644 index 000000000000..da31d0b8e9a3 --- /dev/null +++ b/services/core/java/com/android/server/location/CallerIdentity.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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.location; + +/** + * Represents the calling process's uid, pid, and package name. + */ +public class CallerIdentity { + public final int mUid; + public final int mPid; + public final String mPackageName; + + public CallerIdentity(int uid, int pid, String packageName) { + mUid = uid; + mPid = pid; + mPackageName = packageName; + } +} diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index ab9f711b4238..f368e7b8494e 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -24,6 +24,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.database.ContentObserver; import android.hardware.location.GeofenceHardware; import android.hardware.location.GeofenceHardwareImpl; import android.location.Criteria; @@ -168,21 +169,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int AGPS_SUPL_MODE_MSA = 0x02; private static final int AGPS_SUPL_MODE_MSB = 0x01; - // Handler messages - private static final int CHECK_LOCATION = 1; - private static final int ENABLE = 2; private static final int SET_REQUEST = 3; - private static final int UPDATE_NETWORK_STATE = 4; private static final int INJECT_NTP_TIME = 5; private static final int DOWNLOAD_XTRA_DATA = 6; private static final int UPDATE_LOCATION = 7; // Handle external location from network listener - private static final int ADD_LISTENER = 8; - private static final int REMOVE_LISTENER = 9; private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11; private static final int SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED = 12; private static final int INITIALIZE_HANDLER = 13; - private static final int REQUEST_SUPL_CONNECTION = 14; - private static final int RELEASE_SUPL_CONNECTION = 15; private static final int REQUEST_LOCATION = 16; private static final int REPORT_LOCATION = 17; // HAL reports location private static final int REPORT_SV_STATUS = 18; // HAL reports SV status @@ -311,6 +304,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // true if we are enabled, protected by this private boolean mEnabled = true; + private boolean mShutdown; + // states for injecting ntp and downloading xtra data private static final int STATE_PENDING_NETWORK = 0; private static final int STATE_DOWNLOADING = 1; @@ -349,7 +344,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private GnssPositionMode mLastPositionMode; // Current request from underlying location clients. - private ProviderRequest mProviderRequest = null; + private ProviderRequest mProviderRequest; // The WorkSource associated with the most recent client request (i.e, most recent call to // setRequest). private WorkSource mWorkSource = null; @@ -368,11 +363,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private int mC2KServerPort; private boolean mSuplEsEnabled = false; - private final Context mContext; private final Looper mLooper; private final LocationExtras mLocationExtras = new LocationExtras(); private final GnssStatusListenerHelper mGnssStatusListenerHelper; - private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper; private final GnssMeasurementsProvider mGnssMeasurementsProvider; private final GnssNavigationMessageProvider mGnssNavigationMessageProvider; private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener(); @@ -530,8 +523,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // Disable GPS if we are in device idle mode. boolean disableGps = mPowerManager.isDeviceIdleMode(); final PowerSaveState result = - mPowerManager.getPowerSaveState(ServiceType.GPS); - switch (result.gpsMode) { + mPowerManager.getPowerSaveState(ServiceType.LOCATION); + switch (result.locationMode) { case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF: // If we are in battery saver mode and the screen is off, disable GPS. disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive(); @@ -539,6 +532,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } if (disableGps != mDisableGps) { mDisableGps = disableGps; + updateEnabled(); updateRequirements(); } } @@ -562,9 +556,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements public GnssLocationProvider(Context context, LocationProviderManager locationProviderManager, Looper looper) { - super(locationProviderManager); + super(context, locationProviderManager); - mContext = context; mLooper = looper; // Create a wake lock @@ -637,23 +630,32 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mGnssMetrics = new GnssMetrics(mBatteryStats); mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this); - mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext, - looper, this); - mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist); + GnssSatelliteBlacklistHelper gnssSatelliteBlacklistHelper = + new GnssSatelliteBlacklistHelper(mContext, + looper, this); + mHandler.post(gnssSatelliteBlacklistHelper::updateSatelliteBlacklist); mGnssBatchingProvider = new GnssBatchingProvider(); mGnssGeofenceProvider = new GnssGeofenceProvider(); - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiverAsUser(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (getSendingUserId() == UserHandle.USER_ALL) { - mEnabled = false; - handleDisable(); + mShutdown = true; + updateEnabled(); } } - }, UserHandle.ALL, intentFilter, null, mHandler); + }, UserHandle.ALL, new IntentFilter(Intent.ACTION_SHUTDOWN), null, mHandler); + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), + true, + new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + updateEnabled(); + } + }, UserHandle.USER_ALL); setProperties(PROPERTIES); setEnabled(true); @@ -867,12 +869,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements return GPS_POSITION_MODE_STANDALONE; } - private void handleEnable() { + private boolean handleEnable() { if (DEBUG) Log.d(TAG, "handleEnable"); - boolean enabled = native_init(); + boolean inited = native_init(); - if (enabled) { + if (inited) { mSupportsXtra = native_supports_xtra(); // TODO: remove the following native calls if we can make sure they are redundant. @@ -889,11 +891,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mGnssNavigationMessageProvider.onGpsEnabledChanged(); mGnssBatchingProvider.enable(); } else { - synchronized (mLock) { - mEnabled = false; - } Log.w(TAG, "Failed to enable location provider"); } + + return inited; } private void handleDisable() { @@ -912,6 +913,26 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mGnssNavigationMessageProvider.onGpsEnabledChanged(); } + private void updateEnabled() { + synchronized (mLock) { + boolean enabled = + ((mProviderRequest != null && mProviderRequest.reportLocation + && mProviderRequest.forceLocation) || ( + mContext.getSystemService(LocationManager.class).isLocationEnabled() + && !mDisableGps)) && !mShutdown; + if (enabled == mEnabled) { + return; + } + + if (enabled) { + mEnabled = handleEnable(); + } else { + mEnabled = false; + handleDisable(); + } + } + } + public boolean isEnabled() { synchronized (mLock) { return mEnabled; @@ -944,6 +965,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private void handleSetRequest(ProviderRequest request, WorkSource source) { mProviderRequest = request; mWorkSource = source; + updateEnabled(); updateRequirements(); } @@ -1492,8 +1514,11 @@ public class GnssLocationProvider extends AbstractLocationProvider implements class_init_native(); native_init_once(); if (isEnabled()) { - // re-calls native_init() and other setup. - handleEnable(); + synchronized (mLock) { + mEnabled = false; + } + updateEnabled(); + // resend configuration into the restarted HAL service. reloadGpsProperties(); } @@ -1692,7 +1717,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements /* requestorIdEncoding= */ 0, /* textEncoding= */ 0, mSuplEsEnabled, - mEnabled, + isEnabled(), userResponse); return true; @@ -1758,7 +1783,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements notification.requestorIdEncoding, notification.textEncoding, mSuplEsEnabled, - mEnabled, + isEnabled(), /* userResponse= */ 0); } @@ -1883,9 +1908,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements public void handleMessage(Message msg) { int message = msg.what; switch (message) { - case ENABLE: - handleEnable(); - break; case SET_REQUEST: GpsRequest gpsRequest = (GpsRequest) msg.obj; handleSetRequest(gpsRequest.request, gpsRequest.source); @@ -2000,8 +2022,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements new NetworkLocationListener(), getLooper()); - // enable gps provider, it will never be disabled (legacy behavior) - sendEmptyMessage(ENABLE); + updateEnabled(); } } @@ -2045,8 +2066,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements */ private String messageIdAsString(int message) { switch (message) { - case ENABLE: - return "ENABLE"; case SET_REQUEST: return "SET_REQUEST"; case INJECT_NTP_TIME: diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java index 77dee8241bea..1fc7192916df 100644 --- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java @@ -95,15 +95,11 @@ public abstract class GnssMeasurementsProvider */ public void injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections) { - mHandler.post( - new Runnable() { - @Override - public void run() { - if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) { - Log.e(TAG, "Failure in injecting GNSS corrections."); - } - } - }); + mHandler.post(() -> { + if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) { + Log.e(TAG, "Failure in injecting GNSS corrections."); + } + }); } @Override @@ -115,15 +111,14 @@ public abstract class GnssMeasurementsProvider } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { - foreach( - (IGnssMeasurementsListener listener, int uid, String packageName) -> { - if (!hasPermission(uid, packageName)) { - logPermissionDisabledEventNotReported( - TAG, packageName, "GNSS measurements"); - return; - } - listener.onGnssMeasurementsReceived(event); - }); + foreach((IGnssMeasurementsListener listener, CallerIdentity callerIdentity) -> { + if (!hasPermission(mContext, callerIdentity)) { + logPermissionDisabledEventNotReported( + TAG, callerIdentity.mPackageName, "GNSS measurements"); + return; + } + listener.onGnssMeasurementsReceived(event); + }); } /** Updates the framework about the capabilities of the GNSS chipset */ @@ -182,7 +177,7 @@ public abstract class GnssMeasurementsProvider @Override public void execute(IGnssMeasurementsListener listener, - int uid, String packageName) throws RemoteException { + CallerIdentity callerIdentity) throws RemoteException { listener.onStatusChanged(mStatus); } } diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java index 679919f8fc67..80a3f9bd2aba 100644 --- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java +++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java @@ -86,7 +86,7 @@ public abstract class GnssNavigationMessageProvider } public void onNavigationMessageAvailable(final GnssNavigationMessage event) { - foreach((IGnssNavigationMessageListener listener, int uid, String packageName) -> { + foreach((IGnssNavigationMessageListener listener, CallerIdentity callerIdentity) -> { listener.onGnssNavigationMessageReceived(event); } ); @@ -136,7 +136,7 @@ public abstract class GnssNavigationMessageProvider @Override public void execute(IGnssNavigationMessageListener listener, - int uid, String packageName) throws RemoteException { + CallerIdentity callerIdentity) throws RemoteException { listener.onStatusChanged(mStatus); } } diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java index 454dbddc406a..d67d0c5fe612 100644 --- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java +++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java @@ -48,18 +48,18 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns public void onStatusChanged(boolean isNavigating) { if (isNavigating) { - foreach((IGnssStatusListener listener, int uid, String packageName) -> { + foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> { listener.onGnssStarted(); }); } else { - foreach((IGnssStatusListener listener, int uid, String packageName) -> { + foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> { listener.onGnssStopped(); }); } } public void onFirstFix(final int timeToFirstFix) { - foreach((IGnssStatusListener listener, int uid, String packageName) -> { + foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> { listener.onFirstFix(timeToFirstFix); } ); @@ -72,9 +72,10 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns final float[] elevations, final float[] azimuths, final float[] carrierFreqs) { - foreach((IGnssStatusListener listener, int uid, String packageName) -> { - if (!hasPermission(uid, packageName)) { - logPermissionDisabledEventNotReported(TAG, packageName, "GNSS status"); + foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> { + if (!hasPermission(mContext, callerIdentity)) { + logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName, + "GNSS status"); return; } listener.onSvStatusChanged(svCount, prnWithFlags, cn0s, elevations, azimuths, @@ -83,9 +84,9 @@ public abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGns } public void onNmeaReceived(final long timestamp, final String nmea) { - foreach((IGnssStatusListener listener, int uid, String packageName) -> { - if (!hasPermission(uid, packageName)) { - logPermissionDisabledEventNotReported(TAG, packageName, "NMEA"); + foreach((IGnssStatusListener listener, CallerIdentity callerIdentity) -> { + if (!hasPermission(mContext, callerIdentity)) { + logPermissionDisabledEventNotReported(TAG, callerIdentity.mPackageName, "NMEA"); return; } listener.onNmeaReceived(timestamp, nmea); diff --git a/services/core/java/com/android/server/location/LocationPermissionUtil.java b/services/core/java/com/android/server/location/LocationPermissionUtil.java new file mode 100644 index 000000000000..4465f31cb45b --- /dev/null +++ b/services/core/java/com/android/server/location/LocationPermissionUtil.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 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.location; + +import android.content.Context; +import android.content.pm.PackageManager; + +/** + * Encapsulates utility functions and classes related to location permission checking. + */ +public final class LocationPermissionUtil { + /** + * Returns true if the calling process identified by {@code callerIdentity} is enabled to + * report location to AppOps service before providing device location identifiable information + * to its clients. Packages with these permissions must report any reporting of location + * information to apps, via AppOps. + * + * <p>The calling package represented by {@code callerIdentity} is considered a part of the + * extended Location Manager Service if it has all of the permissions below. + * <ul> + * <li>{@link android.Manifest.permission#LOCATION_HARDWARE} + * <li>{@link android.Manifest.permission#UPDATE_APP_OPS_STATS} + * </ul> + * + * <p>Any package with these permissions, that passes along location information from Android + * framework to apps, must report to AppOps, similarly to Location Manager Service - i.e. + * whenever it reports device location or location identifiable information such as + * GNSS status, GNSS measurements, etc. to its clients. + */ + public static boolean doesCallerReportToAppOps(Context context, CallerIdentity callerIdentity) { + return hasPermissionLocationHardware(context, callerIdentity) + && hasPermissionUpdateAppOpsStats(context, callerIdentity); + } + + private static boolean hasPermissionLocationHardware(Context context, + CallerIdentity callerIdentity) { + return context.checkPermission(android.Manifest.permission.LOCATION_HARDWARE, + callerIdentity.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED; + } + + private static boolean hasPermissionUpdateAppOpsStats(Context context, + CallerIdentity callerIdentity) { + return context.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, + callerIdentity.mPid, callerIdentity.mUid) == PackageManager.PERMISSION_GRANTED; + } + + private LocationPermissionUtil() {} +} diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 776beb50be62..34c8786b00b3 100644 --- a/services/core/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java @@ -16,8 +16,11 @@ package com.android.server.location; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + import android.annotation.Nullable; import android.content.Context; +import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -39,6 +42,10 @@ import com.android.server.ServiceWatcher; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * Proxy for ILocationProvider implementations. @@ -48,14 +55,21 @@ public class LocationProviderProxy extends AbstractLocationProvider { private static final String TAG = "LocationProviderProxy"; private static final boolean D = LocationManagerService.D; + // used to ensure that updates to mProviderPackages are atomic + private final Object mProviderPackagesLock = new Object(); + // used to ensure that updates to mRequest and mWorkSource are atomic private final Object mRequestLock = new Object(); - private final ServiceWatcher mServiceWatcher; - private final ILocationProviderManager.Stub mManager = new ILocationProviderManager.Stub() { // executed on binder thread @Override + public void onSetAdditionalProviderPackages(List<String> packageNames) { + LocationProviderProxy.this.onSetAdditionalProviderPackages(packageNames); + } + + // executed on binder thread + @Override public void onSetEnabled(boolean enabled) { LocationProviderProxy.this.setEnabled(enabled); } @@ -73,6 +87,11 @@ public class LocationProviderProxy extends AbstractLocationProvider { } }; + private final ServiceWatcher mServiceWatcher; + + @GuardedBy("mProviderPackagesLock") + private final CopyOnWriteArrayList<String> mProviderPackages = new CopyOnWriteArrayList<>(); + @GuardedBy("mRequestLock") @Nullable private ProviderRequest mRequest; @@ -101,7 +120,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { private LocationProviderProxy(Context context, LocationProviderManager locationProviderManager, String action, int overlaySwitchResId, int defaultServicePackageNameResId, int initialPackageNamesResId) { - super(locationProviderManager); + super(context, locationProviderManager); mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId, @@ -114,6 +133,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { @Override protected void onUnbind() { + resetProviderPackages(Collections.emptyList()); setEnabled(false); setProperties(null); } @@ -131,6 +151,8 @@ public class LocationProviderProxy extends AbstractLocationProvider { ILocationProvider service = ILocationProvider.Stub.asInterface(binder); if (D) Log.d(TAG, "applying state to connected service " + mServiceWatcher); + resetProviderPackages(Collections.emptyList()); + service.setLocationProviderManager(mManager); synchronized (mRequestLock) { @@ -140,9 +162,11 @@ public class LocationProviderProxy extends AbstractLocationProvider { } } - @Nullable - public String getConnectedPackageName() { - return mServiceWatcher.getCurrentPackageName(); + @Override + public List<String> getProviderPackages() { + synchronized (mProviderPackagesLock) { + return mProviderPackages; + } } @Override @@ -193,4 +217,30 @@ public class LocationProviderProxy extends AbstractLocationProvider { service.sendExtraCommand(command, extras); }); } + + private void onSetAdditionalProviderPackages(List<String> packageNames) { + resetProviderPackages(packageNames); + } + + private void resetProviderPackages(List<String> additionalPackageNames) { + ArrayList<String> permittedPackages = new ArrayList<>(additionalPackageNames.size()); + for (String packageName : additionalPackageNames) { + try { + mContext.getPackageManager().getPackageInfo(packageName, MATCH_SYSTEM_ONLY); + permittedPackages.add(packageName); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, mServiceWatcher + " specified unknown additional provider package: " + + packageName); + } + } + + synchronized (mProviderPackagesLock) { + mProviderPackages.clear(); + String myPackage = mServiceWatcher.getCurrentPackageName(); + if (myPackage != null) { + mProviderPackages.add(myPackage); + mProviderPackages.addAll(permittedPackages); + } + } + } } diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java index fe91c63e712b..6accad8a93a0 100644 --- a/services/core/java/com/android/server/location/MockProvider.java +++ b/services/core/java/com/android/server/location/MockProvider.java @@ -17,6 +17,7 @@ package com.android.server.location; import android.annotation.Nullable; +import android.content.Context; import android.location.Location; import android.location.LocationProvider; import android.os.Bundle; @@ -41,9 +42,9 @@ public class MockProvider extends AbstractLocationProvider { private long mStatusUpdateTime; private Bundle mExtras; - public MockProvider( + public MockProvider(Context context, LocationProviderManager locationProviderManager, ProviderProperties properties) { - super(locationProviderManager); + super(context, locationProviderManager); mEnabled = true; mLocation = null; diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java index 30260b2fe14c..3a841c91399e 100644 --- a/services/core/java/com/android/server/location/PassiveProvider.java +++ b/services/core/java/com/android/server/location/PassiveProvider.java @@ -16,6 +16,7 @@ package com.android.server.location; +import android.content.Context; import android.location.Criteria; import android.location.Location; import android.os.Bundle; @@ -42,8 +43,8 @@ public class PassiveProvider extends AbstractLocationProvider { private boolean mReportLocation; - public PassiveProvider(LocationProviderManager locationProviderManager) { - super(locationProviderManager); + public PassiveProvider(Context context, LocationProviderManager locationProviderManager) { + super(context, locationProviderManager); mReportLocation = false; diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java index e69b2ec28ebc..f03c99b0272e 100644 --- a/services/core/java/com/android/server/location/RemoteListenerHelper.java +++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java @@ -71,10 +71,10 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { return mIsRegistered; } - public boolean addListener(@NonNull TListener listener, int uid, String packageName) { + public boolean addListener(@NonNull TListener listener, CallerIdentity callerIdentity) { Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener."); IBinder binder = listener.asBinder(); - LinkedListener deathListener = new LinkedListener(listener, uid, packageName); + LinkedListener deathListener = new LinkedListener(listener, callerIdentity); synchronized (mListenerMap) { if (mListenerMap.containsKey(binder)) { // listener already added @@ -137,7 +137,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { protected abstract ListenerOperation<TListener> getHandlerOperation(int result); protected interface ListenerOperation<TListener extends IInterface> { - void execute(TListener listener, int uid, String packageName) throws RemoteException; + void execute(TListener listener, CallerIdentity callerIdentity) throws RemoteException; } protected void foreach(ListenerOperation<TListener> operation) { @@ -177,9 +177,16 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { } } - protected boolean hasPermission(int uid, String packageName) { - return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, uid, packageName) - == AppOpsManager.MODE_ALLOWED; + protected boolean hasPermission(Context context, CallerIdentity callerIdentity) { + if (LocationPermissionUtil.doesCallerReportToAppOps(context, callerIdentity)) { + // The caller is identified as a location provider that will report location + // access to AppOps. Skip noteOp but do checkOp to check for location permission. + return mAppOps.checkOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid, + callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED; + } + + return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid, + callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED; } protected void logPermissionDisabledEventNotReported(String tag, String packageName, @@ -254,13 +261,11 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { private class LinkedListener implements IBinder.DeathRecipient { private final TListener mListener; - private final int mUid; - private final String mPackageName; + private final CallerIdentity mCallerIdentity; - LinkedListener(@NonNull TListener listener, int uid, String packageName) { + LinkedListener(@NonNull TListener listener, CallerIdentity callerIdentity) { mListener = listener; - mUid = uid; - mPackageName = packageName; + mCallerIdentity = callerIdentity; } @Override @@ -282,8 +287,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> { @Override public void run() { try { - mOperation.execute(mLinkedListener.mListener, mLinkedListener.mUid, - mLinkedListener.mPackageName); + mOperation.execute(mLinkedListener.mListener, mLinkedListener.mCallerIdentity); } catch (RemoteException e) { Log.v(mTag, "Error in monitored listener.", e); } diff --git a/services/core/java/com/android/server/media/MediaUpdateService.java b/services/core/java/com/android/server/media/MediaUpdateService.java deleted file mode 100644 index 7304f0788a1d..000000000000 --- a/services/core/java/com/android/server/media/MediaUpdateService.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 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.media; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.media.IMediaUpdateService; -import android.os.Build; -import android.os.IBinder; -import android.os.Handler; -import android.os.PatternMatcher; -import android.os.ServiceManager; -import android.os.SystemProperties; -import android.os.UserHandle; -import android.text.TextUtils; -import android.util.Log; -import android.util.Slog; -import com.android.server.SystemService; -import java.util.HashMap; - -/** This class provides a system service that manages media framework updates. */ -public class MediaUpdateService extends SystemService { - private static final String TAG = "MediaUpdateService"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final String MEDIA_UPDATE_PACKAGE_NAME = - SystemProperties.get("ro.mediacomponents.package"); - private static final String EXTRACTOR_UPDATE_SERVICE_NAME = "media.extractor.update"; - private static final String CODEC_UPDATE_SERVICE_NAME = "media.codec.update"; - private static final String[] UPDATE_SERVICE_NAME_ARRAY = { - EXTRACTOR_UPDATE_SERVICE_NAME, CODEC_UPDATE_SERVICE_NAME, - }; - private final HashMap<String, IMediaUpdateService> mUpdateServiceMap = new HashMap<>(); - private final Handler mHandler = new Handler(); - - public MediaUpdateService(Context context) { - super(context); - } - - @Override - public void onStart() { - if (("userdebug".equals(android.os.Build.TYPE) || "eng".equals(android.os.Build.TYPE)) - && !TextUtils.isEmpty(MEDIA_UPDATE_PACKAGE_NAME)) { - for (String serviceName : UPDATE_SERVICE_NAME_ARRAY) { - connect(serviceName); - } - registerBroadcastReceiver(); - } - } - - private void connect(final String serviceName) { - IBinder binder = ServiceManager.getService(serviceName); - if (binder != null) { - try { - binder.linkToDeath(new IBinder.DeathRecipient() { - @Override - public void binderDied() { - Slog.w(TAG, "service " + serviceName + " died; reconnecting"); - synchronized (mUpdateServiceMap) { - mUpdateServiceMap.remove(serviceName); - } - connect(serviceName); - } - }, 0); - } catch (Exception e) { - binder = null; - } - } - if (binder != null) { - synchronized (mUpdateServiceMap) { - mUpdateServiceMap.put(serviceName, - IMediaUpdateService.Stub.asInterface(binder)); - } - mHandler.post(new Runnable() { - @Override - public void run() { - packageStateChanged(serviceName); - } - }); - } else { - Slog.w(TAG, serviceName + " not found."); - } - } - - private void registerBroadcastReceiver() { - BroadcastReceiver updateReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_SYSTEM) - != UserHandle.USER_SYSTEM) { - // Ignore broadcast for non system users. We don't want to update system - // service multiple times. - return; - } - switch (intent.getAction()) { - case Intent.ACTION_PACKAGE_REMOVED: - if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) { - // The existing package is updated. Will be handled with the - // following ACTION_PACKAGE_ADDED case. - return; - } - // fall-thru - case Intent.ACTION_PACKAGE_CHANGED: - case Intent.ACTION_PACKAGE_ADDED: - for (String serviceName : UPDATE_SERVICE_NAME_ARRAY) { - packageStateChanged(serviceName); - } - break; - } - } - }; - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - filter.addDataScheme("package"); - filter.addDataSchemeSpecificPart(MEDIA_UPDATE_PACKAGE_NAME, PatternMatcher.PATTERN_LITERAL); - - getContext().registerReceiverAsUser(updateReceiver, UserHandle.ALL, filter, - null /* broadcast permission */, null /* handler */); - } - - private void packageStateChanged(String serviceName) { - ApplicationInfo packageInfo = null; - boolean pluginsAvailable = false; - try { - packageInfo = getContext().getPackageManager().getApplicationInfo( - MEDIA_UPDATE_PACKAGE_NAME, PackageManager.MATCH_SYSTEM_ONLY); - pluginsAvailable = packageInfo.enabled; - } catch (Exception e) { - Slog.v(TAG, "package '" + MEDIA_UPDATE_PACKAGE_NAME + "' not installed"); - } - if (packageInfo != null && Build.VERSION.SDK_INT != packageInfo.targetSdkVersion) { - Slog.w(TAG, "This update package is not for this platform version. Ignoring. " - + "platform:" + Build.VERSION.SDK_INT - + " targetSdk:" + packageInfo.targetSdkVersion); - pluginsAvailable = false; - } - loadPlugins(serviceName, - (packageInfo != null && pluginsAvailable) ? packageInfo.sourceDir : ""); - } - - private void loadPlugins(String serviceName, String apkPath) { - try { - IMediaUpdateService service = null; - synchronized (serviceName) { - service = mUpdateServiceMap.get(serviceName); - } - if (service != null) { - service.loadPlugins(apkPath); - } else { - Slog.w(TAG, "service " + serviceName + " passed away"); - } - } catch (Exception e) { - Slog.w(TAG, "Error in loadPlugins for " + serviceName, e); - } - } -} diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java index be15fdaf5abe..b85abd98b00f 100644 --- a/services/core/java/com/android/server/notification/NotificationDelegate.java +++ b/services/core/java/com/android/server/notification/NotificationDelegate.java @@ -51,7 +51,7 @@ public interface NotificationDelegate { * Notifies that smart replies and actions have been added to the UI. */ void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount, - boolean generatedByAssistant); + boolean generatedByAssistant, boolean editBeforeSending); /** * Notifies a smart reply is sent. @@ -59,9 +59,9 @@ public interface NotificationDelegate { * @param key the notification key * @param clickedIndex the index of clicked reply * @param reply the reply that is sent - * @param generatedByAssistant specifies is the reply generated by NAS * @param notificationLocation the location of the notification containing the smart reply + * @param modifiedBeforeSending whether the user changed the smart reply before sending */ void onNotificationSmartReplySent(String key, int clickedIndex, CharSequence reply, - boolean generatedByAssistant, int notificationLocation); + int notificationLocation, boolean modifiedBeforeSending); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index ba187c0884b9..34a6663c4352 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -917,20 +917,21 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, - int smartActionCount, boolean generatedByAssistant) { + int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending) { synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { r.setNumSmartRepliesAdded(smartReplyCount); r.setNumSmartActionsAdded(smartActionCount); r.setSuggestionsGeneratedByAssistant(generatedByAssistant); + r.setEditChoicesBeforeSending(editBeforeSending); } } } @Override public void onNotificationSmartReplySent(String key, int replyIndex, CharSequence reply, - boolean generatedByAssistant, int notificationLocation) { + int notificationLocation, boolean modifiedBeforeSending) { synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); @@ -940,14 +941,20 @@ public class NotificationManagerService extends SystemService { .setSubtype(replyIndex) .addTaggedData( MetricsEvent.NOTIFICATION_SMART_SUGGESTION_ASSISTANT_GENERATED, - generatedByAssistant ? 1 : 0) + r.getSuggestionsGeneratedByAssistant() ? 1 : 0) .addTaggedData(MetricsEvent.NOTIFICATION_LOCATION, - notificationLocation); + notificationLocation) + .addTaggedData( + MetricsEvent.NOTIFICATION_SMART_REPLY_EDIT_BEFORE_SENDING, + r.getEditChoicesBeforeSending() ? 1 : 0) + .addTaggedData( + MetricsEvent.NOTIFICATION_SMART_REPLY_MODIFIED_BEFORE_SENDING, + modifiedBeforeSending ? 1 : 0); mMetricsLogger.write(logMaker); // Treat clicking on a smart reply as a user interaction. reportUserInteraction(r); mAssistants.notifyAssistantSuggestedReplySent( - r.sbn, reply, generatedByAssistant); + r.sbn, reply, r.getSuggestionsGeneratedByAssistant()); } } } @@ -981,7 +988,10 @@ public class NotificationManagerService extends SystemService { r.getSuggestionsGeneratedByAssistant() ? 1 : 0) // The fields in the NotificationVisibility.NotificationLocation enum map // directly to the fields in the MetricsEvent.NotificationLocation enum. - .addTaggedData(MetricsEvent.NOTIFICATION_LOCATION, notificationLocation); + .addTaggedData(MetricsEvent.NOTIFICATION_LOCATION, notificationLocation) + .addTaggedData( + MetricsEvent.NOTIFICATION_SMART_REPLY_EDIT_BEFORE_SENDING, + r.getEditChoicesBeforeSending() ? 1 : 0); mMetricsLogger.write(logMaker); } } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index ab49ebb66fbf..b3394b4c599f 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -178,6 +178,7 @@ public final class NotificationRecord { private int mNumberOfSmartRepliesAdded; private int mNumberOfSmartActionsAdded; private boolean mSuggestionsGeneratedByAssistant; + private boolean mEditChoicesBeforeSending; private boolean mHasSeenSmartReplies; /** * Whether this notification (and its channels) should be considered user locked. Used in @@ -1136,6 +1137,14 @@ public final class NotificationRecord { return mSuggestionsGeneratedByAssistant; } + public boolean getEditChoicesBeforeSending() { + return mEditChoicesBeforeSending; + } + + public void setEditChoicesBeforeSending(boolean editChoicesBeforeSending) { + mEditChoicesBeforeSending = editChoicesBeforeSending; + } + public boolean hasSeenSmartReplies() { return mHasSeenSmartReplies; } diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java index f736056c5c7f..1dada92ab118 100644 --- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java +++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java @@ -17,8 +17,10 @@ package com.android.server.os; import android.annotation.RequiresPermission; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.UserInfo; import android.os.Binder; import android.os.BugreportParams; import android.os.IDumpstate; @@ -28,26 +30,29 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.UserManager; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; + import java.io.FileDescriptor; // TODO(b/111441001): -// 1. Handle the case where another bugreport is in progress -// 2. Make everything threadsafe -// 3. Pass validation & other errors on listener +// Intercept onFinished() & implement death recipient here and shutdown +// bugreportd service. /** * Implementation of the service that provides a privileged API to capture and consume bugreports. * - * <p>Delegates the actualy generation to a native implementation of {@code Dumpstate}. + * <p>Delegates the actualy generation to a native implementation of {@code IDumpstate}. */ class BugreportManagerServiceImpl extends IDumpstate.Stub { private static final String TAG = "BugreportManagerService"; private static final String BUGREPORT_SERVICE = "bugreportd"; private static final long DEFAULT_BUGREPORT_SERVICE_TIMEOUT_MILLIS = 30 * 1000; - private IDumpstate mDs = null; + private final Object mLock = new Object(); private final Context mContext; private final AppOpsManager mAppOps; @@ -59,43 +64,44 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { @Override @RequiresPermission(android.Manifest.permission.DUMP) public IDumpstateToken setListener(String name, IDumpstateListener listener, - boolean getSectionDetails) throws RemoteException { - // TODO(b/111441001): Figure out if lazy setting of listener should be allowed - // and if so how to handle it. + boolean getSectionDetails) { throw new UnsupportedOperationException("setListener is not allowed on this service"); } - // TODO(b/111441001): Intercept onFinished here in system server and shutdown - // the bugreportd service. @Override @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(int callingUidUnused, String callingPackage, FileDescriptor bugreportFd, FileDescriptor screenshotFd, - int bugreportMode, IDumpstateListener listener) throws RemoteException { - int callingUid = Binder.getCallingUid(); - // TODO(b/111441001): validate all arguments & ensure primary user - validate(bugreportMode); + int bugreportMode, IDumpstateListener listener) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport"); + Preconditions.checkNotNull(callingPackage); + Preconditions.checkNotNull(bugreportFd); + Preconditions.checkNotNull(listener); + validateBugreportMode(bugreportMode); + ensureIsPrimaryUser(); + int callingUid = Binder.getCallingUid(); mAppOps.checkPackage(callingUid, callingPackage); - mDs = getDumpstateService(); - if (mDs == null) { - Slog.w(TAG, "Unable to get bugreport service"); - // TODO(b/111441001): pass error on listener - return; + + synchronized (mLock) { + startBugreportLocked(callingUid, callingPackage, bugreportFd, screenshotFd, + bugreportMode, listener); } - mDs.startBugreport(callingUid, callingPackage, - bugreportFd, screenshotFd, bugreportMode, listener); } @Override @RequiresPermission(android.Manifest.permission.DUMP) - public void cancelBugreport() throws RemoteException { - // This tells init to cancel bugreportd service. - SystemProperties.set("ctl.stop", BUGREPORT_SERVICE); - mDs = null; + public void cancelBugreport() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport"); + // This tells init to cancel bugreportd service. Note that this is achieved through setting + // a system property which is not thread-safe. So the lock here offers thread-safety only + // among callers of the API. + synchronized (mLock) { + SystemProperties.set("ctl.stop", BUGREPORT_SERVICE); + } } - private boolean validate(@BugreportParams.BugreportMode int mode) { + private void validateBugreportMode(@BugreportParams.BugreportMode int mode) { if (mode != BugreportParams.BUGREPORT_MODE_FULL && mode != BugreportParams.BUGREPORT_MODE_INTERACTIVE && mode != BugreportParams.BUGREPORT_MODE_REMOTE @@ -103,9 +109,66 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { && mode != BugreportParams.BUGREPORT_MODE_TELEPHONY && mode != BugreportParams.BUGREPORT_MODE_WIFI) { Slog.w(TAG, "Unknown bugreport mode: " + mode); - return false; + throw new IllegalArgumentException("Unknown bugreport mode: " + mode); + } + } + + /** + * Validates that the current user is the primary user. + * + * @throws IllegalArgumentException if the current user is not the primary user + */ + private void ensureIsPrimaryUser() { + UserInfo currentUser = null; + try { + currentUser = ActivityManager.getService().getCurrentUser(); + } catch (RemoteException e) { + // Impossible to get RemoteException for an in-process call. + } + + UserInfo primaryUser = UserManager.get(mContext).getPrimaryUser(); + if (currentUser == null) { + logAndThrow("No current user. Only primary user is allowed to take bugreports."); + } + if (primaryUser == null) { + logAndThrow("No primary user. Only primary user is allowed to take bugreports."); + } + if (primaryUser.id != currentUser.id) { + logAndThrow("Current user not primary user. Only primary user" + + " is allowed to take bugreports."); + } + } + + @GuardedBy("mLock") + private void startBugreportLocked(int callingUid, String callingPackage, + FileDescriptor bugreportFd, FileDescriptor screenshotFd, + int bugreportMode, IDumpstateListener listener) { + if (isDumpstateBinderServiceRunningLocked()) { + Slog.w(TAG, "'dumpstate' is already running. Cannot start a new bugreport" + + " while another one is currently in progress."); + // TODO(b/111441001): Use a new error code; add this to the documentation of the API. + reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR); + return; + } + + IDumpstate ds = startAndGetDumpstateBinderServiceLocked(); + if (ds == null) { + Slog.w(TAG, "Unable to get bugreport service"); + reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR); + return; + } + try { + ds.startBugreport(callingUid, callingPackage, + bugreportFd, screenshotFd, bugreportMode, listener); + } catch (RemoteException e) { + reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR); } - return true; + } + + @GuardedBy("mLock") + private boolean isDumpstateBinderServiceRunningLocked() { + IDumpstate ds = IDumpstate.Stub.asInterface(ServiceManager.getService("dumpstate")); + return ds != null; } /* @@ -115,8 +178,12 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { * <p>Generating bugreports requires root privileges. To limit the footprint * of the root access, the actual generation in Dumpstate binary is accessed as a * oneshot service 'bugreport'. + * + * <p>Note that starting the service is achieved through setting a system property, which is + * not thread-safe. So the lock here offers thread-safety only among callers of the API. */ - private IDumpstate getDumpstateService() { + @GuardedBy("mLock") + private IDumpstate startAndGetDumpstateBinderServiceLocked() { // Start bugreport service. SystemProperties.set("ctl.start", BUGREPORT_SERVICE); @@ -145,4 +212,18 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { } return ds; } + + private void reportError(IDumpstateListener listener, int errorCode) { + try { + listener.onError(errorCode); + } catch (RemoteException e) { + // Something went wrong in binder or app process. There's nothing to do here. + Slog.w(TAG, "onError() transaction threw RemoteException: " + e.getMessage()); + } + } + + private void logAndThrow(String message) { + Slog.w(TAG, message); + throw new IllegalArgumentException(message); + } } diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java index fe8113372697..89895c523275 100644 --- a/services/core/java/com/android/server/pm/DumpState.java +++ b/services/core/java/com/android/server/pm/DumpState.java @@ -41,6 +41,7 @@ public final class DumpState { public static final int DUMP_CHANGES = 1 << 22; public static final int DUMP_VOLUMES = 1 << 23; public static final int DUMP_SERVICE_PERMISSIONS = 1 << 24; + public static final int DUMP_APEX = 1 << 25; public static final int OPTION_SHOW_FILTERS = 1 << 0; public static final int OPTION_DUMP_ALL_COMPONENTS = 1 << 1; diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index af50c87c9069..21965e4e83a2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -567,8 +567,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this, mInstallThread.getLooper(), mStagingManager, sessionId, userId, installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false, - false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.NO_ERROR, - ""); + false, null, SessionInfo.INVALID_ID, false, false, false, + SessionInfo.STAGED_SESSION_NO_ERROR, ""); synchronized (mSessions) { mSessions.put(sessionId, session); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 995f33521330..d06fc513c0e8 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -267,7 +267,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private boolean mStagedSessionFailed; @GuardedBy("mLock") - private int mStagedSessionErrorCode = SessionInfo.NO_ERROR; + private int mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR; @GuardedBy("mLock") private String mStagedSessionErrorMessage; @@ -1463,7 +1463,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) { try { - mSigningDetails = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts( + mSigningDetails = ApkSignatureVerifier.unsafeGetCertsWithoutVerification( pkgInfo.applicationInfo.sourceDir, PackageParser.SigningDetails.SignatureSchemeVersion.JAR); } catch (PackageParserException e) { @@ -2004,7 +2004,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mStagedSessionReady = true; mStagedSessionApplied = false; mStagedSessionFailed = false; - mStagedSessionErrorCode = SessionInfo.NO_ERROR; + mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR; mStagedSessionErrorMessage = ""; } mCallback.onStagedSessionChanged(this); @@ -2030,7 +2030,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mStagedSessionReady = false; mStagedSessionApplied = true; mStagedSessionFailed = false; - mStagedSessionErrorCode = SessionInfo.NO_ERROR; + mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR; mStagedSessionErrorMessage = ""; } mCallback.onStagedSessionChanged(this); @@ -2298,7 +2298,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final boolean isFailed = readBooleanAttribute(in, ATTR_IS_FAILED); final boolean isApplied = readBooleanAttribute(in, ATTR_IS_APPLIED); final int stagedSessionErrorCode = readIntAttribute(in, ATTR_STAGED_SESSION_ERROR_CODE, - SessionInfo.NO_ERROR); + SessionInfo.STAGED_SESSION_NO_ERROR); final String stagedSessionErrorMessage = readStringAttribute(in, ATTR_STAGED_SESSION_ERROR_MESSAGE); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c63dc32a3a48..e18da7f7b319 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -120,6 +120,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.apex.ApexInfo; +import android.apex.ApexSessionInfo; import android.apex.IApexService; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -983,6 +984,9 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") private CheckPermissionDelegate mCheckPermissionDelegate; + @GuardedBy("mPackages") + private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider; + private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> { private Context mContext; private ComponentName mIntentFilterVerifierComponent; @@ -1926,7 +1930,7 @@ public class PackageManagerService extends IPackageManager.Stub final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting.getInstallReason(userId) != PackageManager.INSTALL_REASON_DEVICE_RESTORE) { - mSettings.setDefaultBrowserPackageNameLPw(null, userId); + setDefaultBrowserPackageName(null, userId); } } @@ -2940,7 +2944,6 @@ public class PackageManagerService extends IPackageManager.Stub if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) { for (UserInfo user : sUserManager.getUsers(true)) { mSettings.applyDefaultPreferredAppsLPw(user.id); - applyFactoryDefaultBrowserLPw(user.id); primeDomainVerificationsLPw(user.id); } } @@ -3013,8 +3016,6 @@ public class PackageManagerService extends IPackageManager.Stub ver.fingerprint = Build.FINGERPRINT; } - checkDefaultBrowser(); - // clear only after permissions and other defaults have been updated mExistingSystemPackages.clear(); mPromoteSystemApps = false; @@ -3669,58 +3670,6 @@ public class PackageManagerService extends IPackageManager.Stub scheduleWriteSettingsLocked(); } - @GuardedBy("mPackages") - private void applyFactoryDefaultBrowserLPw(int userId) { - // The default browser app's package name is stored in a string resource, - // with a product-specific overlay used for vendor customization. - String browserPkg = mContext.getResources().getString( - com.android.internal.R.string.default_browser); - if (!TextUtils.isEmpty(browserPkg)) { - // non-empty string => required to be a known package - PackageSetting ps = mSettings.mPackages.get(browserPkg); - if (ps == null) { - Slog.e(TAG, "Product default browser app does not exist: " + browserPkg); - browserPkg = null; - } else { - mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId); - } - } - - // Nothing valid explicitly set? Make the factory-installed browser the explicit - // default. If there's more than one, just leave everything alone. - if (browserPkg == null) { - calculateDefaultBrowserLPw(userId); - } - } - - @GuardedBy("mPackages") - private void calculateDefaultBrowserLPw(int userId) { - List<String> allBrowsers = resolveAllBrowserApps(userId); - final String browserPkg = (allBrowsers.size() == 1) ? allBrowsers.get(0) : null; - mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId); - } - - private List<String> resolveAllBrowserApps(int userId) { - // Resolve the canonical browser intent and check that the handleAllWebDataURI boolean is set - List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null, - PackageManager.MATCH_ALL, userId); - - final int count = list.size(); - List<String> result = new ArrayList<>(count); - for (int i=0; i<count; i++) { - ResolveInfo info = list.get(i); - if (info.activityInfo == null - || !info.handleAllWebDataURI - || (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 - || result.contains(info.activityInfo.packageName)) { - continue; - } - result.add(info.activityInfo.packageName); - } - - return result; - } - private boolean packageIsBrowser(String packageName, int userId) { List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null, PackageManager.MATCH_ALL, userId); @@ -3734,20 +3683,6 @@ public class PackageManagerService extends IPackageManager.Stub return false; } - private void checkDefaultBrowser() { - final int myUserId = UserHandle.myUserId(); - final String packageName = getDefaultBrowserPackageName(myUserId); - if (packageName != null) { - PackageInfo info = getPackageInfo(packageName, 0, myUserId); - if (info == null) { - Slog.w(TAG, "Default browser no longer installed: " + packageName); - synchronized (mPackages) { - applyFactoryDefaultBrowserLPw(myUserId); // leaves ambiguous when > 1 - } - } - } - } - @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { @@ -4006,13 +3941,13 @@ public class PackageManagerService extends IPackageManager.Stub if (apex != null) { try { final ApexInfo activePkg = apex.getActivePackage(packageName); - if (activePkg != null) { + if (activePkg != null && !TextUtils.isEmpty(activePkg.packagePath)) { try { return PackageParser.generatePackageInfoFromApex( new File(activePkg.packagePath), true /* collect certs */); } catch (PackageParserException pe) { - throw new IllegalStateException("Unable to parse: " + activePkg, - pe); + Log.e(TAG, "Unable to parse package at " + + activePkg.packagePath, pe); } } } catch (RemoteException e) { @@ -13491,6 +13426,10 @@ public class PackageManagerService extends IPackageManager.Stub return false; } + if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) { + return false; + } + boolean ensureVerifyAppsEnabled = isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS); // Check if installing from ADB @@ -13644,15 +13583,28 @@ public class PackageManagerService extends IPackageManager.Stub mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } - + if (userId == UserHandle.USER_ALL) { + return false; + } + PackageManagerInternal.DefaultBrowserProvider provider; synchronized (mPackages) { - boolean result = mSettings.setDefaultBrowserPackageNameLPw(packageName, userId); - if (packageName != null) { - mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowser( - packageName, userId); + provider = mDefaultBrowserProvider; + } + if (provider == null) { + Slog.e(TAG, "mDefaultBrowserProvider is null"); + return false; + } + boolean successful = provider.setDefaultBrowser(packageName, userId); + if (!successful) { + return false; + } + if (packageName != null) { + synchronized (mPackages) { + mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowser(packageName, + userId); } - return result; } + return true; } @Override @@ -13664,9 +13616,15 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return null; } + PackageManagerInternal.DefaultBrowserProvider provider; synchronized (mPackages) { - return mSettings.getDefaultBrowserPackageNameLPw(userId); + provider = mDefaultBrowserProvider; + } + if (provider == null) { + Slog.e(TAG, "mDefaultBrowserProvider is null"); + return null; } + return provider.getDefaultBrowser(userId); } /** @@ -19418,7 +19376,7 @@ public class PackageManagerService extends IPackageManager.Stub // significant refactoring to keep all default apps in the package // manager (cleaner but more work) or have the services provide // callbacks to the package manager to request a default app reset. - applyFactoryDefaultBrowserLPw(userId); + setDefaultBrowserPackageName(null, userId); clearIntentFilterVerificationsLPw(userId); primeDomainVerificationsLPw(userId); resetUserChangesToRuntimePermissionsAndFlagsLPw(userId); @@ -20859,6 +20817,7 @@ public class PackageManagerService extends IPackageManager.Stub pw.println(" -h: print this help"); pw.println(" --all-components: include all component names in package dump"); pw.println(" cmd may be one of:"); + pw.println(" apex: list active APEXes and APEX session state"); pw.println(" l[ibraries]: list known shared libraries"); pw.println(" f[eatures]: list device features"); pw.println(" k[eysets]: print known keysets"); @@ -21387,6 +21346,54 @@ public class PackageManagerService extends IPackageManager.Stub if (dumpState.onTitlePrinted()) pw.println(); mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120)); } + + if (!checkin && dumpState.isDumping(DumpState.DUMP_APEX)) { + final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120); + ipw.println(); + ipw.println("Active APEX packages:"); + ipw.increaseIndent(); + final IApexService apex = IApexService.Stub.asInterface( + ServiceManager.getService("apexservice")); + try { + final ApexInfo[] activeApexes = apex.getActivePackages(); + for (ApexInfo ai : activeApexes) { + if (packageName != null && !packageName.equals(ai.packageName)) { + continue; + } + ipw.println(ai.packageName); + ipw.increaseIndent(); + ipw.println("Version: " + Long.toString(ai.versionCode)); + ipw.println("Path: " + ai.packagePath); + ipw.decreaseIndent(); + } + ipw.decreaseIndent(); + ipw.println(); + ipw.println("APEX session state:"); + ipw.increaseIndent(); + final ApexSessionInfo[] sessions = apex.getSessions(); + for (ApexSessionInfo si : sessions) { + ipw.println("Session ID: " + Integer.toString(si.sessionId)); + ipw.increaseIndent(); + if (si.isUnknown) { + ipw.println("State: UNKNOWN"); + } else if (si.isVerified) { + ipw.println("State: VERIFIED"); + } else if (si.isStaged) { + ipw.println("State: STAGED"); + } else if (si.isActivated) { + ipw.println("State: ACTIVATED"); + } else if (si.isActivationPendingRetry) { + ipw.println("State: ACTIVATION PENDING RETRY"); + } else if (si.isActivationFailed) { + ipw.println("State: ACTIVATION FAILED"); + } + ipw.decreaseIndent(); + } + ipw.decreaseIndent(); + } catch (RemoteException e) { + ipw.println("Couldn't communicate with apexd."); + } + } } //TODO: b/111402650 @@ -22711,7 +22718,6 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mPackages) { scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageListLocked(userId); - applyFactoryDefaultBrowserLPw(userId); primeDomainVerificationsLPw(userId); } } @@ -23909,6 +23915,21 @@ public class PackageManagerService extends IPackageManager.Stub public void finishPackageInstall(int token, boolean didLaunch) { PackageManagerService.this.finishPackageInstall(token, didLaunch); } + + @Nullable + @Override + public String removeLegacyDefaultBrowserPackageName(int userId) { + synchronized (mPackages) { + return mSettings.removeDefaultBrowserPackageNameLPw(userId); + } + } + + @Override + public void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider) { + synchronized (mPackages) { + mDefaultBrowserProvider = provider; + } + } } @GuardedBy("mPackages") diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index b0f232607d88..975ffb25a784 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -1327,21 +1327,8 @@ public final class Settings { return result; } - boolean setDefaultBrowserPackageNameLPw(String packageName, int userId) { - if (userId == UserHandle.USER_ALL) { - return false; - } - if (packageName != null) { - mDefaultBrowserApp.put(userId, packageName); - } else { - mDefaultBrowserApp.remove(userId); - } - writePackageRestrictionsLPr(userId); - return true; - } - - String getDefaultBrowserPackageNameLPw(int userId) { - return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.get(userId); + String removeDefaultBrowserPackageNameLPw(int userId) { + return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.removeReturnOld(userId); } boolean setDefaultDialerPackageNameLPw(String packageName, int userId) { diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 84fd01a25021..55eb7ea7da4d 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -21,6 +21,7 @@ import android.apex.ApexInfo; import android.apex.ApexInfoList; import android.apex.ApexSessionInfo; import android.apex.IApexService; +import android.content.Context; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.Intent; @@ -33,6 +34,7 @@ import android.content.pm.PackageParser.SigningDetails; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.ParceledListSlice; import android.content.pm.Signature; +import android.content.rollback.IRollbackManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -186,6 +188,7 @@ public class StagingManager { private void preRebootVerification(@NonNull PackageInstallerSession session) { boolean success = true; + // STOPSHIP: TODO(b/123753157): Verify APKs through Package Verifier. if (!sessionContainsApex(session)) { // TODO: Decide whether we want to fail fast by detecting signature mismatches for APKs, // right away. @@ -215,7 +218,7 @@ public class StagingManager { if (!success) { session.setStagedSessionFailed( - SessionInfo.VERIFICATION_FAILED, + SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more details."); } @@ -227,7 +230,7 @@ public class StagingManager { for (ApexInfo apexPackage : apexInfoList.apexInfos) { if (!validateApexSignature(apexPackage.packagePath, apexPackage.packageName)) { - session.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED, + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APK-container signature verification failed for package " + apexPackage.packageName + ". Signature of file " + apexPackage.packagePath + " does not match the signature of " @@ -238,9 +241,26 @@ public class StagingManager { } } + if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) { + // If rollback is enabled for this session, we call through to the RollbackManager + // with the list of sessions it must enable rollback for. Note that notifyStagedSession + // is a synchronous operation. + final IRollbackManager rm = IRollbackManager.Stub.asInterface( + ServiceManager.getService(Context.ROLLBACK_SERVICE)); + try { + // NOTE: To stay consistent with the non-staged install flow, we don't fail the + // entire install if rollbacks can't be enabled. + if (!rm.notifyStagedSession(session.sessionId)) { + Slog.e(TAG, "Unable to enable rollback for session: " + session.sessionId); + } + } catch (RemoteException re) { + // Cannot happen, the rollback manager is in the same process. + } + } + session.setStagedSessionReady(); if (!sendMarkStagedSessionReadyRequest(session.sessionId)) { - session.setStagedSessionFailed(SessionInfo.VERIFICATION_FAILED, + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "APEX staging failed, check logcat messages from apexd for more " + "details."); } @@ -276,7 +296,7 @@ public class StagingManager { return; } if (apexSessionInfo.isActivationFailed || apexSessionInfo.isUnknown) { - session.setStagedSessionFailed(SessionInfo.ACTIVATION_FAILED, + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, "APEX activation failed. Check logcat messages from apexd for " + "more information."); return; @@ -301,8 +321,9 @@ public class StagingManager { } // The APEX part of the session is activated, proceed with the installation of APKs. if (!installApksInSession(session)) { - session.setStagedSessionFailed(SessionInfo.ACTIVATION_FAILED, - "APK installation for staged session " + session.sessionId + " failed."); + session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, + "APEX activation failed. Check logcat messages from apexd for " + + "more information."); return; } session.setStagedSessionApplied(); @@ -335,6 +356,7 @@ public class StagingManager { PackageInstaller.SessionParams params = originalSession.params.copy(); params.isStaged = false; + params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION; int apkSessionId = mPi.createSession( params, originalSession.getInstallerPackageName(), originalSession.userId); PackageInstallerSession apkSession = mPi.getSession(apkSessionId); diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING index 09bacd6ed332..0892b32a6b91 100644 --- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING @@ -18,6 +18,14 @@ "include-filter": "android.permission.cts.SplitPermissionTest" } ] + }, + { + "name": "CtsStatsdHostTestCases", + "options": [ + { + "include-filter": "android.cts.statsd.atom.UidAtomTests#testDangerousPermissionState" + } + ] } ] }
\ No newline at end of file diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java index bfe7725f3073..e7de8ddf87d1 100644 --- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java +++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManagerInternal; import android.os.Debug; import android.provider.Settings; import android.telecom.TelecomManager; @@ -29,6 +30,7 @@ import android.util.Slog; import com.android.internal.telephony.SmsApplication; import com.android.internal.util.CollectionUtils; +import com.android.server.LocalServices; import com.android.server.role.RoleManagerService; import java.util.Collection; @@ -113,6 +115,13 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder ? setting : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage()); } + case RoleManager.ROLE_BROWSER: { + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( + userId); + return CollectionUtils.singletonOrEmpty(packageName); + } default: { Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName); return Collections.emptyList(); diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index 1d74e1f8e56b..a122ed854a93 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -128,7 +128,7 @@ public class BatterySaverPolicy extends ContentObserver { new ArrayMap<>(), /* filesForNoninteractive */ false, /* forceAllAppsStandby */ false, /* forceBackgroundCheck */ - PowerManager.LOCATION_MODE_NO_CHANGE /* gpsMode */ + PowerManager.LOCATION_MODE_NO_CHANGE /* locationMode */ ); private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY; @@ -152,7 +152,7 @@ public class BatterySaverPolicy extends ContentObserver { new ArrayMap<>(), /* filesForNoninteractive */ true, /* forceAllAppsStandby */ true, /* forceBackgroundCheck */ - PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* gpsMode */ + PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* locationMode */ ); private final Object mLock; @@ -416,7 +416,7 @@ public class BatterySaverPolicy extends ContentObserver { if (currPolicy.disableAod) sb.append("o"); if (currPolicy.enableQuickDoze) sb.append("q"); - sb.append(currPolicy.gpsMode); + sb.append(currPolicy.locationMode); mEventLogKeys = sb.toString(); } @@ -554,12 +554,13 @@ public class BatterySaverPolicy extends ContentObserver { public final boolean forceBackgroundCheck; /** - * This is the flag to decide the gps mode in battery saver mode. + * This is the flag to decide the location mode in battery saver mode. This was + * previously called gpsMode. * * @see Settings.Global#BATTERY_SAVER_CONSTANTS * @see #KEY_GPS_MODE */ - public final int gpsMode; + public final int locationMode; private final int mHashCode; @@ -582,7 +583,7 @@ public class BatterySaverPolicy extends ContentObserver { ArrayMap<String, String> filesForNoninteractive, boolean forceAllAppsStandby, boolean forceBackgroundCheck, - int gpsMode) { + int locationMode) { this.adjustBrightnessFactor = adjustBrightnessFactor; this.advertiseIsEnabled = advertiseIsEnabled; @@ -602,7 +603,7 @@ public class BatterySaverPolicy extends ContentObserver { this.filesForNoninteractive = filesForNoninteractive; this.forceAllAppsStandby = forceAllAppsStandby; this.forceBackgroundCheck = forceBackgroundCheck; - this.gpsMode = gpsMode; + this.locationMode = locationMode; mHashCode = Objects.hash( adjustBrightnessFactor, @@ -623,7 +624,7 @@ public class BatterySaverPolicy extends ContentObserver { filesForNoninteractive, forceAllAppsStandby, forceBackgroundCheck, - gpsMode); + locationMode); } static Policy fromConfig(BatterySaverPolicyConfig config) { @@ -721,7 +722,7 @@ public class BatterySaverPolicy extends ContentObserver { defaultPolicy.forceAllAppsStandby); boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, defaultPolicy.forceBackgroundCheck); - int gpsMode = parser.getInt(KEY_GPS_MODE, defaultPolicy.gpsMode); + int locationMode = parser.getInt(KEY_GPS_MODE, defaultPolicy.locationMode); return new Policy( adjustBrightnessFactor, @@ -745,7 +746,7 @@ public class BatterySaverPolicy extends ContentObserver { (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(), forceAllAppsStandby, forceBackgroundCheck, - gpsMode + locationMode ); } @@ -770,7 +771,7 @@ public class BatterySaverPolicy extends ContentObserver { && enableQuickDoze == other.enableQuickDoze && forceAllAppsStandby == other.forceAllAppsStandby && forceBackgroundCheck == other.forceBackgroundCheck - && gpsMode == other.gpsMode + && locationMode == other.locationMode && filesForInteractive.equals(other.filesForInteractive) && filesForNoninteractive.equals(other.filesForNoninteractive); } @@ -795,11 +796,11 @@ public class BatterySaverPolicy extends ContentObserver { final PowerSaveState.Builder builder = new PowerSaveState.Builder() .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled); switch (type) { - case ServiceType.GPS: + case ServiceType.LOCATION: boolean isEnabled = currPolicy.advertiseIsEnabled - || currPolicy.gpsMode != PowerManager.LOCATION_MODE_NO_CHANGE; + || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE; return builder.setBatterySaverEnabled(isEnabled) - .setGpsMode(currPolicy.gpsMode) + .setLocationMode(currPolicy.locationMode) .build(); case ServiceType.ANIMATION: return builder.setBatterySaverEnabled(currPolicy.disableAnimation) @@ -910,7 +911,7 @@ public class BatterySaverPolicy extends ContentObserver { public int getGpsMode() { synchronized (mLock) { - return getCurrentPolicyLocked().gpsMode; + return getCurrentPolicyLocked().locationMode; } } @@ -995,7 +996,7 @@ public class BatterySaverPolicy extends ContentObserver { pw.print(indent); pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor); pw.print(indent); - pw.println(" " + KEY_GPS_MODE + "=" + p.gpsMode); + pw.println(" " + KEY_GPS_MODE + "=" + p.locationMode); pw.print(indent); pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby); pw.print(indent); diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java index be2544d42a65..107cb2cc1a2e 100644 --- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java +++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java @@ -101,6 +101,20 @@ public class RemoteRoleControllerService { callback)); } + /** + * @see RoleControllerService#onSmsKillSwitchToggled(boolean) + */ + public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) { + mConnection.enqueueCall(new Connection.Call( + (s, cb) -> s.onSmsKillSwitchToggled(smsRestrictionEnabled), + new IRoleManagerCallback.Default() { + @Override + public void onFailure() { + Slog.e(LOG_TAG, "Failed onSmsKillSwitchToggled"); + } + })); + } + private static final class Connection implements ServiceConnection { private static final long UNBIND_DELAY_MILLIS = 15 * 1000; diff --git a/services/core/java/com/android/server/role/RoleManagerServiceInternal.java b/services/core/java/com/android/server/role/RoleManagerInternal.java index 3afc3f731eb9..7598bf70d77a 100644 --- a/services/core/java/com/android/server/role/RoleManagerServiceInternal.java +++ b/services/core/java/com/android/server/role/RoleManagerInternal.java @@ -17,22 +17,23 @@ package com.android.server.role; import android.annotation.NonNull; -import android.os.UserHandle; +import android.annotation.UserIdInt; import android.util.ArrayMap; import android.util.ArraySet; /** - * Internal calls into {@link RoleManagerService} + * Internal calls into {@link RoleManagerService}. */ -public abstract class RoleManagerServiceInternal { +public abstract class RoleManagerInternal { + /** - * Get all roles and packages hold them. + * Get all roles and their holders. * - * @param user The user to query to roles for + * @param userId The user to query to roles for * * @return The roles and their holders */ @NonNull - public abstract ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser( - @NonNull UserHandle user); + public abstract ArrayMap<String, ArraySet<String>> getRolesAndHolders( + @UserIdInt int userId); } diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index d72270e3f36d..84305be0aed5 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -38,7 +38,9 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.Signature; +import android.database.ContentObserver; import android.database.CursorWindow; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -49,6 +51,7 @@ import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.UserHandle; import android.os.UserManagerInternal; +import android.provider.Settings; import android.service.sms.FinancialSmsService; import android.telephony.IFinancialSmsCallback; import android.text.TextUtils; @@ -146,8 +149,11 @@ public class RoleManagerService extends SystemService implements RoleUserState.C mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mAppOpsManager = context.getSystemService(AppOpsManager.class); - LocalServices.addService(RoleManagerServiceInternal.class, - new RoleManagerServiceInternalImpl()); + LocalServices.addService(RoleManagerInternal.class, new Internal()); + + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider()); registerUserRemovedReceiver(); } @@ -189,6 +195,18 @@ public class RoleManagerService extends SystemService implements RoleUserState.C performInitialGrantsIfNecessary(userId); } }, UserHandle.SYSTEM, intentFilter, null /* broadcastPermission */, null /* handler */); + + getContext().getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED), false, + new ContentObserver(getContext().getMainThreadHandler()) { + @Override + public void onChange(boolean selfChange, Uri uri, int userId) { + getOrCreateControllerService(userId).onSmsKillSwitchToggled( + Settings.Global.getInt( + getContext().getContentResolver(), + Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0) == 1); + } + }, UserHandle.USER_ALL); } @Override @@ -360,10 +378,10 @@ public class RoleManagerService extends SystemService implements RoleUserState.C notifyRoleHoldersChangedForListeners(listeners, roleName, userId); } - RemoteCallbackList<IOnRoleHoldersChangedListener> allUserListeners = getListeners( + RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners( UserHandle.USER_ALL); - if (allUserListeners != null) { - notifyRoleHoldersChangedForListeners(allUserListeners, roleName, userId); + if (allUsersListeners != null) { + notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId); } } @@ -386,19 +404,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - /** - * Get all roles and packages hold them. - * - * @param user The user to query to roles for - * - * @return The roles and their holders - */ - @NonNull - private ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser(@NonNull UserHandle user) { - RoleUserState userState = getOrCreateUserState(user.getIdentifier()); - return userState.getRoleHolders(); - } - private class Stub extends IRoleManager.Stub { @Override @@ -406,8 +411,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); int userId = UserHandle.getUserId(getCallingUid()); - RoleUserState userState = getOrCreateUserState(userId); - return userState.isRoleAvailable(roleName); + return getOrCreateUserState(userId).isRoleAvailable(roleName); } @Override @@ -418,7 +422,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C mAppOpsManager.checkPackage(callingUid, packageName); int userId = UserHandle.getUserId(callingUid); - ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId); + ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName); if (roleHolders == null) { return false; } @@ -433,24 +437,17 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return Collections.emptyList(); } - userId = handleIncomingUser(userId, "getRoleHoldersAsUser", false); + userId = handleIncomingUser(userId, false, "getRoleHoldersAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "getRoleHoldersAsUser"); - ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId); + ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName); if (roleHolders == null) { return Collections.emptyList(); } return new ArrayList<>(roleHolders); } - @Nullable - private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName, - @UserIdInt int userId) { - RoleUserState userState = getOrCreateUserState(userId); - return userState.getRoleHolders(roleName); - } - @Override public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @UserIdInt int userId, @NonNull IRoleManagerCallback callback) { @@ -461,7 +458,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return; } - userId = handleIncomingUser(userId, "addRoleHolderAsUser", false); + userId = handleIncomingUser(userId, false, "addRoleHolderAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "addRoleHolderAsUser"); @@ -478,7 +475,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return; } - userId = handleIncomingUser(userId, "removeRoleHolderAsUser", false); + userId = handleIncomingUser(userId, false, "removeRoleHolderAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "removeRoleHolderAsUser"); @@ -495,7 +492,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return; } - userId = handleIncomingUser(userId, "clearRoleHoldersAsUser", false); + userId = handleIncomingUser(userId, false, "clearRoleHoldersAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "clearRoleHoldersAsUser"); @@ -510,8 +507,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return; } - userId = handleIncomingUser(userId, "addOnRoleHoldersChangedListenerAsUser", - true); + userId = handleIncomingUser(userId, true, "addOnRoleHoldersChangedListenerAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS, "addOnRoleHoldersChangedListenerAsUser"); @@ -528,8 +524,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C Slog.e(LOG_TAG, "user " + userId + " does not exist"); return; } - userId = handleIncomingUser(userId, "removeOnRoleHoldersChangedListenerAsUser", - true); + userId = handleIncomingUser(userId, true, "removeOnRoleHoldersChangedListenerAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS, "removeOnRoleHoldersChangedListenerAsUser"); @@ -548,8 +543,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C "setRoleNamesFromController"); int userId = UserHandle.getCallingUserId(); - RoleUserState userState = getOrCreateUserState(userId); - userState.setRoleNames(roleNames); + getOrCreateUserState(userId).setRoleNames(roleNames); } @Override @@ -562,8 +556,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C "addRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); - RoleUserState userState = getOrCreateUserState(userId); - return userState.addRoleHolder(roleName, packageName); + return getOrCreateUserState(userId).addRoleHolder(roleName, packageName); } @Override @@ -576,8 +569,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C "removeRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); - RoleUserState userState = getOrCreateUserState(userId); - return userState.removeRoleHolder(roleName, packageName); + return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName); } @Override @@ -588,13 +580,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C "getRolesHeldFromController"); int userId = UserHandle.getCallingUserId(); - RoleUserState userState = getOrCreateUserState(userId); - return userState.getHeldRoles(packageName); + return getOrCreateUserState(userId).getHeldRoles(packageName); } @CheckResult - private int handleIncomingUser(@UserIdInt int userId, @NonNull String name, - boolean allowAll) { + private int handleIncomingUser(@UserIdInt int userId, boolean allowAll, + @NonNull String name) { return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId, allowAll, true, name, null); } @@ -694,15 +685,51 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } - /** - * Entry point for internal calls into role manager - */ - private final class RoleManagerServiceInternalImpl extends RoleManagerServiceInternal { + private class Internal extends RoleManagerInternal { @NonNull @Override - public ArrayMap<String, ArraySet<String>> getRoleHoldersAsUser(@NonNull UserHandle user) { - return RoleManagerService.this.getRoleHoldersAsUser(user); + public ArrayMap<String, ArraySet<String>> getRolesAndHolders(@UserIdInt int userId) { + return getOrCreateUserState(userId).getRolesAndHolders(); + } + } + + private class DefaultBrowserProvider implements PackageManagerInternal.DefaultBrowserProvider { + + @Nullable + @Override + public String getDefaultBrowser(@UserIdInt int userId) { + return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders( + RoleManager.ROLE_BROWSER)); + } + + @Override + public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) { + CompletableFuture<Void> future = new CompletableFuture<>(); + IRoleManagerCallback callback = new IRoleManagerCallback.Stub() { + @Override + public void onSuccess() { + future.complete(null); + } + @Override + public void onFailure() { + future.completeExceptionally(new RuntimeException()); + } + }; + if (packageName != null) { + getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER, + packageName, callback); + } else { + getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, + callback); + } + try { + future.get(5, TimeUnit.SECONDS); + return true; + } catch (InterruptedException | ExecutionException | TimeoutException e) { + Slog.e(LOG_TAG, "Exception while setting default browser: " + packageName, e); + return false; + } } } } diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java index 5030e349a485..c7e3fa4f2074 100644 --- a/services/core/java/com/android/server/role/RoleUserState.java +++ b/services/core/java/com/android/server/role/RoleUserState.java @@ -576,13 +576,14 @@ public class RoleUserState { * @return A copy of the roles and their holders */ @NonNull - public ArrayMap<String, ArraySet<String>> getRoleHolders() { + public ArrayMap<String, ArraySet<String>> getRolesAndHolders() { synchronized (mLock) { return snapshotRolesLocked(); } } @GuardedBy("mLock") + @NonNull private ArrayMap<String, ArraySet<String>> snapshotRolesLocked() { ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>(); for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) { @@ -615,7 +616,8 @@ public class RoleUserState { } } - private static @NonNull File getFile(@UserIdInt int userId) { + @NonNull + private static File getFile(@UserIdInt int userId) { return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME); } diff --git a/services/core/java/com/android/server/role/TEST_MAPPING b/services/core/java/com/android/server/role/TEST_MAPPING new file mode 100644 index 000000000000..9efd292738be --- /dev/null +++ b/services/core/java/com/android/server/role/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsStatsdHostTestCases", + "options": [ + { + "include-filter": "android.cts.statsd.atom.UidAtomTests#testRoleHolder" + } + ] + }, + { + "name": "CtsRoleTestCases" + } + ] +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/RollbackData.java index a4f306489c60..467bb28f5744 100644 --- a/services/core/java/com/android/server/rollback/RollbackData.java +++ b/services/core/java/com/android/server/rollback/RollbackData.java @@ -50,6 +50,12 @@ class RollbackData { public Instant timestamp; /** + * The session ID for the staged session if this rollback data represents a staged session, + * {@code -1} otherwise. + */ + public int stagedSessionId; + + /** * Whether this Rollback is currently in progress. This field is true from the point * we commit a {@code PackageInstaller} session containing these packages to the point the * {@code PackageInstaller} calls into the {@code onFinished} callback. @@ -57,8 +63,9 @@ class RollbackData { // NOTE: All accesses to this field are from the RollbackManager handler thread. public boolean inProgress = false; - RollbackData(int rollbackId, File backupDir) { + RollbackData(int rollbackId, File backupDir, int stagedSessionId) { this.rollbackId = rollbackId; this.backupDir = backupDir; + this.stagedSessionId = stagedSessionId; } } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 4c2b3c20c008..7885abe17c5b 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -54,12 +54,12 @@ import java.security.SecureRandom; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.concurrent.LinkedBlockingQueue; /** * Implementation of service that manages APK level rollbacks. @@ -157,6 +157,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } }, filter, null, getHandler()); + // NOTE: A new intent filter is being created here because this broadcast + // doesn't use a data scheme ("package") like above. + IntentFilter sessionUpdatedFilter = new IntentFilter(); + sessionUpdatedFilter.addAction(PackageInstaller.ACTION_SESSION_UPDATED); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + onStagedSessionUpdated(intent); + } + }, sessionUpdatedFilter, null, getHandler()); + IntentFilter enableRollbackFilter = new IntentFilter(); enableRollbackFilter.addAction(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK); try { @@ -210,8 +221,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { List<RollbackInfo> rollbacks = new ArrayList<>(); for (int i = 0; i < mAvailableRollbacks.size(); ++i) { RollbackData data = mAvailableRollbacks.get(i); - rollbacks.add(new RollbackInfo(data.rollbackId, data.packages, - Collections.emptyList())); + // TODO: Pass the correct value for isStaged instead of + // assuming always false. + rollbacks.add(new RollbackInfo(data.rollbackId, data.packages, false)); } return new ParceledListSlice<>(rollbacks); } @@ -364,8 +376,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { return; } + // TODO: Set the correct values for isStaged and + // committedSessionId. addRecentlyExecutedRollback(new RollbackInfo( - data.rollbackId, data.packages, causePackages)); + data.rollbackId, data.packages, false, causePackages, + PackageInstaller.SessionInfo.INVALID_ID)); sendSuccess(statusReceiver); Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED); @@ -685,30 +700,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private boolean enableRollback(int installFlags, File newPackageCodePath, int[] installedUsers) { - if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { - Log.e(TAG, "Rollbacks not supported for instant app install"); - return false; - } - if ((installFlags & PackageManager.INSTALL_APEX) != 0) { - Log.e(TAG, "Rollbacks not supported for apex install"); - return false; - } - // Get information about the package to be installed. - PackageParser.PackageLite newPackage = null; - try { - newPackage = PackageParser.parsePackageLite(newPackageCodePath, 0); - } catch (PackageParser.PackageParserException e) { - Log.e(TAG, "Unable to parse new package", e); - return false; - } - - String packageName = newPackage.packageName; - Log.i(TAG, "Enabling rollback for install of " + packageName); + // Find the session id associated with this install. + // TODO: It would be nice if package manager or package installer told + // us the session directly, rather than have to search for it + // ourselves. + PackageInstaller.SessionInfo session = null; - // Figure out the session id associated with this install. - int parentSessionId = PackageInstaller.SessionInfo.INVALID_ID; - int childSessionId = PackageInstaller.SessionInfo.INVALID_ID; PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); for (PackageInstaller.SessionInfo info : installer.getAllSessions()) { if (info.isMultiPackage()) { @@ -716,31 +714,64 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageInstaller.SessionInfo child = installer.getSessionInfo(childId); if (sessionMatchesForEnableRollback(child, installFlags, newPackageCodePath)) { // TODO: Check we only have one matching session? - parentSessionId = info.getSessionId(); - childSessionId = childId; + session = child; + break; } } - } else { - if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) { - // TODO: Check we only have one matching session? - parentSessionId = info.getSessionId(); - childSessionId = parentSessionId; - } + } else if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) { + // TODO: Check we only have one matching session? + session = info; + break; } } - if (parentSessionId == PackageInstaller.SessionInfo.INVALID_ID) { + if (session == null) { Log.e(TAG, "Unable to find session id for enabled rollback."); return false; } + return enableRollbackForSession(session, installedUsers, true); + } + + /** + * Do code and userdata backups to enable rollback of the given session. + * In case of multiPackage sessions, <code>session</code> should be one of + * the child sessions, not the parent session. + */ + private boolean enableRollbackForSession(PackageInstaller.SessionInfo session, + int[] installedUsers, boolean snapshotUserData) { + // TODO: Don't attempt to enable rollback for split installs. + final int installFlags = session.installFlags; + if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { + Log.e(TAG, "Rollback is not enabled."); + return false; + } + if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { + Log.e(TAG, "Rollbacks not supported for instant app install"); + return false; + } + + // Get information about the package to be installed. + PackageParser.PackageLite newPackage = null; + try { + newPackage = PackageParser.parsePackageLite(new File(session.resolvedBaseCodePath), 0); + } catch (PackageParser.PackageParserException e) { + Log.e(TAG, "Unable to parse new package", e); + return false; + } + + String packageName = newPackage.packageName; + Log.i(TAG, "Enabling rollback for install of " + packageName + + ", session:" + session.sessionId); + VersionedPackage newVersion = new VersionedPackage(packageName, newPackage.versionCode); + final boolean isApex = ((installFlags & PackageManager.INSTALL_APEX) != 0); // Get information about the currently installed package. PackageManager pm = mContext.getPackageManager(); PackageInfo pkgInfo = null; try { - pkgInfo = pm.getPackageInfo(packageName, 0); + pkgInfo = pm.getPackageInfo(packageName, isApex ? PackageManager.MATCH_APEX : 0); } catch (PackageManager.NameNotFoundException e) { // TODO: Support rolling back fresh package installs rather than // fail here. Test this case. @@ -751,19 +782,34 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { VersionedPackage installedVersion = new VersionedPackage(packageName, pkgInfo.getLongVersionCode()); - final IntArray pendingBackups = mUserdataHelper.snapshotAppData(packageName, - installedUsers); + IntArray pendingBackups = IntArray.wrap(new int[0]); + if (snapshotUserData && !isApex) { + pendingBackups = mUserdataHelper.snapshotAppData(packageName, installedUsers); + } PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion, - pendingBackups, new ArrayList<>()); + pendingBackups, new ArrayList<>(), isApex); RollbackData data; try { + int childSessionId = session.getSessionId(); + int parentSessionId = session.getParentSessionId(); + if (parentSessionId == PackageInstaller.SessionInfo.INVALID_ID) { + parentSessionId = childSessionId; + } + synchronized (mLock) { + // TODO: no need to add to mChildSessions if childSessionId is + // the same as parentSessionId. mChildSessions.put(childSessionId, parentSessionId); data = mPendingRollbacks.get(parentSessionId); if (data == null) { int rollbackId = allocateRollbackIdLocked(); - data = mRollbackStore.createAvailableRollback(rollbackId); + if (session.isStaged()) { + data = mRollbackStore.createPendingStagedRollback(rollbackId, + parentSessionId); + } else { + data = mRollbackStore.createAvailableRollback(rollbackId); + } mPendingRollbacks.put(parentSessionId, data); } data.packages.add(info); @@ -814,6 +860,56 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { }); } + @Override + public boolean notifyStagedSession(int sessionId) { + final LinkedBlockingQueue<Boolean> result = new LinkedBlockingQueue<>(); + + // NOTE: We post this runnable on the RollbackManager's binder thread because we'd prefer + // to preserve the invariant that all operations that modify state happen there. + getHandler().post(() -> { + PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); + + final PackageInstaller.SessionInfo session = installer.getSessionInfo(sessionId); + if (session == null) { + Log.e(TAG, "No matching install session for: " + sessionId); + result.offer(false); + return; + } + + if (!session.isMultiPackage()) { + if (!enableRollbackForSession(session, null, false)) { + Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + result.offer(false); + return; + } + } else { + for (int childSessionId : session.getChildSessionIds()) { + final PackageInstaller.SessionInfo childSession = + installer.getSessionInfo(childSessionId); + if (childSession == null) { + Log.e(TAG, "No matching child install session for: " + childSessionId); + result.offer(false); + return; + } + if (!enableRollbackForSession(childSession, null, false)) { + Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + result.offer(false); + return; + } + } + } + + result.offer(true); + }); + + try { + return result.take(); + } catch (InterruptedException ie) { + Log.e(TAG, "Interrupted while waiting for notifyStagedSession response"); + return false; + } + } + /** * Gets the version of the package currently installed. * Returns null if the package is not currently installed. @@ -851,57 +947,97 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void onFinished(int sessionId, boolean success) { - RollbackData data = null; - synchronized (mLock) { - Integer parentSessionId = mChildSessions.remove(sessionId); - if (parentSessionId != null) { - sessionId = parentSessionId; - } - data = mPendingRollbacks.remove(sessionId); + // If sessionId refers to a staged session, we can't deal with it here since the + // session might take an unbounded amount of time to become "ready" after the package + // installer session is committed. In those cases, we respond to it in response to + // a session ready broadcast. + PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller(); + PackageInstaller.SessionInfo si = packageInstaller.getSessionInfo(sessionId); + if (si != null && si.isStaged()) { + return; } - if (data != null) { - if (success) { - try { - data.timestamp = Instant.now(); - - mRollbackStore.saveAvailableRollback(data); - synchronized (mLock) { - // Note: There is a small window of time between when - // the session has been committed by the package - // manager and when we make the rollback available - // here. Presumably the window is small enough that - // nobody will want to roll back the newly installed - // package before we make the rollback available. - // TODO: We'll lose the rollback data if the - // device reboots between when the session is - // committed and this point. Revisit this after - // adding support for rollback of staged installs. - ensureRollbackDataLoadedLocked(); - mAvailableRollbacks.add(data); - } - // TODO(zezeozue): Provide API to explicitly start observing instead - // of doing this for all rollbacks. If we do this for all rollbacks, - // should document in PackageInstaller.SessionParams#setEnableRollback - // After enabling and commiting any rollback, observe packages and - // prepare to rollback if packages crashes too frequently. - List<String> packages = new ArrayList<>(); - for (int i = 0; i < data.packages.size(); i++) { - packages.add(data.packages.get(i).getPackageName()); - } - mPackageHealthObserver.startObservingHealth(packages, - ROLLBACK_LIFETIME_DURATION_MILLIS); - scheduleExpiration(ROLLBACK_LIFETIME_DURATION_MILLIS); - } catch (IOException e) { - Log.e(TAG, "Unable to enable rollback", e); - mRollbackStore.deleteAvailableRollback(data); + completeEnableRollback(sessionId, success); + } + } + + private void completeEnableRollback(int sessionId, boolean success) { + RollbackData data = null; + synchronized (mLock) { + Integer parentSessionId = mChildSessions.remove(sessionId); + if (parentSessionId != null) { + sessionId = parentSessionId; + } + + data = mPendingRollbacks.remove(sessionId); + } + + if (data != null) { + if (success) { + try { + data.timestamp = Instant.now(); + + mRollbackStore.saveAvailableRollback(data); + synchronized (mLock) { + // Note: There is a small window of time between when + // the session has been committed by the package + // manager and when we make the rollback available + // here. Presumably the window is small enough that + // nobody will want to roll back the newly installed + // package before we make the rollback available. + // TODO: We'll lose the rollback data if the + // device reboots between when the session is + // committed and this point. Revisit this after + // adding support for rollback of staged installs. + ensureRollbackDataLoadedLocked(); + mAvailableRollbacks.add(data); + } + // TODO(zezeozue): Provide API to explicitly start observing instead + // of doing this for all rollbacks. If we do this for all rollbacks, + // should document in PackageInstaller.SessionParams#setEnableRollback + // After enabling and commiting any rollback, observe packages and + // prepare to rollback if packages crashes too frequently. + List<String> packages = new ArrayList<>(); + for (int i = 0; i < data.packages.size(); i++) { + packages.add(data.packages.get(i).getPackageName()); } - } else { - // The install session was aborted, clean up the pending - // install. + mPackageHealthObserver.startObservingHealth(packages, + ROLLBACK_LIFETIME_DURATION_MILLIS); + scheduleExpiration(ROLLBACK_LIFETIME_DURATION_MILLIS); + } catch (IOException e) { + Log.e(TAG, "Unable to enable rollback", e); mRollbackStore.deleteAvailableRollback(data); } + } else { + // The install session was aborted, clean up the pending + // install. + mRollbackStore.deleteAvailableRollback(data); + } + } + } + + private void onStagedSessionUpdated(Intent intent) { + PackageInstaller.SessionInfo pi = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); + if (pi == null) { + Log.e(TAG, "Missing intent extra: " + PackageInstaller.EXTRA_SESSION); + return; + } + + if (pi.isStaged()) { + if (!pi.isSessionFailed()) { + // TODO: The session really isn't "enabled" at this point, since more work might + // be required post reboot. + // TODO: We need to make this case consistent with the call from onFinished. + // Ideally, we'd call completeEnableRollback excatly once per multi-package session + // with the parentSessionId only. + completeEnableRollback(pi.sessionId, pi.isSessionReady()); + } else { + // TODO: Clean up the saved rollback when the session fails. This may need to be + // unified with the case where things fail post reboot. } + } else { + Log.e(TAG, "Received onStagedSessionUpdated for: " + pi.sessionId + + ", which isn't staged"); } } diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 8e041602c75f..3c6a54af4bd7 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -26,6 +26,7 @@ import android.content.rollback.RollbackManager; import android.os.Handler; import android.os.HandlerThread; import android.text.TextUtils; +import android.util.Pair; import android.util.Slog; import android.util.StatsLog; @@ -64,10 +65,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve return PackageHealthObserverImpact.USER_IMPACT_NONE; } - RollbackInfo rollback = - getAvailableMainlineRollback(mContext.getSystemService(RollbackManager.class), - failedPackage, moduleMetadataPackage); - if (rollback == null) { + if (getAvailableRollback(mContext.getSystemService(RollbackManager.class), + failedPackage, moduleMetadataPackage) == null) { // Don't handle the notification, no rollbacks available for the package return PackageHealthObserverImpact.USER_IMPACT_NONE; } @@ -84,38 +83,46 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); - RollbackInfo rollback = getAvailableMainlineRollback(rollbackManager, + Pair<RollbackInfo, Boolean> rollbackPair = getAvailableRollback(rollbackManager, failedPackage, moduleMetadataPackage); - if (rollback == null) { - Slog.w(TAG, "Expected rollback but no mainline rollback found for package: [ " + if (rollbackPair == null) { + Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ " + failedPackage.getPackageName() + "] with versionCode: [" + failedPackage.getVersionCode() + "]"); return false; } - - StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, - StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE, - moduleMetadataPackage.getPackageName(), - moduleMetadataPackage.getVersionCode()); + RollbackInfo rollback = rollbackPair.first; + // We only log mainline package rollbacks, so check if rollback contains the + // module metadata provider, if it does, the rollback is a mainline rollback + boolean hasModuleMetadataPackage = rollbackPair.second; + + if (hasModuleMetadataPackage) { + StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, + StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE, + moduleMetadataPackage.getPackageName(), + moduleMetadataPackage.getVersionCode()); + } LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> { - int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, - RollbackManager.STATUS_FAILURE); - if (status == RollbackManager.STATUS_SUCCESS) { - StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, - StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, - moduleMetadataPackage.getPackageName(), - moduleMetadataPackage.getVersionCode()); - } else { - StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, - StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, - moduleMetadataPackage.getPackageName(), - moduleMetadataPackage.getVersionCode()); + if (hasModuleMetadataPackage) { + int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, + RollbackManager.STATUS_FAILURE); + if (status == RollbackManager.STATUS_SUCCESS) { + StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, + StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, + moduleMetadataPackage.getPackageName(), + moduleMetadataPackage.getVersionCode()); + } else { + StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, + StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, + moduleMetadataPackage.getPackageName(), + moduleMetadataPackage.getVersionCode()); + } } }); mHandler.post(() -> rollbackManager.commitRollback(rollback.getRollbackId(), - Collections.singletonList(moduleMetadataPackage), + Collections.singletonList(failedPackage), rollbackReceiver.getIntentSender())); // Assume rollback executed successfully return true; @@ -134,7 +141,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs); } - private RollbackInfo getAvailableMainlineRollback(RollbackManager rollbackManager, + private Pair<RollbackInfo, Boolean> getAvailableRollback(RollbackManager rollbackManager, VersionedPackage failedPackage, VersionedPackage moduleMetadataPackage) { for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) { // We only rollback mainline packages, so check if rollback contains the @@ -149,8 +156,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve && packageRollback.getVersionRolledBackFrom().getVersionCode() == failedPackage.getVersionCode(); } - if (hasModuleMetadataPackage && hasFailedPackage) { - return rollback; + if (hasFailedPackage) { + return new Pair<RollbackInfo, Boolean>(rollback, hasModuleMetadataPackage); } } return null; @@ -159,7 +166,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve private VersionedPackage getModuleMetadataPackage() { String packageName = mContext.getResources().getString( R.string.config_defaultModuleMetadataProvider); - if (!TextUtils.isEmpty(packageName)) { + if (TextUtils.isEmpty(packageName)) { return null; } diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index d8e1f6203956..ff516902a5b3 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -178,9 +178,12 @@ class RollbackStore { int rollbackId = element.getInt("rollbackId"); List<PackageRollbackInfo> packages = packageRollbackInfosFromJson( element.getJSONArray("packages")); + boolean isStaged = element.getBoolean("isStaged"); List<VersionedPackage> causePackages = versionedPackagesFromJson( element.getJSONArray("causePackages")); - RollbackInfo rollback = new RollbackInfo(rollbackId, packages, causePackages); + int committedSessionId = element.getInt("committedSessionId"); + RollbackInfo rollback = new RollbackInfo(rollbackId, packages, isStaged, + causePackages, committedSessionId); recentlyExecutedRollbacks.add(rollback); } } catch (IOException | JSONException e) { @@ -198,7 +201,13 @@ class RollbackStore { */ RollbackData createAvailableRollback(int rollbackId) throws IOException { File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId)); - return new RollbackData(rollbackId, backupDir); + return new RollbackData(rollbackId, backupDir, -1); + } + + RollbackData createPendingStagedRollback(int rollbackId, int stagedSessionId) + throws IOException { + File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId)); + return new RollbackData(rollbackId, backupDir, stagedSessionId); } /** @@ -237,6 +246,7 @@ class RollbackStore { dataJson.put("rollbackId", data.rollbackId); dataJson.put("packages", toJson(data.packages)); dataJson.put("timestamp", data.timestamp.toString()); + dataJson.put("stagedSessionId", data.stagedSessionId); PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json")); pw.println(dataJson.toString()); @@ -270,7 +280,9 @@ class RollbackStore { JSONObject element = new JSONObject(); element.put("rollbackId", rollback.getRollbackId()); element.put("packages", toJson(rollback.getPackages())); + element.put("isStaged", rollback.isStaged()); element.put("causePackages", versionedPackagesToJson(rollback.getCausePackages())); + element.put("committedSessionId", rollback.getCommittedSessionId()); array.put(element); } @@ -294,7 +306,9 @@ class RollbackStore { IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath())); int rollbackId = dataJson.getInt("rollbackId"); - RollbackData data = new RollbackData(rollbackId, backupDir); + int stagedSessionId = dataJson.getInt("stagedSessionId"); + RollbackData data = new RollbackData(rollbackId, backupDir, + stagedSessionId); data.packages.addAll(packageRollbackInfosFromJson(dataJson.getJSONArray("packages"))); data.timestamp = Instant.parse(dataJson.getString("timestamp")); return data; @@ -326,6 +340,8 @@ class RollbackStore { json.put("pendingBackups", convertToJsonArray(pendingBackups)); json.put("pendingRestores", convertToJsonArray(pendingRestores)); + json.put("isApex", info.isApex()); + return json; } @@ -340,8 +356,10 @@ class RollbackStore { final ArrayList<RestoreInfo> pendingRestores = convertToRestoreInfoArray( json.getJSONArray("pendingRestores")); + final boolean isApex = json.getBoolean("isApex"); + return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo, - pendingBackups, pendingRestores); + pendingBackups, pendingRestores, isApex); } private JSONArray versionedPackagesToJson(List<VersionedPackage> packages) diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 48e64338262f..35867728f2c9 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -118,7 +118,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.am.MemoryStatUtil.MemoryStat; -import com.android.server.role.RoleManagerServiceInternal; +import com.android.server.role.RoleManagerInternal; import com.android.server.storage.DiskStatsFileLogger; import com.android.server.storage.DiskStatsLoggingService; @@ -1780,8 +1780,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) { StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); final long elapsedMillis = SystemClock.elapsedRealtime(); - // Fails every 10 buckets. - if (mDebugFailingElapsedClockPullCount++ % 10 == 0) { + // Fails every 5 buckets. + if (mDebugFailingElapsedClockPullCount++ % 5 == 0) { mDebugFailingElapsedClockPreviousValue = elapsedMillis; throw new RuntimeException("Failing debug elapsed clock"); } @@ -1867,16 +1867,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { long callingToken = Binder.clearCallingIdentity(); try { PackageManager pm = mContext.getPackageManager(); - RoleManagerServiceInternal rm = - LocalServices.getService(RoleManagerServiceInternal.class); + RoleManagerInternal rmi = LocalServices.getService(RoleManagerInternal.class); List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers(); int numUsers = users.size(); for (int userNum = 0; userNum < numUsers; userNum++) { - UserHandle user = users.get(userNum).getUserHandle(); + int userId = users.get(userNum).getUserHandle().getIdentifier(); - ArrayMap<String, ArraySet<String>> roles = rm.getRoleHoldersAsUser(user); + ArrayMap<String, ArraySet<String>> roles = rmi.getRolesAndHolders( + userId); int numRoles = roles.size(); for (int roleNum = 0; roleNum < numRoles; roleNum++) { @@ -1889,7 +1889,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { PackageInfo pkg; try { - pkg = pm.getPackageInfoAsUser(holderName, 0, user.getIdentifier()); + pkg = pm.getPackageInfoAsUser(holderName, 0, userId); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Role holder " + holderName + " not found"); return; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index d932a4040cb0..0493ae908f12 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -1280,12 +1280,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, - int smartActionCount, boolean generatedByAssistant) { + int smartActionCount, boolean generatedByAssistant, boolean editBeforeSending) { enforceStatusBarService(); long identity = Binder.clearCallingIdentity(); try { mNotificationDelegate.onNotificationSmartSuggestionsAdded(key, smartReplyCount, - smartActionCount, generatedByAssistant); + smartActionCount, generatedByAssistant, editBeforeSending); } finally { Binder.restoreCallingIdentity(identity); } @@ -1293,13 +1293,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void onNotificationSmartReplySent( - String key, int replyIndex, CharSequence reply, boolean generatedByAssistant, - int notificationLocation) throws RemoteException { + String key, int replyIndex, CharSequence reply, int notificationLocation, + boolean modifiedBeforeSending) throws RemoteException { enforceStatusBarService(); long identity = Binder.clearCallingIdentity(); try { mNotificationDelegate.onNotificationSmartReplySent(key, replyIndex, reply, - generatedByAssistant, notificationLocation); + notificationLocation, modifiedBeforeSending); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index 5b3a2fee4dd6..62421ac4fc76 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -1436,9 +1436,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } } - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); proto.write(ID, mDisplayId); proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance); final ActivityStack focusedStack = getFocusedStack(); @@ -1453,7 +1454,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = mStacks.get(stackNdx); - stack.writeToProto(proto, STACKS); + stack.writeToProto(proto, STACKS, logLevel); } proto.end(token); } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index ad76af695df3..ef4064846381 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3467,7 +3467,7 @@ final class ActivityRecord extends ConfigurationContainer { * {@code ActivityRecordProto} is the outer-most proto data. */ void writeToProto(ProtoOutputStream proto) { - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + super.writeToProto(proto, CONFIGURATION_CONTAINER, WindowTraceLogLevel.ALL); writeIdentifierToProto(proto, IDENTIFIER); proto.write(STATE, mState.toString()); proto.write(VISIBLE, visible); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 6fc201448f33..6f07be82d267 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -5655,13 +5655,14 @@ class ActivityStack extends ConfigurationContainer { return shouldSleepActivities() || mService.mShuttingDown; } - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); proto.write(ID, mStackId); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); - task.writeToProto(proto, TASKS); + task.writeToProto(proto, TASKS, logLevel); } if (mResumedActivity != null) { mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 14c481455752..b6bac6131986 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6587,7 +6587,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // The output proto of "activity --proto activities" // is ActivityManagerServiceDumpActivitiesProto mRootActivityContainer.writeToProto(proto, - ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR); + ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR, + WindowTraceLogLevel.ALL); } } diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index ed029cd722cf..6fcc331bf62f 100644 --- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java +++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java @@ -158,7 +158,9 @@ class AppWindowThumbnail implements Animatable { final long token = proto.start(fieldId); proto.write(WIDTH, mWidth); proto.write(HEIGHT, mHeight); - mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR); + if (mSurfaceAnimator.isAnimating()) { + mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR); + } proto.end(token); } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 29ba16633258..3246a8702cd1 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -2885,10 +2885,16 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + // Critical log level logs only visible elements to mitigate performance overheard + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); writeNameToProto(proto, NAME); - super.writeToProto(proto, WINDOW_TOKEN, trim); + super.writeToProto(proto, WINDOW_TOKEN, logLevel); proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing); proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart()); proto.write(IS_REALLY_ANIMATING, isReallyAnimating()); @@ -2907,7 +2913,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree proto.write(ALL_DRAWN, allDrawn); proto.write(LAST_ALL_DRAWN, mLastAllDrawn); proto.write(REMOVED, removed); - if (startingWindow != null){ + if (startingWindow != null) { startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW); } proto.write(STARTING_DISPLAYED, startingDisplayed); diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index d86cf0fba01e..97062a6065e2 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -331,6 +331,10 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { return boundsChange; } + boolean hasOverrideConfiguration() { + return mHasOverrideConfiguration; + } + public WindowConfiguration getWindowConfiguration() { return mFullConfiguration.windowConfiguration; } @@ -551,18 +555,24 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @param proto Stream to write the ConfigurationContainer object to. * @param fieldId Field Id of the ConfigurationContainer as defined in the parent * message. - * @param trim If true, reduce amount of data written. + * @param logLevel Determines the amount of data to be written to the Protobuf. * @hide */ @CallSuper - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { - final long token = proto.start(fieldId); - if (!trim || mHasOverrideConfiguration) { - mRequestedOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION); + protected void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + // Critical log level logs only visible elements to mitigate performance overheard + if (logLevel != WindowTraceLogLevel.ALL && !mHasOverrideConfiguration) { + return; } - if (!trim) { - mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION); - mMergedOverrideConfiguration.writeToProto(proto, MERGED_OVERRIDE_CONFIGURATION); + + final long token = proto.start(fieldId); + mRequestedOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION, + logLevel != WindowTraceLogLevel.CRITICAL); + if (logLevel == WindowTraceLogLevel.ALL) { + mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION, false /* critical */); + mMergedOverrideConfiguration.writeToProto(proto, MERGED_OVERRIDE_CONFIGURATION, + false /* critical */); } proto.end(token); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 9fb922fe4f7e..18df88b37c61 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -20,8 +20,10 @@ import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LE import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -2679,27 +2681,33 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + // Critical log level logs only visible elements to mitigate performance overheard + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); proto.write(ID, mDisplayId); for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); - stack.writeToProto(proto, STACKS, trim); + stack.writeToProto(proto, STACKS, logLevel); } mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER); mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER); for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) { final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i); - windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, trim); + windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, logLevel); } for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) { final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i); - windowToken.writeToProto(proto, BELOW_APP_WINDOWS, trim); + windowToken.writeToProto(proto, BELOW_APP_WINDOWS, logLevel); } for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) { final WindowToken windowToken = mImeWindowsContainers.getChildAt(i); - windowToken.writeToProto(proto, IME_WINDOWS, trim); + windowToken.writeToProto(proto, IME_WINDOWS, logLevel); } proto.write(DPI, mBaseDisplayDensity); mDisplayInfo.writeToProto(proto, DISPLAY_INFO); @@ -3244,6 +3252,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mInputMethodTarget = target; mInputMethodTargetWaitingAnim = targetWaitingAnim; assignWindowLayers(false /* setLayoutNeeded */); + mInsetsStateController.onImeTargetChanged(target); } boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) { diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 66666e681e7a..f67b11b26b12 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -26,6 +26,7 @@ import static android.view.ViewRootImpl.sNewInsetsMode; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Point; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import android.view.InsetsState; @@ -135,6 +136,12 @@ class InsetsSourceProvider { mTmpRect.inset(mWin.mGivenContentInsets); } mSource.setFrame(mTmpRect); + if (mControl != null) { + final Rect frame = mWin.getWindowFrames().mFrame; + if (mControl.setSurfacePosition(frame.left, frame.top)) { + mStateController.notifyControlChanged(mControllingWin); + } + } setServerVisible(mWin.wouldBeVisibleIfPolicyIgnored() && mWin.mPolicyVisibility && !mWin.mGivenInsetsPending); } @@ -157,7 +164,8 @@ class InsetsSourceProvider { mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter, !mClientVisible /* hidden */); mControllingWin = target; - mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash); + mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash, + new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top)); } boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) { @@ -213,7 +221,8 @@ class InsetsSourceProvider { public void startAnimation(SurfaceControl animationLeash, Transaction t, OnAnimationFinishedCallback finishCallback) { mCapturedLeash = animationLeash; - t.setPosition(mCapturedLeash, mSource.getFrame().left, mSource.getFrame().top); + final Rect frame = mWin.getWindowFrames().mFrame; + t.setPosition(mCapturedLeash, frame.left, frame.top); } @Override diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index bb0cbb1de470..afae9c4ac228 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -204,6 +204,11 @@ class InsetsStateController { mTypeWinControlMap.put(type, win); } + void notifyControlChanged(WindowState target) { + mPendingControlChanged.add(target); + notifyPendingInsetsControlChanged(); + } + private void notifyPendingInsetsControlChanged() { if (mPendingControlChanged.isEmpty()) { return; diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index ecab1f14e5e0..fb5b1d85a4a2 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -2369,12 +2369,13 @@ class RootActivityContainer extends ConfigurationContainer return printed; } - void writeToProto(ProtoOutputStream proto, long fieldId) { + protected void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx); - activityDisplay.writeToProto(proto, DISPLAYS); + activityDisplay.writeToProto(proto, DISPLAYS, logLevel); } mStackSupervisor.getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER); // TODO(b/111541062): Update tests to look for resumed activities on all displays diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 8fb79477eb2f..300cd17f33dd 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -999,17 +999,22 @@ class RootWindowContainer extends WindowContainer<DisplayContent> @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); if (mWmService.mDisplayReady) { final int count = mChildren.size(); for (int i = 0; i < count; ++i) { final DisplayContent displayContent = mChildren.get(i); - displayContent.writeToProto(proto, DISPLAYS, trim); + displayContent.writeToProto(proto, DISPLAYS, logLevel); } } - if (!trim) { + if (logLevel == WindowTraceLogLevel.ALL) { forAllWindows((w) -> { w.writeIdentifierToProto(proto, WINDOWS); }, true); diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java index 1a8a9110c649..c600e0f4a657 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimator.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java @@ -325,7 +325,7 @@ class SurfaceAnimator { if (mAnimation != null) { mAnimation.writeToProto(proto, ANIMATION_ADAPTER); } - if (mLeash != null){ + if (mLeash != null) { mLeash.writeToProto(proto, LEASH); } proto.write(ANIMATION_START_DELAYED, mAnimationStartDelayed); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 7a86c96a6c43..888d74163163 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -316,6 +316,7 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta mRotation = rotation; + updateSurfacePosition(); return boundsChange; } @@ -358,6 +359,7 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta } else { mOverrideDisplayedBounds.setEmpty(); } + updateSurfacePosition(); } /** @@ -795,13 +797,18 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); proto.write(ID, mTaskId); for (int i = mChildren.size() - 1; i >= 0; i--) { final AppWindowToken appWindowToken = mChildren.get(i); - appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, trim); + appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, logLevel); } proto.write(FILLS_PARENT, matchParentBounds()); getBounds().writeToProto(proto, BOUNDS); diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index 0529ed128130..af38c0680c51 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -2476,9 +2476,14 @@ class TaskRecord extends ConfigurationContainer { return toString(); } - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); + super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); proto.write(ID, taskId); for (int i = mActivities.size() - 1; i >= 0; i--) { ActivityRecord activity = mActivities.get(i); diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 6d4bcdcea871..53cd5ea8bf16 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1340,12 +1340,17 @@ public class TaskStack extends WindowContainer<Task> implements @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); proto.write(ID, mStackId); for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) { - mChildren.get(taskNdx).writeToProto(proto, TASKS, trim); + mChildren.get(taskNdx).writeToProto(proto, TASKS, logLevel); } proto.write(FILLS_PARENT, matchParentBounds()); getRawBounds().writeToProto(proto, BOUNDS); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index f33056976e6c..b246da444a04 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -45,6 +45,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Builder; import android.view.SurfaceSession; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; import com.android.server.wm.SurfaceAnimator.Animatable; @@ -1096,17 +1097,25 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * * @param proto Stream to write the WindowContainer object to. * @param fieldId Field Id of the WindowContainer as defined in the parent message. - * @param trim If true, reduce the amount of data written. + * @param logLevel Determines the amount of data to be written to the Protobuf. * @hide */ @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + boolean isVisible = isVisible(); + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, CONFIGURATION_CONTAINER, trim); + super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); proto.write(ORIENTATION, mOrientation); - proto.write(VISIBLE, isVisible()); - mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR); + proto.write(VISIBLE, isVisible); + if (mSurfaceAnimator.isAnimating()) { + mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR); + } proto.end(token); } @@ -1323,6 +1332,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y); } + @VisibleForTesting + Point getLastSurfacePosition() { + return mLastSurfacePosition; + } + /** * Displayed bounds specify where to display this container at. It differs from bounds during * certain operations (like animation or interactive dragging). diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 975e62a44b0a..3bb660825843 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -841,11 +841,8 @@ public class WindowManagerService extends IWindowManager.Stub try { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction"); synchronized (mGlobalLock) { - try { - traceStateLocked(where); - } finally { - SurfaceControl.closeTransaction(); - } + SurfaceControl.closeTransaction(); + traceStateLocked(where); } } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); @@ -4436,7 +4433,8 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus); lastFocus.reportFocusChangedSerialized(false, mInTouchMode); } - } break; + break; + } case REPORT_LOSING_FOCUS: { final DisplayContent displayContent = (DisplayContent) msg.obj; @@ -4453,7 +4451,8 @@ public class WindowManagerService extends IWindowManager.Stub losers.get(i)); losers.get(i).reportFocusChangedSerialized(false, mInTouchMode); } - } break; + break; + } case WINDOW_FREEZE_TIMEOUT: { final DisplayContent displayContent = (DisplayContent) msg.obj; @@ -4617,12 +4616,13 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case NOTIFY_ACTIVITY_DRAWN: + case NOTIFY_ACTIVITY_DRAWN: { try { mActivityTaskManager.notifyActivityDrawn((IBinder) msg.obj); } catch (RemoteException e) { } break; + } case ALL_WINDOWS_DRAWN: { Runnable callback; synchronized (mGlobalLock) { @@ -4659,8 +4659,8 @@ public class WindowManagerService extends IWindowManager.Stub } } } + break; } - break; case CHECK_IF_BOOT_ANIMATION_FINISHED: { final boolean bootAnimationComplete; synchronized (mGlobalLock) { @@ -4670,15 +4670,15 @@ public class WindowManagerService extends IWindowManager.Stub if (bootAnimationComplete) { performEnableScreen(); } + break; } - break; case RESET_ANR_MESSAGE: { synchronized (mGlobalLock) { mLastANRState = null; } mAtmInternal.clearSavedANRState(); + break; } - break; case WALLPAPER_DRAW_PENDING_TIMEOUT: { synchronized (mGlobalLock) { final WallpaperController wallpaperController = @@ -4688,16 +4688,16 @@ public class WindowManagerService extends IWindowManager.Stub mWindowPlacerLocked.performSurfacePlacement(); } } + break; } - break; case UPDATE_DOCKED_STACK_DIVIDER: { synchronized (mGlobalLock) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); displayContent.getDockedDividerController().reevaluateVisibility(false); displayContent.adjustForImeIfNeeded(); } + break; } - break; case WINDOW_REPLACEMENT_TIMEOUT: { synchronized (mGlobalLock) { for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) { @@ -4706,8 +4706,8 @@ public class WindowManagerService extends IWindowManager.Stub } mWindowReplacementTimeouts.clear(); } + break; } - break; case WINDOW_HIDE_TIMEOUT: { final WindowState window = (WindowState) msg.obj; synchronized (mGlobalLock) { @@ -4727,44 +4727,44 @@ public class WindowManagerService extends IWindowManager.Stub window.setDisplayLayoutNeeded(); mWindowPlacerLocked.performSurfacePlacement(); } + break; } - break; case RESTORE_POINTER_ICON: { synchronized (mGlobalLock) { restorePointerIconLocked((DisplayContent)msg.obj, msg.arg1, msg.arg2); } + break; } - break; case SEAMLESS_ROTATION_TIMEOUT: { final DisplayContent displayContent = (DisplayContent) msg.obj; synchronized (mGlobalLock) { displayContent.onSeamlessRotationTimeout(); } + break; } - break; case SET_HAS_OVERLAY_UI: { mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1); + break; } - break; case SET_RUNNING_REMOTE_ANIMATION: { mAmInternal.setRunningRemoteAnimation(msg.arg1, msg.arg2 == 1); + break; } - break; case ANIMATION_FAILSAFE: { synchronized (mGlobalLock) { if (mRecentsAnimationController != null) { mRecentsAnimationController.scheduleFailsafe(); } } + break; } - break; case RECOMPUTE_FOCUS: { synchronized (mGlobalLock) { updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /* updateInputWindows */); } + break; } - break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG_WM, "handleMessage: exit"); @@ -5742,11 +5742,11 @@ public class WindowManagerService extends IWindowManager.Stub * {@link com.android.server.wm.WindowManagerServiceDumpProto}. * * @param proto Stream to write the WindowContainer object to. - * @param trim If true, reduce the amount of data written. + * @param logLevel Determines the amount of data to be written to the Protobuf. */ - void writeToProtoLocked(ProtoOutputStream proto, boolean trim) { + void writeToProtoLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) { mPolicy.writeToProto(proto, POLICY); - mRoot.writeToProto(proto, ROOT_WINDOW_CONTAINER, trim); + mRoot.writeToProto(proto, ROOT_WINDOW_CONTAINER, logLevel); final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent(); if (topFocusedDisplayContent.mCurrentFocus != null) { topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW); @@ -5765,13 +5765,13 @@ public class WindowManagerService extends IWindowManager.Stub } void traceStateLocked(String where) { - Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked"); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "traceStateLocked"); try { mWindowTracing.traceStateLocked(where, this); } catch (Exception e) { Log.wtf(TAG, "Exception while tracing state", e); } finally { - Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } } @@ -6074,7 +6074,7 @@ public class WindowManagerService extends IWindowManager.Stub if (useProto) { final ProtoOutputStream proto = new ProtoOutputStream(fd); synchronized (mGlobalLock) { - writeToProtoLocked(proto, false /* trim */); + writeToProtoLocked(proto, WindowTraceLogLevel.ALL); } proto.flush(); return; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 05c19b55df7a..4bc140095f1b 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3221,9 +3221,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + boolean isVisible = isVisible(); + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); writeIdentifierToProto(proto, IDENTIFIER); proto.write(DISPLAY_ID, getDisplayId()); proto.write(STACK_ID, getStackId()); @@ -3235,7 +3241,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.writeToProto(proto, ANIMATOR); proto.write(ANIMATING_EXIT, mAnimatingExit); for (int i = 0; i < mChildren.size(); i++) { - mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, trim); + mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, logLevel); } proto.write(REQUESTED_WIDTH, mRequestedWidth); proto.write(REQUESTED_HEIGHT, mRequestedHeight); @@ -3247,7 +3253,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP proto.write(DESTROYING, mDestroying); proto.write(REMOVED, mRemoved); proto.write(IS_ON_SCREEN, isOnScreen()); - proto.write(IS_VISIBLE, isVisible()); + proto.write(IS_VISIBLE, isVisible); proto.write(PENDING_SEAMLESS_ROTATION, mPendingSeamlessRotate != null); proto.write(FINISHED_SEAMLESS_ROTATION_FRAME, mFinishSeamlessRotateFrameNumber); proto.write(FORCE_SEAMLESS_ROTATION, mForceSeamlesslyRotate); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 9c1378211e6d..3b9b8bab9e61 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -270,13 +270,18 @@ class WindowToken extends WindowContainer<WindowState> { @CallSuper @Override - public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { + public void writeToProto(ProtoOutputStream proto, long fieldId, + @WindowTraceLogLevel int logLevel) { + if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { + return; + } + final long token = proto.start(fieldId); - super.writeToProto(proto, WINDOW_CONTAINER, trim); + super.writeToProto(proto, WINDOW_CONTAINER, logLevel); proto.write(HASH_CODE, System.identityHashCode(this)); for (int i = 0; i < mChildren.size(); i++) { final WindowState w = mChildren.get(i); - w.writeToProto(proto, WINDOWS, trim); + w.writeToProto(proto, WINDOWS, logLevel); } proto.write(HIDDEN, mHidden); proto.write(WAITING_TO_SHOW, waitingToShow); diff --git a/services/core/java/com/android/server/wm/WindowTraceBuffer.java b/services/core/java/com/android/server/wm/WindowTraceBuffer.java index 2f672f24cc4f..e4461ea90c91 100644 --- a/services/core/java/com/android/server/wm/WindowTraceBuffer.java +++ b/services/core/java/com/android/server/wm/WindowTraceBuffer.java @@ -40,7 +40,7 @@ abstract class WindowTraceBuffer { private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L; final Object mBufferLock = new Object(); - final Queue<byte[]> mBuffer = new ArrayDeque<>(); + final Queue<ProtoOutputStream> mBuffer = new ArrayDeque<>(); final File mTraceFile; int mBufferSize; private final int mBufferCapacity; @@ -64,8 +64,7 @@ abstract class WindowTraceBuffer { * than the buffer size. */ void add(ProtoOutputStream proto) { - byte[] protoBytes = proto.getBytes(); - int protoLength = protoBytes.length; + int protoLength = proto.getRawSize(); if (protoLength > mBufferCapacity) { throw new IllegalStateException("Trace object too large for the buffer. Buffer size:" + mBufferCapacity + " Object size: " + protoLength); @@ -73,7 +72,7 @@ abstract class WindowTraceBuffer { synchronized (mBufferLock) { boolean canAdd = canAdd(protoLength); if (canAdd) { - mBuffer.offer(protoBytes); + mBuffer.add(proto); mBufferSize += protoLength; } mBufferLock.notify(); @@ -97,7 +96,7 @@ abstract class WindowTraceBuffer { @VisibleForTesting boolean contains(byte[] other) { return mBuffer.stream() - .anyMatch(p -> Arrays.equals(p, other)); + .anyMatch(p -> Arrays.equals(p.getBytes(), other)); } private void initTraceFile() throws IOException { diff --git a/services/core/java/com/android/server/wm/WindowTraceLogLevel.java b/services/core/java/com/android/server/wm/WindowTraceLogLevel.java new file mode 100644 index 000000000000..2165c66a10e8 --- /dev/null +++ b/services/core/java/com/android/server/wm/WindowTraceLogLevel.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@IntDef({ + WindowTraceLogLevel.ALL, + WindowTraceLogLevel.TRIM, + WindowTraceLogLevel.CRITICAL, +}) +@Retention(RetentionPolicy.SOURCE) +@interface WindowTraceLogLevel{ + /** + * Logs all elements with maximum amount of information. + * + * Used to store the current window manager state when generating a bug report + */ + int ALL = 0; + /** + * Logs all elements but doesn't write all configuration data + * + * Default log level for manually activated Winscope traces + */ + int TRIM = 1; + /** + * Logs only visible elements, with the minimum amount of performance overhead + * + * Default log level for continuous traces + */ + int CRITICAL = 2; +} diff --git a/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java b/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java index eaedde9ea842..5888b7a799cf 100644 --- a/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java +++ b/services/core/java/com/android/server/wm/WindowTraceQueueBuffer.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.os.Build.IS_USER; import android.util.Log; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -67,19 +68,18 @@ class WindowTraceQueueBuffer extends WindowTraceBuffer { private void loop() throws IOException, InterruptedException { while (!mCancel) { - byte[] proto; + ProtoOutputStream proto; synchronized (mBufferLock) { mBufferLock.wait(); - proto = mBuffer.poll(); if (proto != null) { - mBufferSize -= proto.length; + mBufferSize -= proto.getRawSize(); } } - if (proto != null) { try (OutputStream os = new FileOutputStream(mTraceFile, true)) { - os.write(proto); + byte[] protoBytes = proto.getBytes(); + os.write(protoBytes); } } } @@ -97,7 +97,6 @@ class WindowTraceQueueBuffer extends WindowTraceBuffer { mCancel = true; mBufferLock.notify(); } - if (mConsumerThread != null) { mConsumerThread.join(); mConsumerThread = null; diff --git a/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java b/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java index 7c69f2368845..77d30be816bc 100644 --- a/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java +++ b/services/core/java/com/android/server/wm/WindowTraceRingBuffer.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import android.util.proto.ProtoOutputStream; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -49,20 +51,20 @@ class WindowTraceRingBuffer extends WindowTraceBuffer { synchronized (mBufferLock) { try (OutputStream os = new FileOutputStream(mTraceFile, true)) { while (!mBuffer.isEmpty()) { - byte[] proto; - proto = mBuffer.poll(); - mBufferSize -= proto.length; - os.write(proto); + ProtoOutputStream proto = mBuffer.poll(); + mBufferSize -= proto.getRawSize(); + byte[] protoBytes = proto.getBytes(); + os.write(protoBytes); } } } } private void discardOldest() { - byte[] item = mBuffer.poll(); + ProtoOutputStream item = mBuffer.poll(); if (item == null) { throw new IllegalStateException("No element to discard from buffer"); } - mBufferSize -= item.length; + mBufferSize -= item.getRawSize(); } } diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java index 4c9a917c9248..8b1ffa8387d7 100644 --- a/services/core/java/com/android/server/wm/WindowTracing.java +++ b/services/core/java/com/android/server/wm/WindowTracing.java @@ -53,6 +53,7 @@ class WindowTracing { private WindowTraceBuffer mTraceBuffer; + private @WindowTraceLogLevel int mWindowTraceLogLevel = WindowTraceLogLevel.TRIM; private boolean mContinuousMode; private boolean mEnabled; private volatile boolean mEnabledLockFree; @@ -118,6 +119,8 @@ class WindowTracing { + "trace is restarted."); } mContinuousMode = continuous; + mWindowTraceLogLevel = (continuous) ? WindowTraceLogLevel.CRITICAL : + WindowTraceLogLevel.TRIM; } private void appendTraceEntry(ProtoOutputStream proto) { @@ -166,22 +169,26 @@ class WindowTracing { return; } - ProtoOutputStream os = new ProtoOutputStream(); - long tokenOuter = os.start(ENTRY); - os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos()); - os.write(WHERE, where); - - Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked"); + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToBufferLocked"); try { - long tokenInner = os.start(WINDOW_MANAGER_SERVICE); - service.writeToProtoLocked(os, true /* trim */); - os.end(tokenInner); + ProtoOutputStream os = new ProtoOutputStream(); + long tokenOuter = os.start(ENTRY); + os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos()); + os.write(WHERE, where); + + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeToProtoLocked"); + try { + long tokenInner = os.start(WINDOW_MANAGER_SERVICE); + service.writeToProtoLocked(os, mWindowTraceLogLevel); + os.end(tokenInner); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } + os.end(tokenOuter); + appendTraceEntry(os); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); } - os.end(tokenOuter); - appendTraceEntry(os); - Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); } /** diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 3729eaf63ddb..5c7b287354da 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -127,6 +127,7 @@ cc_defaults { "android.frameworks.schedulerservice@1.0", "android.frameworks.sensorservice@1.0", "android.system.suspend@1.0", + "suspend_control_aidl_interface-cpp", ], static_libs: [ diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 024760d46760..5c19ad33617c 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -32,8 +32,8 @@ #include <android/hardware/power/1.0/IPower.h> #include <android/hardware/power/1.1/IPower.h> #include <android/hardware/power/stats/1.0/IPowerStats.h> -#include <android/system/suspend/1.0/ISystemSuspend.h> -#include <android/system/suspend/1.0/ISystemSuspendCallback.h> +#include <android/system/suspend/BnSuspendCallback.h> +#include <android/system/suspend/ISuspendControlService.h> #include <android_runtime/AndroidRuntime.h> #include <jni.h> @@ -46,14 +46,14 @@ using android::hardware::Return; using android::hardware::Void; +using android::system::suspend::BnSuspendCallback; using android::hardware::power::V1_0::PowerStatePlatformSleepState; using android::hardware::power::V1_0::PowerStateVoter; using android::hardware::power::V1_0::Status; using android::hardware::power::V1_1::PowerStateSubsystem; using android::hardware::power::V1_1::PowerStateSubsystemSleepState; using android::hardware::hidl_vec; -using android::system::suspend::V1_0::ISystemSuspend; -using android::system::suspend::V1_0::ISystemSuspendCallback; +using android::system::suspend::ISuspendControlService; using IPowerV1_1 = android::hardware::power::V1_1::IPower; using IPowerV1_0 = android::hardware::power::V1_0::IPower; @@ -68,7 +68,7 @@ static sem_t wakeup_sem; extern sp<IPowerV1_0> getPowerHalV1_0(); extern sp<IPowerV1_1> getPowerHalV1_1(); extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName); -extern sp<ISystemSuspend> getSuspendHal(); +extern sp<ISuspendControlService> getSuspendControl(); // Java methods used in getLowPowerStats static jmethodID jgetAndUpdatePlatformState = NULL; @@ -103,17 +103,17 @@ struct PowerHalDeathRecipient : virtual public hardware::hidl_death_recipient { sp<PowerHalDeathRecipient> gDeathRecipient = new PowerHalDeathRecipient(); -class WakeupCallback : public ISystemSuspendCallback { -public: - Return<void> notifyWakeup(bool success) override { - ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted"); +class WakeupCallback : public BnSuspendCallback { + public: + binder::Status notifyWakeup(bool success) override { + ALOGI("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted"); int ret = sem_post(&wakeup_sem); if (ret < 0) { char buf[80]; strerror_r(errno, buf, sizeof(buf)); ALOGE("Error posting wakeup sem: %s\n", buf); } - return Void(); + return binder::Status::ok(); } }; @@ -136,9 +136,12 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf) jniThrowException(env, "java/lang/IllegalStateException", buf); return -1; } - ALOGV("Registering callback..."); - sp<ISystemSuspend> suspendHal = getSuspendHal(); - suspendHal->registerCallback(new WakeupCallback()); + sp<ISuspendControlService> suspendControl = getSuspendControl(); + bool isRegistered = false; + suspendControl->registerCallback(new WakeupCallback(), &isRegistered); + if (!isRegistered) { + ALOGE("Failed to register wakeup callback"); + } } // Wait for wakeup. diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp index 0c9b5f4999a0..9be728bac532 100644 --- a/services/core/jni/com_android_server_power_PowerManagerService.cpp +++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp @@ -20,6 +20,7 @@ #include <android/hardware/power/1.1/IPower.h> #include <android/system/suspend/1.0/ISystemSuspend.h> +#include <android/system/suspend/ISuspendControlService.h> #include <nativehelper/JNIHelp.h> #include "jni.h" @@ -30,13 +31,14 @@ #include <android-base/chrono_utils.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> +#include <binder/IServiceManager.h> +#include <hardware/power.h> +#include <hardware_legacy/power.h> +#include <hidl/ServiceManagement.h> #include <utils/Timers.h> #include <utils/misc.h> #include <utils/String8.h> #include <utils/Log.h> -#include <hardware/power.h> -#include <hardware_legacy/power.h> -#include <hidl/ServiceManagement.h> #include "com_android_server_power_PowerManagerService.h" @@ -48,6 +50,7 @@ using android::String8; using android::system::suspend::V1_0::ISystemSuspend; using android::system::suspend::V1_0::IWakeLock; using android::system::suspend::V1_0::WakeLockType; +using android::system::suspend::ISuspendControlService; using IPowerV1_1 = android::hardware::power::V1_1::IPower; using IPowerV1_0 = android::hardware::power::V1_0::IPower; @@ -176,6 +179,7 @@ void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t } static sp<ISystemSuspend> gSuspendHal = nullptr; +static sp<ISuspendControlService> gSuspendControl = nullptr; static sp<IWakeLock> gSuspendBlocker = nullptr; static std::mutex gSuspendMutex; @@ -191,18 +195,33 @@ sp<ISystemSuspend> getSuspendHal() { return gSuspendHal; } +sp<ISuspendControlService> getSuspendControl() { + static std::once_flag suspendControlFlag; + std::call_once(suspendControlFlag, [](){ + while(gSuspendControl == nullptr) { + sp<IBinder> control = + defaultServiceManager()->getService(String16("suspend_control")); + if (control != nullptr) { + gSuspendControl = interface_cast<ISuspendControlService>(control); + } + } + }); + return gSuspendControl; +} + void enableAutoSuspend() { static bool enabled = false; - - std::lock_guard<std::mutex> lock(gSuspendMutex); if (!enabled) { - sp<ISystemSuspend> suspendHal = getSuspendHal(); - suspendHal->enableAutosuspend(); - enabled = true; + sp<ISuspendControlService> suspendControl = getSuspendControl(); + suspendControl->enableAutosuspend(&enabled); } - if (gSuspendBlocker) { - gSuspendBlocker->release(); - gSuspendBlocker.clear(); + + { + std::lock_guard<std::mutex> lock(gSuspendMutex); + if (gSuspendBlocker) { + gSuspendBlocker->release(); + gSuspendBlocker.clear(); + } } } diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp index 988d75cfb984..bf96f9a3b71b 100644 --- a/services/core/jni/com_android_server_security_VerityUtils.cpp +++ b/services/core/jni/com_android_server_security_VerityUtils.cpp @@ -27,6 +27,8 @@ #include <sys/stat.h> #include <sys/types.h> +#include <type_traits> + #include <android-base/unique_fd.h> // TODO(112037636): Always include once fsverity.h is upstreamed. @@ -99,8 +101,14 @@ namespace { class JavaByteArrayHolder { public: - static JavaByteArrayHolder* newArray(JNIEnv* env, jsize size) { - return new JavaByteArrayHolder(env, size); + JavaByteArrayHolder(const JavaByteArrayHolder &other) = delete; + JavaByteArrayHolder(JavaByteArrayHolder &&other) + : mEnv(other.mEnv), mBytes(other.mBytes), mElements(other.mElements) { + other.mElements = nullptr; + } + + static JavaByteArrayHolder newArray(JNIEnv* env, jsize size) { + return JavaByteArrayHolder(env, size); } jbyte* getRaw() { @@ -113,6 +121,10 @@ class JavaByteArrayHolder { return mBytes; } + ~JavaByteArrayHolder() { + LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released"); + } + private: JavaByteArrayHolder(JNIEnv* env, jsize size) { mEnv = env; @@ -121,10 +133,6 @@ class JavaByteArrayHolder { memset(mElements, 0, size); } - virtual ~JavaByteArrayHolder() { - LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released"); - } - JNIEnv* mEnv; jbyteArray mBytes; jbyte* mElements; @@ -143,8 +151,10 @@ int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) { } int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) { - auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest) + kSha256Bytes); - fsverity_digest* data = reinterpret_cast<fsverity_digest*>(raii->getRaw()); + using Storage = std::aligned_storage_t<sizeof(fsverity_digest) + kSha256Bytes>; + + Storage bytes; + fsverity_digest *data = reinterpret_cast<fsverity_digest *>(&bytes); data->digest_size = kSha256Bytes; // the only input/output parameter const char* path = env->GetStringUTFChars(filePath, nullptr); @@ -160,7 +170,7 @@ int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) { jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) { auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes); - fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii->getRaw()); + fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii.getRaw()); data->digest_algorithm = FS_VERITY_ALG_SHA256; data->digest_size = kSha256Bytes; @@ -172,13 +182,13 @@ jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteAr const jbyte* src = env->GetByteArrayElements(digest, nullptr); memcpy(data->digest, src, kSha256Bytes); - return raii->release(); + return raii.release(); } jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) { auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor)); - fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii->getRaw()); + fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii.getRaw()); memcpy(desc->magic, FS_VERITY_MAGIC, sizeof(desc->magic)); desc->major_version = 1; @@ -191,29 +201,29 @@ jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong f desc->orig_file_size = fileSize; desc->auth_ext_count = 1; - return raii->release(); + return raii.release(); } jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId, jint extensionDataSize) { auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension)); - fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii->getRaw()); + fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii.getRaw()); ext->length = sizeof(fsverity_extension) + extensionDataSize; ext->type = extensionId; - return raii->release(); + return raii.release(); } jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */, jint offsetToDescriptorHead) { auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer)); - fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii->getRaw()); + fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii.getRaw()); footer->desc_reverse_offset = offsetToDescriptorHead + sizeof(fsverity_footer); memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic)); - return raii->release(); + return raii.release(); } const JNINativeMethod sMethods[] = { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 8f5ce74e4582..1155f499d619 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4765,6 +4765,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override @PasswordComplexity public int getPasswordComplexity() { + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.GET_USER_PASSWORD_COMPLEXITY_LEVEL) + .setStrings(mInjector.getPackageManager() + .getPackagesForUid(mInjector.binderGetCallingUid())) + .write(); final int callingUserId = mInjector.userHandleGetCallingUserId(); enforceUserUnlocked(callingUserId); mContext.enforceCallingOrSelfPermission( diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 71ed5ae685bb..ab30cda271f0 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -102,7 +102,6 @@ import com.android.server.lights.LightsService; import com.android.server.media.MediaResourceMonitorService; import com.android.server.media.MediaRouterService; import com.android.server.media.MediaSessionService; -import com.android.server.media.MediaUpdateService; import com.android.server.media.projection.MediaProjectionManagerService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; @@ -1286,47 +1285,45 @@ public final class SystemServer { } traceEnd(); - if (!mOnlyCore) { - if (context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI)) { - // Wifi Service must be started first for wifi-related services. - traceBeginAndSlog("StartWifi"); - mSystemServiceManager.startService(WIFI_SERVICE_CLASS); - traceEnd(); - traceBeginAndSlog("StartWifiScanning"); - mSystemServiceManager.startService( - "com.android.server.wifi.scanner.WifiScanningService"); - traceEnd(); - } + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI)) { + // Wifi Service must be started first for wifi-related services. + traceBeginAndSlog("StartWifi"); + mSystemServiceManager.startService(WIFI_SERVICE_CLASS); + traceEnd(); + traceBeginAndSlog("StartWifiScanning"); + mSystemServiceManager.startService( + "com.android.server.wifi.scanner.WifiScanningService"); + traceEnd(); + } - if (context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_RTT)) { - traceBeginAndSlog("StartRttService"); - mSystemServiceManager.startService( - "com.android.server.wifi.rtt.RttService"); - traceEnd(); - } + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI_RTT)) { + traceBeginAndSlog("StartRttService"); + mSystemServiceManager.startService( + "com.android.server.wifi.rtt.RttService"); + traceEnd(); + } - if (context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_AWARE)) { - traceBeginAndSlog("StartWifiAware"); - mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS); - traceEnd(); - } + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI_AWARE)) { + traceBeginAndSlog("StartWifiAware"); + mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS); + traceEnd(); + } - if (context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_DIRECT)) { - traceBeginAndSlog("StartWifiP2P"); - mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS); - traceEnd(); - } + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WIFI_DIRECT)) { + traceBeginAndSlog("StartWifiP2P"); + mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS); + traceEnd(); + } - if (context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_LOWPAN)) { - traceBeginAndSlog("StartLowpan"); - mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS); - traceEnd(); - } + if (context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_LOWPAN)) { + traceBeginAndSlog("StartLowpan"); + mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS); + traceEnd(); } if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) || @@ -1688,10 +1685,6 @@ public final class SystemServer { mSystemServiceManager.startService(MediaSessionService.class); traceEnd(); - traceBeginAndSlog("StartMediaUpdateService"); - mSystemServiceManager.startService(MediaUpdateService.class); - traceEnd(); - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) { traceBeginAndSlog("StartHdmiControlService"); mSystemServiceManager.startService(HdmiControlService.class); diff --git a/services/tests/servicestests/src/com/android/server/BinderCallsStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/BinderCallsStatsServiceTest.java index f75617ec5200..d459163fed9a 100644 --- a/services/tests/servicestests/src/com/android/server/BinderCallsStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/BinderCallsStatsServiceTest.java @@ -40,14 +40,10 @@ public class BinderCallsStatsServiceTest { protected int getCallingUid() { return Process.myUid(); } - - protected int getCallingWorkSourceUid() { - return 1; - } }; workSourceProvider.systemReady(InstrumentationRegistry.getContext()); - assertEquals(1, workSourceProvider.resolveWorkSourceUid()); + assertEquals(1, workSourceProvider.resolveWorkSourceUid(1)); } @Test @@ -57,14 +53,10 @@ public class BinderCallsStatsServiceTest { // System process uid which as UPDATE_DEVICE_STATS. return 1001; } - - protected int getCallingWorkSourceUid() { - return 1; - } }; workSourceProvider.systemReady(InstrumentationRegistry.getContext()); - assertEquals(1, workSourceProvider.resolveWorkSourceUid()); + assertEquals(1, workSourceProvider.resolveWorkSourceUid(1)); } @Test @@ -74,13 +66,9 @@ public class BinderCallsStatsServiceTest { // UID without permissions. return Integer.MAX_VALUE; } - - protected int getCallingWorkSourceUid() { - return 1; - } }; workSourceProvider.systemReady(InstrumentationRegistry.getContext()); - assertEquals(Integer.MAX_VALUE, workSourceProvider.resolveWorkSourceUid()); + assertEquals(Integer.MAX_VALUE, workSourceProvider.resolveWorkSourceUid(1)); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java index 48c89025e865..11bd29d8a163 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java @@ -23,8 +23,10 @@ import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.Looper; import android.os.test.TestLooper; + import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -42,9 +44,8 @@ public class ArcTerminationActionFromAvrTest { private TestLooper mTestLooper = new TestLooper(); private boolean mSendCecCommandSuccess; private boolean mShouldDispatchReportArcTerminated; - private boolean mArcEnabled; - private boolean mSetArcStatusCalled; private Instrumentation mInstrumentation; + @Nullable private Boolean mArcEnabled = null; @Before public void setUp() { @@ -102,7 +103,6 @@ public class ArcTerminationActionFromAvrTest { @Override void setArcStatus(boolean enabled) { - mSetArcStatusCalled = true; mArcEnabled = enabled; } }; @@ -110,45 +110,38 @@ public class ArcTerminationActionFromAvrTest { Looper looper = mTestLooper.getLooper(); hdmiControlService.setIoLooper(looper); - mArcEnabled = true; mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem); } @Test - public void testSendMessage_NotSuccess() { + public void testSendMessage_notSuccess() { mSendCecCommandSuccess = false; mShouldDispatchReportArcTerminated = false; - mSetArcStatusCalled = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.dispatchAll(); - assertThat(mSetArcStatusCalled).isFalse(); - assertThat(mArcEnabled).isTrue(); + assertThat(mArcEnabled).isNull(); } @Test - public void testReportArcTerminated_NotReceived() { + public void testReportArcTerminated_notReceived() { mSendCecCommandSuccess = true; mShouldDispatchReportArcTerminated = false; - mSetArcStatusCalled = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.moveTimeForward(1000); mTestLooper.dispatchAll(); - assertThat(mSetArcStatusCalled).isFalse(); - assertThat(mArcEnabled).isTrue(); + assertThat(mArcEnabled).isNull(); } @Test - public void testReportArcTerminated_Received() { + public void testReportArcTerminated_received() { mSendCecCommandSuccess = true; mShouldDispatchReportArcTerminated = true; - mSetArcStatusCalled = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.moveTimeForward(1000); mTestLooper.dispatchAll(); - assertThat(mSetArcStatusCalled).isTrue(); assertThat(mArcEnabled).isFalse(); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index feae4eed7eb1..b8799c3f16f7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -60,6 +60,11 @@ public class HdmiCecLocalDevicePlaybackTest { boolean isControlEnabled() { return true; } + + @Override + void writeStringSystemProperty(String key, String value) { + // do nothing + } }; mMyLooper = mTestLooper.getLooper(); @@ -92,4 +97,39 @@ public class HdmiCecLocalDevicePlaybackTest { // TODO(amyjojo): Move set and get LocalActivePath to Control Service. assertThat(mHdmiCecLocalDevicePlayback.getLocalActivePath()).isEqualTo(1); } + + @Test + public void handleSetSystemAudioModeOn_audioSystemBroadcast() { + mHdmiControlService.setSystemAudioActivated(false); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse(); + HdmiCecMessage message = + HdmiCecMessageBuilder.buildSetSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, Constants.ADDR_BROADCAST, true); + assertThat(mHdmiCecLocalDevicePlayback.handleSetSystemAudioMode(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } + + @Test + public void handleSetSystemAudioModeOff_audioSystemToPlayback() { + mHdmiCecLocalDevicePlayback.mService.setSystemAudioActivated(true); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + // This direct message to Playback device is invalid. + // Test should ignore it and still keep the system audio mode on. + HdmiCecMessage message = + HdmiCecMessageBuilder.buildSetSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, mHdmiCecLocalDevicePlayback.mAddress, false); + assertThat(mHdmiCecLocalDevicePlayback.handleSetSystemAudioMode(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } + + @Test + public void handleSystemAudioModeStatusOn_DirectltToLocalDeviceFromAudioSystem() { + mHdmiControlService.setSystemAudioActivated(false); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse(); + HdmiCecMessage message = + HdmiCecMessageBuilder.buildReportSystemAudioMode( + Constants.ADDR_AUDIO_SYSTEM, mHdmiCecLocalDevicePlayback.mAddress, true); + assertThat(mHdmiCecLocalDevicePlayback.handleSystemAudioModeStatus(message)).isTrue(); + assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue(); + } } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java index 742ae41ed9f0..26722fd64b4a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java @@ -173,7 +173,8 @@ public class PackageInstallerSessionTest { /* isReady */ staged ? true : false, /* isFailed */ false, /* isApplied */false, - /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.VERIFICATION_FAILED, + /* stagedSessionErrorCode */ + PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, /* stagedSessionErrorMessage */ "some error"); } diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java index e32a7894e546..9dcacf3021b8 100644 --- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java +++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java @@ -166,12 +166,12 @@ public class BatterySaverPolicyTest extends AndroidTestCase { @SmallTest public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() { - testServiceDefaultValue_On(ServiceType.GPS); + testServiceDefaultValue_On(ServiceType.LOCATION); mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL); PowerSaveState stateOn = - mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS); - assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE); + mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION); + assertThat(stateOn.locationMode).isEqualTo(DEFAULT_GPS_MODE); } @SmallTest @@ -222,9 +222,9 @@ public class BatterySaverPolicyTest extends AndroidTestCase { assertThat(dataSaverState.batterySaverEnabled).isTrue(); final PowerSaveState gpsState = - mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS); + mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION); assertThat(gpsState.batterySaverEnabled).isTrue(); - assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE); + assertThat(gpsState.locationMode).isEqualTo(GPS_MODE); final PowerSaveState quickDozeState = mBatterySaverPolicy.getBatterySaverPolicy( ServiceType.QUICK_DOZE); diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java index 33cbf7ae8ba6..f1e6bc25dabf 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java @@ -80,10 +80,10 @@ public class AppDataRollbackHelperTest { } private static RollbackData createInProgressRollbackData(String packageName) { - RollbackData data = new RollbackData(1, new File("/does/not/exist")); + RollbackData data = new RollbackData(1, new File("/does/not/exist"), -1); data.packages.add(new PackageRollbackInfo( new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1), - new IntArray(), new ArrayList<>())); + new IntArray(), new ArrayList<>(), false)); data.inProgress = true; return data; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 4cae3b3f9ae7..72aa0f2ba09e 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -3925,13 +3925,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testOnNotificationSmartReplySent() { final int replyIndex = 2; final String reply = "Hello"; + final boolean modifiedBeforeSending = true; final boolean generatedByAssistant = true; NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.setSuggestionsGeneratedByAssistant(generatedByAssistant); mService.addNotification(r); mService.mNotificationDelegate.onNotificationSmartReplySent( - r.getKey(), replyIndex, reply, generatedByAssistant, NOTIFICATION_LOCATION_UNKNOWN); + r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, + modifiedBeforeSending); verify(mAssistants).notifyAssistantSuggestedReplySent( eq(r.sbn), eq(reply), eq(generatedByAssistant)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index f1506a0ebc22..192915fe903c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -379,4 +379,39 @@ public class ActivityRecordTests extends ActivityTestsBase { mSupervisor.endDeferResume(); assertEquals(true, mActivity.shouldMakeActive(null /* activeActivity */)); } + + @Test + public void testPushConfigurationWhenLaunchTaskBehind() throws Exception { + mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing"); + + final TestActivityStack stack = (TestActivityStack) new StackBuilder(mRootActivityContainer) + .build(); + try { + stack.setIsTranslucent(false); + assertFalse(mStack.shouldBeVisible(null /* starting */)); + + mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration()); + mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(), + mActivity.getConfiguration())); + + mActivity.mLaunchTaskBehind = true; + mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION; + final Configuration newConfig = new Configuration(mActivity.getConfiguration()); + newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT + ? Configuration.ORIENTATION_LANDSCAPE + : Configuration.ORIENTATION_PORTRAIT; + + mTask.onConfigurationChanged(newConfig); + + mActivity.ensureActivityConfiguration(0 /* globalChanges */, + false /* preserveWindow */, true /* ignoreStopState */); + + final ActivityConfigurationChangeItem expected = + ActivityConfigurationChangeItem.obtain(newConfig); + verify(mService.getLifecycleManager()).scheduleTransaction( + eq(mActivity.app.getThread()), eq(mActivity.appToken), eq(expected)); + } finally { + stack.getDisplay().removeChild(stack); + } + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index ae211d3f1e38..41842010d3a3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.graphics.Point; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -123,4 +125,19 @@ public class TaskTests extends WindowTestsBase { assertEquals(1, task2.positionInParent()); assertTrue(task.mOnDisplayChangedCalled); } + + @Test + public void testBounds() { + final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent); + final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1); + + // Check that setting bounds also updates surface position + Rect bounds = new Rect(10, 10, 100, 200); + task.setBounds(bounds); + assertEquals(new Point(bounds.left, bounds.top), task.getLastSurfacePosition()); + + Rect dispBounds = new Rect(20, 30, 110, 220); + task.setOverrideDisplayedBounds(dispBounds); + assertEquals(new Point(dispBounds.left, dispBounds.top), task.getLastSurfacePosition()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java index c653762fb96f..64ceb1bf8dff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java @@ -16,9 +16,12 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOW_CONFIG_ALWAYS_ON_TOP; import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION; @@ -26,7 +29,9 @@ import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE; import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; import android.app.WindowConfiguration; import android.content.res.Configuration; @@ -35,7 +40,6 @@ import android.platform.test.annotations.Presubmit; import android.view.DisplayInfo; import android.view.Surface; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import org.junit.Before; @@ -47,7 +51,6 @@ import org.junit.Test; * Build/Install/Run: * atest FrameworksServicesTests:WindowConfigurationTests */ -@FlakyTest(bugId = 74078662) @SmallTest @Presubmit public class WindowConfigurationTests extends WindowTestsBase { @@ -110,39 +113,39 @@ public class WindowConfigurationTests extends WindowTestsBase { final Configuration config2 = new Configuration(config1); final WindowConfiguration winConfig2 = config2.windowConfiguration; - assertEquals(config1.compareTo(config2), 0); - assertEquals(winConfig1.compareTo(winConfig2), 0); + assertEquals(0, config1.compareTo(config2)); + assertEquals(0, winConfig1.compareTo(winConfig2)); // Different windowing mode winConfig2.setWindowingMode(WINDOWING_MODE_FREEFORM); - assertNotEquals(config1.compareTo(config2), 0); - assertNotEquals(winConfig1.compareTo(winConfig2), 0); + assertNotEquals(0, config1.compareTo(config2)); + assertNotEquals(0, winConfig1.compareTo(winConfig2)); winConfig2.setWindowingMode(winConfig1.getWindowingMode()); // Different always on top state winConfig2.setAlwaysOnTop(true); - assertNotEquals(config1.compareTo(config2), 0); - assertNotEquals(winConfig1.compareTo(winConfig2), 0); + assertNotEquals(0, config1.compareTo(config2)); + assertNotEquals(0, winConfig1.compareTo(winConfig2)); winConfig2.setAlwaysOnTop(winConfig1.isAlwaysOnTop()); // Different bounds winConfig2.setAppBounds(0, 2, 3, 4); - assertNotEquals(config1.compareTo(config2), 0); - assertNotEquals(winConfig1.compareTo(winConfig2), 0); + assertNotEquals(0, config1.compareTo(config2)); + assertNotEquals(0, winConfig1.compareTo(winConfig2)); winConfig2.setAppBounds(winConfig1.getAppBounds()); // No bounds - assertEquals(config1.compareTo(blankConfig), -1); - assertEquals(winConfig1.compareTo(blankWinConfig), -1); + assertEquals(-1, config1.compareTo(blankConfig)); + assertEquals(-1, winConfig1.compareTo(blankWinConfig)); // Different rotation winConfig2.setRotation(Surface.ROTATION_180); - assertNotEquals(config1.compareTo(config2), 0); - assertNotEquals(winConfig1.compareTo(winConfig2), 0); + assertNotEquals(0, config1.compareTo(config2)); + assertNotEquals(0, winConfig1.compareTo(winConfig2)); winConfig2.setRotation(winConfig1.getRotation()); - assertEquals(blankConfig.compareTo(config1), 1); - assertEquals(blankWinConfig.compareTo(winConfig1), 1); + assertEquals(1, blankConfig.compareTo(config1)); + assertEquals(1, blankWinConfig.compareTo(winConfig1)); } @Test @@ -165,12 +168,54 @@ public class WindowConfigurationTests extends WindowTestsBase { final Rect appBounds = mWm.computeNewConfiguration( mDisplayContent.getDisplayId()).windowConfiguration.getAppBounds(); - // The bounds should always be positioned in the top left. - assertEquals(appBounds.left, 0); - assertEquals(appBounds.top, 0); + // The bounds should always be positioned in the top left besides cutout. + final int expectedLeft = info.displayCutout != null + ? info.displayCutout.getSafeInsetLeft() : 0; + final int expectedTop = info.displayCutout != null + ? info.displayCutout.getSafeInsetTop() : 0; + assertEquals(expectedLeft, appBounds.left); + assertEquals(expectedTop, appBounds.top); // The bounds should equal the defined app width and height - assertEquals(appBounds.width(), info.appWidth); - assertEquals(appBounds.height(), info.appHeight); + assertEquals(info.appWidth, appBounds.width()); + assertEquals(info.appHeight, appBounds.height()); + } + + /** Ensure the window always has a caption in Freeform window mode or display mode. */ + @Test + public void testCaptionShownForFreeformWindowingMode() { + final WindowConfiguration config = new WindowConfiguration(); + config.setActivityType(ACTIVITY_TYPE_STANDARD); + config.setWindowingMode(WINDOWING_MODE_FREEFORM); + config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN); + assertTrue(config.hasWindowDecorCaption()); + + config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); + assertTrue(config.hasWindowDecorCaption()); + + config.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + assertTrue(config.hasWindowDecorCaption()); + + config.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN); + assertFalse(config.hasWindowDecorCaption()); + } + + /** Caption should not show for non-standard activity window. */ + @Test + public void testCaptionNotShownForNonStandardActivityType() { + final WindowConfiguration config = new WindowConfiguration(); + config.setActivityType(ACTIVITY_TYPE_HOME); + config.setWindowingMode(WINDOWING_MODE_FREEFORM); + config.setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); + assertFalse(config.hasWindowDecorCaption()); + + config.setActivityType(ACTIVITY_TYPE_ASSISTANT); + assertFalse(config.hasWindowDecorCaption()); + + config.setActivityType(ACTIVITY_TYPE_RECENTS); + assertFalse(config.hasWindowDecorCaption()); + + config.setActivityType(ACTIVITY_TYPE_STANDARD); + assertTrue(config.hasWindowDecorCaption()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java index df3ef551d5a1..2b8e307e23b7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTraceBufferTest.java @@ -67,27 +67,25 @@ public class WindowTraceBufferTest { ProtoOutputStream toWrite1 = getDummy(1); ProtoOutputStream toWrite2 = getDummy(2); ProtoOutputStream toWrite3 = getDummy(3); - byte[] toWrite1Bytes = toWrite1.getBytes(); - byte[] toWrite2Bytes = toWrite2.getBytes(); - byte[] toWrite3Bytes = toWrite3.getBytes(); - - final int objectSize = toWrite1.getBytes().length; + final int objectSize = toWrite1.getRawSize(); final int bufferCapacity = objectSize * 2; final WindowTraceBuffer buffer = buildQueueBuffer(bufferCapacity); buffer.add(toWrite1); + byte[] toWrite1Bytes = toWrite1.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWrite1Bytes)); buffer.add(toWrite2); + byte[] toWrite2Bytes = toWrite2.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWrite1Bytes)); assertTrue("Second element should be in the list", buffer.contains(toWrite2Bytes)); buffer.add(toWrite3); - + byte[] toWrite3Bytes = toWrite3.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWrite1Bytes)); assertTrue("Second element should be in the list", @@ -105,7 +103,7 @@ public class WindowTraceBufferTest { @Test public void testTraceRingBuffer_addItem() throws Exception { ProtoOutputStream toWrite = getDummy(1); - final int objectSize = toWrite.getBytes().length; + final int objectSize = toWrite.getRawSize(); final WindowTraceBuffer buffer = buildRingBuffer(objectSize); @@ -125,25 +123,25 @@ public class WindowTraceBufferTest { ProtoOutputStream toWrite1 = getDummy(1); ProtoOutputStream toWrite2 = getDummy(2); ProtoOutputStream toWrite3 = getDummy(3); - byte[] toWrite1Bytes = toWrite1.getBytes(); - byte[] toWrite2Bytes = toWrite2.getBytes(); - byte[] toWrite3Bytes = toWrite3.getBytes(); - final int objectSize = toWrite1.getBytes().length; + final int objectSize = toWrite1.getRawSize(); final int bufferCapacity = objectSize * 2 + 1; final WindowTraceBuffer buffer = buildRingBuffer(bufferCapacity); buffer.add(toWrite1); + byte[] toWrite1Bytes = toWrite1.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWrite1Bytes)); buffer.add(toWrite2); + byte[] toWrite2Bytes = toWrite2.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWrite1Bytes)); assertTrue("Second element should be in the list", buffer.contains(toWrite2Bytes)); buffer.add(toWrite3); + byte[] toWrite3Bytes = toWrite3.getBytes(); assertTrue("First element should not be in the list", !buffer.contains(toWrite1Bytes)); assertTrue("Second element should be in the list", @@ -161,9 +159,7 @@ public class WindowTraceBufferTest { public void testTraceRingBuffer_addItemMustOverwriteMultiple() throws Exception { ProtoOutputStream toWriteSmall1 = getDummy(1); ProtoOutputStream toWriteSmall2 = getDummy(2); - byte[] toWriteSmall1Bytes = toWriteSmall1.getBytes(); - byte[] toWriteSmall2Bytes = toWriteSmall2.getBytes(); - final int objectSize = toWriteSmall1.getBytes().length; + final int objectSize = toWriteSmall1.getRawSize(); final int bufferCapacity = objectSize * 2; final WindowTraceBuffer buffer = buildRingBuffer(bufferCapacity); @@ -171,20 +167,21 @@ public class WindowTraceBufferTest { ProtoOutputStream toWriteBig = new ProtoOutputStream(); toWriteBig.write(MAGIC_NUMBER, 1); toWriteBig.write(MAGIC_NUMBER, 2); - byte[] toWriteBigBytes = toWriteBig.getBytes(); - toWriteBig.flush(); buffer.add(toWriteSmall1); + byte[] toWriteSmall1Bytes = toWriteSmall1.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWriteSmall1Bytes)); buffer.add(toWriteSmall2); + byte[] toWriteSmall2Bytes = toWriteSmall2.getBytes(); assertTrue("First element should be in the list", buffer.contains(toWriteSmall1Bytes)); assertTrue("Second element should be in the list", buffer.contains(toWriteSmall2Bytes)); buffer.add(toWriteBig); + byte[] toWriteBigBytes = toWriteBig.getBytes(); assertTrue("Third element should overwrite all others", !buffer.contains(toWriteSmall1Bytes)); assertTrue("Third element should overwrite all others", diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java index 46d6835e4569..b81a8e72301a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java @@ -123,7 +123,7 @@ public class WindowTracingTest { mWindowTracing.startTrace(mock(PrintWriter.class)); mWindowTracing.traceStateLocked("where", mWmMock); - verify(mWmMock).writeToProtoLocked(any(), eq(true)); + verify(mWmMock).writeToProtoLocked(any(), eq(WindowTraceLogLevel.TRIM)); } @Test diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 85939d498755..a6d7ee6d85e2 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -432,6 +432,7 @@ public class UsageStatsService extends SystemService implements synchronized (mLock) { mHandler.removeMessages(MSG_REPORT_EVENT); Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); + event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; // orderly shutdown, the last event is DEVICE_SHUTDOWN. reportEventToAllUserId(event); flushToDiskLocked(); @@ -449,6 +450,7 @@ public class UsageStatsService extends SystemService implements */ void prepareForPossibleShutdown() { Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); + event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget(); mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK); } diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index d52d32faa7d1..3cb22162e36c 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -143,6 +143,7 @@ class UserUsageStatsService { if (size == 0 || currentDailyStats.events.get(size - 1).mEventType != DEVICE_SHUTDOWN) { // The last event in event list is not DEVICE_SHUTDOWN, then we insert one. final Event event = new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved); + event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; currentDailyStats.addEvent(event); } } diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index f5b4308a1b50..37caeb2044ff 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -58,6 +58,8 @@ cc_library_static { "util.cc", "layout_validation.cc", ], + // b/123880763, clang-tidy analyzer has segmentation fault with dex_builder.cc + tidy_checks: ["-clang-analyzer-*"], host_supported: true, } diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java index 4da79b34a55e..b407b2a03bc4 100644 --- a/telephony/java/android/telephony/AvailableNetworkInfo.java +++ b/telephony/java/android/telephony/AvailableNetworkInfo.java @@ -114,7 +114,7 @@ public final class AvailableNetworkInfo implements Parcelable { in.readStringList(mMccMncs); } - public AvailableNetworkInfo(int subId, int priority, ArrayList<String> mccMncs) { + public AvailableNetworkInfo(int subId, int priority, List<String> mccMncs) { mSubId = subId; mPriority = priority; mMccMncs = new ArrayList<String>(mccMncs); diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java index a4cce9c9a7b9..0d4f09f98b43 100644 --- a/telephony/java/android/telephony/CallAttributes.java +++ b/telephony/java/android/telephony/CallAttributes.java @@ -117,9 +117,9 @@ public class CallAttributes implements Parcelable { CallAttributes s = (CallAttributes) o; - return (mPreciseCallState == s.mPreciseCallState + return (Objects.equals(mPreciseCallState, s.mPreciseCallState) && mNetworkType == s.mNetworkType - && mCallQuality == s.mCallQuality); + && Objects.equals(mCallQuality, s.mCallQuality)); } /** diff --git a/telephony/java/android/telephony/DebugEventReporter.java b/telephony/java/android/telephony/DebugEventReporter.java new file mode 100644 index 000000000000..14b7dd6d1b72 --- /dev/null +++ b/telephony/java/android/telephony/DebugEventReporter.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2019 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.telephony; + +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.ParcelUuid; + +import com.android.internal.util.IndentingPrintWriter; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.List; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A Simple Surface for Telephony to notify a loosely-coupled debugger of particular issues. + * + * DebugEventReporter allows an optional external logging component to receive events detected by + * the framework and take action. This log surface is designed to provide maximium flexibility + * to the receiver of these events. Envisioned use cases of this include notifying a vendor + * component of: an event that necessitates (timely) log collection on non-AOSP components; + * notifying a vendor component of a rare event that should prompt further action such as a + * bug report or user intervention for debug purposes. + * + * <p>This surface is not intended to enable a diagnostic monitor, nor is it intended to support + * streaming logs. + * + * @hide + */ +public final class DebugEventReporter { + private static final String TAG = "DebugEventReporter"; + + private static Context sContext = null; + + private static Map<UUID, Integer> sEvents = new ConcurrentHashMap<>(); + + /* + * Because this is only supporting system packages, once we find a package, it will be the + * same package until the next system upgrade. Thus, to save time in processing debug events + * we can cache this info and skip the resolution process after it's done the first time. + */ + private static String sDebugPackageName = null; + + private DebugEventReporter() {}; + + /** + * If enabled, build and send an intent to a Debug Service for logging. + * + * This method sends the {@link TelephonyManager#DEBUG_EVENT DEBUG_EVENT} broadcast, which is + * system protected. Invoking this method unless you are the system will result in an error. + * + * @param eventId a fixed event ID that will be sent for each instance of the same event. This + * ID should be generated randomly. + * @param description an optional description, that if included will be used as the subject for + * identification and discussion of this event. This description should ideally be + * static and must not contain any sensitive information (especially PII). + */ + public static void sendEvent(@NonNull UUID eventId, String description) { + if (sContext == null) { + Rlog.w(TAG, "DebugEventReporter not yet initialized, dropping event=" + eventId); + return; + } + + // If this event has already occurred, skip sending intents for it; regardless log its + // invocation here. + Integer count = sEvents.containsKey(eventId) ? sEvents.get(eventId) + 1 : 1; + sEvents.put(eventId, count); + if (count > 1) return; + + // Even if we are initialized, that doesn't mean that a package name has been found. + // This is normal in many cases, such as when no debug package is installed on the system, + // so drop these events silently. + if (sDebugPackageName == null) return; + + Intent dbgIntent = new Intent(TelephonyManager.ACTION_DEBUG_EVENT); + dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_ID, new ParcelUuid(eventId)); + if (description != null) { + dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_DESCRIPTION, description); + } + dbgIntent.setPackage(sDebugPackageName); + sContext.sendBroadcast(dbgIntent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE); + } + + /** + * Initialize the DebugEventReporter with the current context. + * + * This method must be invoked before any calls to sendEvent() will succeed. This method should + * only be invoked at most once. + * + * @param context a Context object used to initialize this singleton DebugEventReporter in + * the current process. + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public static void initialize(@NonNull Context context) { + if (context == null) { + throw new IllegalArgumentException("DebugEventReporter needs a non-null context."); + } + + // Ensure that this context has sufficient permissions to send debug events. + context.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, + "This app does not have privileges to send debug events"); + + sContext = context; + + // Check to see if there is a valid debug package; if there are multiple, that's a config + // error, so just take the first one. + PackageManager pm = sContext.getPackageManager(); + if (pm == null) return; + List<ResolveInfo> packages = pm.queryBroadcastReceivers( + new Intent(TelephonyManager.ACTION_DEBUG_EVENT), + PackageManager.MATCH_SYSTEM_ONLY + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); + if (packages == null || packages.isEmpty()) return; + if (packages.size() > 1) { + Rlog.e(TAG, "Multiple DebugEvent Receivers installed."); + } + + for (ResolveInfo r : packages) { + if (r.activityInfo == null + || pm.checkPermission( + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + r.activityInfo.packageName) + != PackageManager.PERMISSION_GRANTED) { + Rlog.w(TAG, + "Found package without proper permissions or no activity" + + r.activityInfo.packageName); + continue; + } + Rlog.d(TAG, "Found a valid package " + r.activityInfo.packageName); + sDebugPackageName = r.activityInfo.packageName; + break; + } + // Initialization may only be performed once. + } + + /** Dump the contents of the DebugEventReporter */ + public static void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { + if (sContext == null) return; + IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); + sContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); + pw.println("Initialized=" + (sContext != null ? "Yes" : "No")); + pw.println("Debug Package=" + sDebugPackageName); + pw.println("Event Counts:"); + pw.increaseIndent(); + for (UUID event : sEvents.keySet()) { + pw.println(event + ": " + sEvents.get(event)); + } + pw.decreaseIndent(); + pw.flush(); + } +} diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index 59f3e1f0e7f7..19e1931a30df 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -287,11 +287,11 @@ public final class PreciseCallState implements Parcelable { return false; } PreciseCallState other = (PreciseCallState) obj; - return (mRingingCallState != other.mRingingCallState && - mForegroundCallState != other.mForegroundCallState && - mBackgroundCallState != other.mBackgroundCallState && - mDisconnectCause != other.mDisconnectCause && - mPreciseDisconnectCause != other.mPreciseDisconnectCause); + return (mRingingCallState == other.mRingingCallState + && mForegroundCallState == other.mForegroundCallState + && mBackgroundCallState == other.mBackgroundCallState + && mDisconnectCause == other.mDisconnectCause + && mPreciseDisconnectCause == other.mPreciseDisconnectCause); } @Override diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 7c3bde4293c7..739589412f0b 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1351,6 +1351,38 @@ public class TelephonyManager { @SystemApi public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000; + /** + * Intent sent when an error occurs that debug tools should log and possibly take further + * action such as capturing vendor-specific logs. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT"; + + /** + * An arbitrary ParcelUuid which should be consistent for each occurrence of the same event. + * + * This field must be included in all events. + * + * @hide + */ + @SystemApi + public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID"; + + /** + * A freeform string description of the event. + * + * This field is optional for all events and as a guideline should not exceed 80 characters + * and should be as short as possible to convey the essence of the event. + * + * @hide + */ + @SystemApi + public static final String EXTRA_DEBUG_EVENT_DESCRIPTION = + "android.telephony.extra.DEBUG_EVENT_DESCRIPTION"; + // // // Device Info @@ -7974,9 +8006,7 @@ public class TelephonyManager { * support for the feature and device firmware support. * * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise. - * @hide */ - @TestApi public boolean isRttSupported() { try { ITelephony telephony = getITelephony(); @@ -9702,10 +9732,10 @@ public class TelephonyManager { * * <p> * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} * @hide */ - @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled() { String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; boolean isEnabled = false; @@ -10093,12 +10123,17 @@ public class TelephonyManager { * Get preferred opportunistic data subscription Id * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}), - * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}. + * or has either READ_PRIVILEGED_PHONE_STATE + * or {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission. * @return subId preferred opportunistic subscription id or * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred * subscription id * */ + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + android.Manifest.permission.READ_PHONE_STATE + }) public int getPreferredOpportunisticDataSubscription() { String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java index 4d95e552c1da..d8d2d9e5951a 100644 --- a/telephony/java/android/telephony/ims/ImsReasonInfo.java +++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java @@ -465,7 +465,7 @@ public final class ImsReasonInfo implements Parcelable { public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511; /** - * Upgrade Downgrade request cacncelled by the user who initiated it + * Upgrade Downgrade request cancelled by the user who initiated it */ public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512; @@ -887,6 +887,185 @@ public final class ImsReasonInfo implements Parcelable { public static final int CODE_OEM_CAUSE_15 = 0xf00f; /** + * @hide + */ + @IntDef(value = { + CODE_UNSPECIFIED, + CODE_LOCAL_ILLEGAL_ARGUMENT, + CODE_LOCAL_ILLEGAL_STATE, + CODE_LOCAL_INTERNAL_ERROR, + CODE_LOCAL_IMS_SERVICE_DOWN, + CODE_LOCAL_NO_PENDING_CALL, + CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE, + CODE_LOCAL_POWER_OFF, + CODE_LOCAL_LOW_BATTERY, + CODE_LOCAL_NETWORK_NO_SERVICE, + CODE_LOCAL_NETWORK_NO_LTE_COVERAGE, + CODE_LOCAL_NETWORK_ROAMING, + CODE_LOCAL_NETWORK_IP_CHANGED, + CODE_LOCAL_SERVICE_UNAVAILABLE, + CODE_LOCAL_NOT_REGISTERED, + CODE_LOCAL_CALL_EXCEEDED, + CODE_LOCAL_CALL_BUSY, + CODE_LOCAL_CALL_DECLINE, + CODE_LOCAL_CALL_VCC_ON_PROGRESSING, + CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED, + CODE_LOCAL_CALL_CS_RETRY_REQUIRED, + CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED, + CODE_LOCAL_CALL_TERMINATED, + CODE_LOCAL_HO_NOT_FEASIBLE, + CODE_TIMEOUT_1XX_WAITING, + CODE_TIMEOUT_NO_ANSWER, + CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE, + CODE_CALL_BARRED, + CODE_FDN_BLOCKED, + CODE_IMEI_NOT_ACCEPTED, + CODE_DIAL_MODIFIED_TO_USSD, + CODE_DIAL_MODIFIED_TO_SS, + CODE_DIAL_MODIFIED_TO_DIAL, + CODE_DIAL_MODIFIED_TO_DIAL_VIDEO, + CODE_DIAL_VIDEO_MODIFIED_TO_DIAL, + CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO, + CODE_DIAL_VIDEO_MODIFIED_TO_SS, + CODE_DIAL_VIDEO_MODIFIED_TO_USSD, + CODE_SIP_REDIRECTED, + CODE_SIP_BAD_REQUEST, + CODE_SIP_FORBIDDEN, + CODE_SIP_NOT_FOUND, + CODE_SIP_NOT_SUPPORTED, + CODE_SIP_REQUEST_TIMEOUT, + CODE_SIP_TEMPRARILY_UNAVAILABLE, + CODE_SIP_BAD_ADDRESS, + CODE_SIP_BUSY, + CODE_SIP_REQUEST_CANCELLED, + CODE_SIP_NOT_ACCEPTABLE, + CODE_SIP_NOT_REACHABLE, + CODE_SIP_CLIENT_ERROR, + CODE_SIP_TRANSACTION_DOES_NOT_EXIST, + CODE_SIP_SERVER_INTERNAL_ERROR, + CODE_SIP_SERVICE_UNAVAILABLE, + CODE_SIP_SERVER_TIMEOUT, + CODE_SIP_SERVER_ERROR, + CODE_SIP_USER_REJECTED, + CODE_SIP_GLOBAL_ERROR, + CODE_EMERGENCY_TEMP_FAILURE, + CODE_EMERGENCY_PERM_FAILURE, + CODE_SIP_USER_MARKED_UNWANTED, + CODE_SIP_METHOD_NOT_ALLOWED, + CODE_SIP_PROXY_AUTHENTICATION_REQUIRED, + CODE_SIP_REQUEST_ENTITY_TOO_LARGE, + CODE_SIP_REQUEST_URI_TOO_LARGE, + CODE_SIP_EXTENSION_REQUIRED, + CODE_SIP_INTERVAL_TOO_BRIEF, + CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST, + CODE_SIP_LOOP_DETECTED, + CODE_SIP_TOO_MANY_HOPS, + CODE_SIP_AMBIGUOUS, + CODE_SIP_REQUEST_PENDING, + CODE_SIP_UNDECIPHERABLE, + CODE_MEDIA_INIT_FAILED, + CODE_MEDIA_NO_DATA, + CODE_MEDIA_NOT_ACCEPTABLE, + CODE_MEDIA_UNSPECIFIED, + CODE_USER_TERMINATED, + CODE_USER_NOANSWER, + CODE_USER_IGNORE, + CODE_USER_DECLINE, + CODE_LOW_BATTERY, + CODE_BLACKLISTED_CALL_ID, + CODE_USER_TERMINATED_BY_REMOTE, + CODE_USER_REJECTED_SESSION_MODIFICATION, + CODE_USER_CANCELLED_SESSION_MODIFICATION, + CODE_SESSION_MODIFICATION_FAILED, + CODE_UT_NOT_SUPPORTED, + CODE_UT_SERVICE_UNAVAILABLE, + CODE_UT_OPERATION_NOT_ALLOWED, + CODE_UT_NETWORK_ERROR, + CODE_UT_CB_PASSWORD_MISMATCH, + CODE_UT_SS_MODIFIED_TO_DIAL, + CODE_UT_SS_MODIFIED_TO_USSD, + CODE_UT_SS_MODIFIED_TO_SS, + CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO, + CODE_ECBM_NOT_SUPPORTED, + CODE_MULTIENDPOINT_NOT_SUPPORTED, + CODE_REGISTRATION_ERROR, + CODE_ANSWERED_ELSEWHERE, + CODE_CALL_PULL_OUT_OF_SYNC, + CODE_CALL_END_CAUSE_CALL_PULL, + CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE, + CODE_REJECTED_ELSEWHERE, + CODE_SUPP_SVC_FAILED, + CODE_SUPP_SVC_CANCELLED, + CODE_SUPP_SVC_REINVITE_COLLISION, + CODE_IWLAN_DPD_FAILURE, + CODE_EPDG_TUNNEL_ESTABLISH_FAILURE, + CODE_EPDG_TUNNEL_REKEY_FAILURE, + CODE_EPDG_TUNNEL_LOST_CONNECTION, + CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED, + CODE_REMOTE_CALL_DECLINE, + CODE_DATA_LIMIT_REACHED, + CODE_DATA_DISABLED, + CODE_WIFI_LOST, + CODE_IKEV2_AUTH_FAILURE, + CODE_RADIO_OFF, + CODE_NO_VALID_SIM, + CODE_RADIO_INTERNAL_ERROR, + CODE_NETWORK_RESP_TIMEOUT, + CODE_NETWORK_REJECT, + CODE_RADIO_ACCESS_FAILURE, + CODE_RADIO_LINK_FAILURE, + CODE_RADIO_LINK_LOST, + CODE_RADIO_UPLINK_FAILURE, + CODE_RADIO_SETUP_FAILURE, + CODE_RADIO_RELEASE_NORMAL, + CODE_RADIO_RELEASE_ABNORMAL, + CODE_ACCESS_CLASS_BLOCKED, + CODE_NETWORK_DETACH, + CODE_SIP_ALTERNATE_EMERGENCY_CALL, + CODE_UNOBTAINABLE_NUMBER, + CODE_NO_CSFB_IN_CS_ROAM, + CODE_REJECT_UNKNOWN, + CODE_REJECT_ONGOING_CALL_WAITING_DISABLED, + CODE_REJECT_CALL_ON_OTHER_SUB, + CODE_REJECT_1X_COLLISION, + CODE_REJECT_SERVICE_NOT_REGISTERED, + CODE_REJECT_CALL_TYPE_NOT_ALLOWED, + CODE_REJECT_ONGOING_E911_CALL, + CODE_REJECT_ONGOING_CALL_SETUP, + CODE_REJECT_MAX_CALL_LIMIT_REACHED, + CODE_REJECT_UNSUPPORTED_SIP_HEADERS, + CODE_REJECT_UNSUPPORTED_SDP_HEADERS, + CODE_REJECT_ONGOING_CALL_TRANSFER, + CODE_REJECT_INTERNAL_ERROR, + CODE_REJECT_QOS_FAILURE, + CODE_REJECT_ONGOING_HANDOVER, + CODE_REJECT_VT_TTY_NOT_ALLOWED, + CODE_REJECT_ONGOING_CALL_UPGRADE, + CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED, + CODE_REJECT_ONGOING_CONFERENCE_CALL, + CODE_REJECT_VT_AVPF_NOT_ALLOWED, + CODE_REJECT_ONGOING_ENCRYPTED_CALL, + CODE_REJECT_ONGOING_CS_CALL, + CODE_OEM_CAUSE_1, + CODE_OEM_CAUSE_2, + CODE_OEM_CAUSE_3, + CODE_OEM_CAUSE_4, + CODE_OEM_CAUSE_5, + CODE_OEM_CAUSE_6, + CODE_OEM_CAUSE_7, + CODE_OEM_CAUSE_8, + CODE_OEM_CAUSE_9, + CODE_OEM_CAUSE_10, + CODE_OEM_CAUSE_11, + CODE_OEM_CAUSE_12, + CODE_OEM_CAUSE_13, + CODE_OEM_CAUSE_14, + CODE_OEM_CAUSE_15 + }, prefix = "CODE_") + @Retention(RetentionPolicy.SOURCE) + public @interface ImsCode {} + + /** * Network string error messages. * mExtraMessage may have these values. */ @@ -964,7 +1143,7 @@ public final class ImsReasonInfo implements Parcelable { /** * @return an integer representing more information about the completion of an operation. */ - public int getCode() { + public @ImsCode int getCode() { return mCode; } diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index b171f7940944..6e98a0af244a 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -372,14 +372,6 @@ public class ProvisioningManager { } } - private static SubscriptionManager getSubscriptionManager(Context context) { - SubscriptionManager manager = context.getSystemService(SubscriptionManager.class); - if (manager == null) { - throw new RuntimeException("Could not find SubscriptionManager."); - } - return manager; - } - private static ITelephony getITelephony() { ITelephony binder = ITelephony.Stub.asInterface( ServiceManager.getService(Context.TELEPHONY_SERVICE)); diff --git a/telephony/java/android/telephony/mbms/GroupCallCallback.java b/telephony/java/android/telephony/mbms/GroupCallCallback.java index 77e36bbcf2ae..603f4e6d2030 100644 --- a/telephony/java/android/telephony/mbms/GroupCallCallback.java +++ b/telephony/java/android/telephony/mbms/GroupCallCallback.java @@ -57,7 +57,7 @@ public interface GroupCallCallback { * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - void onError(@GroupCallError int errorCode, @Nullable String message); + default void onError(@GroupCallError int errorCode, @Nullable String message) {} /** * Called to indicate this call has changed state. @@ -65,8 +65,8 @@ public interface GroupCallCallback { * See {@link GroupCall#STATE_STOPPED}, {@link GroupCall#STATE_STARTED} * and {@link GroupCall#STATE_STALLED}. */ - void onGroupCallStateChanged(@GroupCall.GroupCallState int state, - @GroupCall.GroupCallStateChangeReason int reason); + default void onGroupCallStateChanged(@GroupCall.GroupCallState int state, + @GroupCall.GroupCallStateChangeReason int reason) {} /** * Broadcast Signal Strength updated. @@ -78,5 +78,6 @@ public interface GroupCallCallback { * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available * for this call due to timing, geography or popularity. */ - void onBroadcastSignalStrengthUpdated(@IntRange(from = -1, to = 4) int signalStrength); + default void onBroadcastSignalStrengthUpdated( + @IntRange(from = -1, to = 4) int signalStrength) {} } diff --git a/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java index 04e7ba1af372..ac7e17271e34 100644 --- a/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java +++ b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java @@ -57,7 +57,7 @@ public interface MbmsGroupCallSessionCallback { * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - void onError(@GroupCallError int errorCode, @Nullable String message); + default void onError(@GroupCallError int errorCode, @Nullable String message) {} /** * Indicates that the list of currently available SAIs has been updated. The app may use this @@ -70,8 +70,8 @@ public interface MbmsGroupCallSessionCallback { * @param availableSais A list of lists of available SAIS in neighboring cells, where each list * contains the available SAIs in an individual cell. */ - void onAvailableSaisUpdated(@NonNull List<Integer> currentSais, - @NonNull List<List<Integer>> availableSais); + default void onAvailableSaisUpdated(@NonNull List<Integer> currentSais, + @NonNull List<List<Integer>> availableSais) {} /** * Called soon after the app calls {@link MbmsGroupCallSession#create}. The information supplied @@ -85,7 +85,7 @@ public interface MbmsGroupCallSessionCallback { * @param interfaceName The interface name for the data link. * @param index The index for the data link. */ - void onServiceInterfaceAvailable(@NonNull String interfaceName, int index); + default void onServiceInterfaceAvailable(@NonNull String interfaceName, int index) {} /** * Called to indicate that the middleware has been initialized and is ready. @@ -95,5 +95,5 @@ public interface MbmsGroupCallSessionCallback { * delivered via {@link #onError(int, String)} with error code * {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}. */ - void onMiddlewareReady(); + default void onMiddlewareReady() {} } diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp deleted file mode 100644 index 3d57d568dbd6..000000000000 --- a/tests/RollbackTest/Android.bp +++ /dev/null @@ -1,64 +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. - -android_app { - name: "RollbackTestAppAv1", - manifest: "TestApp/Av1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], -} - -android_app { - name: "RollbackTestAppAv2", - manifest: "TestApp/Av2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], -} - -android_app { - name: "RollbackTestAppACrashingV2", - manifest: "TestApp/ACrashingV2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], -} - -android_app { - name: "RollbackTestAppBv1", - manifest: "TestApp/Bv1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], -} - -android_app { - name: "RollbackTestAppBv2", - manifest: "TestApp/Bv2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], -} - -android_test { - name: "RollbackTest", - srcs: ["src/**/*.java"], - static_libs: ["android-support-test"], - test_suites: ["general-tests"], - java_resources: [ - ":RollbackTestAppAv1", - ":RollbackTestAppAv2", - ":RollbackTestAppACrashingV2", - ":RollbackTestAppBv1", - ":RollbackTestAppBv2", - ], - test_config: "RollbackTest.xml", - sdk_version: "system_current", -} diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk new file mode 100644 index 000000000000..40d4eff53577 --- /dev/null +++ b/tests/RollbackTest/Android.mk @@ -0,0 +1,96 @@ +# 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. + +LOCAL_PATH:= $(call my-dir) + +# RollbackTestAppAv1.apk +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src) +LOCAL_MANIFEST_FILE := TestApp/Av1.xml +LOCAL_PACKAGE_NAME := RollbackTestAppAv1 +include $(BUILD_PACKAGE) +ROLLBACK_TEST_APP_AV1 := $(LOCAL_INSTALLED_MODULE) + +# RollbackTestAppAv2.apk +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src) +LOCAL_MANIFEST_FILE := TestApp/Av2.xml +LOCAL_PACKAGE_NAME := RollbackTestAppAv2 +include $(BUILD_PACKAGE) +ROLLBACK_TEST_APP_AV2 := $(LOCAL_INSTALLED_MODULE) + +# RollbackTestAppACrashingV2.apk +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src) +LOCAL_MANIFEST_FILE := TestApp/ACrashingV2.xml +LOCAL_PACKAGE_NAME := RollbackTestAppACrashingV2 +include $(BUILD_PACKAGE) +ROLLBACK_TEST_APP_A_CRASHING_V2 := $(LOCAL_INSTALLED_MODULE) + +# RollbackTestAppBv1.apk +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src) +LOCAL_MANIFEST_FILE := TestApp/Bv1.xml +LOCAL_PACKAGE_NAME := RollbackTestAppBv1 +include $(BUILD_PACKAGE) +ROLLBACK_TEST_APP_BV1 := $(LOCAL_INSTALLED_MODULE) + +# RollbackTestAppBv2.apk +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, TestApp/src) +LOCAL_MANIFEST_FILE := TestApp/Bv2.xml +LOCAL_PACKAGE_NAME := RollbackTestAppBv2 +include $(BUILD_PACKAGE) +ROLLBACK_TEST_APP_BV2 := $(LOCAL_INSTALLED_MODULE) + +# RollbackTest +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_PACKAGE_NAME := RollbackTest +LOCAL_MODULE_TAGS := tests +LOCAL_STATIC_JAVA_LIBRARIES := android-support-test +LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_COMPATIBILITY_SUPPORT_FILES := $(ROLLBACK_TEST_APEX_V1) +LOCAL_JAVA_RESOURCE_FILES := \ + $(ROLLBACK_TEST_APP_AV1) \ + $(ROLLBACK_TEST_APP_AV2) \ + $(ROLLBACK_TEST_APP_A_CRASHING_V2) \ + $(ROLLBACK_TEST_APP_BV1) \ + $(ROLLBACK_TEST_APP_BV2) \ + $(ROLLBACK_TEST_APEX_V2) +LOCAL_SDK_VERSION := system_current +LOCAL_TEST_CONFIG := RollbackTest.xml +include $(BUILD_PACKAGE) + +# Clean up local variables +ROLLBACK_TEST_APP_AV1 := +ROLLBACK_TEST_APP_AV2 := +ROLLBACK_TEST_APP_A_CRASHING_V2 := +ROLLBACK_TEST_APP_BV1 := +ROLLBACK_TEST_APP_BV2 := diff --git a/tests/RollbackTest/TestApex/Android.bp b/tests/RollbackTest/TestApex/Android.bp new file mode 100644 index 000000000000..a2a8e1783f3b --- /dev/null +++ b/tests/RollbackTest/TestApex/Android.bp @@ -0,0 +1,56 @@ +// Copyright (C) 2019 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. + +apex { + name: "com.android.tests.rollback.testapex.RollbackTestApexV1", + manifest: "RollbackTestApexV1.json", + file_contexts: "apex.test", + prebuilts: ["RollbackTestApex.prebuilt.txt"], + key: "RollbackTestApex.key", + installable: false, +} + +apex { + name: "com.android.tests.rollback.testapex.RollbackTestApexV2", + manifest: "RollbackTestApexV2.json", + file_contexts: "apex.test", + prebuilts: ["RollbackTestApex.prebuilt.txt"], + key: "RollbackTestApex.key", + installable: false, +} + +apex_key { + name: "RollbackTestApex.key", + public_key: "com.android.tests.rollback.testapex.avbpubkey", + private_key: "com.android.tests.rollback.testapex.pem", + installable: false, +} + +prebuilt_etc { + name: "RollbackTestApex.prebuilt.txt", + src: "RollbackTestApex.prebuilt.txt", +} + +filegroup { + name: "RollbackTestApexV1_filegroup", + srcs: [":com.android.tests.rollback.testapex.RollbackTestApexV1"], + export_to_make_var: "ROLLBACK_TEST_APEX_V1", +} + +filegroup { + name: "RollbackTestApexV2_filegroup", + srcs: [":com.android.tests.rollback.testapex.RollbackTestApexV2"], + export_to_make_var: "ROLLBACK_TEST_APEX_V2", +} + diff --git a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt b/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt new file mode 100644 index 000000000000..e871146fb824 --- /dev/null +++ b/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt @@ -0,0 +1,3 @@ + +This file contains dummy content to include in the RollbackTestApex. + diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV1.json b/tests/RollbackTest/TestApex/RollbackTestApexV1.json new file mode 100644 index 000000000000..c3239ca0d902 --- /dev/null +++ b/tests/RollbackTest/TestApex/RollbackTestApexV1.json @@ -0,0 +1,4 @@ +{ + "name": "com.android.tests.rollback.testapex", + "version": 1 +} diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV2.json b/tests/RollbackTest/TestApex/RollbackTestApexV2.json new file mode 100644 index 000000000000..9de3f4590877 --- /dev/null +++ b/tests/RollbackTest/TestApex/RollbackTestApexV2.json @@ -0,0 +1,4 @@ +{ + "name": "com.android.tests.rollback.testapex", + "version": 2 +} diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey Binary files differnew file mode 100644 index 000000000000..b347331bc539 --- /dev/null +++ b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem new file mode 100644 index 000000000000..7181ce5c2a73 --- /dev/null +++ b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEArBLX+v6RMiK6soQFgbc0RZ+wticTD5sCbu9Q5B5WT7UnV1Wt +cNI/n2bjks3UYNxTneOzMQOVjd4ln0BYZoNvoDtrc1BsYABpt4FywSq1zz/3sp3L +3Vp8vaUyRsx0Da+PcOdYHPFs1WPX3Shw3MSPhUO/72KTm6GhO/cHEPEzSQLaw/zO +8FiPpDdRqILqVJlu1DZ+i1DO+To9mKt59uLlxy3F+HAMnQaNW6+2NCV/vdCxQrEL +m7PpsM6DymsFKcvVra1Il4apKkYNgcgTQ+AlmyPxGo6twfZvRMrU3bcrUmrg3OAx +tMD7MufXlKkoFMlT5clrQ7P2ErKoFxhTVWhBL5ZJv/lKwaTfxCLyNvYQ7JALKtOL +9xx4c77NdyYVjxMDAJ7E+Uj3QjdOv3FxM38Fcvt0zN4SSlmDjEDtm2e2w53Ztgz1 +zHAuNllIW1zGdPqa+ROoa9JLJePlyNXG9Rn1sSkjM9WwteaJ3nrdje6uBsvo7I9g +1MWab2XNXQwJNHACICtyU7QPryGP4U/lyHqWEkdoXrs8O36gmTGU/EsJYSIVILax +0HZC3zkmxHgiN95ZvD+Y5Y9HDXAN04kT8O1V/QD4QUCP8MGXNrkQP/JZAnu5Y2D1 +Wrn/7Tft2ON3OpH5vUgR99bKR549LcRrYgxeTnci3xkOsnTjZRxEUJFQgVUCAwEA +AQKCAgEAlBzIMbDLk+cW4rAG+WeTo9ZXygKKQqV/i7OM4j5GtudMTL1fxDwFLZTn +kCaBhzo+8ynaxPa71ViA87n0HZFHFRnwXFq+XkgctyrCdwjnY9RAxktS/l5z/t1i +EFTOFDWod1t6mbcpoegGF8RGmZDLpL7zR/+G5LBUU4RHXcrwBQli+s3x5imkwoon +TLAbOeSz5BBgDlTpQtdhy7bWDa+ybya0QCtagBLyvBfb8rjQYrduzOQOBODw5xJr +mGFUGWztqUf9swfjNpMD71EjXApk9EwUrXJgmBMiJYmdfpa6wH9kvFpyDo8J6gBr +rPeJm5LMF3+vR6Bw0Bld3DtBB8PsTrockOdeJNHfnY54480e7AahfM5gkeuIYC4P +E3CIbyAgpS8+OLpsXP207AOjFz1TLiOqyDUDsBqSMNEQ7QbIPTQw8UZ/o0vEoqEv +RrJAvIAv0KUcFNUL0t6VX2OXbV+i+T85wPey3XqK9P8Zzc8NUEGJ2paDUkSuemKC +nF9/siGaoBHXsNUkQuV9xYo4co66MHDGAx/OdUM5lPiUcrF/bR+ZUA3p1BLUQXbQ +aJD9uKlvJ4ZRSwhR/fQc5UiVWl3l76k+0Ia/Ddd1ArphVhbvGPOsm3W7wJ6KukSk +rBJh1PPV1HnA+icS2Wvu2kVdz9+39cQUYJIICO1uwWfPIb/R5MUCggEBAOSwkwXs +jqewNc6X4mc19RGKIMUvOrRrQkOOY33pI+BjoqI8cl+NOHNB7F8/gVnHIfhZpOG6 +WD5St1/qlSPT1Nte+38P+woAp5mdclZyRgYb4MjZybZihUPIPVgUbxiZTDHy1Sw0 +kRgmvaV3ccvG9/9bBUKNr9Z+XySsIhq5DzY+yIZ33vhLB/0g05x2HVIsSlsRWzri +lw0iX/v07bdIRUIv7QB8xcLY/23pIbHAXS8DaknN8YxpKtjilOnUWVp/dx4SIcJY +6PtSBfPcwVJ2MA/xXWBvDP82/XxvbxKnjj8lvkbfqMC6jrXJBw3NT/he8b932IBb +PwLGU4hoKvjXfUcCggEBAMCfa4N1KUXW0Mo3BcDk2Hk8zVYuTPDNTWg1Mxb46sn+ +HNVJKU0OrejM2hNNCwzJG7eVQBorJj5XefhaQFTvWoLKbf1YZuWKaQrRwKkHEqDi +edplA2RkpUebeS4KYIr22rzu3ZrZqiJmRU5kAS9hwOzwFvnXUgGy7IoZKXhpo0HK +xvwylb/C5FXh97tecDdH/5evB/DC515TIhPzUQ5tpT0oAl9MU7Pe1E/opzrD/0sR +dqKVJcl9vBRbtcAIkCOVpLoA9T2VvisafZAJaRXc3ACFMceewgpVAtBCsWUtLfvW +fHMHWfti5je19SWg7bUK56uHJ0vdAI+irkfpe1t0aoMCggEAR5cPL3eSYOREs9vQ +QEcf5NG82H2kfv5kzAkzFCN7267VJryNgWQQG+SzPk3/DD/OXpSRjShsn3X9ecVR +0tlpdRMS3//8snDqBqjHNlCnoxnvEHE9OB83YLS6n2wmKykyNSCzoxcBpPHbxITT +1tr+n626w87fEOKWnkBUnND59h1JYO79mfTDF3bDR+Oh4iuDS2bvjEuKxc3RBmry +T8IMDGA8bT6iGhEcRSgKKD7z7NfA2kHiL/ZsN2EXBOw43J+yhnNephx3MtXGj0S4 +MDxXZ2ZDuQCKrQpl6CJqPwi8+v+xxTYW+d5s9nNsBeIT+sieHTZDTEtEOnYjiDwz +15p92QKCAQEAkMwGNQawpOhLgYcFEzC0LcbwEFWzztx10N0U77LkRD16jTZ3Do73 +WmYLlLC4mr7e0A0o58MB96EodfHaJD7dSi5Dqkt25hw6xEBS1H0Vms1EjlCa0S/7 +Mq4D1QFF+5B/c8EX4ty20S8R8FCqt2SDc1kz3FHpOo+20kUB8Jtwdveox1J7UXB+ +1rSL1lSyhEviLbMMhAbvh+90UYz5pJ/1s9hMmDi3PyJFdWBNvZYyZcrV5He7tRCI +fsFGCfol6CoIby5jLA1Rq/M46jq4vQ+ObfGyLv3/nWa0O7u2wHjK9WIRoSKomJmK +t9xXURb9Obfd2Qo7FwMl9dNzsWkpKuGDYwKCAQB+hiWu2C+0foJ4Z8auM1SK8be4 +waplfD7qIvONE/vtl+VAN+eVpz5kkQJfXiafktAHahgEdSx43bofR0Kv0/R7IRs3 +M1WYAr0w+19TXLXkuh2oYIbcoGrIN3HMmlKMv44xh/QUhRe337cCLejP0SESNN+k +5wT91SbJwuCw/QsG3sD6NIMtCNWdcsAQq/ruhz7pQ/JZUFOueV0tkzbK+oNHWbNU +lS99qjPaVCXZFlz/t2/89cljh9mtRjcfXIBfuTijN9sXNcLTXsfLsyHJ86eEbI2U +o2JQ7Sjs10LpiwBbNNHBmulARgRONNMgik6tpNIS0tk9eke0lCX42bDFtAD4 +-----END RSA PRIVATE KEY----- diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java index 2310c829347e..97958acde21b 100644 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java +++ b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java @@ -33,7 +33,7 @@ public class CrashingMainActivity extends Activity { throw new RuntimeException("Intended force crash"); } - public void incrementCountAndBroadcast() { + private void incrementCountAndBroadcast() { SharedPreferences preferences = getSharedPreferences("prefs", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); int count = preferences.getInt("crash_count", 0); diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index ace0e6d14c58..4b277ae850c5 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -37,7 +37,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -629,12 +628,9 @@ public class RollbackTest { assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode()); } - // TODO: Allow installing test app along atomically with module metadata package so that - // a failed test app will be flagged as a failed mainline app /** * Test bad update automatic rollback. */ - @Ignore @Test public void testBadUpdateRollback() throws Exception { BroadcastReceiver crashCountReceiver = null; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 50468cbe7050..e2d59d648563 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -194,6 +194,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -500,17 +501,17 @@ public class ConnectivityServiceTest { public void unwanted() { mDisconnected.open(); } @Override - public void startPacketKeepalive(Message msg) { + public void startSocketKeepalive(Message msg) { int slot = msg.arg1; if (mExpectedKeepaliveSlot != null) { assertEquals((int) mExpectedKeepaliveSlot, slot); } - onPacketKeepaliveEvent(slot, mStartKeepaliveError); + onSocketKeepaliveEvent(slot, mStartKeepaliveError); } @Override - public void stopPacketKeepalive(Message msg) { - onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); + public void stopSocketKeepalive(Message msg) { + onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError); } @Override @@ -3817,10 +3818,17 @@ public class ConnectivityServiceTest { @Test public void testNattSocketKeepalives() throws Exception { + final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor(); + doTestNattSocketKeepalivesWithExecutor(executorSingleThread); + executorSingleThread.shutdown(); + + final Executor executorInline = (Runnable r) -> r.run(); + doTestNattSocketKeepalivesWithExecutor(executorInline); + } + + private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception { // TODO: 1. Move this outside of ConnectivityServiceTest. - // 2. Add helper function to test against newSingleThreadExecutor as well as inline - // executor. - // 3. Make test to verify that Nat-T keepalive socket is created by IpSecService. + // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService. final int srcPort = 12345; final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); @@ -3834,8 +3842,6 @@ public class ConnectivityServiceTest { final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort); - final Executor executor = Executors.newSingleThreadExecutor(); - LinkProperties lp = new LinkProperties(); lp.setInterfaceName("wlan12"); lp.addLinkAddress(new LinkAddress(myIPv6, 64)); @@ -3952,6 +3958,11 @@ public class ConnectivityServiceTest { ka2.stop(); callback2.expectStopped(); + + testSocket.close(); + testSocket2.close(); + + mWiFiNetworkAgent.disconnect(); } @Test diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index c50e6a778cda..c5b9cf137dd8 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -1099,9 +1099,13 @@ public class WifiConfiguration implements Parcelable { */ public static final int DISABLED_BY_WRONG_PASSWORD = 13; /** + * This network is disabled because service is not subscribed + */ + public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 14; + /** * This Maximum disable reason value */ - public static final int NETWORK_SELECTION_DISABLED_MAX = 14; + public static final int NETWORK_SELECTION_DISABLED_MAX = 15; /** * Quality network selection disable reason String (for debug purpose) @@ -1120,7 +1124,8 @@ public class WifiConfiguration implements Parcelable { "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT", "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER", "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH", - "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD" + "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD", + "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION" }; /** |