diff options
501 files changed, 10403 insertions, 5511 deletions
diff --git a/Android.bp b/Android.bp index 41d5f28a2680..c568d3676916 100644 --- a/Android.bp +++ b/Android.bp @@ -162,6 +162,7 @@ java_defaults { "core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl", "core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl", "core/java/android/hardware/biometrics/IBiometricServiceLockoutResetCallback.aidl", + "core/java/android/hardware/display/IColorDisplayManager.aidl", "core/java/android/hardware/display/IDisplayManager.aidl", "core/java/android/hardware/display/IDisplayManagerCallback.aidl", "core/java/android/hardware/display/IVirtualDisplayCallback.aidl", @@ -290,7 +291,6 @@ java_defaults { "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl", "core/java/android/service/gatekeeper/IGateKeeperService.aidl", "core/java/android/service/intelligence/IIntelligenceService.aidl", - "core/java/android/service/notification/INotificationListener.aidl", "core/java/android/service/notification/IStatusBarNotificationHolder.aidl", "core/java/android/service/notification/IConditionListener.aidl", @@ -573,6 +573,7 @@ java_defaults { "telephony/java/com/android/internal/telephony/IApnSourceService.aidl", "telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl", "telephony/java/com/android/internal/telephony/IMms.aidl", + "telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl", "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl", "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl", @@ -653,6 +654,8 @@ java_defaults { "core/java/com/android/server/DropboxLogTags.logtags", "core/java/org/chromium/arc/EventLogTags.logtags", + ":platform-properties", + ":framework-statslog-gen", ], @@ -782,9 +785,11 @@ java_library { java_library_host { name: "inspector-annotation", srcs: [ - "core/java/android/view/inspector/InspectableChildren.java", "core/java/android/view/inspector/InspectableNodeName.java", "core/java/android/view/inspector/InspectableProperty.java", + // Needed for the ResourceId.ID_NULL constant + "core/java/android/content/res/ResourceId.java", + "core/java/android/annotation/AnyRes.java", ], } diff --git a/Android.mk b/Android.mk index b7dda9a45ed8..92e33e988249 100644 --- a/Android.mk +++ b/Android.mk @@ -76,10 +76,9 @@ $(OUT_DOCS)/offline-sdk-timestamp: $(OUT_DOCS)/offline-sdk-docs-docs.zip .KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS) $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ - frameworks/base/config/hiddenapi-light-greylist.txt \ - frameworks/base/config/hiddenapi-vendor-list.txt \ + frameworks/base/config/hiddenapi-greylist.txt \ + frameworks/base/config/hiddenapi-greylist-max-p.txt \ frameworks/base/config/hiddenapi-greylist-max-o.txt \ - frameworks/base/config/hiddenapi-max-sdk-p-blacklist.txt \ frameworks/base/config/hiddenapi-force-blacklist.txt \ $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \ @@ -88,10 +87,9 @@ $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ --public $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \ --private $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \ --csv $(PRIVATE_FLAGS_INPUTS) \ - --greylist \ - frameworks/base/config/hiddenapi-light-greylist.txt \ - frameworks/base/config/hiddenapi-vendor-list.txt \ + --greylist frameworks/base/config/hiddenapi-greylist.txt \ --greylist-ignore-conflicts $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \ + --greylist-max-p frameworks/base/config/hiddenapi-greylist-max-p.txt \ --greylist-max-o-ignore-conflicts \ frameworks/base/config/hiddenapi-greylist-max-o.txt \ --blacklist frameworks/base/config/hiddenapi-force-blacklist.txt \ diff --git a/api/current.txt b/api/current.txt index 079539e3c5f4..2eb90d50c1c8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7692,6 +7692,7 @@ package android.appwidget { method protected void prepareView(android.view.View); method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo); method public void setExecutor(java.util.concurrent.Executor); + method public void setOnLightBackground(boolean); method public void updateAppWidget(android.widget.RemoteViews); method public void updateAppWidgetOptions(android.os.Bundle); method public void updateAppWidgetSize(android.os.Bundle, int, int, int, int); @@ -13728,6 +13729,7 @@ package android.graphics { public abstract class ColorSpace { method public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[]); method public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[], android.graphics.ColorSpace.Adaptation); + method public static float[] cctToIlluminantdXyz(int); method public static float[] chromaticAdaptation(android.graphics.ColorSpace.Adaptation, float[], float[]); method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace); method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent); @@ -24550,16 +24552,30 @@ package android.media { public final class MediaFormat { ctor public MediaFormat(); + ctor public MediaFormat(android.media.MediaFormat); + method public boolean containsFeature(java.lang.String); method public boolean containsKey(java.lang.String); method public static android.media.MediaFormat createAudioFormat(java.lang.String, int, int); method public static android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String); method public static android.media.MediaFormat createVideoFormat(java.lang.String, int, int); method public java.nio.ByteBuffer getByteBuffer(java.lang.String); + method public java.nio.ByteBuffer getByteBuffer(java.lang.String, java.nio.ByteBuffer); method public boolean getFeatureEnabled(java.lang.String); + method public java.util.Set<java.lang.String> getFeatures(); method public float getFloat(java.lang.String); + method public float getFloat(java.lang.String, float); method public int getInteger(java.lang.String); + method public int getInteger(java.lang.String, int); + method public java.util.Set<java.lang.String> getKeys(); method public long getLong(java.lang.String); + method public long getLong(java.lang.String, long); + method public java.lang.Number getNumber(java.lang.String); + method public java.lang.Number getNumber(java.lang.String, java.lang.Number); method public java.lang.String getString(java.lang.String); + method public java.lang.String getString(java.lang.String, java.lang.String); + method public int getValueTypeForKey(java.lang.String); + method public void removeFeature(java.lang.String); + method public void removeKey(java.lang.String); method public void setByteBuffer(java.lang.String, java.nio.ByteBuffer); method public void setFeatureEnabled(java.lang.String, boolean); method public void setFloat(java.lang.String, float); @@ -24664,6 +24680,12 @@ package android.media { field public static final java.lang.String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled"; field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8"; field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; + field public static final int TYPE_BYTE_BUFFER = 5; // 0x5 + field public static final int TYPE_FLOAT = 3; // 0x3 + field public static final int TYPE_INTEGER = 1; // 0x1 + field public static final int TYPE_LONG = 2; // 0x2 + field public static final int TYPE_NULL = 0; // 0x0 + field public static final int TYPE_STRING = 4; // 0x4 } public final class MediaMetadata implements android.os.Parcelable { @@ -29062,7 +29084,7 @@ package android.net.wifi { method public static int compareSignalLevel(int, int); method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String); method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String); - method public android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String); + method public deprecated android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String); method public deprecated boolean disableNetwork(int); method public deprecated boolean disconnect(); method public deprecated boolean enableNetwork(int, boolean); @@ -29124,9 +29146,10 @@ package android.net.wifi { field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0 field public static final deprecated java.lang.String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE"; field public static final deprecated java.lang.String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE"; - field public static final int WIFI_MODE_FULL = 1; // 0x1 + field public static final deprecated int WIFI_MODE_FULL = 1; // 0x1 field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3 - field public static final int WIFI_MODE_SCAN_ONLY = 2; // 0x2 + field public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; // 0x4 + field public static final deprecated int WIFI_MODE_SCAN_ONLY = 2; // 0x2 field public static final java.lang.String WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED"; field public static final int WIFI_STATE_DISABLED = 1; // 0x1 field public static final int WIFI_STATE_DISABLING = 0; // 0x0 @@ -33537,6 +33560,7 @@ package android.os { method public static boolean isExternalStorageRemovable(); method public static boolean isExternalStorageRemovable(java.io.File); field public static java.lang.String DIRECTORY_ALARMS; + field public static java.lang.String DIRECTORY_AUDIOBOOKS; field public static java.lang.String DIRECTORY_DCIM; field public static java.lang.String DIRECTORY_DOCUMENTS; field public static java.lang.String DIRECTORY_DOWNLOADS; @@ -37296,6 +37320,7 @@ package android.provider { method public static java.lang.String getVolumeName(android.net.Uri); method public static android.provider.MediaStore.PendingSession openPending(android.content.Context, android.net.Uri); method public static android.net.Uri setIncludePending(android.net.Uri); + method public static android.net.Uri setRequireOriginal(android.net.Uri); field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE"; field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE"; field public static final java.lang.String ACTION_REVIEW = "android.provider.action.REVIEW"; @@ -37393,6 +37418,7 @@ package android.provider { field public static final java.lang.String COMPOSER = "composer"; field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String IS_ALARM = "is_alarm"; + field public static final java.lang.String IS_AUDIOBOOK = "is_audiobook"; field public static final java.lang.String IS_MUSIC = "is_music"; field public static final java.lang.String IS_NOTIFICATION = "is_notification"; field public static final java.lang.String IS_PODCAST = "is_podcast"; @@ -37511,8 +37537,8 @@ package android.provider { field public static final java.lang.String DATE_TAKEN = "datetaken"; field public static final java.lang.String DESCRIPTION = "description"; field public static final java.lang.String IS_PRIVATE = "isprivate"; - field public static final java.lang.String LATITUDE = "latitude"; - field public static final java.lang.String LONGITUDE = "longitude"; + field public static final deprecated java.lang.String LATITUDE = "latitude"; + field public static final deprecated java.lang.String LONGITUDE = "longitude"; field public static final deprecated java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic"; field public static final java.lang.String ORIENTATION = "orientation"; field public static final deprecated java.lang.String PICASA_ID = "picasa_id"; @@ -37636,8 +37662,8 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String IS_PRIVATE = "isprivate"; field public static final java.lang.String LANGUAGE = "language"; - field public static final java.lang.String LATITUDE = "latitude"; - field public static final java.lang.String LONGITUDE = "longitude"; + field public static final deprecated java.lang.String LATITUDE = "latitude"; + field public static final deprecated java.lang.String LONGITUDE = "longitude"; field public static final deprecated java.lang.String MINI_THUMB_MAGIC = "mini_thumb_magic"; field public static final java.lang.String RESOLUTION = "resolution"; field public static final java.lang.String TAGS = "tags"; @@ -42898,6 +42924,19 @@ package android.telephony { field public static final int BAND_9 = 9; // 0x9 } + public final class AvailableNetworkInfo implements android.os.Parcelable { + ctor public AvailableNetworkInfo(int, int, java.util.ArrayList<java.lang.String>); + method public int describeContents(); + method public java.util.List<java.lang.String> getMccMncs(); + method public int getPriority(); + method public int getSubId(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.AvailableNetworkInfo> CREATOR; + field public static final int PRIORITY_HIGH = 1; // 0x1 + field public static final int PRIORITY_LOW = 3; // 0x3 + field public static final int PRIORITY_MED = 2; // 0x2 + } + public class CarrierConfigManager { method public android.os.PersistableBundle getConfig(); method public android.os.PersistableBundle getConfigForSubId(int); @@ -43876,6 +43915,7 @@ package android.telephony { method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri); method public deprecated void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean); + method public boolean updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>); field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL"; field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; @@ -45848,6 +45888,7 @@ package android.text.style { method public java.util.Locale getLocaleObject(); method public int getSpanTypeId(); method public java.lang.String[] getSuggestions(); + method public int getUnderlineColor(); method public void setFlags(int); method public void updateDrawState(android.text.TextPaint); method public void writeToParcel(android.os.Parcel, int); @@ -47848,6 +47889,7 @@ package android.view { method public final boolean isFunctionPressed(); method public static final boolean isGamepadButton(int); method public final boolean isLongPress(); + method public static final boolean isMediaSessionKey(int); method public final boolean isMetaPressed(); method public static boolean isModifierKey(int); method public final boolean isNumLockOn(); @@ -51963,10 +52005,90 @@ package android.view.inputmethod { } +package android.view.inspector { + + public abstract interface InspectionCompanion<T> { + method public default java.lang.String getNodeName(); + method public abstract void mapProperties(android.view.inspector.PropertyMapper); + method public abstract void readProperties(T, android.view.inspector.PropertyReader); + } + + public static class InspectionCompanion.UninitializedPropertyMapException extends java.lang.RuntimeException { + ctor public InspectionCompanion.UninitializedPropertyMapException(); + } + + public final class IntEnumMapping { + method public java.lang.String nameOf(int); + } + + public static final class IntEnumMapping.Builder { + ctor public IntEnumMapping.Builder(); + method public android.view.inspector.IntEnumMapping.Builder addValue(java.lang.String, int); + method public android.view.inspector.IntEnumMapping build(); + method public void clear(); + } + + public final class IntFlagMapping { + method public java.lang.String[] namesOf(int); + } + + public static final class IntFlagMapping.Builder { + ctor public IntFlagMapping.Builder(); + method public android.view.inspector.IntFlagMapping.Builder addFlag(java.lang.String, int); + method public android.view.inspector.IntFlagMapping.Builder addFlag(java.lang.String, int, int); + method public android.view.inspector.IntFlagMapping build(); + method public void clear(); + } + + public abstract interface PropertyMapper { + method public abstract int mapBoolean(java.lang.String, int); + method public abstract int mapByte(java.lang.String, int); + method public abstract int mapChar(java.lang.String, int); + method public abstract int mapColor(java.lang.String, int); + method public abstract int mapDouble(java.lang.String, int); + method public abstract int mapFloat(java.lang.String, int); + method public abstract int mapGravity(java.lang.String, int); + method public abstract int mapInt(java.lang.String, int); + method public abstract int mapIntEnum(java.lang.String, int, android.view.inspector.IntEnumMapping); + method public abstract int mapIntFlag(java.lang.String, int, android.view.inspector.IntFlagMapping); + method public abstract int mapLong(java.lang.String, int); + method public abstract int mapObject(java.lang.String, int); + method public abstract int mapShort(java.lang.String, int); + } + + public static class PropertyMapper.PropertyConflictException extends java.lang.RuntimeException { + ctor public PropertyMapper.PropertyConflictException(java.lang.String, java.lang.String, java.lang.String); + } + + public abstract interface PropertyReader { + method public abstract void readBoolean(int, boolean); + method public abstract void readByte(int, byte); + method public abstract void readChar(int, char); + method public abstract void readColor(int, int); + method public abstract void readColor(int, long); + method public abstract void readColor(int, android.graphics.Color); + method public abstract void readDouble(int, double); + method public abstract void readFloat(int, float); + method public abstract void readGravity(int, int); + method public abstract void readInt(int, int); + method public abstract void readIntEnum(int, int); + method public abstract void readIntFlag(int, int); + method public abstract void readLong(int, long); + method public abstract void readObject(int, java.lang.Object); + method public abstract void readShort(int, short); + } + + public static class PropertyReader.PropertyTypeMismatchException extends java.lang.RuntimeException { + ctor public PropertyReader.PropertyTypeMismatchException(int, java.lang.String, java.lang.String, java.lang.String); + ctor public PropertyReader.PropertyTypeMismatchException(int, java.lang.String, java.lang.String); + } + +} + package android.view.intelligence { - public final class IntelligenceManager { - method public android.content.ComponentName getIntelligenceServiceComponentName(); + public final class ContentCaptureManager { + method public android.content.ComponentName getServiceComponentName(); method public boolean isContentCaptureEnabled(); method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int); method public void notifyViewAppeared(android.view.ViewStructure); @@ -54960,6 +55082,7 @@ package android.widget { method public void setInt(int, java.lang.String, int); method public void setIntent(int, java.lang.String, android.content.Intent); method public void setLabelFor(int, int); + method public void setLightBackgroundLayoutId(int); method public void setLong(int, java.lang.String, long); method public void setOnClickFillInIntent(int, android.content.Intent); method public void setOnClickPendingIntent(int, android.app.PendingIntent); diff --git a/api/system-current.txt b/api/system-current.txt index e152cf4e398d..0215b2f681df 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -25,7 +25,6 @@ package android { field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE"; - field public static final java.lang.String BIND_INTELLIGENCE_SERVICE = "android.permission.BIND_INTELLIGENCE_SERVICE"; field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET"; field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"; field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"; @@ -34,6 +33,7 @@ package android { field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE"; field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"; field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"; + field public static final java.lang.String BIND_SMART_SUGGESTIONS_SERVICE = "android.permission.BIND_SMART_SUGGESTIONS_SERVICE"; field public static final java.lang.String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE"; field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE"; field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE"; @@ -57,6 +57,7 @@ package android { field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"; field public static final java.lang.String CONNECTIVITY_INTERNAL = "android.permission.CONNECTIVITY_INTERNAL"; field public static final java.lang.String CONNECTIVITY_USE_RESTRICTED_NETWORKS = "android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"; + field public static final java.lang.String CONTROL_DISPLAY_COLOR_TRANSFORMS = "android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS"; field public static final java.lang.String CONTROL_DISPLAY_SATURATION = "android.permission.CONTROL_DISPLAY_SATURATION"; field public static final java.lang.String CONTROL_INCALL_EXPERIENCE = "android.permission.CONTROL_INCALL_EXPERIENCE"; field public static final java.lang.String CONTROL_KEYGUARD_SECURE_NOTIFICATIONS = "android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"; @@ -108,6 +109,7 @@ package android { field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS"; field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS"; + field public static final java.lang.String MANAGE_SMART_SUGGESTIONS = "android.permission.MANAGE_SMART_SUGGESTIONS"; field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER"; field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB"; @@ -3013,6 +3015,7 @@ package android.media.audiopolicy { package android.media.session { public final class MediaSessionManager { + method public android.media.session.ISession createSession(android.media.session.MediaSession.CallbackStub, java.lang.String, int); method public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, android.os.Handler); method public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, android.os.Handler); } @@ -3693,7 +3696,6 @@ package android.net.wifi { method public void disableEphemeralNetwork(java.lang.String); method public void forget(int, android.net.wifi.WifiManager.ActionListener); method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>); - method public java.util.List<android.net.wifi.hotspot2.OsuProvider> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>); method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks(); method public android.net.wifi.WifiConfiguration getWifiApConfiguration(); method public int getWifiApState(); @@ -4310,6 +4312,7 @@ package android.os { public class UserManager { method public void clearSeedAccountData(); + method public android.os.UserHandle getProfileParent(android.os.UserHandle); method public java.lang.String getSeedAccountName(); method public android.os.PersistableBundle getSeedAccountOptions(); method public java.lang.String getSeedAccountType(); @@ -4629,6 +4632,7 @@ package android.provider { public static final class Settings.Secure extends android.provider.Settings.NameValueTable { method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean); method public static void resetToDefaults(android.content.ContentResolver, java.lang.String); + field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled"; field public static final java.lang.String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete"; field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification"; field public static final java.lang.String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count"; @@ -4641,6 +4645,8 @@ package android.provider { field public static final java.lang.String HUSH_GESTURE_USED = "hush_gesture_used"; field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled"; field public static final java.lang.String LAST_SETUP_SHOWN = "last_setup_shown"; + field public static final java.lang.String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis"; + field public static final java.lang.String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis"; field public static final java.lang.String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications"; field public static final java.lang.String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications"; field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count"; @@ -4978,6 +4984,13 @@ package android.service.euicc { package android.service.intelligence { + public final class ContentCaptureEventsRequest implements android.os.Parcelable { + method public int describeContents(); + method public java.util.List<android.view.intelligence.ContentCaptureEvent> getEvents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.intelligence.ContentCaptureEventsRequest> CREATOR; + } + public final class FillCallback { method public void onSuccess(android.service.intelligence.FillResponse); } @@ -5012,16 +5025,6 @@ package android.service.intelligence { field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L } - public abstract class IntelligenceService extends android.app.Service { - ctor public IntelligenceService(); - method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData); - method public abstract void onContentCaptureEvent(android.service.intelligence.InteractionSessionId, java.util.List<android.view.intelligence.ContentCaptureEvent>); - method public void onCreateInteractionSession(android.service.intelligence.InteractionContext, android.service.intelligence.InteractionSessionId); - method public void onDestroyInteractionSession(android.service.intelligence.InteractionSessionId); - method public void onFillRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.FillRequest, android.os.CancellationSignal, android.service.intelligence.FillController, android.service.intelligence.FillCallback); - field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.IntelligenceService"; - } - public final class InteractionContext implements android.os.Parcelable { method public int describeContents(); method public android.content.ComponentName getActivityComponent(); @@ -5057,6 +5060,21 @@ package android.service.intelligence { method public android.service.intelligence.PresentationParams.Area getSubArea(android.graphics.Rect); } + public abstract class SmartSuggestionsService extends android.app.Service { + ctor public SmartSuggestionsService(); + method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities(); + method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages(); + method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData); + method public abstract void onContentCaptureEventsRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.ContentCaptureEventsRequest); + method public void onCreateInteractionSession(android.service.intelligence.InteractionContext, android.service.intelligence.InteractionSessionId); + method public void onDestroyInteractionSession(android.service.intelligence.InteractionSessionId); + method public void onFillRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.FillRequest, android.os.CancellationSignal, android.service.intelligence.FillController, android.service.intelligence.FillCallback); + method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean); + method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>); + method public final void setPackageContentCaptureEnabled(java.lang.String, boolean); + field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.SmartSuggestionsService"; + } + public final class SnapshotData implements android.os.Parcelable { method public int describeContents(); method public android.app.assist.AssistContent getAssistContent(); @@ -5697,6 +5715,26 @@ package android.telephony { field public static final int RESULT_SUCCESS = 0; // 0x0 } + public abstract interface NumberVerificationCallback { + method public default void onCallReceived(java.lang.String); + method public default void onVerificationFailed(int); + field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4 + field public static final int REASON_IN_ECBM = 5; // 0x5 + field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6 + field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2 + field public static final int REASON_TIMED_OUT = 1; // 0x1 + field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3 + field public static final int REASON_UNSPECIFIED = 0; // 0x0 + } + + public final class PhoneNumberRange implements android.os.Parcelable { + ctor public PhoneNumberRange(java.lang.String, java.lang.String, java.lang.String, java.lang.String); + method public int describeContents(); + method public boolean matches(java.lang.String); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR; + } + public class PhoneStateListener { method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -5861,6 +5899,7 @@ package android.telephony { method public boolean needsOtaServiceProvisioning(); method public boolean rebootRadio(); method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback); + method public void requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback); method public boolean resetRadioConfig(); method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method public void setCarrierDataEnabled(boolean); @@ -5890,6 +5929,7 @@ package android.telephony { field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + field public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000L; // 0xea60L field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4 field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5 field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6 @@ -7241,14 +7281,6 @@ package android.view.intelligence { field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7 } - public final class IntelligenceManager { - method public java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities(); - method public java.util.Set<java.lang.String> getContentCaptureDisabledPackages(); - method public void setActivityContentCaptureEnabled(android.content.ComponentName, boolean); - method public void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>); - method public void setPackageContentCaptureEnabled(java.lang.String, boolean); - } - public final class ViewNode extends android.app.assist.AssistStructure.ViewNode { method public android.view.autofill.AutofillId getParentAutofillId(); } diff --git a/api/test-current.txt b/api/test-current.txt index 74b974e4ce8c..46cbb52f6efa 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1002,6 +1002,7 @@ package android.provider { } public static final class Settings.Secure extends android.provider.Settings.NameValueTable { + method public static void resetToDefaults(android.content.ContentResolver, java.lang.String); field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled"; field public static final java.lang.String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service"; field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification"; @@ -1013,6 +1014,8 @@ package android.provider { field public static final java.lang.String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length"; field public static final java.lang.String DISABLED_PRINT_SERVICES = "disabled_print_services"; field public static final deprecated java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages"; + field public static final java.lang.String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis"; + field public static final java.lang.String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis"; field public static final java.lang.String SYNC_PARENT_SOUNDS = "sync_parent_sounds"; field public static final java.lang.String USER_SETUP_COMPLETE = "user_setup_complete"; field public static final java.lang.String VOICE_INTERACTION_SERVICE = "voice_interaction_service"; diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java index 1597c8c9c2b2..52a2ab407f91 100644 --- a/cmds/content/src/com/android/commands/content/Content.java +++ b/cmds/content/src/com/android/commands/content/Content.java @@ -77,7 +77,7 @@ public class Content { + " <BINDING> binds a typed value to a column and is formatted:\n" + " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n" + " <TYPE> specifies data type such as:\n" - + " b - boolean, s - string, i - integer, l - long, f - float, d - double\n" + + " b - boolean, s - string, i - integer, l - long, f - float, d - double, n - null\n" + " Note: Omit the value for passing an empty string, e.g column:s:\n" + " Example:\n" + " # Add \"new_setting\" secure setting with value \"new_value\".\n" @@ -153,6 +153,7 @@ public class Content { private static final String TYPE_LONG = "l"; private static final String TYPE_FLOAT = "f"; private static final String TYPE_DOUBLE = "d"; + private static final String TYPE_NULL = "n"; private static final String COLON = ":"; private static final String ARGUMENT_PREFIX = "--"; @@ -410,6 +411,8 @@ public class Content { values.put(column, Long.parseLong(value)); } else if (TYPE_FLOAT.equalsIgnoreCase(type) || TYPE_DOUBLE.equalsIgnoreCase(type)) { values.put(column, Double.parseDouble(value)); + } else if (TYPE_NULL.equalsIgnoreCase(type)) { + values.putNull(column); } else { throw new IllegalArgumentException("Unsupported type: " + type); } diff --git a/config/hiddenapi-max-sdk-p-blacklist.txt b/config/hiddenapi-greylist-max-p.txt index e69de29bb2d1..e69de29bb2d1 100644 --- a/config/hiddenapi-max-sdk-p-blacklist.txt +++ b/config/hiddenapi-greylist-max-p.txt diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-greylist.txt index e10f72913d22..579ef938fb1d 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -51,6 +51,7 @@ Landroid/app/backup/IBackupManager;->setBackupEnabled(Z)V Landroid/app/backup/IFullBackupRestoreObserver$Stub;-><init>()V Landroid/app/backup/IRestoreObserver$Stub;-><init>()V Landroid/app/DownloadManager;->restartDownload([J)V +Landroid/app/IActivityController$Stub;-><init>()V Landroid/app/IActivityManager$Stub$Proxy;->getConfiguration()Landroid/content/res/Configuration; Landroid/app/IActivityManager$Stub$Proxy;->getLaunchedFromUid(Landroid/os/IBinder;)I Landroid/app/IActivityManager$Stub$Proxy;->getProcessLimit()I @@ -62,25 +63,35 @@ Landroid/app/IActivityManager$Stub$Proxy;->updatePersistentConfiguration(Landroi Landroid/app/IActivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager; Landroid/app/IActivityManager;->bindService(Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/content/Intent;Ljava/lang/String;Landroid/app/IServiceConnection;ILjava/lang/String;I)I Landroid/app/IActivityManager;->broadcastIntent(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;Landroid/content/IIntentReceiver;ILjava/lang/String;Landroid/os/Bundle;[Ljava/lang/String;ILandroid/os/Bundle;ZZI)I +Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V +Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V Landroid/app/IActivityManager;->checkPermission(Ljava/lang/String;II)I +Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V Landroid/app/IActivityManager;->finishActivity(Landroid/os/IBinder;ILandroid/content/Intent;I)Z Landroid/app/IActivityManager;->finishHeavyWeightApp()V Landroid/app/IActivityManager;->finishReceiver(Landroid/os/IBinder;ILjava/lang/String;Landroid/os/Bundle;ZI)V Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V Landroid/app/IActivityManager;->getAllStackInfos()Ljava/util/List; Landroid/app/IActivityManager;->getConfiguration()Landroid/content/res/Configuration; +Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo; +Landroid/app/IActivityManager;->getFilteredTasks(III)Ljava/util/List; Landroid/app/IActivityManager;->getIntentForIntentSender(Landroid/content/IIntentSender;)Landroid/content/Intent; Landroid/app/IActivityManager;->getIntentSender(ILjava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I[Landroid/content/Intent;[Ljava/lang/String;ILandroid/os/Bundle;I)Landroid/content/IIntentSender; Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String; Landroid/app/IActivityManager;->getLaunchedFromUid(Landroid/os/IBinder;)I +Landroid/app/IActivityManager;->getLockTaskModeState()I Landroid/app/IActivityManager;->getMemoryInfo(Landroid/app/ActivityManager$MemoryInfo;)V Landroid/app/IActivityManager;->getPackageProcessState(Ljava/lang/String;Ljava/lang/String;)I Landroid/app/IActivityManager;->getProcessLimit()I +Landroid/app/IActivityManager;->getProcessMemoryInfo([I)[Landroid/os/Debug$MemoryInfo; Landroid/app/IActivityManager;->getProcessPss([I)[J Landroid/app/IActivityManager;->getProviderMimeType(Landroid/net/Uri;I)Ljava/lang/String; +Landroid/app/IActivityManager;->getRecentTasks(III)Landroid/content/pm/ParceledListSlice; +Landroid/app/IActivityManager;->getRunningAppProcesses()Ljava/util/List; Landroid/app/IActivityManager;->getServices(II)Ljava/util/List; Landroid/app/IActivityManager;->getTaskBounds(I)Landroid/graphics/Rect; Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I +Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot; Landroid/app/IActivityManager;->handleApplicationStrictModeViolation(Landroid/os/IBinder;ILandroid/os/StrictMode$ViolationInfo;)V Landroid/app/IActivityManager;->hang(Landroid/os/IBinder;Z)V Landroid/app/IActivityManager;->isInLockTaskMode()Z @@ -98,9 +109,11 @@ Landroid/app/IActivityManager;->profileControl(Ljava/lang/String;IZLandroid/app/ Landroid/app/IActivityManager;->publishContentProviders(Landroid/app/IApplicationThread;Ljava/util/List;)V Landroid/app/IActivityManager;->registerProcessObserver(Landroid/app/IProcessObserver;)V Landroid/app/IActivityManager;->registerReceiver(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/IIntentReceiver;Landroid/content/IntentFilter;Ljava/lang/String;II)Landroid/content/Intent; +Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V Landroid/app/IActivityManager;->registerUserSwitchObserver(Landroid/app/IUserSwitchObserver;Ljava/lang/String;)V Landroid/app/IActivityManager;->removeContentProviderExternal(Ljava/lang/String;Landroid/os/IBinder;)V Landroid/app/IActivityManager;->removeStack(I)V +Landroid/app/IActivityManager;->removeTask(I)Z Landroid/app/IActivityManager;->requestBugReport(I)V Landroid/app/IActivityManager;->resizeDockedStack(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;)V Landroid/app/IActivityManager;->resizeStack(ILandroid/graphics/Rect;ZZZI)V @@ -120,8 +133,12 @@ Landroid/app/IActivityManager;->setProcessMemoryTrimLevel(Ljava/lang/String;II)Z Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V Landroid/app/IActivityManager;->setTaskResizeable(II)V Landroid/app/IActivityManager;->shutdown(I)Z +Landroid/app/IActivityManager;->startActivity(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;)I +Landroid/app/IActivityManager;->startActivityAsUser(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;I)I +Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I Landroid/app/IActivityManager;->startBinderTracking()Z Landroid/app/IActivityManager;->startInstrumentation(Landroid/content/ComponentName;Ljava/lang/String;ILandroid/os/Bundle;Landroid/app/IInstrumentationWatcher;Landroid/app/IUiAutomationConnection;ILjava/lang/String;)Z +Landroid/app/IActivityManager;->startRecentsActivity(Landroid/content/Intent;Landroid/app/IAssistDataReceiver;Landroid/view/IRecentsAnimationRunner;)V Landroid/app/IActivityManager;->startSystemLockTaskMode(I)V Landroid/app/IActivityManager;->startUserInBackground(I)Z Landroid/app/IActivityManager;->stopAppSwitches()V @@ -144,12 +161,16 @@ Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I Landroid/app/IAlarmManager$Stub;->TRANSACTION_set:I Landroid/app/IAlarmManager;->getNextAlarmClock(I)Landroid/app/AlarmManager$AlarmClockInfo; Landroid/app/IAlarmManager;->set(Ljava/lang/String;IJJJILandroid/app/PendingIntent;Landroid/app/IAlarmListener;Ljava/lang/String;Landroid/os/WorkSource;Landroid/app/AlarmManager$AlarmClockInfo;)V +Landroid/app/IAlarmManager;->setTime(J)Z Landroid/app/IApplicationThread;->scheduleBindService(Landroid/os/IBinder;Landroid/content/Intent;ZI)V Landroid/app/IApplicationThread;->scheduleCreateService(Landroid/os/IBinder;Landroid/content/pm/ServiceInfo;Landroid/content/res/CompatibilityInfo;I)V Landroid/app/IApplicationThread;->scheduleStopService(Landroid/os/IBinder;)V Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V Landroid/app/IApplicationThread;->scheduleUnbindService(Landroid/os/IBinder;Landroid/content/Intent;)V Landroid/app/IAppTask;->getTaskInfo()Landroid/app/ActivityManager$RecentTaskInfo; +Landroid/app/IAssistDataReceiver$Stub;-><init>()V +Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V +Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V Landroid/app/IInputForwarder;->forwardEvent(Landroid/view/InputEvent;)Z Landroid/app/IInstrumentationWatcher$Stub;-><init>()V Landroid/app/IInstrumentationWatcher$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IInstrumentationWatcher; @@ -236,6 +257,7 @@ Landroid/bluetooth/IBluetooth;->fetchRemoteUuids(Landroid/bluetooth/BluetoothDev Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String; Landroid/bluetooth/IBluetooth;->getRemoteAlias(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String; Landroid/bluetooth/IBluetooth;->isEnabled()Z +Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V Landroid/bluetooth/IBluetoothA2dp$Stub;-><init>()V Landroid/bluetooth/IBluetoothA2dp$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothA2dp; Landroid/bluetooth/IBluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z @@ -266,6 +288,10 @@ Landroid/bluetooth/IBluetoothManager;->unregisterStateChangeCallback(Landroid/bl Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap; Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V +Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V +Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V +Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V +Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V Landroid/content/ContentProviderProxy;->mRemote:Landroid/os/IBinder; Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard; @@ -312,11 +338,13 @@ Landroid/content/om/IOverlayManager;->getOverlayInfo(Ljava/lang/String;I)Landroi Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->onRemoveCompleted(Ljava/lang/String;Z)V +Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver; Landroid/content/pm/IPackageDataObserver$Stub;->DESCRIPTOR:Ljava/lang/String; Landroid/content/pm/IPackageDataObserver$Stub;->TRANSACTION_onRemoveCompleted:I Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V +Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver; Landroid/content/pm/IPackageDeleteObserver$Stub;->DESCRIPTOR:Ljava/lang/String; Landroid/content/pm/IPackageDeleteObserver$Stub;->TRANSACTION_packageDeleted:I @@ -325,6 +353,7 @@ Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBi Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V Landroid/content/pm/IPackageDeleteObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver2; Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V +Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V Landroid/content/pm/IPackageInstaller;->uninstall(Landroid/content/pm/VersionedPackage;Ljava/lang/String;ILandroid/content/IntentSender;I)V Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder; @@ -364,11 +393,14 @@ Landroid/content/pm/IPackageManager;->checkUidSignatures(II)I Landroid/content/pm/IPackageManager;->clearPackagePreferredActivities(Ljava/lang/String;)V Landroid/content/pm/IPackageManager;->currentToCanonicalPackageNames([Ljava/lang/String;)[Ljava/lang/String; Landroid/content/pm/IPackageManager;->deleteApplicationCacheFiles(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V +Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo; Landroid/content/pm/IPackageManager;->getApplicationEnabledSetting(Ljava/lang/String;I)I +Landroid/content/pm/IPackageManager;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo; Landroid/content/pm/IPackageManager;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String; Landroid/content/pm/IPackageManager;->getBlockUninstallForUser(Ljava/lang/String;I)Z Landroid/content/pm/IPackageManager;->getComponentEnabledSetting(Landroid/content/ComponentName;I)I Landroid/content/pm/IPackageManager;->getFlagsForUid(I)I +Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName; Landroid/content/pm/IPackageManager;->getInstalledApplications(II)Landroid/content/pm/ParceledListSlice; Landroid/content/pm/IPackageManager;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice; Landroid/content/pm/IPackageManager;->getInstallerPackageName(Ljava/lang/String;)Ljava/lang/String; @@ -376,6 +408,7 @@ Landroid/content/pm/IPackageManager;->getInstallLocation()I Landroid/content/pm/IPackageManager;->getInstrumentationInfo(Landroid/content/ComponentName;I)Landroid/content/pm/InstrumentationInfo; Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo; Landroid/content/pm/IPackageManager;->getNameForUid(I)Ljava/lang/String; +Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo; Landroid/content/pm/IPackageManager;->getPackageInstaller()Landroid/content/pm/IPackageInstaller; Landroid/content/pm/IPackageManager;->getPackagesForUid(I)[Ljava/lang/String; Landroid/content/pm/IPackageManager;->getPackageUid(Ljava/lang/String;II)I @@ -415,6 +448,7 @@ Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver; Landroid/content/pm/IPackageStatsObserver$Stub;->DESCRIPTOR:Ljava/lang/String; Landroid/content/pm/IPackageStatsObserver$Stub;->TRANSACTION_onGetStatsCompleted:I +Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService; Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V @@ -438,6 +472,7 @@ Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)La Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V +Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService; Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager; @@ -447,7 +482,10 @@ Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landr Landroid/location/ICountryListener$Stub;-><init>()V Landroid/location/IGeocodeProvider$Stub;-><init>()V Landroid/location/IGeocodeProvider$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/IGeocodeProvider; +Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; +Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; Landroid/location/IGeofenceProvider$Stub;-><init>()V +Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V Landroid/location/ILocationListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/location/ILocationListener$Stub$Proxy;->mRemote:Landroid/os/IBinder; Landroid/location/ILocationListener$Stub;-><init>()V @@ -460,6 +498,10 @@ 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/ILocationManager;->reportLocation(Landroid/location/Location;Z)V +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 Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String; Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String; @@ -486,6 +528,17 @@ Landroid/media/MediaFile;-><init>()V Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager; +Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V +Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->openInputBridge(Landroid/os/IBinder;Ljava/lang/String;III)V +Landroid/media/tv/ITvRemoteServiceInput;->sendKeyDown(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendKeyUp(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerDown(Landroid/os/IBinder;III)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerSync(Landroid/os/IBinder;)V +Landroid/media/tv/ITvRemoteServiceInput;->sendPointerUp(Landroid/os/IBinder;I)V +Landroid/media/tv/ITvRemoteServiceInput;->sendTimestamp(Landroid/os/IBinder;J)V +Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveLinkProperties()Landroid/net/LinkProperties; Landroid/net/IConnectivityManager$Stub$Proxy;->getActiveNetworkInfo()Landroid/net/NetworkInfo; @@ -499,6 +552,7 @@ Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landro Landroid/net/IConnectivityManager;->getActiveLinkProperties()Landroid/net/LinkProperties; Landroid/net/IConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; Landroid/net/IConnectivityManager;->getAllNetworkInfo()[Landroid/net/NetworkInfo; +Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState; Landroid/net/IConnectivityManager;->getLastTetherError(Ljava/lang/String;)I Landroid/net/IConnectivityManager;->getNetworkInfo(I)Landroid/net/NetworkInfo; Landroid/net/IConnectivityManager;->getTetherableIfaces()[Ljava/lang/String; @@ -508,9 +562,12 @@ Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String; Landroid/net/IConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String; Landroid/net/IConnectivityManager;->reportInetCondition(II)V Landroid/net/IConnectivityManager;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V +Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd; +Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V Landroid/net/INetworkPolicyListener$Stub;-><init>()V Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager; +Landroid/net/INetworkPolicyManager;->getNetworkQuotaInfo(Landroid/net/NetworkState;)Landroid/net/NetworkQuotaInfo; Landroid/net/INetworkPolicyManager;->getRestrictBackground()Z Landroid/net/INetworkPolicyManager;->getUidPolicy(I)I Landroid/net/INetworkPolicyManager;->setNetworkPolicies([Landroid/net/NetworkPolicy;)V @@ -520,14 +577,19 @@ Landroid/net/INetworkPolicyManager;->snoozeLimit(Landroid/net/NetworkTemplate;)V Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkScoreService; Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String; +Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService; Landroid/net/INetworkStatsService;->forceUpdate()V Landroid/net/INetworkStatsService;->getDataLayerSnapshotForUid(I)Landroid/net/NetworkStats; Landroid/net/INetworkStatsService;->getMobileIfaces()[Ljava/lang/String; Landroid/net/INetworkStatsService;->openSession()Landroid/net/INetworkStatsSession; Landroid/net/INetworkStatsService;->openSessionForUsageStats(ILjava/lang/String;)Landroid/net/INetworkStatsSession; Landroid/net/INetworkStatsSession;->close()V +Landroid/net/INetworkStatsSession;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory; +Landroid/net/INetworkStatsSession;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory; Landroid/net/INetworkStatsSession;->getSummaryForAllUid(Landroid/net/NetworkTemplate;JJZ)Landroid/net/NetworkStats; Landroid/net/INetworkStatsSession;->getSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats; +Landroid/net/InterfaceConfiguration;-><init>()V +Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange; Landroid/net/MobileLinkQualityInfo;-><init>()V Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager; Landroid/net/nsd/INsdManager;->getMessenger()Landroid/os/Messenger; @@ -552,7 +614,12 @@ Landroid/nfc/INfcAdapterExtras;->getDriverName(Ljava/lang/String;)Ljava/lang/Str Landroid/nfc/INfcAdapterExtras;->open(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle; Landroid/nfc/INfcAdapterExtras;->setCardEmulationRoute(Ljava/lang/String;I)V Landroid/nfc/INfcAdapterExtras;->transceive(Ljava/lang/String;[B)Landroid/os/Bundle; +Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V +Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable; Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;)Landroid/os/AsyncResult; +Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult; +Landroid/os/AsyncResult;->result:Ljava/lang/Object; +Landroid/os/AsyncResult;->userObj:Ljava/lang/Object; Landroid/os/AsyncTask;->mFuture:Ljava/util/concurrent/FutureTask; Landroid/os/AsyncTask;->mStatus:Landroid/os/AsyncTask$Status; Landroid/os/AsyncTask;->mTaskInvoked:Ljava/util/concurrent/atomic/AtomicBoolean; @@ -569,18 +636,24 @@ Landroid/os/BatteryManager;->EXTRA_MAX_CHARGING_CURRENT:Ljava/lang/String; Landroid/os/BatteryManager;->EXTRA_MAX_CHARGING_VOLTAGE:Ljava/lang/String; Landroid/os/BatteryStats$Counter;-><init>()V Landroid/os/BatteryStats$Counter;->getCountLocked(I)I +Landroid/os/BatteryStats$HistoryItem;-><init>()V Landroid/os/BatteryStats$HistoryItem;->batteryHealth:B +Landroid/os/BatteryStats$HistoryItem;->batteryLevel:B Landroid/os/BatteryStats$HistoryItem;->batteryPlugType:B Landroid/os/BatteryStats$HistoryItem;->batteryStatus:B Landroid/os/BatteryStats$HistoryItem;->batteryVoltage:C Landroid/os/BatteryStats$HistoryItem;->clear()V +Landroid/os/BatteryStats$HistoryItem;->cmd:B Landroid/os/BatteryStats$HistoryItem;->CMD_UPDATE:B Landroid/os/BatteryStats$HistoryItem;->next:Landroid/os/BatteryStats$HistoryItem; Landroid/os/BatteryStats$HistoryItem;->same(Landroid/os/BatteryStats$HistoryItem;)Z Landroid/os/BatteryStats$HistoryItem;->setTo(JBLandroid/os/BatteryStats$HistoryItem;)V Landroid/os/BatteryStats$HistoryItem;->setTo(Landroid/os/BatteryStats$HistoryItem;)V Landroid/os/BatteryStats$HistoryItem;->states2:I +Landroid/os/BatteryStats$HistoryItem;->states:I +Landroid/os/BatteryStats$HistoryItem;->time:J Landroid/os/BatteryStats$Timer;-><init>()V +Landroid/os/BatteryStats$Timer;->getCountLocked(I)I Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J Landroid/os/BatteryStats$Uid$Pkg$Serv;->getLaunches(I)I Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStarts(I)I @@ -604,6 +677,8 @@ Landroid/os/BatteryStats$Uid$Sensor;->getHandle()I Landroid/os/BatteryStats$Uid$Sensor;->getSensorTime()Landroid/os/BatteryStats$Timer; Landroid/os/BatteryStats$Uid$Sensor;->GPS:I Landroid/os/BatteryStats$Uid$Wakelock;-><init>()V +Landroid/os/BatteryStats$Uid$Wakelock;->getWakeTime(I)Landroid/os/BatteryStats$Timer; +Landroid/os/BatteryStats$Uid;-><init>()V Landroid/os/BatteryStats$Uid;->getAudioTurnedOnTimer()Landroid/os/BatteryStats$Timer; Landroid/os/BatteryStats$Uid;->getFullWifiLockTime(JI)J Landroid/os/BatteryStats$Uid;->getMobileRadioActiveTime(I)J @@ -616,6 +691,7 @@ Landroid/os/BatteryStats$Uid;->getVideoTurnedOnTimer()Landroid/os/BatteryStats$T Landroid/os/BatteryStats$Uid;->getWakelockStats()Landroid/util/ArrayMap; Landroid/os/BatteryStats$Uid;->getWifiBatchedScanTime(IJI)J Landroid/os/BatteryStats$Uid;->getWifiMulticastTime(JI)J +Landroid/os/BatteryStats$Uid;->getWifiRunningTime(JI)J Landroid/os/BatteryStats$Uid;->getWifiScanTime(JI)J Landroid/os/BatteryStats;-><init>()V Landroid/os/BatteryStats;->computeBatteryRealtime(JI)J @@ -627,6 +703,7 @@ Landroid/os/BatteryStats;->getBatteryUptime(J)J Landroid/os/BatteryStats;->getGlobalWifiRunningTime(JI)J Landroid/os/BatteryStats;->getMobileRadioActiveTime(JI)J Landroid/os/BatteryStats;->getNetworkActivityBytes(II)J +Landroid/os/BatteryStats;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z Landroid/os/BatteryStats;->getPhoneOnTime(JI)J Landroid/os/BatteryStats;->getPhoneSignalStrengthTime(IJI)J Landroid/os/BatteryStats;->getScreenBrightnessTime(IJI)J @@ -640,6 +717,10 @@ Landroid/os/BatteryStats;->STATS_CURRENT:I Landroid/os/BatteryStats;->WAKE_TYPE_PARTIAL:I Landroid/os/Binder;->execTransact(IJJI)Z Landroid/os/Binder;->mObject:J +Landroid/os/Broadcaster;-><init>()V +Landroid/os/Broadcaster;->broadcast(Landroid/os/Message;)V +Landroid/os/Broadcaster;->cancelRequest(ILandroid/os/Handler;I)V +Landroid/os/Broadcaster;->request(ILandroid/os/Handler;I)V Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String; Landroid/os/Build;->getLong(Ljava/lang/String;)J Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String; @@ -713,6 +794,7 @@ Landroid/os/Environment;->buildExternalStorageAppMediaDirs(Ljava/lang/String;)[L Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File; Landroid/os/Environment;->buildPaths([Ljava/io/File;[Ljava/lang/String;)[Ljava/io/File; Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File; +Landroid/os/Environment;->getLegacyExternalStorageDirectory()Ljava/io/File; Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File; Landroid/os/Environment;->initForCurrentUser()V Landroid/os/Environment;->maybeTranslateEmulatedPathToInternal(Ljava/io/File;)Ljava/io/File; @@ -733,12 +815,15 @@ Landroid/os/FileUtils;->setPermissions(Ljava/lang/String;III)I Landroid/os/FileUtils;->stringToFile(Ljava/io/File;Ljava/lang/String;)V Landroid/os/FileUtils;->stringToFile(Ljava/lang/String;Ljava/lang/String;)V Landroid/os/FileUtils;->sync(Ljava/io/FileOutputStream;)Z +Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V Landroid/os/Handler;-><init>(Z)V Landroid/os/Handler;->getIMessenger()Landroid/os/IMessenger; +Landroid/os/Handler;->getMain()Landroid/os/Handler; Landroid/os/Handler;->getPostMessage(Ljava/lang/Runnable;Ljava/lang/Object;)Landroid/os/Message; Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback; Landroid/os/Handler;->mLooper:Landroid/os/Looper; Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger; +Landroid/os/HwBinder;->reportSyspropChanged()V Landroid/os/HwParcel;-><init>(Z)V Landroid/os/HwRemoteBinder;-><init>()V Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V @@ -749,16 +834,26 @@ Landroid/os/IDeviceIdleController;->addPowerSaveTempWhitelistApp(Ljava/lang/Stri Landroid/os/IDeviceIdleController;->getAppIdTempWhitelist()[I Landroid/os/IDeviceIdleController;->getFullPowerWhitelistExceptIdle()[Ljava/lang/String; Landroid/os/INetworkManagementService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V +Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService; +Landroid/os/INetworkManagementService;->clearInterfaceAddresses(Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->disableIpv6(Ljava/lang/String;)V Landroid/os/INetworkManagementService;->disableNat(Ljava/lang/String;Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->enableIpv6(Ljava/lang/String;)V Landroid/os/INetworkManagementService;->enableNat(Ljava/lang/String;Ljava/lang/String;)V Landroid/os/INetworkManagementService;->getInterfaceConfig(Ljava/lang/String;)Landroid/net/InterfaceConfiguration; Landroid/os/INetworkManagementService;->getIpForwardingEnabled()Z +Landroid/os/INetworkManagementService;->isBandwidthControlEnabled()Z Landroid/os/INetworkManagementService;->isTetheringStarted()Z Landroid/os/INetworkManagementService;->listTetheredInterfaces()[Ljava/lang/String; +Landroid/os/INetworkManagementService;->registerObserver(Landroid/net/INetworkManagementEventObserver;)V +Landroid/os/INetworkManagementService;->setInterfaceConfig(Ljava/lang/String;Landroid/net/InterfaceConfiguration;)V +Landroid/os/INetworkManagementService;->setInterfaceIpv6PrivacyExtensions(Ljava/lang/String;Z)V Landroid/os/INetworkManagementService;->setIpForwardingEnabled(Z)V +Landroid/os/INetworkManagementService;->setIPv6AddrGenMode(Ljava/lang/String;I)V Landroid/os/INetworkManagementService;->startTethering([Ljava/lang/String;)V Landroid/os/INetworkManagementService;->stopTethering()V Landroid/os/INetworkManagementService;->tetherInterface(Ljava/lang/String;)V +Landroid/os/INetworkManagementService;->unregisterObserver(Landroid/net/INetworkManagementEventObserver;)V Landroid/os/INetworkManagementService;->untetherInterface(Ljava/lang/String;)V Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController; @@ -767,12 +862,15 @@ Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager; Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I +Landroid/os/IPowerManager;->goToSleep(JII)V Landroid/os/IPowerManager;->isInteractive()Z Landroid/os/IPowerManager;->nap(J)V +Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V Landroid/os/IPowerManager;->releaseWakeLock(Landroid/os/IBinder;I)V Landroid/os/IPowerManager;->userActivity(JII)V Landroid/os/IPowerManager;->wakeUp(JLjava/lang/String;Ljava/lang/String;)V Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem; +Landroid/os/IRemoteCallback$Stub;-><init>()V Landroid/os/IRemoteCallback;->sendResult(Landroid/os/Bundle;)V Landroid/os/IServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder; Landroid/os/IServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder; @@ -798,6 +896,7 @@ Landroid/os/Message;->flags:I Landroid/os/Message;->markInUse()V Landroid/os/Message;->next:Landroid/os/Message; Landroid/os/Message;->recycleUnchecked()V +Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message; Landroid/os/Message;->target:Landroid/os/Handler; Landroid/os/Message;->toString(J)Ljava/lang/String; Landroid/os/Message;->when:J @@ -817,13 +916,16 @@ Landroid/os/Parcel;->mCreators:Ljava/util/HashMap; Landroid/os/Parcel;->mNativePtr:J Landroid/os/Parcel;->readArrayMap(Landroid/util/ArrayMap;Ljava/lang/ClassLoader;)V Landroid/os/Parcel;->readArraySet(Ljava/lang/ClassLoader;)Landroid/util/ArraySet; +Landroid/os/Parcel;->readBlob()[B Landroid/os/Parcel;->readCharSequence()Ljava/lang/CharSequence; Landroid/os/Parcel;->readCreator(Landroid/os/Parcelable$Creator;Ljava/lang/ClassLoader;)Landroid/os/Parcelable; Landroid/os/Parcel;->readExceptionCode()I Landroid/os/Parcel;->readParcelableCreator(Ljava/lang/ClassLoader;)Landroid/os/Parcelable$Creator; Landroid/os/Parcel;->readRawFileDescriptor()Ljava/io/FileDescriptor; +Landroid/os/Parcel;->readStringArray()[Ljava/lang/String; Landroid/os/Parcel;->writeArrayMap(Landroid/util/ArrayMap;)V Landroid/os/Parcel;->writeArraySet(Landroid/util/ArraySet;)V +Landroid/os/Parcel;->writeBlob([B)V Landroid/os/Parcel;->writeCharSequence(Ljava/lang/CharSequence;)V Landroid/os/Parcel;->writeParcelableCreator(Landroid/os/Parcelable;)V Landroid/os/ParcelableParcel;-><init>(Ljava/lang/ClassLoader;)V @@ -890,15 +992,27 @@ Landroid/os/Process;->SHELL_UID:I Landroid/os/Process;->VPN_UID:I Landroid/os/Process;->WIFI_UID:I Landroid/os/RecoverySystem;->verifyPackageCompatibility(Ljava/io/InputStream;)Z +Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V +Landroid/os/Registrant;->clear()V Landroid/os/Registrant;->getHandler()Landroid/os/Handler; Landroid/os/Registrant;->messageForRegistrant()Landroid/os/Message; +Landroid/os/Registrant;->notifyRegistrant()V +Landroid/os/Registrant;->notifyRegistrant(Landroid/os/AsyncResult;)V Landroid/os/Registrant;->notifyResult(Ljava/lang/Object;)V +Landroid/os/RegistrantList;-><init>()V Landroid/os/RegistrantList;->add(Landroid/os/Handler;ILjava/lang/Object;)V +Landroid/os/RegistrantList;->add(Landroid/os/Registrant;)V +Landroid/os/RegistrantList;->addUnique(Landroid/os/Handler;ILjava/lang/Object;)V Landroid/os/RegistrantList;->get(I)Ljava/lang/Object; +Landroid/os/RegistrantList;->notifyRegistrants()V +Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V Landroid/os/RegistrantList;->notifyResult(Ljava/lang/Object;)V +Landroid/os/RegistrantList;->remove(Landroid/os/Handler;)V +Landroid/os/RegistrantList;->removeCleared()V Landroid/os/RegistrantList;->size()I Landroid/os/RemoteCallback;->mHandler:Landroid/os/Handler; Landroid/os/RemoteCallbackList;->mCallbacks:Landroid/util/ArrayMap; +Landroid/os/RemoteException;->rethrowFromSystemServer()Ljava/lang/RuntimeException; Landroid/os/SELinux;->checkSELinuxAccess(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z Landroid/os/SELinux;->getContext()Ljava/lang/String; Landroid/os/SELinux;->getFileContext(Ljava/lang/String;)Ljava/lang/String; @@ -920,6 +1034,7 @@ Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/ Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder; Landroid/os/ServiceManagerProxy;->mRemote:Landroid/os/IBinder; Landroid/os/ServiceSpecificException;-><init>(ILjava/lang/String;)V +Landroid/os/ServiceSpecificException;->errorCode:I Landroid/os/SharedMemory;->getFd()I Landroid/os/ShellCommand;->peekNextArg()Ljava/lang/String; Landroid/os/StatFs;->mStat:Landroid/system/StructStatVfs; @@ -927,6 +1042,7 @@ Landroid/os/storage/IObbActionListener$Stub;-><init>()V Landroid/os/storage/IObbActionListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IObbActionListener; Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager; +Landroid/os/storage/StorageEventListener;-><init>()V Landroid/os/StrictMode$Span;->finish()V Landroid/os/StrictMode$ThreadPolicy;->mask:I Landroid/os/StrictMode$VmPolicy$Builder;->mMask:I @@ -954,8 +1070,12 @@ Landroid/os/SystemProperties;->native_get_int(Ljava/lang/String;I)I Landroid/os/SystemProperties;->native_get_long(Ljava/lang/String;J)J Landroid/os/SystemProperties;->native_set(Ljava/lang/String;Ljava/lang/String;)V Landroid/os/SystemProperties;->PROP_NAME_MAX:I +Landroid/os/SystemProperties;->reportSyspropChanged()V Landroid/os/SystemProperties;->sChangeCallbacks:Ljava/util/ArrayList; Landroid/os/SystemProperties;->set(Ljava/lang/String;Ljava/lang/String;)V +Landroid/os/SystemService;->start(Ljava/lang/String;)V +Landroid/os/SystemService;->stop(Ljava/lang/String;)V +Landroid/os/SystemVibrator;-><init>()V Landroid/os/SystemVibrator;-><init>(Landroid/content/Context;)V Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V @@ -994,6 +1114,7 @@ Landroid/os/UserHandle;->getCallingUserId()I Landroid/os/UserHandle;->getUid(II)I Landroid/os/UserHandle;->getUserId(I)I Landroid/os/UserHandle;->isIsolated(I)Z +Landroid/os/UserHandle;->isSameApp(II)Z Landroid/os/UserHandle;->mHandle:I Landroid/os/UserHandle;->MU_ENABLED:Z Landroid/os/UserHandle;->OWNER:Landroid/os/UserHandle; @@ -1023,6 +1144,7 @@ Landroid/os/UserManager;->getUserSerialNumber(I)I Landroid/os/UserManager;->getUserStartRealtime()J Landroid/os/UserManager;->getUserUnlockRealtime()J Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z +Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z Landroid/os/UserManager;->isDeviceInDemoMode(Landroid/content/Context;)Z Landroid/os/UserManager;->isGuestUser(I)Z Landroid/os/UserManager;->isLinkedUser()Z @@ -1072,6 +1194,7 @@ Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I Landroid/R$styleable;->CalendarView_weekNumberColor:I Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I +Landroid/R$styleable;->CheckBoxPreference:[I Landroid/R$styleable;->CheckedTextView:[I Landroid/R$styleable;->CheckedTextView_checkMark:I Landroid/R$styleable;->CompoundButton:[I @@ -1382,7 +1505,18 @@ Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V Landroid/telecom/Log;->i(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V Landroid/telecom/Log;->w(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V Landroid/telephony/CarrierMessagingServiceManager;-><init>()V +Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V +Landroid/telephony/ims/compat/ImsService;-><init>()V +Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V +Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V Landroid/telephony/JapanesePhoneNumberFormatter;->format(Landroid/text/Editable;)V +Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V +Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V +Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService; +Landroid/telephony/mbms/vendor/IMbmsStreamingService;->getPlaybackUri(ILjava/lang/String;)Landroid/net/Uri; +Landroid/telephony/mbms/vendor/IMbmsStreamingService;->initialize(Landroid/telephony/mbms/IMbmsStreamingSessionCallback;I)I +Landroid/telephony/mbms/vendor/IMbmsStreamingService;->requestUpdateStreamingServices(ILjava/util/List;)I +Landroid/telephony/mbms/vendor/IMbmsStreamingService;->startStreaming(ILjava/lang/String;Landroid/telephony/mbms/IStreamingServiceCallback;)I Landroid/telephony/SmsCbCmasInfo;->getCategory()I Landroid/telephony/SmsCbCmasInfo;->getCertainty()I Landroid/telephony/SmsCbCmasInfo;->getMessageClass()I @@ -1424,10 +1558,21 @@ Landroid/view/accessibility/IAccessibilityManager;->getEnabledAccessibilityServi Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;-><init>()V Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager; +Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V Landroid/view/IDockedStackListener$Stub;-><init>()V Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats; +Landroid/view/IRecentsAnimationController;->finish(Z)V +Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot; Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V +Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V +Landroid/view/IRecentsAnimationRunner$Stub;-><init>()V +Landroid/view/IRecentsAnimationRunner;->onAnimationCanceled()V +Landroid/view/IRecentsAnimationRunner;->onAnimationStart(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;Landroid/graphics/Rect;Landroid/graphics/Rect;)V +Landroid/view/IRemoteAnimationFinishedCallback;->onAnimationFinished()V +Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V +Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V +Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V Landroid/view/IRotationWatcher$Stub;-><init>()V Landroid/view/IWindow$Stub;-><init>()V Landroid/view/IWindow$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindow; @@ -1439,6 +1584,9 @@ Landroid/view/IWindowManager$Stub$Proxy;->hasNavigationBar(I)Z Landroid/view/IWindowManager$Stub$Proxy;->watchRotation(Landroid/view/IRotationWatcher;I)I Landroid/view/IWindowManager$Stub;-><init>()V Landroid/view/IWindowManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowManager; +Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V +Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z +Landroid/view/IWindowManager;->endProlongedAnimations()V Landroid/view/IWindowManager;->executeAppTransition()V Landroid/view/IWindowManager;->freezeRotation(I)V Landroid/view/IWindowManager;->getAnimationScale(I)F @@ -1447,16 +1595,20 @@ Landroid/view/IWindowManager;->getBaseDisplaySize(ILandroid/graphics/Point;)V Landroid/view/IWindowManager;->getDockedStackSide()I Landroid/view/IWindowManager;->getInitialDisplayDensity(I)I Landroid/view/IWindowManager;->getInitialDisplaySize(ILandroid/graphics/Point;)V +Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V Landroid/view/IWindowManager;->hasNavigationBar(I)Z Landroid/view/IWindowManager;->isKeyguardLocked()Z Landroid/view/IWindowManager;->isKeyguardSecure()Z Landroid/view/IWindowManager;->isSafeModeEnabled()Z Landroid/view/IWindowManager;->lockNow(Landroid/os/Bundle;)V +Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;ZI)V +Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;I)V Landroid/view/IWindowManager;->registerDockedStackListener(Landroid/view/IDockedStackListener;)V Landroid/view/IWindowManager;->removeRotationWatcher(Landroid/view/IRotationWatcher;)V Landroid/view/IWindowManager;->setAnimationScale(IF)V Landroid/view/IWindowManager;->setAnimationScales([F)V Landroid/view/IWindowManager;->setInTouchMode(Z)V +Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V Landroid/view/IWindowManager;->setShelfHeight(ZI)V Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V Landroid/view/IWindowManager;->showStrictModeViolation(Z)V @@ -1496,6 +1648,7 @@ Lcom/android/ims/ImsCall;->isMultiparty()Z Lcom/android/ims/ImsCall;->reject(I)V Lcom/android/ims/ImsCall;->terminate(I)V Lcom/android/ims/ImsConfigListener$Stub;-><init>()V +Lcom/android/ims/ImsConfigListener;->onSetFeatureResponse(IIII)V Lcom/android/ims/ImsEcbm;->exitEmergencyCallbackMode()V Lcom/android/ims/ImsManager;->getConfigInterface()Lcom/android/ims/ImsConfig; Lcom/android/ims/ImsManager;->getInstance(Landroid/content/Context;I)Lcom/android/ims/ImsManager; @@ -1505,12 +1658,48 @@ Lcom/android/ims/ImsManager;->isVolteEnabledByPlatform(Landroid/content/Context; Lcom/android/ims/ImsUtInterface;->queryCallForward(ILjava/lang/String;Landroid/os/Message;)V Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession; +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionConferenceStateUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsConferenceState;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandover(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandoverFailed(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHeld(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestDelivered(Lcom/android/ims/internal/IImsCallSession;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeComplete(Lcom/android/ims/internal/IImsCallSession;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeStarted(Lcom/android/ims/internal/IImsCallSession;Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMultipartyStateChanged(Lcom/android/ims/internal/IImsCallSession;Z)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionProgressing(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsStreamMediaProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStarted(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStartFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionSuppServiceReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsSuppServiceNotification;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTerminated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V +Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V Lcom/android/ims/internal/IImsEcbm$Stub;-><init>()V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationChangeFailed(ILandroid/telephony/ims/ImsReasonInfo;)V Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnected()V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V +Lcom/android/ims/internal/IImsRegistrationListener;->registrationProgressingWithRadioTech(I)V +Lcom/android/ims/internal/IImsRegistrationListener;->voiceMessageCountUpdate(I)V Lcom/android/ims/internal/IImsService$Stub;-><init>()V Lcom/android/ims/internal/IImsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsService; Lcom/android/ims/internal/IImsUt$Stub;-><init>()V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallBarringQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallForwardQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsCallForwardInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallWaitingQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueried(Lcom/android/ims/internal/IImsUt;ILandroid/os/Bundle;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V +Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V Lcom/android/ims/internal/IImsVideoCallCallback;->changeCallDataUsage(J)V Lcom/android/ims/internal/IImsVideoCallCallback;->changeCameraCapabilities(Landroid/telecom/VideoProfile$CameraCapabilities;)V Lcom/android/ims/internal/IImsVideoCallCallback;->changePeerDimensions(II)V @@ -1521,7 +1710,52 @@ Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(I Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V Lcom/android/ims/internal/ImsVideoCallProviderWrapper;-><init>(Lcom/android/ims/internal/IImsVideoCallProvider;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceUnavailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/options/IOptionsListener;->sipResponseReceived(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsSipResponse;Lcom/android/ims/internal/uce/options/OptionsCapInfo;)V +Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V +Lcom/android/ims/internal/uce/options/IOptionsService;->addListener(ILcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getMyInfo(II)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->listCapInfoReceived(Lcom/android/ims/internal/uce/presence/PresRlmiInfo;[Lcom/android/ims/internal/uce/presence/PresResInfo;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->publishTriggering(Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceUnAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->sipResponseReceived(Lcom/android/ims/internal/uce/presence/PresSipResponse;)V +Lcom/android/ims/internal/uce/presence/IPresenceListener;->unpublishMessageSent()V +Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V +Lcom/android/ims/internal/uce/presence/IPresenceService;->addListener(ILcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->publishMyCap(ILcom/android/ims/internal/uce/presence/PresCapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; +Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V +Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V +Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I +Lcom/android/ims/internal/uce/uceservice/IUceService;->createPresenceService(Lcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)I +Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyOptionsService(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyPresenceService(I)V +Lcom/android/ims/internal/uce/uceservice/IUceService;->getOptionsService()Lcom/android/ims/internal/uce/options/IOptionsService; +Lcom/android/ims/internal/uce/uceservice/IUceService;->getPresenceService()Lcom/android/ims/internal/uce/presence/IPresenceService; +Lcom/android/ims/internal/uce/uceservice/IUceService;->getServiceStatus()Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->isServiceStarted()Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->startService(Lcom/android/ims/internal/uce/uceservice/IUceListener;)Z +Lcom/android/ims/internal/uce/uceservice/IUceService;->stopService()Z Lcom/android/internal/app/AlertActivity;-><init>()V Lcom/android/internal/app/AlertActivity;->mAlert:Lcom/android/internal/app/AlertController; Lcom/android/internal/app/AlertActivity;->mAlertParams:Lcom/android/internal/app/AlertController$AlertParams; @@ -1552,6 +1786,7 @@ Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_setUserRestrictions: Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_startOperation:I Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_startWatchingMode:I Lcom/android/internal/app/IAppOpsService$Stub;->TRANSACTION_stopWatchingMode:I +Lcom/android/internal/app/IAppOpsService;->finishOperation(Landroid/os/IBinder;IILjava/lang/String;)V Lcom/android/internal/app/IAppOpsService;->getOpsForPackage(ILjava/lang/String;[I)Ljava/util/List; Lcom/android/internal/app/IAppOpsService;->getPackagesForOps([I)Ljava/util/List; Lcom/android/internal/app/IAppOpsService;->resetAllModes(ILjava/lang/String;)V @@ -1599,6 +1834,7 @@ Lcom/android/internal/appwidget/IAppWidgetService;->bindRemoteViewsService(Ljava Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetIds(Landroid/content/ComponentName;)[I Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetViews(Ljava/lang/String;I)Landroid/widget/RemoteViews; Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V +Lcom/android/internal/content/PackageMonitor;-><init>()V Lcom/android/internal/database/SortCursor;-><init>([Landroid/database/Cursor;Ljava/lang/String;)V Lcom/android/internal/database/SortCursor;->mCursor:Landroid/database/Cursor; Lcom/android/internal/database/SortCursor;->mCursors:[Landroid/database/Cursor; @@ -1612,6 +1848,14 @@ Lcom/android/internal/location/GpsNetInitiatedHandler;->decodeString(Ljava/lang/ Lcom/android/internal/location/GpsNetInitiatedHandler;->handleNiNotification(Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;)V Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V +Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider; +Lcom/android/internal/location/ILocationProvider;->disable()V +Lcom/android/internal/location/ILocationProvider;->enable()V +Lcom/android/internal/location/ILocationProvider;->getProperties()Lcom/android/internal/location/ProviderProperties; +Lcom/android/internal/location/ILocationProvider;->getStatus(Landroid/os/Bundle;)I +Lcom/android/internal/location/ILocationProvider;->getStatusUpdateTime()J +Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)Z +Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V Lcom/android/internal/logging/MetricsLogger;-><init>()V Lcom/android/internal/net/LegacyVpnInfo;-><init>()V Lcom/android/internal/net/VpnConfig;-><init>()V @@ -1981,6 +2225,7 @@ Lcom/android/internal/R$styleable;->MapView_apiKey:I Lcom/android/internal/R$styleable;->MenuGroup:[I Lcom/android/internal/R$styleable;->MenuItem:[I Lcom/android/internal/R$styleable;->MenuView:[I +Lcom/android/internal/R$styleable;->NumberPicker:[I Lcom/android/internal/R$styleable;->PopupWindow:[I Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I Lcom/android/internal/R$styleable;->PopupWindow_popupBackground:I @@ -2106,6 +2351,7 @@ Lcom/android/internal/R$styleable;->TextView_textStyle:I Lcom/android/internal/R$styleable;->TextView_typeface:I Lcom/android/internal/R$styleable;->TextView_width:I Lcom/android/internal/R$styleable;->Theme:[I +Lcom/android/internal/R$styleable;->TwoLineListItem:[I Lcom/android/internal/R$styleable;->View:[I Lcom/android/internal/R$styleable;->ViewAnimator:[I Lcom/android/internal/R$styleable;->ViewFlipper:[I @@ -3126,6 +3372,7 @@ Lcom/android/internal/telephony/ITelephony;->enableLocationUpdates()V Lcom/android/internal/telephony/ITelephony;->getActivePhoneType()I Lcom/android/internal/telephony/ITelephony;->getCallState()I Lcom/android/internal/telephony/ITelephony;->getDataActivity()I +Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z Lcom/android/internal/telephony/ITelephony;->getDataState()I Lcom/android/internal/telephony/ITelephony;->getNetworkType()I Lcom/android/internal/telephony/ITelephony;->handlePinMmi(Ljava/lang/String;)Z diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt deleted file mode 100644 index a21fa3063f17..000000000000 --- a/config/hiddenapi-vendor-list.txt +++ /dev/null @@ -1,247 +0,0 @@ -Landroid/app/IActivityController$Stub;-><init>()V -Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V -Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V -Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V -Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo; -Landroid/app/IActivityManager;->getFilteredTasks(III)Ljava/util/List; -Landroid/app/IActivityManager;->getLockTaskModeState()I -Landroid/app/IActivityManager;->getProcessMemoryInfo([I)[Landroid/os/Debug$MemoryInfo; -Landroid/app/IActivityManager;->getRecentTasks(III)Landroid/content/pm/ParceledListSlice; -Landroid/app/IActivityManager;->getRunningAppProcesses()Ljava/util/List; -Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot; -Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V -Landroid/app/IActivityManager;->removeTask(I)Z -Landroid/app/IActivityManager;->startActivity(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;)I -Landroid/app/IActivityManager;->startActivityAsUser(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;I)I -Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I -Landroid/app/IActivityManager;->startRecentsActivity(Landroid/content/Intent;Landroid/app/IAssistDataReceiver;Landroid/view/IRecentsAnimationRunner;)V -Landroid/app/IAlarmManager;->setTime(J)Z -Landroid/app/IAssistDataReceiver$Stub;-><init>()V -Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V -Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V -Landroid/bluetooth/IBluetooth;->sendConnectionStateChange(Landroid/bluetooth/BluetoothDevice;III)V -Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V -Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V -Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V -Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V -Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V -Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V -Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V -Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo; -Landroid/content/pm/IPackageManager;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo; -Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName; -Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo; -Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V -Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V -Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; -Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String; -Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V -Landroid/location/ILocationManager;->getNetworkProviderPackage()Ljava/lang/String; -Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V -Landroid/location/INetInitiatedListener$Stub;-><init>()V -Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z -Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V -Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V -Landroid/media/tv/ITvRemoteServiceInput;->closeInputBridge(Landroid/os/IBinder;)V -Landroid/media/tv/ITvRemoteServiceInput;->openInputBridge(Landroid/os/IBinder;Ljava/lang/String;III)V -Landroid/media/tv/ITvRemoteServiceInput;->sendKeyDown(Landroid/os/IBinder;I)V -Landroid/media/tv/ITvRemoteServiceInput;->sendKeyUp(Landroid/os/IBinder;I)V -Landroid/media/tv/ITvRemoteServiceInput;->sendPointerDown(Landroid/os/IBinder;III)V -Landroid/media/tv/ITvRemoteServiceInput;->sendPointerSync(Landroid/os/IBinder;)V -Landroid/media/tv/ITvRemoteServiceInput;->sendPointerUp(Landroid/os/IBinder;I)V -Landroid/media/tv/ITvRemoteServiceInput;->sendTimestamp(Landroid/os/IBinder;J)V -Landroid/net/ConnectivityManager$PacketKeepaliveCallback;-><init>()V -Landroid/net/IConnectivityManager;->getAllNetworkState()[Landroid/net/NetworkState; -Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd; -Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V -Landroid/net/INetworkPolicyManager;->getNetworkQuotaInfo(Landroid/net/NetworkState;)Landroid/net/NetworkQuotaInfo; -Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService; -Landroid/net/INetworkStatsSession;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory; -Landroid/net/INetworkStatsSession;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory; -Landroid/net/InterfaceConfiguration;-><init>()V -Landroid/net/LinkProperties$ProvisioningChange;->values()[Landroid/net/LinkProperties$ProvisioningChange; -Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V -Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable; -Landroid/os/AsyncResult;->forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult; -Landroid/os/AsyncResult;->result:Ljava/lang/Object; -Landroid/os/AsyncResult;->userObj:Ljava/lang/Object; -Landroid/os/BatteryStats$HistoryItem;-><init>()V -Landroid/os/BatteryStats$HistoryItem;->batteryLevel:B -Landroid/os/BatteryStats$HistoryItem;->cmd:B -Landroid/os/BatteryStats$HistoryItem;->states:I -Landroid/os/BatteryStats$HistoryItem;->time:J -Landroid/os/BatteryStats$Timer;->getCountLocked(I)I -Landroid/os/BatteryStats$Uid$Wakelock;->getWakeTime(I)Landroid/os/BatteryStats$Timer; -Landroid/os/BatteryStats$Uid;-><init>()V -Landroid/os/BatteryStats$Uid;->getWifiRunningTime(JI)J -Landroid/os/BatteryStats;->getNextHistoryLocked(Landroid/os/BatteryStats$HistoryItem;)Z -Landroid/os/Broadcaster;-><init>()V -Landroid/os/Broadcaster;->broadcast(Landroid/os/Message;)V -Landroid/os/Broadcaster;->cancelRequest(ILandroid/os/Handler;I)V -Landroid/os/Broadcaster;->request(ILandroid/os/Handler;I)V -Landroid/os/Environment;->getLegacyExternalStorageDirectory()Ljava/io/File; -Landroid/os/Handler;-><init>(Landroid/os/Looper;Landroid/os/Handler$Callback;Z)V -Landroid/os/Handler;->getMain()Landroid/os/Handler; -Landroid/os/HwBinder;->reportSyspropChanged()V -Landroid/os/INetworkManagementService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/INetworkManagementService; -Landroid/os/INetworkManagementService;->clearInterfaceAddresses(Ljava/lang/String;)V -Landroid/os/INetworkManagementService;->disableIpv6(Ljava/lang/String;)V -Landroid/os/INetworkManagementService;->enableIpv6(Ljava/lang/String;)V -Landroid/os/INetworkManagementService;->isBandwidthControlEnabled()Z -Landroid/os/INetworkManagementService;->registerObserver(Landroid/net/INetworkManagementEventObserver;)V -Landroid/os/INetworkManagementService;->setInterfaceConfig(Ljava/lang/String;Landroid/net/InterfaceConfiguration;)V -Landroid/os/INetworkManagementService;->setInterfaceIpv6PrivacyExtensions(Ljava/lang/String;Z)V -Landroid/os/INetworkManagementService;->setIPv6AddrGenMode(Ljava/lang/String;I)V -Landroid/os/INetworkManagementService;->unregisterObserver(Landroid/net/INetworkManagementEventObserver;)V -Landroid/os/IPowerManager;->goToSleep(JII)V -Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V -Landroid/os/IRemoteCallback$Stub;-><init>()V -Landroid/os/Message;->setCallback(Ljava/lang/Runnable;)Landroid/os/Message; -Landroid/os/Parcel;->readBlob()[B -Landroid/os/Parcel;->readStringArray()[Ljava/lang/String; -Landroid/os/Parcel;->writeBlob([B)V -Landroid/os/Registrant;-><init>(Landroid/os/Handler;ILjava/lang/Object;)V -Landroid/os/Registrant;->clear()V -Landroid/os/Registrant;->notifyRegistrant()V -Landroid/os/Registrant;->notifyRegistrant(Landroid/os/AsyncResult;)V -Landroid/os/RegistrantList;-><init>()V -Landroid/os/RegistrantList;->add(Landroid/os/Registrant;)V -Landroid/os/RegistrantList;->addUnique(Landroid/os/Handler;ILjava/lang/Object;)V -Landroid/os/RegistrantList;->notifyRegistrants()V -Landroid/os/RegistrantList;->notifyRegistrants(Landroid/os/AsyncResult;)V -Landroid/os/RegistrantList;->remove(Landroid/os/Handler;)V -Landroid/os/RegistrantList;->removeCleared()V -Landroid/os/RemoteException;->rethrowFromSystemServer()Ljava/lang/RuntimeException; -Landroid/os/ServiceSpecificException;->errorCode:I -Landroid/os/storage/StorageEventListener;-><init>()V -Landroid/os/SystemProperties;->reportSyspropChanged()V -Landroid/os/SystemService;->start(Ljava/lang/String;)V -Landroid/os/SystemService;->stop(Ljava/lang/String;)V -Landroid/os/SystemVibrator;-><init>()V -Landroid/os/UserHandle;->isSameApp(II)Z -Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z -Landroid/R$styleable;->CheckBoxPreference:[I -Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V -Landroid/telephony/ims/compat/ImsService;-><init>()V -Landroid/telephony/ims/compat/stub/ImsCallSessionImplBase;-><init>()V -Landroid/telephony/ims/compat/stub/ImsUtListenerImplBase;-><init>()V -Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V -Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V -Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService; -Landroid/telephony/mbms/vendor/IMbmsStreamingService;->getPlaybackUri(ILjava/lang/String;)Landroid/net/Uri; -Landroid/telephony/mbms/vendor/IMbmsStreamingService;->initialize(Landroid/telephony/mbms/IMbmsStreamingSessionCallback;I)I -Landroid/telephony/mbms/vendor/IMbmsStreamingService;->requestUpdateStreamingServices(ILjava/util/List;)I -Landroid/telephony/mbms/vendor/IMbmsStreamingService;->startStreaming(ILjava/lang/String;Landroid/telephony/mbms/IStreamingServiceCallback;)I -Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V -Landroid/view/IRecentsAnimationController;->finish(Z)V -Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot; -Landroid/view/IRecentsAnimationController;->setInputConsumerEnabled(Z)V -Landroid/view/IRecentsAnimationRunner$Stub;-><init>()V -Landroid/view/IRecentsAnimationRunner;->onAnimationCanceled()V -Landroid/view/IRecentsAnimationRunner;->onAnimationStart(Landroid/view/IRecentsAnimationController;[Landroid/view/RemoteAnimationTarget;Landroid/graphics/Rect;Landroid/graphics/Rect;)V -Landroid/view/IRemoteAnimationFinishedCallback;->onAnimationFinished()V -Landroid/view/IRemoteAnimationRunner$Stub;-><init>()V -Landroid/view/IRemoteAnimationRunner;->onAnimationCancelled()V -Landroid/view/IRemoteAnimationRunner;->onAnimationStart([Landroid/view/RemoteAnimationTarget;Landroid/view/IRemoteAnimationFinishedCallback;)V -Landroid/view/IWindowManager;->createInputConsumer(Landroid/os/IBinder;Ljava/lang/String;ILandroid/view/InputChannel;)V -Landroid/view/IWindowManager;->destroyInputConsumer(Ljava/lang/String;I)Z -Landroid/view/IWindowManager;->endProlongedAnimations()V -Landroid/view/IWindowManager;->getStableInsets(ILandroid/graphics/Rect;)V -Landroid/view/IWindowManager;->overridePendingAppTransitionMultiThumbFuture(Landroid/view/IAppTransitionAnimationSpecsFuture;Landroid/os/IRemoteCallback;ZI)V -Landroid/view/IWindowManager;->overridePendingAppTransitionRemote(Landroid/view/RemoteAnimationAdapter;I)V -Landroid/view/IWindowManager;->setNavBarVirtualKeyHapticFeedbackEnabled(Z)V -Lcom/android/ims/ImsConfigListener;->onSetFeatureResponse(IIII)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionConferenceStateUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsConferenceState;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandover(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHandoverFailed(Lcom/android/ims/internal/IImsCallSession;IILandroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHeld(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionHoldReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestDelivered(Lcom/android/ims/internal/IImsCallSession;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionInviteParticipantsRequestFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeComplete(Lcom/android/ims/internal/IImsCallSession;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMergeStarted(Lcom/android/ims/internal/IImsCallSession;Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionMultipartyStateChanged(Lcom/android/ims/internal/IImsCallSession;Z)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionProgressing(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsStreamMediaProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionResumeReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStarted(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionStartFailed(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionSuppServiceReceived(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsSuppServiceNotification;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTerminated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionTtyModeReceived(Lcom/android/ims/internal/IImsCallSession;I)V -Lcom/android/ims/internal/IImsCallSessionListener;->callSessionUpdated(Lcom/android/ims/internal/IImsCallSession;Landroid/telephony/ims/ImsCallProfile;)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationAssociatedUriChanged([Landroid/net/Uri;)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationChangeFailed(ILandroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationConnectedWithRadioTech(I)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationDisconnected(Landroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationFeatureCapabilityChanged(I[I[I)V -Lcom/android/ims/internal/IImsRegistrationListener;->registrationProgressingWithRadioTech(I)V -Lcom/android/ims/internal/IImsRegistrationListener;->voiceMessageCountUpdate(I)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallBarringQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallForwardQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsCallForwardInfo;)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationCallWaitingQueried(Lcom/android/ims/internal/IImsUt;I[Landroid/telephony/ims/ImsSsInfo;)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueried(Lcom/android/ims/internal/IImsUt;ILandroid/os/Bundle;)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V -Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->serviceUnavailable(Lcom/android/ims/internal/uce/common/StatusCode;)V -Lcom/android/ims/internal/uce/options/IOptionsListener;->sipResponseReceived(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsSipResponse;Lcom/android/ims/internal/uce/options/OptionsCapInfo;)V -Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V -Lcom/android/ims/internal/uce/options/IOptionsService;->addListener(ILcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->getMyInfo(II)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->listCapInfoReceived(Lcom/android/ims/internal/uce/presence/PresRlmiInfo;[Lcom/android/ims/internal/uce/presence/PresResInfo;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->publishTriggering(Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->serviceUnAvailable(Lcom/android/ims/internal/uce/common/StatusCode;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->sipResponseReceived(Lcom/android/ims/internal/uce/presence/PresSipResponse;)V -Lcom/android/ims/internal/uce/presence/IPresenceListener;->unpublishMessageSent()V -Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V -Lcom/android/ims/internal/uce/presence/IPresenceService;->addListener(ILcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactCap(ILjava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->getContactListCap(I[Ljava/lang/String;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->getVersion(I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->publishMyCap(ILcom/android/ims/internal/uce/presence/PresCapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode; -Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V -Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V -Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I -Lcom/android/ims/internal/uce/uceservice/IUceService;->createPresenceService(Lcom/android/ims/internal/uce/presence/IPresenceListener;Lcom/android/ims/internal/uce/common/UceLong;)I -Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyOptionsService(I)V -Lcom/android/ims/internal/uce/uceservice/IUceService;->destroyPresenceService(I)V -Lcom/android/ims/internal/uce/uceservice/IUceService;->getOptionsService()Lcom/android/ims/internal/uce/options/IOptionsService; -Lcom/android/ims/internal/uce/uceservice/IUceService;->getPresenceService()Lcom/android/ims/internal/uce/presence/IPresenceService; -Lcom/android/ims/internal/uce/uceservice/IUceService;->getServiceStatus()Z -Lcom/android/ims/internal/uce/uceservice/IUceService;->isServiceStarted()Z -Lcom/android/ims/internal/uce/uceservice/IUceService;->startService(Lcom/android/ims/internal/uce/uceservice/IUceListener;)Z -Lcom/android/ims/internal/uce/uceservice/IUceService;->stopService()Z -Lcom/android/internal/app/IAppOpsService;->finishOperation(Landroid/os/IBinder;IILjava/lang/String;)V -Lcom/android/internal/content/PackageMonitor;-><init>()V -Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider; -Lcom/android/internal/location/ILocationProvider;->disable()V -Lcom/android/internal/location/ILocationProvider;->enable()V -Lcom/android/internal/location/ILocationProvider;->getProperties()Lcom/android/internal/location/ProviderProperties; -Lcom/android/internal/location/ILocationProvider;->getStatus(Landroid/os/Bundle;)I -Lcom/android/internal/location/ILocationProvider;->getStatusUpdateTime()J -Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)Z -Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V -Lcom/android/internal/R$styleable;->NumberPicker:[I -Lcom/android/internal/R$styleable;->TwoLineListItem:[I -Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 05bb9a1c2139..f3f065a27e6f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -122,7 +122,7 @@ import android.view.autofill.AutofillManager.AutofillClient; import android.view.autofill.AutofillPopupWindow; import android.view.autofill.IAutofillWindowPresenter; import android.view.intelligence.ContentCaptureEvent; -import android.view.intelligence.IntelligenceManager; +import android.view.intelligence.ContentCaptureManager; import android.widget.AdapterView; import android.widget.Toast; import android.widget.Toolbar; @@ -824,8 +824,8 @@ public class Activity extends ContextThemeWrapper /** The autofill manager. Always access via {@link #getAutofillManager()}. */ @Nullable private AutofillManager mAutofillManager; - /** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */ - @Nullable private IntelligenceManager mIntelligenceManager; + /** The content capture manager. Always access via {@link #getContentCaptureManager()}. */ + @Nullable private ContentCaptureManager mContentCaptureManager; private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks = new ArrayList<Application.ActivityLifecycleCallbacks>(); @@ -1016,39 +1016,39 @@ public class Activity extends ContextThemeWrapper } /** - * (Creates, sets, and ) returns the intelligence manager + * (Creates, sets, and ) returns the content capture manager * - * @return The intelligence manager + * @return The content capture manager */ - @NonNull private IntelligenceManager getIntelligenceManager() { - if (mIntelligenceManager == null) { - mIntelligenceManager = getSystemService(IntelligenceManager.class); + @NonNull private ContentCaptureManager getContentCaptureManager() { + if (mContentCaptureManager == null) { + mContentCaptureManager = getSystemService(ContentCaptureManager.class); } - return mIntelligenceManager; + return mContentCaptureManager; } - private void notifyIntelligenceManagerIfNeeded(@ContentCaptureEvent.EventType int event) { - final IntelligenceManager im = getIntelligenceManager(); - if (im == null || !im.isContentCaptureEnabled()) { + private void notifyContentCaptureManagerIfNeeded(@ContentCaptureEvent.EventType int event) { + final ContentCaptureManager cm = getContentCaptureManager(); + if (cm == null || !cm.isContentCaptureEnabled()) { return; } switch (event) { case ContentCaptureEvent.TYPE_ACTIVITY_CREATED: //TODO(b/111276913): decide whether the InteractionSessionId should be // saved / restored in the activity bundle. - im.onActivityCreated(mToken, getComponentName()); + cm.onActivityCreated(mToken, getComponentName()); break; case ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED: - im.onActivityDestroyed(); + cm.onActivityDestroyed(); break; case ContentCaptureEvent.TYPE_ACTIVITY_STARTED: case ContentCaptureEvent.TYPE_ACTIVITY_RESUMED: case ContentCaptureEvent.TYPE_ACTIVITY_PAUSED: case ContentCaptureEvent.TYPE_ACTIVITY_STOPPED: - im.onActivityLifecycleEvent(event); + cm.onActivityLifecycleEvent(event); break; default: - Log.w(TAG, "notifyIntelligenceManagerIfNeeded(): invalid type " + event); + Log.w(TAG, "notifyContentCaptureManagerIfNeeded(): invalid type " + event); } } @@ -1057,6 +1057,7 @@ public class Activity extends ContextThemeWrapper super.attachBaseContext(newBase); if (newBase != null) { newBase.setAutofillClient(this); + newBase.setContentCaptureSupported(true); } } @@ -1066,6 +1067,12 @@ public class Activity extends ContextThemeWrapper return this; } + /** @hide */ + @Override + public boolean isContentCaptureSupported() { + return true; + } + /** * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives * lifecycle callbacks for only this Activity. @@ -1410,7 +1417,7 @@ public class Activity extends ContextThemeWrapper mRestoredFromBundle = savedInstanceState != null; mCalled = true; - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED); } /** @@ -1644,7 +1651,7 @@ public class Activity extends ContextThemeWrapper if (mAutoFillResetNeeded) { getAutofillManager().onVisibleForAutofill(); } - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED); } /** @@ -1735,7 +1742,7 @@ public class Activity extends ContextThemeWrapper } } } - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED); mCalled = true; } @@ -2129,7 +2136,7 @@ public class Activity extends ContextThemeWrapper mAutoFillIgnoreFirstResumePause = false; } } - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED); mCalled = true; } @@ -2318,7 +2325,7 @@ public class Activity extends ContextThemeWrapper getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL, mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)); } - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED); } } @@ -2390,7 +2397,7 @@ public class Activity extends ContextThemeWrapper dispatchActivityDestroyed(); - notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED); + notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED); } @@ -6806,7 +6813,7 @@ public class Activity extends ContextThemeWrapper } void dumpIntelligenceManager(String prefix, PrintWriter writer) { - final IntelligenceManager im = getIntelligenceManager(); + final ContentCaptureManager im = getContentCaptureManager(); if (im != null) { im.dump(prefix, writer); } else { diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 446d98e97936..2c435a27cbce 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -31,7 +31,6 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.IWindowManager; import android.view.InputDevice; -import android.view.InputEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceControl; @@ -291,9 +290,14 @@ public class ActivityView extends ViewGroup { return super.onGenericMotionEvent(event); } - private boolean injectInputEvent(InputEvent event) { + private boolean injectInputEvent(MotionEvent event) { if (mInputForwarder != null) { try { + // The touch event that the ActivityView gets is in View space, but the event needs + // to get forwarded in screen space. This offsets the touch event by the location + // the ActivityView is on screen and sends it to the input forwarder. + getLocationOnScreen(mLocationOnScreen); + event.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]); return mInputForwarder.forwardEvent(event); } catch (RemoteException e) { e.rethrowAsRuntimeException(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 28ecb27b53d2..6f0b6c8687db 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -217,6 +217,8 @@ class ContextImpl extends Context { private AutofillClient mAutofillClient = null; private boolean mIsAutofillCompatEnabled; + private boolean mIsContentCaptureSupported = false; + private final Object mSync = new Object(); @GuardedBy("mSync") @@ -2376,6 +2378,18 @@ class ContextImpl extends Context { mIsAutofillCompatEnabled = autofillCompatEnabled; } + /** @hide */ + @Override + public boolean isContentCaptureSupported() { + return mIsContentCaptureSupported; + } + + /** @hide */ + @Override + public void setContentCaptureSupported(boolean supported) { + mIsContentCaptureSupported = supported; + } + @UnsupportedAppUsage static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo = new LoadedApk(mainThread); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index e83bcd0e6647..88fb025bf406 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -96,6 +96,7 @@ interface IActivityManager { String callingPackage); void unregisterUidObserver(in IUidObserver observer); boolean isUidActive(int uid, String callingPackage); + int getUidProcessState(int uid, in String callingPackage); // =============== End of transactions used on native side as well ============================ // Special low-level communication with activity manager. @@ -379,8 +380,6 @@ interface IActivityManager { void noteAlarmFinish(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag); int getPackageProcessState(in String packageName, in String callingPackage); void updateDeviceOwner(in String packageName); - int getUidProcessState(int uid, in String callingPackage); - // Start of N transactions // Start Binder transaction tracking for all applications. diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl index ce8880940c78..e116d989ca75 100644 --- a/core/java/android/app/IUidObserver.aidl +++ b/core/java/android/app/IUidObserver.aidl @@ -43,8 +43,6 @@ oneway interface IUidObserver { */ void onUidIdle(int uid, boolean disabled); - // =============== End of transactions used on native side as well ============================ - /** * General report of a state change of an uid. * @@ -55,6 +53,8 @@ oneway interface IUidObserver { */ void onUidStateChanged(int uid, int procState, long procStateSeq); + // =============== End of transactions used on native side as well ============================ + /** * Report when the cached state of a uid has changed. * If true, a uid has become cached -- that is, it has some active processes that are diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 3f1075448c84..719bba0a35af 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -696,6 +696,23 @@ public final class LoadedApk { return loaders; } + private StrictMode.ThreadPolicy allowThreadDiskReads() { + if (mActivityThread == null) { + // When LoadedApk is used without an ActivityThread (usually in a + // zygote context), don't call into StrictMode, as it initializes + // the binder subsystem, which we don't want. + return null; + } + + return StrictMode.allowThreadDiskReads(); + } + + private void setThreadPolicy(StrictMode.ThreadPolicy policy) { + if (mActivityThread != null && policy != null) { + StrictMode.setThreadPolicy(policy); + } + } + private void createOrUpdateClassLoaderLocked(List<String> addedPaths) { if (mPackageName.equals("android")) { // Note: This branch is taken for system server and we don't need to setup @@ -718,8 +735,11 @@ public final class LoadedApk { // Avoid the binder call when the package is the current application package. // The activity manager will perform ensure that dexopt is performed before - // spinning up the process. - if (!Objects.equals(mPackageName, ActivityThread.currentPackageName()) && mIncludeCode) { + // spinning up the process. Similarly, don't call into binder when we don't + // have an ActivityThread object. + if (mActivityThread != null + && !Objects.equals(mPackageName, ActivityThread.currentPackageName()) + && mIncludeCode) { try { ActivityThread.getPackageManager().notifyPackageUse(mPackageName, PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE); @@ -790,12 +810,12 @@ public final class LoadedApk { // mIncludeCode == false). if (!mIncludeCode) { if (mDefaultClassLoader == null) { - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader( "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, libraryPermittedPath, mBaseClassLoader, null /* classLoaderName */); - StrictMode.setThreadPolicy(oldPolicy); + setThreadPolicy(oldPolicy); mAppComponentFactory = AppComponentFactory.DEFAULT; } @@ -822,7 +842,7 @@ public final class LoadedApk { if (mDefaultClassLoader == null) { // Temporarily disable logging of disk reads on the Looper thread // as this is early and necessary. - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders( mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath, @@ -834,18 +854,18 @@ public final class LoadedApk { mApplicationInfo.classLoaderName, sharedLibraries); mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader); - StrictMode.setThreadPolicy(oldPolicy); + setThreadPolicy(oldPolicy); // Setup the class loader paths for profiling. needToSetupJitProfiles = true; } if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) { // Temporarily disable logging of disk reads on the Looper thread as this is necessary - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); try { ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths); } finally { - StrictMode.setThreadPolicy(oldPolicy); + setThreadPolicy(oldPolicy); } } @@ -879,11 +899,11 @@ public final class LoadedApk { extraLibPaths.add("/product/lib" + abiSuffix); } if (!extraLibPaths.isEmpty()) { - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); try { ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, extraLibPaths); } finally { - StrictMode.setThreadPolicy(oldPolicy); + setThreadPolicy(oldPolicy); } } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 0281e6a0631e..aa1b5af9b112 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -8263,7 +8263,7 @@ public class Notification implements Parcelable customContent = customContent.clone(); remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress); remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */); - remoteViews.setReapplyDisallowed(); + remoteViews.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED); } // also update the end margin if there is an image Resources resources = mBuilder.mContext.getResources(); @@ -8394,7 +8394,7 @@ public class Notification implements Parcelable customContent.overrideTextColors(mBuilder.getPrimaryTextColor(mBuilder.mParams)); remoteViews.removeAllViews(id); remoteViews.addView(id, customContent); - remoteViews.setReapplyDisallowed(); + remoteViews.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED); } return remoteViews; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 89ec19bbc6dd..25fa897f2a56 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1424,7 +1424,62 @@ public class NotificationManager { return other.priorityCategories == priorityCategories && other.priorityCallSenders == priorityCallSenders && other.priorityMessageSenders == priorityMessageSenders - && other.suppressedVisualEffects == suppressedVisualEffects; + && suppressedVisualEffectsEqual(suppressedVisualEffects, + other.suppressedVisualEffects); + } + + + private boolean suppressedVisualEffectsEqual(int suppressedEffects, + int otherSuppressedVisualEffects) { + if (suppressedEffects == otherSuppressedVisualEffects) { + return true; + } + + if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) { + suppressedEffects |= SUPPRESSED_EFFECT_PEEK; + } + if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) { + suppressedEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; + suppressedEffects |= SUPPRESSED_EFFECT_LIGHTS; + suppressedEffects |= SUPPRESSED_EFFECT_AMBIENT; + } + + if ((otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) { + otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK; + } + if ((otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) { + otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; + otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS; + otherSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT; + } + + if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) + != (otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON)) { + int currSuppressedEffects = (suppressedEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0 + ? otherSuppressedVisualEffects : suppressedEffects; + if ((currSuppressedEffects & SUPPRESSED_EFFECT_PEEK) == 0) { + return false; + } + } + + if ((suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) + != (otherSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF)) { + int currSuppressedEffects = (suppressedEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0 + ? otherSuppressedVisualEffects : suppressedEffects; + if ((currSuppressedEffects & SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) == 0 + || (currSuppressedEffects & SUPPRESSED_EFFECT_LIGHTS) == 0 + || (currSuppressedEffects & SUPPRESSED_EFFECT_AMBIENT) == 0) { + return false; + } + } + + int thisWithoutOldEffects = suppressedEffects + & ~SUPPRESSED_EFFECT_SCREEN_ON + & ~SUPPRESSED_EFFECT_SCREEN_OFF; + int otherWithoutOldEffects = otherSuppressedVisualEffects + & ~SUPPRESSED_EFFECT_SCREEN_ON + & ~SUPPRESSED_EFFECT_SCREEN_OFF; + return thisWithoutOldEffects == otherWithoutOldEffects; } @Override diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 0123551230b0..0404e80df9e2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -59,6 +59,7 @@ import android.hardware.SystemSensorManager; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.IBiometricService; import android.hardware.camera2.CameraManager; +import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.hardware.face.FaceManager; import android.hardware.face.IFaceService; @@ -165,8 +166,8 @@ import android.view.accessibility.CaptioningManager; import android.view.autofill.AutofillManager; import android.view.autofill.IAutoFillManager; import android.view.inputmethod.InputMethodManager; +import android.view.intelligence.ContentCaptureManager; import android.view.intelligence.IIntelligenceManager; -import android.view.intelligence.IntelligenceManager; import android.view.textclassifier.TextClassificationManager; import android.view.textservice.TextServicesManager; @@ -199,6 +200,7 @@ final class SystemServiceRegistry { private SystemServiceRegistry() { } static { + //CHECKSTYLE:OFF IndentationCheck registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class, new CachedServiceFetcher<AccessibilityManager>() { @Override @@ -385,6 +387,14 @@ final class SystemServiceRegistry { return new DisplayManager(ctx.getOuterContext()); }}); + registerService(Context.COLOR_DISPLAY_SERVICE, ColorDisplayManager.class, + new CachedServiceFetcher<ColorDisplayManager>() { + @Override + public ColorDisplayManager createService(ContextImpl ctx) { + return new ColorDisplayManager(); + } + }); + // InputMethodManager has its own cache strategy based on display id to support apps that // still assume InputMethodManager is a per-process singleton and it's safe to directly // access internal fields via reflection. Hence directly use ServiceFetcher instead of @@ -1050,15 +1060,20 @@ final class SystemServiceRegistry { return new AutofillManager(ctx.getOuterContext(), service); }}); - registerService(Context.INTELLIGENCE_MANAGER_SERVICE, IntelligenceManager.class, - new CachedServiceFetcher<IntelligenceManager>() { + registerService(Context.CONTENT_CAPTURE_MANAGER_SERVICE, ContentCaptureManager.class, + new CachedServiceFetcher<ContentCaptureManager>() { @Override - public IntelligenceManager createService(ContextImpl ctx) + public ContentCaptureManager createService(ContextImpl ctx) throws ServiceNotFoundException { // Get the services without throwing as this is an optional feature - IBinder b = ServiceManager.getService(Context.INTELLIGENCE_MANAGER_SERVICE); - IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b); - return new IntelligenceManager(ctx.getOuterContext(), service); + Context outerContext = ctx.getOuterContext(); + if (outerContext.isContentCaptureSupported()) { + IBinder b = ServiceManager + .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE); + IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b); + return new ContentCaptureManager(outerContext, service); + } + return null; }}); registerService(Context.VR_SERVICE, VrManager.class, new CachedServiceFetcher<VrManager>() { @@ -1138,6 +1153,7 @@ final class SystemServiceRegistry { throws ServiceNotFoundException { return new RoleManager(ctx.getOuterContext()); }}); + //CHECKSTYLE:ON IndentationCheck } /** diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 98d2a406fc0c..3a9728413151 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -10092,11 +10092,40 @@ public class DevicePolicyManager { if (mService != null) { try { return mService.isPackageAllowedToAccessCalendarForUser(packageName, - mContext.getUserId()); + myUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return false; } + + /** + * Gets a set of package names that are whitelisted to access cross profile calendar APIs. + * + * <p>To query for a specific user, use + * {@link Context#createPackageContextAsUser(String, int, UserHandle)} to create a context for + * that user, and get a {@link DevicePolicyManager} from this context. + * + * @return the set of names of packages that were previously whitelisted via + * {@link #addCrossProfileCalendarPackage(ComponentName, String)}, or an + * empty set if none have been whitelisted. + * + * @see #addCrossProfileCalendarPackage(ComponentName, String) + * @see #removeCrossProfileCalendarPackage(ComponentName, String) + * @see #getCrossProfileCalendarPackages(ComponentName) + * @hide + */ + public @NonNull Set<String> getCrossProfileCalendarPackages() { + throwIfParentInstance("getCrossProfileCalendarPackages"); + if (mService != null) { + try { + return new ArraySet<>(mService.getCrossProfileCalendarPackagesForUser( + myUserId())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return Collections.emptySet(); + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 297676d397bf..fcf74ee301d8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -427,4 +427,5 @@ interface IDevicePolicyManager { boolean removeCrossProfileCalendarPackage(in ComponentName admin, String packageName); List<String> getCrossProfileCalendarPackages(in ComponentName admin); boolean isPackageAllowedToAccessCalendarForUser(String packageName, int userHandle); + List<String> getCrossProfileCalendarPackagesForUser(int userHandle); } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 318dbee99e5a..c740c42c9c0d 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -88,6 +88,7 @@ public class AppWidgetHostView extends FrameLayout { int mViewMode = VIEW_MODE_NOINIT; int mLayoutId = -1; private OnClickHandler mOnClickHandler; + private boolean mOnLightBackground; private Executor mAsyncExecutor; private CancellationSignal mLastExecutionSignal; @@ -374,6 +375,15 @@ public class AppWidgetHostView extends FrameLayout { } /** + * Sets whether the widget should is being displayed on a light/white background and use an + * alternate UI if available. + * @see RemoteViews#setLightBackgroundLayoutId(int) + */ + public void setOnLightBackground(boolean useDarkTextLayout) { + mOnLightBackground = useDarkTextLayout; + } + + /** * Update the AppWidgetProviderInfo for this view, and reset it to the * initial layout. */ @@ -413,6 +423,10 @@ public class AppWidgetHostView extends FrameLayout { mLayoutId = -1; mViewMode = VIEW_MODE_DEFAULT; } else { + if (mOnLightBackground) { + remoteViews = remoteViews.getDarkTextViews(); + } + if (mAsyncExecutor != null && useAsyncIfPossible) { inflateAsync(remoteViews); return; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index ff57b0311d60..fe11acbde0bc 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3126,6 +3126,7 @@ public abstract class Context { //@hide: HDMI_CONTROL_SERVICE, INPUT_SERVICE, DISPLAY_SERVICE, + //@hide COLOR_DISPLAY_SERVICE, USER_SERVICE, RESTRICTIONS_SERVICE, APP_OPS_SERVICE, @@ -3933,12 +3934,13 @@ public abstract class Context { public static final String AUTOFILL_MANAGER_SERVICE = "autofill"; /** - * Official published name of the intelligence service. + * Official published name of the smart suggestions service. * * @hide * @see #getSystemService(String) */ - public static final String INTELLIGENCE_MANAGER_SERVICE = "intelligence"; + // TODO(b/111276913): rename string (will require SELinux change first) + public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "intelligence"; /** * Use with {@link #getSystemService(String)} to access the @@ -4107,6 +4109,16 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.hardware.display.ColorDisplayManager} for controlling color transforms. + * + * @see #getSystemService(String) + * @see android.hardware.display.ColorDisplayManager + * @hide + */ + public static final String COLOR_DISPLAY_SERVICE = "color_display"; + + /** + * Use with {@link #getSystemService(String)} to retrieve a * {@link android.os.UserManager} for managing users on devices that support multiple users. * * @see #getSystemService(String) @@ -5223,6 +5235,25 @@ public abstract class Context { } /** + * Checks whether this context supports content capture. + * + * @hide + */ + // NOTE: for now we just need to check if it's supported so we can optimize calls that can be + // skipped when it isn't. Eventually, we might need a full + // ContentCaptureManager.ContentCaptureClient interface (as it's done with AutofillClient). + // + public boolean isContentCaptureSupported() { + return false; + } + + /** + * @hide + */ + public void setContentCaptureSupported(@SuppressWarnings("unused") boolean supported) { + } + + /** * Throws an exception if the Context is using system resources, * which are non-runtime-overlay-themable and may show inconsistent UI. * @hide diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 2db44b44fd6c..26ed3b736f80 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -1049,4 +1049,20 @@ public class ContextWrapper extends Context { mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled); } } + + /** + * @hide + */ + @Override + public boolean isContentCaptureSupported() { + return mBase.isContentCaptureSupported(); + } + + /** + * @hide + */ + @Override + public void setContentCaptureSupported(boolean supported) { + mBase.setContentCaptureSupported(supported); + } } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 7c3b5e48cb5b..98a135f96d98 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1770,7 +1770,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * is on the package whitelist. * * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT} - * if nothing configured. + * if nothing configured. * @hide */ public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) { diff --git a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java index 79bc9a30b1e2..73addb70ea05 100644 --- a/core/java/android/content/pm/permission/RuntimePermissionPresenter.java +++ b/core/java/android/content/pm/permission/RuntimePermissionPresenter.java @@ -16,13 +16,15 @@ package android.content.pm.permission; +import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -32,7 +34,7 @@ import android.permissionpresenterservice.RuntimePermissionPresenterService; import android.util.Log; import com.android.internal.annotations.GuardedBy; -import com.android.internal.os.SomeArgs; +import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayList; import java.util.Collections; @@ -109,13 +111,11 @@ public final class RuntimePermissionPresenter { */ public void getAppPermissions(@NonNull String packageName, @NonNull OnResultCallback callback, @Nullable Handler handler) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = packageName; - args.arg2 = callback; - args.arg3 = handler; - Message message = mRemoteService.obtainMessage( - RemoteService.MSG_GET_APP_PERMISSIONS, args); - mRemoteService.processMessage(message); + checkNotNull(packageName); + checkNotNull(callback); + + mRemoteService.processMessage(obtainMessage(RemoteService::getAppPermissions, + mRemoteService, packageName, callback, handler)); } /** @@ -124,24 +124,20 @@ public final class RuntimePermissionPresenter { * @param packageName The package for which to revoke * @param permissionName The permission to revoke */ - public void revokeRuntimePermission(String packageName, String permissionName) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = packageName; - args.arg2 = permissionName; - - Message message = mRemoteService.obtainMessage( - RemoteService.MSG_REVOKE_APP_PERMISSIONS, args); - mRemoteService.processMessage(message); + public void revokeRuntimePermission(@NonNull String packageName, + @NonNull String permissionName) { + checkNotNull(packageName); + checkNotNull(permissionName); + + mRemoteService.processMessage(obtainMessage(RemoteService::revokeAppPermissions, + mRemoteService, packageName, permissionName)); } private static final class RemoteService extends Handler implements ServiceConnection { private static final long UNBIND_TIMEOUT_MILLIS = 10000; - public static final int MSG_GET_APP_PERMISSIONS = 1; - public static final int MSG_GET_APPS_USING_PERMISSIONS = 2; - public static final int MSG_UNBIND = 3; - public static final int MSG_REVOKE_APP_PERMISSIONS = 4; + public static final int MSG_UNBIND = 0; private final Object mLock = new Object(); @@ -191,89 +187,74 @@ public final class RuntimePermissionPresenter { } } - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_GET_APP_PERMISSIONS: { - SomeArgs args = (SomeArgs) msg.obj; - final String packageName = (String) args.arg1; - final OnResultCallback callback = (OnResultCallback) args.arg2; - final Handler handler = (Handler) args.arg3; - args.recycle(); - final IRuntimePermissionPresenter remoteInstance; - synchronized (mLock) { - remoteInstance = mRemoteInstance; - } - if (remoteInstance == null) { - return; - } - try { - remoteInstance.getAppPermissions(packageName, - new RemoteCallback(new RemoteCallback.OnResultListener() { - @Override - public void onResult(Bundle result) { - final List<RuntimePermissionPresentationInfo> reportedPermissions; - List<RuntimePermissionPresentationInfo> permissions = null; - if (result != null) { - permissions = result.getParcelableArrayList(KEY_RESULT); - } - if (permissions == null) { - permissions = Collections.emptyList(); - } - reportedPermissions = permissions; - if (handler != null) { - handler.post(new Runnable() { - @Override - public void run() { - callback.onGetAppPermissions(reportedPermissions); - } - }); - } else { - callback.onGetAppPermissions(reportedPermissions); - } + private void getAppPermissions(@NonNull String packageName, + @NonNull OnResultCallback callback, @Nullable Handler handler) { + final IRuntimePermissionPresenter remoteInstance; + synchronized (mLock) { + remoteInstance = mRemoteInstance; + } + if (remoteInstance == null) { + return; + } + try { + remoteInstance.getAppPermissions(packageName, + new RemoteCallback(result -> { + final List<RuntimePermissionPresentationInfo> reportedPermissions; + List<RuntimePermissionPresentationInfo> permissions = null; + if (result != null) { + permissions = result.getParcelableArrayList(KEY_RESULT); + } + if (permissions == null) { + permissions = Collections.emptyList(); + } + reportedPermissions = permissions; + if (handler != null) { + handler.post( + () -> callback.onGetAppPermissions(reportedPermissions)); + } else { + callback.onGetAppPermissions(reportedPermissions); } }, this)); - } catch (RemoteException re) { - Log.e(TAG, "Error getting app permissions", re); - } - scheduleUnbind(); - } break; - - case MSG_UNBIND: { - synchronized (mLock) { - if (mBound) { - mContext.unbindService(this); - mBound = false; - } - mRemoteInstance = null; - } - } break; - - case MSG_REVOKE_APP_PERMISSIONS: { - SomeArgs args = (SomeArgs) msg.obj; - final String packageName = (String) args.arg1; - final String permissionName = (String) args.arg2; - args.recycle(); - final IRuntimePermissionPresenter remoteInstance; - synchronized (mLock) { - remoteInstance = mRemoteInstance; - } - if (remoteInstance == null) { - return; - } - try { - remoteInstance.revokeRuntimePermission(packageName, permissionName); - } catch (RemoteException re) { - Log.e(TAG, "Error getting app permissions", re); - } - } break; + } catch (RemoteException re) { + Log.e(TAG, "Error getting app permissions", re); } + scheduleUnbind(); synchronized (mLock) { scheduleNextMessageIfNeededLocked(); } } + private void revokeAppPermissions(@NonNull String packageName, + @NonNull String permissionName) { + final IRuntimePermissionPresenter remoteInstance; + synchronized (mLock) { + remoteInstance = mRemoteInstance; + } + if (remoteInstance == null) { + return; + } + try { + remoteInstance.revokeRuntimePermission(packageName, permissionName); + } catch (RemoteException re) { + Log.e(TAG, "Error getting app permissions", re); + } + + synchronized (mLock) { + scheduleNextMessageIfNeededLocked(); + } + } + + private void unbind() { + synchronized (mLock) { + if (mBound) { + mContext.unbindService(this); + mBound = false; + } + mRemoteInstance = null; + } + } + @GuardedBy("mLock") private void scheduleNextMessageIfNeededLocked() { if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) { @@ -284,7 +265,8 @@ public final class RuntimePermissionPresenter { private void scheduleUnbind() { removeMessages(MSG_UNBIND); - sendEmptyMessageDelayed(MSG_UNBIND, UNBIND_TIMEOUT_MILLIS); + sendMessageDelayed(PooledLambda.obtainMessage(RemoteService::unbind, this) + .setWhat(MSG_UNBIND), UNBIND_TIMEOUT_MILLIS); } } } diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 7148b124253e..5e402c7edc40 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -393,7 +393,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * doesn't have any recommendation for this use case or the recommended configurations * are invalid. */ - public RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap( + public @Nullable RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap( @RecommendedStreamConfigurationMap.RecommendedUsecase int usecase) { if (((usecase >= RecommendedStreamConfigurationMap.USECASE_PREVIEW) && (usecase <= RecommendedStreamConfigurationMap.USECASE_RAW)) || diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java index 59e4a3366995..068c0ce8d052 100644 --- a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java @@ -17,6 +17,7 @@ package android.hardware.camera2.params; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.ImageFormat; @@ -173,7 +174,7 @@ public final class RecommendedStreamConfigurationMap { * * @return Use case id. */ - public int getRecommendedUseCase() { + public @RecommendedUsecase int getRecommendedUseCase() { return mUsecase; } @@ -326,7 +327,7 @@ public final class RecommendedStreamConfigurationMap { * @throws IllegalArgumentException if input size does not exist in the return value of * getHighSpeedVideoSizes */ - public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(Size size) { + public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(@NonNull Size size) { return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRangesFor(size)); } @@ -349,14 +350,14 @@ public final class RecommendedStreamConfigurationMap { * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizesFor}. * </p> * - * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()} + * @param fpsRange one of the FPS ranges returned by {@link #getHighSpeedVideoFpsRanges()} * @return A non-modifiable set of video sizes to create high speed capture sessions for high * speed streaming use cases. * * @throws IllegalArgumentException if input FPS range does not exist in the return value of * getHighSpeedVideoFpsRanges */ - public @Nullable Set<Size> getHighSpeedVideoSizesFor(Range<Integer> fpsRange) { + public @Nullable Set<Size> getHighSpeedVideoSizesFor(@NonNull Range<Integer> fpsRange) { return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizesFor(fpsRange)); } @@ -390,10 +391,8 @@ public final class RecommendedStreamConfigurationMap { * 0 if the minimum frame duration is not available. * * @throws IllegalArgumentException if {@code format} or {@code size} was not supported - * @throws NullPointerException if {@code size} was {@code null} - * */ - public long getOutputMinFrameDuration(int format, Size size) { + public @IntRange(from = 0) long getOutputMinFrameDuration(int format, @NonNull Size size) { return mRecommendedMap.getOutputMinFrameDuration(format, size); } @@ -409,9 +408,8 @@ public final class RecommendedStreamConfigurationMap { * @return a stall duration {@code >=} 0 in nanoseconds * * @throws IllegalArgumentException if {@code format} or {@code size} was not supported - * @throws NullPointerException if {@code size} was {@code null} */ - public long getOutputStallDuration(int format, Size size) { + public @IntRange(from = 0) long getOutputStallDuration(int format, @NonNull Size size) { return mRecommendedMap.getOutputStallDuration(format, size); } @@ -422,16 +420,12 @@ public final class RecommendedStreamConfigurationMap { * </p> * * @param klass - * a non-{@code null} {@link Class} object reference + * a {@link Class} object reference * @return * a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format, * or {@code null} if the {@code klass} is not a supported output. - * - * - * @throws NullPointerException if {@code klass} was {@code null} - * */ - public <T> @Nullable Set<Size> getOutputSizes(Class<T> klass) { + public <T> @Nullable Set<Size> getOutputSizes(@NonNull Class<T> klass) { if (mSupportsPrivate) { return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass)); } @@ -447,16 +441,15 @@ public final class RecommendedStreamConfigurationMap { * {@link StreamConfigurationMap#getOutputMinFrameDuration(Class, Size)}.</p> * * @param klass - * a class which has a non-empty array returned by {@link #getOutputSizes(Class)} + * a class which has a non-empty array returned by {@link #getOutputSizes(Class)} * @param size an output-compatible size * @return a minimum frame duration {@code >} 0 in nanoseconds, or * 0 if the minimum frame duration is not available. * * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported - * @throws NullPointerException if {@code size} or {@code klass} was {@code null} - * */ - public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) { + public <T> @IntRange(from = 0) long getOutputMinFrameDuration(@NonNull final Class<T> klass, + @NonNull final Size size) { if (mSupportsPrivate) { return mRecommendedMap.getOutputMinFrameDuration(klass, size); } @@ -473,14 +466,13 @@ public final class RecommendedStreamConfigurationMap { * @param klass * a class which has a non-empty array returned by {@link #getOutputSizes(Class)}. * @param size an output-compatible size - * @return a minimum frame duration {@code >=} 0 in nanoseconds, or 0 if the stall duration is + * @return a minimum frame duration {@code >} 0 in nanoseconds, or 0 if the stall duration is * not available. * * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported - * @throws NullPointerException if {@code size} or {@code klass} was {@code null} - * */ - public <T> long getOutputStallDuration(final Class<T> klass, final Size size) { + public <T> @IntRange(from = 0) long getOutputStallDuration(@NonNull final Class<T> klass, + @NonNull final Size size) { if (mSupportsPrivate) { return mRecommendedMap.getOutputStallDuration(klass, size); } @@ -495,14 +487,13 @@ public final class RecommendedStreamConfigurationMap { * <p>For more information refer to {@link StreamConfigurationMap#isOutputSupportedFor}. * </p> * - * @param surface a non-{@code null} {@link Surface} object reference + * @param surface a {@link Surface} object reference * @return {@code true} if this is supported, {@code false} otherwise * - * @throws NullPointerException if {@code surface} was {@code null} * @throws IllegalArgumentException if the Surface endpoint is no longer valid * */ - public boolean isOutputSupportedFor(Surface surface) { + public boolean isOutputSupportedFor(@NonNull Surface surface) { return mRecommendedMap.isOutputSupportedFor(surface); } diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java index 0a76c2bc724e..a4c1332b45d1 100644 --- a/core/java/android/hardware/display/ColorDisplayManager.java +++ b/core/java/android/hardware/display/ColorDisplayManager.java @@ -16,20 +16,81 @@ package android.hardware.display; +import android.annotation.RequiresPermission; +import android.annotation.SystemService; import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import com.android.internal.R; /** * Manages the display's color transforms and modes. + * * @hide */ +@SystemService(Context.COLOR_DISPLAY_SERVICE) public final class ColorDisplayManager { + private final ColorDisplayManagerInternal mManager; + + /** + * @hide + */ + public ColorDisplayManager() { + mManager = ColorDisplayManagerInternal.getInstance(); + } + + /** + * Returns whether the device has a wide color gamut display. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) + public boolean isDeviceColorManaged() { + return mManager.isDeviceColorManaged(); + } + /** * Returns {@code true} if Night Display is supported by the device. */ public static boolean isNightDisplayAvailable(Context context) { return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable); } + + private static class ColorDisplayManagerInternal { + + private static ColorDisplayManagerInternal sInstance; + + private final IColorDisplayManager mCdm; + + private ColorDisplayManagerInternal(IColorDisplayManager colorDisplayManager) { + mCdm = colorDisplayManager; + } + + public static ColorDisplayManagerInternal getInstance() { + synchronized (ColorDisplayManagerInternal.class) { + if (sInstance == null) { + try { + IBinder b = ServiceManager.getServiceOrThrow(Context.COLOR_DISPLAY_SERVICE); + sInstance = new ColorDisplayManagerInternal( + IColorDisplayManager.Stub.asInterface(b)); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException(e); + } + } + return sInstance; + } + } + + boolean isDeviceColorManaged() { + try { + return mCdm.isDeviceColorManaged(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } } diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl new file mode 100644 index 000000000000..f7865899812a --- /dev/null +++ b/core/java/android/hardware/display/IColorDisplayManager.aidl @@ -0,0 +1,22 @@ +/* + * 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.hardware.display; + +/** @hide */ +interface IColorDisplayManager { + boolean isDeviceColorManaged(); +}
\ No newline at end of file diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 0c1aae8bd16c..8904ee61e2e3 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -657,6 +657,12 @@ public class Environment { public static String DIRECTORY_SCREENSHOTS = "Screenshots"; /** + * Standard directory in which to place any audio files which are + * audiobooks. + */ + public static String DIRECTORY_AUDIOBOOKS = "Audiobooks"; + + /** * List of standard storage directories. * <p> * Each of its values have its own constant: @@ -671,6 +677,7 @@ public class Environment { * <li>{@link #DIRECTORY_DOWNLOADS} * <li>{@link #DIRECTORY_DCIM} * <li>{@link #DIRECTORY_DOCUMENTS} + * <li>{@link #DIRECTORY_AUDIOBOOKS} * </ul> * @hide */ @@ -684,7 +691,8 @@ public class Environment { DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, DIRECTORY_DCIM, - DIRECTORY_DOCUMENTS + DIRECTORY_DOCUMENTS, + DIRECTORY_AUDIOBOOKS, }; /** @@ -709,6 +717,7 @@ public class Environment { /** {@hide} */ public static final int HAS_DOWNLOADS = 1 << 7; /** {@hide} */ public static final int HAS_DCIM = 1 << 8; /** {@hide} */ public static final int HAS_DOCUMENTS = 1 << 9; + /** {@hide} */ public static final int HAS_AUDIOBOOKS = 1 << 10; /** {@hide} */ public static final int HAS_ANDROID = 1 << 16; /** {@hide} */ public static final int HAS_OTHER = 1 << 17; @@ -738,6 +747,7 @@ public class Environment { else if (DIRECTORY_DOWNLOADS.equals(name)) res |= HAS_DOWNLOADS; else if (DIRECTORY_DCIM.equals(name)) res |= HAS_DCIM; else if (DIRECTORY_DOCUMENTS.equals(name)) res |= HAS_DOCUMENTS; + else if (DIRECTORY_AUDIOBOOKS.equals(name)) res |= HAS_AUDIOBOOKS; else if (DIRECTORY_ANDROID.equals(name)) res |= HAS_ANDROID; else res |= HAS_OTHER; } diff --git a/core/java/android/os/IThermalService.aidl b/core/java/android/os/IThermalService.aidl index 81603384636e..9280cb9f18b8 100644 --- a/core/java/android/os/IThermalService.aidl +++ b/core/java/android/os/IThermalService.aidl @@ -67,7 +67,7 @@ interface IThermalService { /** * Register a listener for thermal status change. - * @param listener the IThermalStatusListener to be notified. + * @param listener the {@link android.os.IThermalStatusListener} to be notified. * @return true if registered successfully. * {@hide} */ @@ -75,7 +75,7 @@ interface IThermalService { /** * Unregister a previously-registered listener for thermal status. - * @param listener the IThermalStatusListener to no longer be notified. + * @param listener the {@link android.os.IThermalStatusListener} to no longer be notified. * @return true if unregistered successfully. * {@hide} */ @@ -86,5 +86,5 @@ interface IThermalService { * @return status defined in {@link android.os.Temperature}. * {@hide} */ - int getCurrentStatus(); + int getCurrentThermalStatus(); } diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 44b9e311dc0b..6de1ff4bc097 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -17,12 +17,6 @@ package android.os; import static android.system.OsConstants.AF_UNIX; -import static android.system.OsConstants.O_APPEND; -import static android.system.OsConstants.O_CREAT; -import static android.system.OsConstants.O_RDONLY; -import static android.system.OsConstants.O_RDWR; -import static android.system.OsConstants.O_TRUNC; -import static android.system.OsConstants.O_WRONLY; import static android.system.OsConstants.SEEK_SET; import static android.system.OsConstants.SOCK_SEQPACKET; import static android.system.OsConstants.SOCK_STREAM; @@ -254,8 +248,16 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { } /** {@hide} */ - public static ParcelFileDescriptor fromFd( - FileDescriptor fd, Handler handler, final OnCloseListener listener) throws IOException { + public static ParcelFileDescriptor fromPfd(ParcelFileDescriptor pfd, Handler handler, + final OnCloseListener listener) throws IOException { + final FileDescriptor original = new FileDescriptor(); + original.setInt$(pfd.detachFd()); + return fromFd(original, handler, listener); + } + + /** {@hide} */ + public static ParcelFileDescriptor fromFd(FileDescriptor fd, Handler handler, + final OnCloseListener listener) throws IOException { if (handler == null) { throw new IllegalArgumentException("Handler must not be null"); } diff --git a/core/java/android/os/RedactingFileDescriptor.java b/core/java/android/os/RedactingFileDescriptor.java index 60eb5c3c4a89..4e5eaac3442f 100644 --- a/core/java/android/os/RedactingFileDescriptor.java +++ b/core/java/android/os/RedactingFileDescriptor.java @@ -20,15 +20,18 @@ import android.content.Context; import android.os.storage.StorageManager; import android.system.ErrnoException; import android.system.Os; -import android.system.OsConstants; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; + import libcore.io.IoUtils; +import libcore.util.EmptyArray; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.InterruptedIOException; +import java.util.Arrays; /** * Variant of {@link FileDescriptor} that allows its creator to specify regions @@ -40,20 +43,21 @@ public class RedactingFileDescriptor { private static final String TAG = "RedactingFileDescriptor"; private static final boolean DEBUG = true; - private final long[] mRedactRanges; + private volatile long[] mRedactRanges; private FileDescriptor mInner = null; private ParcelFileDescriptor mOuter = null; - private RedactingFileDescriptor(Context context, File file, long[] redactRanges) + private RedactingFileDescriptor(Context context, File file, int mode, long[] redactRanges) throws IOException { mRedactRanges = checkRangesArgument(redactRanges); try { try { - mInner = Os.open(file.getAbsolutePath(), OsConstants.O_RDONLY, 0); + mInner = Os.open(file.getAbsolutePath(), + FileUtils.translateModePfdToPosix(mode), 0); mOuter = context.getSystemService(StorageManager.class) - .openProxyFileDescriptor(ParcelFileDescriptor.MODE_READ_ONLY, mCallback); + .openProxyFileDescriptor(mode, mCallback); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } @@ -78,16 +82,61 @@ public class RedactingFileDescriptor { /** * Open the given {@link File} and returns a {@link ParcelFileDescriptor} - * that offers a redacted, read-only view of the underlying data. + * that offers a redacted view of the underlying data. If a redacted region + * is written to, the newly written data can be read back correctly instead + * of continuing to be redacted. * * @param file The underlying file to open. + * @param mode The {@link ParcelFileDescriptor} mode to open with. * @param redactRanges List of file offsets that should be redacted, stored * as {@code [start1, end1, start2, end2, ...]}. Start values are * inclusive and end values are exclusive. */ - public static ParcelFileDescriptor open(Context context, File file, long[] redactRanges) - throws IOException { - return new RedactingFileDescriptor(context, file, redactRanges).mOuter; + public static ParcelFileDescriptor open(Context context, File file, int mode, + long[] redactRanges) throws IOException { + return new RedactingFileDescriptor(context, file, mode, redactRanges).mOuter; + } + + /** + * Update the given ranges argument to remove any references to the given + * offset and length. This is typically used when a caller has written over + * a previously redacted region. + */ + @VisibleForTesting + public static long[] removeRange(long[] ranges, long start, long end) { + if (start == end) { + return ranges; + } else if (start > end) { + throw new IllegalArgumentException(); + } + + long[] res = EmptyArray.LONG; + for (int i = 0; i < ranges.length; i += 2) { + if (start <= ranges[i] && end >= ranges[i + 1]) { + // Range entirely covered; remove it + } else if (start >= ranges[i] && end <= ranges[i + 1]) { + // Range partially covered; punch a hole + res = Arrays.copyOf(res, res.length + 4); + res[res.length - 4] = ranges[i]; + res[res.length - 3] = start; + res[res.length - 2] = end; + res[res.length - 1] = ranges[i + 1]; + } else { + // Range might covered; adjust edges if needed + res = Arrays.copyOf(res, res.length + 2); + if (end >= ranges[i] && end <= ranges[i + 1]) { + res[res.length - 2] = Math.max(ranges[i], end); + } else { + res[res.length - 2] = ranges[i]; + } + if (start >= ranges[i] && start <= ranges[i + 1]) { + res[res.length - 1] = Math.min(ranges[i + 1], start); + } else { + res[res.length - 1] = ranges[i + 1]; + } + } + } + return res; } private final ProxyFileDescriptorCallback mCallback = new ProxyFileDescriptorCallback() { @@ -126,7 +175,24 @@ public class RedactingFileDescriptor { @Override public int onWrite(long offset, int size, byte[] data) throws ErrnoException { - throw new ErrnoException(TAG, OsConstants.EBADF); + int n = 0; + while (n < size) { + try { + final int res = Os.pwrite(mInner, data, n, size - n, offset + n); + if (res == 0) { + break; + } else { + n += res; + } + } catch (InterruptedIOException e) { + n += e.bytesTransferred; + } + } + + // Clear any relevant redaction ranges before returning, since the + // writer should have access to see the data they just overwrote + mRedactRanges = removeRange(mRedactRanges, offset, offset + n); + return n; } @Override diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java index bf85fbd36e6a..5499181c3cdb 100644 --- a/core/java/android/os/Temperature.java +++ b/core/java/android/os/Temperature.java @@ -28,7 +28,7 @@ import java.lang.annotation.RetentionPolicy; * * @hide */ -public class Temperature implements Parcelable { +public final class Temperature implements Parcelable { /** Temperature value */ private float mValue; /** A temperature type from ThermalHAL */ @@ -44,7 +44,7 @@ public class Temperature implements Parcelable { THROTTLING_MODERATE, THROTTLING_SEVERE, THROTTLING_CRITICAL, - THROTTLING_WARNING, + THROTTLING_EMERGENCY, THROTTLING_SHUTDOWN, }) @Retention(RetentionPolicy.SOURCE) @@ -56,7 +56,7 @@ public class Temperature implements Parcelable { public static final int THROTTLING_MODERATE = ThrottlingSeverity.MODERATE; public static final int THROTTLING_SEVERE = ThrottlingSeverity.SEVERE; public static final int THROTTLING_CRITICAL = ThrottlingSeverity.CRITICAL; - public static final int THROTTLING_WARNING = ThrottlingSeverity.WARNING; + public static final int THROTTLING_EMERGENCY = ThrottlingSeverity.EMERGENCY; public static final int THROTTLING_SHUTDOWN = ThrottlingSeverity.SHUTDOWN; @IntDef(prefix = { "TYPE_" }, value = { diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 92b316914d82..abfcfaacde21 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -2463,6 +2463,27 @@ public class UserManager { } /** + * Get the parent of a user profile. + * + * @param user the handle of the user profile + * + * @return the parent of the user or {@code null} if the user is not profile + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public @Nullable UserHandle getProfileParent(@NonNull UserHandle user) { + UserInfo info = getProfileParent(user.getIdentifier()); + + if (info == null) { + return null; + } + + return UserHandle.of(info.id); + } + + /** * Enables or disables quiet mode for a managed profile. If quiet mode is enabled, apps in a * managed profile don't run, generate notifications, or consume data or battery. * <p> diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 8e11d858128a..d315383a5775 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -56,6 +56,7 @@ import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.provider.Settings; +import android.sysprop.VoldProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -1495,7 +1496,7 @@ public class StorageManager { * framework, so no service needs to check for changes during their lifespan */ public static boolean isBlockEncrypting() { - final String state = SystemProperties.get("vold.encrypt_progress", ""); + final String state = VoldProperties.encrypt_progress().orElse(""); return !"".equalsIgnoreCase(state); } @@ -1511,7 +1512,7 @@ public class StorageManager { * framework, so no service needs to check for changes during their lifespan */ public static boolean inCryptKeeperBounce() { - final String status = SystemProperties.get("vold.decrypt"); + final String status = VoldProperties.decrypt().orElse(""); return "trigger_restart_min_framework".equals(status); } diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java index 18aea03315ef..a41a64422038 100644 --- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java +++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java @@ -16,6 +16,9 @@ package android.permissionpresenterservice; +import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; + import android.annotation.NonNull; import android.annotation.SystemApi; import android.app.Service; @@ -27,12 +30,8 @@ import android.content.pm.permission.RuntimePermissionPresenter; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; -import android.os.Message; import android.os.RemoteCallback; -import com.android.internal.os.SomeArgs; - import java.util.List; /** @@ -63,7 +62,7 @@ public abstract class RuntimePermissionPresenterService extends Service { @Override public final void attachBaseContext(Context base) { super.attachBaseContext(base); - mHandler = new MyHandler(base.getMainLooper()); + mHandler = new Handler(base.getMainLooper()); } /** @@ -71,7 +70,8 @@ public abstract class RuntimePermissionPresenterService extends Service { * * @param packageName The package for which to query. */ - public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName); + public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions( + @NonNull String packageName); /** * Revokes the permission {@code permissionName} for app {@code packageName} @@ -87,61 +87,35 @@ public abstract class RuntimePermissionPresenterService extends Service { return new IRuntimePermissionPresenter.Stub() { @Override public void getAppPermissions(String packageName, RemoteCallback callback) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = packageName; - args.arg2 = callback; - mHandler.obtainMessage(MyHandler.MSG_GET_APP_PERMISSIONS, - args).sendToTarget(); + checkNotNull(packageName, "packageName"); + checkNotNull(callback, "callback"); + + mHandler.sendMessage( + obtainMessage(RuntimePermissionPresenterService::getAppPermissions, + RuntimePermissionPresenterService.this, packageName, callback)); } @Override public void revokeRuntimePermission(String packageName, String permissionName) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = packageName; - args.arg2 = permissionName; - mHandler.obtainMessage(MyHandler.MSG_REVOKE_APP_PERMISSION, - args).sendToTarget(); + checkNotNull(packageName, "packageName"); + checkNotNull(permissionName, "permissionName"); + + mHandler.sendMessage( + obtainMessage(RuntimePermissionPresenterService::onRevokeRuntimePermission, + RuntimePermissionPresenterService.this, packageName, + permissionName)); } }; } - private final class MyHandler extends Handler { - public static final int MSG_GET_APP_PERMISSIONS = 1; - public static final int MSG_GET_APPS_USING_PERMISSIONS = 2; - public static final int MSG_REVOKE_APP_PERMISSION = 3; - - public MyHandler(Looper looper) { - super(looper, null, false); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_GET_APP_PERMISSIONS: { - SomeArgs args = (SomeArgs) msg.obj; - String packageName = (String) args.arg1; - RemoteCallback callback = (RemoteCallback) args.arg2; - args.recycle(); - List<RuntimePermissionPresentationInfo> permissions = - onGetAppPermissions(packageName); - if (permissions != null && !permissions.isEmpty()) { - Bundle result = new Bundle(); - result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, - permissions); - callback.sendResult(result); - } else { - callback.sendResult(null); - } - } break; - case MSG_REVOKE_APP_PERMISSION: { - SomeArgs args = (SomeArgs) msg.obj; - String packageName = (String) args.arg1; - String permissionName = (String) args.arg2; - args.recycle(); - - onRevokeRuntimePermission(packageName, permissionName); - } break; - } + private void getAppPermissions(@NonNull String packageName, @NonNull RemoteCallback callback) { + List<RuntimePermissionPresentationInfo> permissions = onGetAppPermissions(packageName); + if (permissions != null && !permissions.isEmpty()) { + Bundle result = new Bundle(); + result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, permissions); + callback.sendResult(result); + } else { + callback.sendResult(null); } } } diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index 76607e9d42d2..8e37559001db 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -660,7 +660,22 @@ public class FontsContract { if (familyBuilder == null) { return null; } - return new Typeface.CustomFallbackBuilder(familyBuilder.build()).build(); + + final FontFamily family = familyBuilder.build(); + + final FontStyle normal = new FontStyle(FontStyle.FONT_WEIGHT_NORMAL, + FontStyle.FONT_SLANT_UPRIGHT); + Font bestFont = family.getFont(0); + int bestScore = normal.getMatchScore(bestFont.getStyle()); + for (int i = 1; i < family.getSize(); ++i) { + final Font candidate = family.getFont(i); + final int score = normal.getMatchScore(candidate.getStyle()); + if (score < bestScore) { + bestFont = candidate; + bestScore = score; + } + } + return new Typeface.CustomFallbackBuilder(family).setStyle(bestFont.getStyle()).build(); } /** diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index e0e4fe29f48a..0299e416707a 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -37,6 +37,7 @@ import android.database.DatabaseUtils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; +import android.media.ExifInterface; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; @@ -121,6 +122,8 @@ public final class MediaStore { public static final String PARAM_INCLUDE_PENDING = "includePending"; /** {@hide} */ public static final String PARAM_PROGRESS = "progress"; + /** {@hide} */ + public static final String PARAM_REQUIRE_ORIGINAL = "requireOriginal"; /** * Activity Action: Launch a music player. @@ -478,6 +481,24 @@ public final class MediaStore { } /** + * Update the given {@link Uri} to indicate that the caller requires the + * original file contents when calling + * {@link ContentResolver#openFileDescriptor(Uri, String)}. + * <p> + * This can be useful when the caller wants to ensure they're backing up the + * exact bytes of the underlying media, without any Exif redaction being + * performed. + * <p> + * If the original file contents cannot be provided, a + * {@link UnsupportedOperationException} will be thrown when the returned + * {@link Uri} is used, such as when the caller doesn't hold + * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}. + */ + public static @NonNull Uri setRequireOriginal(@NonNull Uri uri) { + return uri.buildUpon().appendQueryParameter(PARAM_REQUIRE_ORIGINAL, "1").build(); + } + + /** * Create a new pending media item using the given parameters. Pending items * are expected to have a short lifetime, and owners should either * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a @@ -1146,13 +1167,25 @@ public final class MediaStore { /** * The latitude where the image was captured. * <P>Type: DOUBLE</P> + * + * @deprecated location details are no longer indexed for privacy + * reasons, and this value is now always {@code null}. + * You can still manually obtain location metadata using + * {@link ExifInterface#getLatLong(float[])}. */ + @Deprecated public static final String LATITUDE = "latitude"; /** * The longitude where the image was captured. * <P>Type: DOUBLE</P> + * + * @deprecated location details are no longer indexed for privacy + * reasons, and this value is now always {@code null}. + * You can still manually obtain location metadata using + * {@link ExifInterface#getLatLong(float[])}. */ + @Deprecated public static final String LONGITUDE = "longitude"; /** @@ -1673,6 +1706,12 @@ public final class MediaStore { public static final String IS_NOTIFICATION = "is_notification"; /** + * Non-zero if the audio file is an audiobook + * <P>Type: INTEGER (boolean)</P> + */ + public static final String IS_AUDIOBOOK = "is_audiobook"; + + /** * The genre of the audio file, if any * <P>Type: TEXT</P> * Does not exist in the database - only used by the media scanner for inserts. @@ -2384,13 +2423,25 @@ public final class MediaStore { /** * The latitude where the video was captured. * <P>Type: DOUBLE</P> + * + * @deprecated location details are no longer indexed for privacy + * reasons, and this value is now always {@code null}. + * You can still manually obtain location metadata using + * {@link ExifInterface#getLatLong(float[])}. */ + @Deprecated public static final String LATITUDE = "latitude"; /** * The longitude where the video was captured. * <P>Type: DOUBLE</P> + * + * @deprecated location details are no longer indexed for privacy + * reasons, and this value is now always {@code null}. + * You can still manually obtain location metadata using + * {@link ExifInterface#getLatLong(float[])}. */ + @Deprecated public static final String LONGITUDE = "longitude"; /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d7729037bfad..74ec0b9c8085 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5075,6 +5075,7 @@ public final class Settings { * @hide */ @SystemApi + @TestApi @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull ContentResolver resolver, @Nullable String tag) { @@ -6278,6 +6279,7 @@ public final class Settings { * * @hide */ + @SystemApi public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled"; @@ -8232,6 +8234,24 @@ public final class Settings { public static final String NOTIFICATION_NEW_INTERRUPTION_MODEL = "new_interruption_model"; /** + * How often to check for location access. + * @hide + */ + @SystemApi + @TestApi + public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = + "location_access_check_interval_millis"; + + /** + * Delay between granting location access and checking it. + * @hide + */ + @SystemApi + @TestApi + public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = + "location_access_check_delay_millis"; + + /** * This are the settings to be backed up. * * NOTE: Settings are backed up and restored in the order they appear @@ -12818,6 +12838,23 @@ public final class Settings { "max_sound_trigger_detection_service_ops_per_day"; /** + * Property used by {@code com.android.server.SystemServer} on start to decide whether + * the Smart Suggestions service should be created or not + * + * <p>By default it should *NOT* be set (in which case the decision is based on whether + * the OEM provides an implementation for the service), but it can be overridden to: + * + * <ul> + * <li>Provide a "kill switch" so OEMs can disable it remotely in case of emergency. + * <li>Enable the CTS tests to be run on AOSP builds + * </ul> + * + * @hide + */ + public static final String SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED = + "smart_suggestions_service_explicitly_enabled"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -13490,6 +13527,13 @@ public final class Settings { */ public static final String WARNING_TEMPERATURE = "warning_temperature"; + + /** + * USB Temperature at which the high temperature alarm notification should be shown. + * @hide + */ + public static final String USB_ALARM_TEMPERATURE = "usb_alarm_temperature"; + /** * Whether the diskstats logging task is enabled/disabled. * @hide diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl b/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl new file mode 100644 index 000000000000..23d607d9838c --- /dev/null +++ b/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.intelligence; + +parcelable ContentCaptureEventsRequest; diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java b/core/java/android/service/intelligence/ContentCaptureEventsRequest.java new file mode 100644 index 000000000000..bc5b92bce999 --- /dev/null +++ b/core/java/android/service/intelligence/ContentCaptureEventsRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.service.intelligence; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.intelligence.ContentCaptureEvent; + +import java.util.List; + +/** + * Batch of content capture events. + * + * @hide + */ +@SystemApi +public final class ContentCaptureEventsRequest implements Parcelable { + + private final List<ContentCaptureEvent> mEvents; + + /** @hide */ + public ContentCaptureEventsRequest(@NonNull List<ContentCaptureEvent> events) { + mEvents = events; + } + + /** + * Gets the events. + */ + @NonNull + public List<ContentCaptureEvent> getEvents() { + return mEvents; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeTypedList(mEvents, flags); + } + + public static final Parcelable.Creator<ContentCaptureEventsRequest> CREATOR = + new Parcelable.Creator<ContentCaptureEventsRequest>() { + + @Override + public ContentCaptureEventsRequest createFromParcel(Parcel parcel) { + return new ContentCaptureEventsRequest(parcel + .createTypedArrayList(ContentCaptureEvent.CREATOR)); + } + + @Override + public ContentCaptureEventsRequest[] newArray(int size) { + return new ContentCaptureEventsRequest[size]; + } + }; +} diff --git a/core/java/android/service/intelligence/FillController.java b/core/java/android/service/intelligence/FillController.java index c5e1242842bb..4a9c85de1fa2 100644 --- a/core/java/android/service/intelligence/FillController.java +++ b/core/java/android/service/intelligence/FillController.java @@ -15,12 +15,12 @@ */ package android.service.intelligence; -import static android.service.intelligence.IntelligenceService.DEBUG; +import static android.service.intelligence.SmartSuggestionsService.DEBUG; import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.RemoteException; -import android.service.intelligence.IntelligenceService.AutofillProxy; +import android.service.intelligence.SmartSuggestionsService.AutofillProxy; import android.util.Log; import android.util.Pair; import android.view.autofill.AutofillId; diff --git a/core/java/android/service/intelligence/FillRequest.java b/core/java/android/service/intelligence/FillRequest.java index 95e922487906..f68db9df6fe3 100644 --- a/core/java/android/service/intelligence/FillRequest.java +++ b/core/java/android/service/intelligence/FillRequest.java @@ -18,7 +18,7 @@ package android.service.intelligence; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; -import android.service.intelligence.IntelligenceService.AutofillProxy; +import android.service.intelligence.SmartSuggestionsService.AutofillProxy; import android.view.autofill.AutofillId; /** diff --git a/core/java/android/service/intelligence/FillWindow.java b/core/java/android/service/intelligence/FillWindow.java index 4ea07bfc86cf..309f6a1b6f1b 100644 --- a/core/java/android/service/intelligence/FillWindow.java +++ b/core/java/android/service/intelligence/FillWindow.java @@ -15,7 +15,7 @@ */ package android.service.intelligence; -import static android.service.intelligence.IntelligenceService.DEBUG; +import static android.service.intelligence.SmartSuggestionsService.DEBUG; import android.annotation.LongDef; import android.annotation.NonNull; diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl index e2260d7d3d76..d6b31079e34c 100644 --- a/core/java/android/service/intelligence/IIntelligenceService.aidl +++ b/core/java/android/service/intelligence/IIntelligenceService.aidl @@ -17,6 +17,7 @@ package android.service.intelligence; import android.os.IBinder; +import android.service.intelligence.ContentCaptureEventsRequest; import android.service.intelligence.InteractionSessionId; import android.service.intelligence.InteractionContext; import android.service.intelligence.SnapshotData; @@ -26,19 +27,19 @@ import android.view.intelligence.ContentCaptureEvent; import java.util.List; - /** * Interface from the system to an intelligence service. * * @hide */ + // TODO(b/111276913): rename / update javadoc (once the final name is defined) oneway interface IIntelligenceService { // Called when session is created (context not null) or destroyed (context null) void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId); - void onContentCaptureEvents(in InteractionSessionId sessionId, - in List<ContentCaptureEvent> events); + void onContentCaptureEventsRequest(in InteractionSessionId sessionId, + in ContentCaptureEventsRequest request); void onActivitySnapshot(in InteractionSessionId sessionId, in SnapshotData snapshotData); diff --git a/core/java/android/service/intelligence/InteractionContext.java b/core/java/android/service/intelligence/InteractionContext.java index 0cc377bb030b..7f4283db28d2 100644 --- a/core/java/android/service/intelligence/InteractionContext.java +++ b/core/java/android/service/intelligence/InteractionContext.java @@ -37,7 +37,7 @@ public final class InteractionContext implements Parcelable { /** * Flag used to indicate that the app explicitly disabled content capture for the activity * (using - * {@link android.view.intelligence.IntelligenceManager#setContentCaptureEnabled()}), + * {@link android.view.intelligence.ContentCaptureManager#setContentCaptureEnabled()}), * in which case the service will just receive activity-level events. */ public static final int FLAG_DISABLED_BY_APP = 0x1; diff --git a/core/java/android/service/intelligence/PresentationParams.java b/core/java/android/service/intelligence/PresentationParams.java index c59069bbb674..95303099793a 100644 --- a/core/java/android/service/intelligence/PresentationParams.java +++ b/core/java/android/service/intelligence/PresentationParams.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.Rect; -import android.service.intelligence.IntelligenceService.AutofillProxy; +import android.service.intelligence.SmartSuggestionsService.AutofillProxy; import android.util.DebugUtils; import android.view.View; diff --git a/core/java/android/service/intelligence/IntelligenceService.java b/core/java/android/service/intelligence/SmartSuggestionsService.java index 040e25e977e4..0e29e70ecc3b 100644 --- a/core/java/android/service/intelligence/IntelligenceService.java +++ b/core/java/android/service/intelligence/SmartSuggestionsService.java @@ -19,8 +19,10 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.CallSuper; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; +import android.content.ComponentName; import android.content.Intent; import android.graphics.Rect; import android.os.CancellationSignal; @@ -43,31 +45,31 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** - * A service used to capture the content of the screen. - * - * <p>The data collected by this service can be analyzed and combined with other sources to provide - * contextual data in other areas of the system such as Autofill. + * A service used to capture the content of the screen to provide contextual data in other areas of + * the system such as Autofill. * * @hide */ @SystemApi -public abstract class IntelligenceService extends Service { +public abstract class SmartSuggestionsService extends Service { - private static final String TAG = "IntelligenceService"; + private static final String TAG = "SmartSuggestionsService"; // TODO(b/111330312): STOPSHIP use dynamic value, or change to false static final boolean DEBUG = true; + static final boolean VERBOSE = false; /** * The {@link Intent} that must be declared as handled by the service. * To be supported, the service must also require the - * {@link android.Manifest.permission#BIND_INTELLIGENCE_SERVICE} permission so + * {@link android.Manifest.permission#BIND_SMART_SUGGESTIONS_SERVICE} permission so * that other applications can not abuse it. */ public static final String SERVICE_INTERFACE = - "android.service.intelligence.IntelligenceService"; + "android.service.intelligence.SmartSuggestionsService"; private Handler mHandler; @@ -80,21 +82,21 @@ public abstract class IntelligenceService extends Service { throws RemoteException { if (context != null) { mHandler.sendMessage( - obtainMessage(IntelligenceService::onCreateInteractionSession, - IntelligenceService.this, context, sessionId)); + obtainMessage(SmartSuggestionsService::onCreateInteractionSession, + SmartSuggestionsService.this, context, sessionId)); } else { mHandler.sendMessage( - obtainMessage(IntelligenceService::onDestroyInteractionSession, - IntelligenceService.this, sessionId)); + obtainMessage(SmartSuggestionsService::onDestroyInteractionSession, + SmartSuggestionsService.this, sessionId)); } } @Override - public void onContentCaptureEvents(InteractionSessionId sessionId, - List<ContentCaptureEvent> events) { + public void onContentCaptureEventsRequest(InteractionSessionId sessionId, + ContentCaptureEventsRequest request) { mHandler.sendMessage( - obtainMessage(IntelligenceService::onContentCaptureEvent, - IntelligenceService.this, sessionId, events)); + obtainMessage(SmartSuggestionsService::onContentCaptureEventsRequest, + SmartSuggestionsService.this, sessionId, request)); } @@ -102,22 +104,22 @@ public abstract class IntelligenceService extends Service { public void onActivitySnapshot(InteractionSessionId sessionId, SnapshotData snapshotData) { mHandler.sendMessage( - obtainMessage(IntelligenceService::onActivitySnapshot, - IntelligenceService.this, sessionId, snapshotData)); + obtainMessage(SmartSuggestionsService::onActivitySnapshot, + SmartSuggestionsService.this, sessionId, snapshotData)); } @Override public void onAutofillRequest(InteractionSessionId sessionId, IBinder client, int autofilSessionId, AutofillId focusedId) { - mHandler.sendMessage(obtainMessage(IntelligenceService::handleOnAutofillRequest, - IntelligenceService.this, sessionId, client, autofilSessionId, focusedId)); + mHandler.sendMessage(obtainMessage(SmartSuggestionsService::handleOnAutofillRequest, + SmartSuggestionsService.this, sessionId, client, autofilSessionId, focusedId)); } @Override public void onDestroyAutofillWindowsRequest(InteractionSessionId sessionId) { mHandler.sendMessage( - obtainMessage(IntelligenceService::handleOnDestroyAutofillWindowsRequest, - IntelligenceService.this, sessionId)); + obtainMessage(SmartSuggestionsService::handleOnDestroyAutofillWindowsRequest, + SmartSuggestionsService.this, sessionId)); } }; @@ -139,25 +141,92 @@ public abstract class IntelligenceService 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 + * chat apps. For example, if the service wants to support view captures on all activities of + * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2}, + * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"), + * Arrays.asList(new ComponentName("ChatApp2", "act1"), + * new ComponentName("ChatApp2", "act2")));} + */ + public final void setContentCaptureWhitelist(@Nullable List<String> packages, + @Nullable List<ComponentName> activities) { + //TODO(b/111276913): implement + } + + /** + * Defines whether content capture should be enabled for activities with such + * {@link android.content.ComponentName}. + * + * <p>Useful to blacklist a particular activity. + */ + public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity, + boolean enabled) { + //TODO(b/111276913): implement + } + + /** + * Defines whether content capture should be enabled for activities of the app with such + * {@code packageName}. + * + * <p>Useful to blacklist any activity from a particular app. + */ + public final void setPackageContentCaptureEnabled(@NonNull String packageName, + boolean enabled) { + //TODO(b/111276913): implement + } + + /** + * Gets the activities where content capture was disabled by + * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}. + */ + @NonNull + public final Set<ComponentName> getContentCaptureDisabledActivities() { + //TODO(b/111276913): implement + return null; + } + + /** + * Gets the apps where content capture was disabled by + * {@link #setPackageContentCaptureEnabled(String, boolean)}. + */ + @NonNull + public final Set<String> getContentCaptureDisabledPackages() { + //TODO(b/111276913): implement + return null; + } + + /** * Creates a new interaction session. * * @param context interaction context * @param sessionId the session's Id */ public void onCreateInteractionSession(@NonNull InteractionContext context, - @NonNull InteractionSessionId sessionId) {} + @NonNull InteractionSessionId sessionId) { + if (VERBOSE) { + Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")"); + } + } /** * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture * session. * * @param sessionId the session's Id - * @param events the events + * @param request the events */ // TODO(b/111276913): rename to onContentCaptureEvents or something like that; also, pass a // Request object so it can be extended - public abstract void onContentCaptureEvent(@NonNull InteractionSessionId sessionId, - @NonNull List<ContentCaptureEvent> events); + public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId, + @NonNull ContentCaptureEventsRequest request); private void handleOnAutofillRequest(@NonNull InteractionSessionId sessionId, @NonNull IBinder client, int autofillSessionId, @NonNull AutofillId focusedId) { @@ -242,8 +311,7 @@ public abstract class IntelligenceService extends Service { } /** - * Notifies the service of {@link IntelligenceSnapshotData snapshot data} associated with a - * session. + * Notifies the service of {@link SnapshotData snapshot data} associated with a session. * * @param sessionId the session's Id * @param snapshotData the data @@ -256,7 +324,11 @@ public abstract class IntelligenceService extends Service { * * @param sessionId the id of the session to destroy */ - public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {} + public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) { + if (VERBOSE) { + Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")"); + } + } /** @hide */ static final class AutofillProxy { diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 8371c31b5ac5..0e2ae837a141 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -806,7 +806,7 @@ public class ZenModeConfig implements Parcelable { if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_CALLS, isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS, defaultPolicy))) { priorityCategories |= Policy.PRIORITY_CATEGORY_CALLS; - messageSenders = getNotificationPolicySenders(zenPolicy.getPriorityCallSenders()); + callSenders = getNotificationPolicySenders(zenPolicy.getPriorityCallSenders()); } if (zenPolicy.isCategoryAllowed(ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS, diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java index 43ab8dc07000..194147c2c154 100644 --- a/core/java/android/service/notification/ZenPolicy.java +++ b/core/java/android/service/notification/ZenPolicy.java @@ -859,6 +859,27 @@ public final class ZenPolicy implements Parcelable { /** * @hide */ + public boolean areValuesSet() { + return getPriorityCategoryReminders() != STATE_UNSET + || getPriorityCategoryEvents() != STATE_UNSET + || getPriorityCategoryMessages() != STATE_UNSET + || getPriorityCategoryCalls() != STATE_UNSET + || getPriorityCategoryRepeatCallers() != STATE_UNSET + || getPriorityCategoryAlarms() != STATE_UNSET + || getPriorityCategoryMedia() != STATE_UNSET + || getPriorityCategorySystem() != STATE_UNSET + || getVisualEffectFullScreenIntent() != STATE_UNSET + || getVisualEffectLights() != STATE_UNSET + || getVisualEffectPeek() != STATE_UNSET + || getVisualEffectStatusBar() != STATE_UNSET + || getVisualEffectBadge() != STATE_UNSET + || getVisualEffectAmbient() != STATE_UNSET + || getVisualEffectNotificationList() != STATE_UNSET; + } + + /** + * @hide + */ public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java index be47320b59bd..433483f717fa 100644 --- a/core/java/android/text/style/SuggestionSpan.java +++ b/core/java/android/text/style/SuggestionSpan.java @@ -369,10 +369,7 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan { /** * @return The color of the underline for that span, or 0 if there is no underline - * - * @hide */ - @UnsupportedAppUsage public int getUnderlineColor() { // The order here should match what is used in updateDrawState final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0; diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 5f348c4a73ed..dee6d908c4c5 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -45,7 +45,6 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_systemui_theme", "true"); DEFAULT_FLAGS.put("settings_dynamic_homepage", "true"); DEFAULT_FLAGS.put("settings_mobile_network_v2", "true"); - DEFAULT_FLAGS.put("settings_data_usage_v2", "true"); DEFAULT_FLAGS.put("settings_seamless_transfer", "false"); DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false"); DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false"); diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index 3ee5f1fcc883..33b3ff4fef59 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -18,6 +18,7 @@ package android.view; import android.annotation.UnsupportedAppUsage; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Message; @@ -225,7 +226,7 @@ public class GestureDetector { private int mMinimumFlingVelocity; private int mMaximumFlingVelocity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); @@ -592,8 +593,8 @@ public class GestureDetector { if (mIsLongpressEnabled) { mHandler.removeMessages(LONG_PRESS); - mHandler.sendEmptyMessageAtTime(LONG_PRESS, - mCurrentDownEvent.getDownTime() + LONGPRESS_TIMEOUT); + mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() + + ViewConfiguration.getLongPressTimeout()); } mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index af41b6942a5e..5e6d3d19fa2f 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -25,6 +25,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.DisplayCutout; import android.view.InsetsState; +import android.view.InsetsSourceControl; import com.android.internal.os.IResultReceiver; import android.util.MergedConfiguration; @@ -60,6 +61,11 @@ oneway interface IWindow { */ void insetsChanged(in InsetsState insetsState); + /** + * Called when this window retrieved control over a specified set of inset sources. + */ + void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls); + void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); void dispatchGetNewSurface(); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 7841d0417a2b..ba5340c826d3 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -16,17 +16,30 @@ package android.view; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Rect; +import android.util.ArraySet; +import android.util.SparseArray; +import android.view.SurfaceControl.Transaction; +import android.view.WindowInsets.Type.InsetType; +import android.view.InsetsState.InternalInsetType; + +import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; /** * Implements {@link WindowInsetsController} on the client. + * @hide */ -class InsetsController { +public class InsetsController implements WindowInsetsController { private final InsetsState mState = new InsetsState(); private final Rect mFrame = new Rect(); + private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>(); + + private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>(); void onFrameChanged(Rect frame) { mFrame.set(frame); @@ -48,6 +61,61 @@ class InsetsController { return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout); } + /** + * Called when the server has dispatched us a new set of inset controls. + */ + public void onControlsChanged(InsetsSourceControl[] activeControls) { + if (activeControls != null) { + for (InsetsSourceControl activeControl : activeControls) { + mTmpControlArray.put(activeControl.getType(), activeControl); + } + } + + // Ensure to update all existing source consumers + for (int i = mSourceConsumers.size() - 1; i >= 0; i--) { + final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i); + final InsetsSourceControl control = mTmpControlArray.get(consumer.getType()); + + // control may be null, but we still need to update the control to null if it got + // revoked. + consumer.setControl(control); + } + + // Ensure to create source consumers if not available yet. + for (int i = mTmpControlArray.size() - 1; i >= 0; i--) { + final InsetsSourceControl control = mTmpControlArray.valueAt(i); + getSourceConsumer(control.getType()).setControl(control); + } + mTmpControlArray.clear(); + } + + @Override + public void show(@InsetType int types) { + final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); + for (int i = internalTypes.size() - 1; i >= 0; i--) { + getSourceConsumer(internalTypes.valueAt(i)).show(); + } + } + + @Override + public void hide(@InsetType int types) { + final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); + for (int i = internalTypes.size() - 1; i >= 0; i--) { + getSourceConsumer(internalTypes.valueAt(i)).hide(); + } + } + + @VisibleForTesting + public @NonNull InsetsSourceConsumer getSourceConsumer(@InternalInsetType int type) { + InsetsSourceConsumer controller = mSourceConsumers.get(type); + if (controller != null) { + return controller; + } + controller = new InsetsSourceConsumer(type, mState, Transaction::new); + mSourceConsumers.put(type, controller); + return controller; + } + void dump(String prefix, PrintWriter pw) { pw.println(prefix); pw.println("InsetsController:"); mState.dump(prefix + " ", pw); diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java new file mode 100644 index 000000000000..e74aa8dfcf4e --- /dev/null +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.view; + +import android.annotation.Nullable; +import android.view.SurfaceControl.Transaction; +import android.view.InsetsState.InternalInsetType; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.function.Supplier; + +/** + * Controls the visibility and animations of a single window insets source. + * @hide + */ +public class InsetsSourceConsumer { + + private final Supplier<Transaction> mTransactionSupplier; + private final @InternalInsetType int mType; + private final InsetsState mState; + private @Nullable InsetsSourceControl mControl; + private boolean mHidden; + + public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state, + Supplier<Transaction> transactionSupplier) { + mType = type; + mState = state; + mTransactionSupplier = transactionSupplier; + } + + public void setControl(@Nullable InsetsSourceControl control) { + if (mControl == control) { + return; + } + mControl = control; + applyHiddenToControl(); + } + + @VisibleForTesting + public InsetsSourceControl getControl() { + return mControl; + } + + int getType() { + return mType; + } + + @VisibleForTesting + public void show() { + setHidden(false); + } + + @VisibleForTesting + public void hide() { + setHidden(true); + } + + private void setHidden(boolean hidden) { + if (mHidden == hidden) { + return; + } + mHidden = hidden; + applyHiddenToControl(); + } + + private void applyHiddenToControl() { + if (mControl == null) { + return; + } + + // TODO: Animation + final Transaction t = mTransactionSupplier.get(); + if (mHidden) { + t.hide(mControl.getLeash()); + } else { + t.show(mControl.getLeash()); + } + t.apply(); + } +} diff --git a/core/java/android/view/InsetsSourceControl.aidl b/core/java/android/view/InsetsSourceControl.aidl new file mode 100644 index 000000000000..755bf456658d --- /dev/null +++ b/core/java/android/view/InsetsSourceControl.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +parcelable InsetsSourceControl; diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java new file mode 100644 index 000000000000..9383e6c57854 --- /dev/null +++ b/core/java/android/view/InsetsSourceControl.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.graphics.Point; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.InsetsState.InternalInsetType; + +/** + * Represents a parcelable object to allow controlling a single {@link InsetsSource}. + * @hide + */ +public class InsetsSourceControl implements Parcelable { + + private final @InternalInsetType int mType; + private final SurfaceControl mLeash; + + public InsetsSourceControl(@InternalInsetType int type, SurfaceControl leash) { + mType = type; + mLeash = leash; + } + + public int getType() { + return mType; + } + + public SurfaceControl getLeash() { + return mLeash; + } + + public InsetsSourceControl(Parcel in) { + mType = in.readInt(); + mLeash = in.readParcelable(null /* loader */); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mType); + dest.writeParcelable(mLeash, 0 /* flags*/); + } + + public static final Creator<InsetsSourceControl> CREATOR + = new Creator<InsetsSourceControl>() { + public InsetsSourceControl createFromParcel(Parcel in) { + return new InsetsSourceControl(in); + } + + public InsetsSourceControl[] newArray(int size) { + return new InsetsSourceControl[size]; + } + }; +} diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 9895adcad23a..689b14fe29c6 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -22,6 +22,9 @@ import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; +import android.util.ArraySet; +import android.view.WindowInsets.Type; +import android.view.WindowInsets.Type.InsetType; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -148,6 +151,22 @@ public class InsetsState implements Parcelable { } } + public static @InternalInsetType ArraySet<Integer> toInternalType(@InsetType int insetTypes) { + final ArraySet<Integer> result = new ArraySet<>(); + if ((insetTypes & Type.TOP_BAR) != 0) { + result.add(TYPE_TOP_BAR); + } + if ((insetTypes & Type.SIDE_BARS) != 0) { + result.add(TYPE_SIDE_BAR_1); + result.add(TYPE_SIDE_BAR_2); + result.add(TYPE_SIDE_BAR_3); + } + if ((insetTypes & Type.IME) != 0) { + result.add(TYPE_IME); + } + return result; + } + public void dump(String prefix, PrintWriter pw) { pw.println(prefix + "InsetsState"); for (int i = mSources.size() - 1; i >= 0; i--) { diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 8b39cc72af8f..9cced4e0052f 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1803,6 +1803,28 @@ public class KeyEvent extends InputEvent implements Parcelable { } /** + * Returns whether this key will be sent to the + * {@link android.media.session.MediaSession.Callback} if not handled. + */ + public static final boolean isMediaSessionKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + return true; + } + return false; + } + + /** * Returns true if the specified keycode is a gamepad button. * @return True if the keycode is a gamepad button, such as {@link #KEYCODE_BUTTON_A}. */ @@ -1861,31 +1883,6 @@ public class KeyEvent extends InputEvent implements Parcelable { } } - /** - * Returns whether this key can be handled by - * {@link android.media.session.MediaSession.Callback}. - * - * @hide - */ - public static final boolean isMediaSessionKey(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_MEDIA_PLAY: - case KeyEvent.KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KeyEvent.KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - return true; - } - return false; - } - - /** Is this a system key? System keys can not be used for menu shortcuts. * @hide */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c5d03741dbba..4b9cbff8c161 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -112,7 +112,7 @@ import android.view.autofill.AutofillValue; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.intelligence.IntelligenceManager; +import android.view.intelligence.ContentCaptureManager; import android.widget.Checkable; import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; @@ -8138,7 +8138,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * is visible. * * <p>The populated structure is then passed to the service through - * {@link IntelligenceManager#notifyViewAppeared(ViewStructure)}. + * {@link ContentCaptureManager#notifyViewAppeared(ViewStructure)}. * * <p><b>Note: </b>the following methods of the {@code structure} will be ignored: * <ul> @@ -8915,7 +8915,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Helper used to notify the {@link IntelligenceManager} when the view is removed or + * Helper used to notify the {@link ContentCaptureManager} when the view is removed or * added, based on whether it's laid out and visible, and without knowing if the parent removed * it from the view hierarchy. * @@ -8931,11 +8931,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * </ol> */ private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) { + // First check if context has client, so it saves a service lookup when it doesn't + if (!mContext.isContentCaptureSupported()) return; - final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class); - if (im == null || !im.isContentCaptureEnabled()) return; + // Then check if it's enabled in the context... + final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class); + if (cm == null || !cm.isContentCaptureEnabled()) return; - // NOTE: isImportantForContentCapture() is more expensive than im.isContentCaptureEnabled() + // ... and finally at the view level + // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled() if (!isImportantForContentCapture()) return; if (appeared) { @@ -8950,9 +8954,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } // All good: notify the manager... - final ViewStructure structure = im.newViewStructure(this); + final ViewStructure structure = cm.newViewStructure(this); onProvideContentCaptureStructure(structure, /* flags= */ 0); - im.notifyViewAppeared(structure); + cm.notifyViewAppeared(structure); // ...and set the flags mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; @@ -8969,7 +8973,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } // All good: notify the manager... - im.notifyViewDisappeared(getAutofillId()); + cm.notifyViewDisappeared(getAutofillId()); // ...and set the flags mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; @@ -10337,6 +10341,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Retrieves the single {@link WindowInsetsController} of the window this view is attached to. + * + * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a + * a window. + * @hide pending unhide + */ + public @Nullable WindowInsetsController getWindowInsetsController() { + if (mAttachInfo != null) { + return mAttachInfo.mViewRootImpl.getInsetsController(); + } + return null; + } + + /** * @hide Compute the insets that should be consumed by this view and the ones * that should propagate to those under it. * diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 937e23813cec..cb4788624935 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -170,7 +170,12 @@ public final class ViewRootImpl implements ViewParent, * fully migrated over. */ private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets"; - private static final boolean USE_NEW_INSETS = + + /** + * @see #USE_NEW_INSETS_PROPERTY + * @hide + */ + public static final boolean USE_NEW_INSETS = SystemProperties.getBoolean(USE_NEW_INSETS_PROPERTY, false); /** @@ -1847,6 +1852,10 @@ public final class ViewRootImpl implements ViewParent, host.dispatchApplyWindowInsets(insets); } + InsetsController getInsetsController() { + return mInsetsController; + } + private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) { return lp.type == TYPE_STATUS_BAR_PANEL || lp.type == TYPE_INPUT_METHOD @@ -1935,7 +1944,6 @@ public final class ViewRootImpl implements ViewParent, // PixelFormat.hasAlpha(lp.format) || lp.format == PixelFormat.RGBX_8888 // However, windows are now always 32 bits by default, so choose 32 bits mAttachInfo.mUse32BitDrawingCache = true; - mAttachInfo.mHasWindowFocus = false; mAttachInfo.mWindowVisibility = viewVisibility; mAttachInfo.mRecomputeGlobalAttributes = false; mLastConfigurationFromResources.setTo(config); @@ -4208,6 +4216,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_POINTER_CAPTURE_CHANGED = 28; private final static int MSG_DRAW_FINISHED = 29; private final static int MSG_INSETS_CHANGED = 30; + private final static int MSG_INSETS_CONTROL_CHANGED = 31; final class ViewRootHandler extends Handler { @Override @@ -4371,11 +4380,22 @@ public final class ViewRootImpl implements ViewParent, case MSG_INSETS_CHANGED: mPendingInsets = (InsetsState) msg.obj; - // TODO: Full traversal not needed here + // TODO: Full traversal not needed here. + if (USE_NEW_INSETS) { + requestLayout(); + } + break; + case MSG_INSETS_CONTROL_CHANGED: { + SomeArgs args = (SomeArgs) msg.obj; + mPendingInsets = (InsetsState) args.arg1; + mInsetsController.onControlsChanged((InsetsSourceControl[]) args.arg2); + + // TODO: Full traversal not necessarily needed here. if (USE_NEW_INSETS) { requestLayout(); } break; + } case MSG_WINDOW_MOVED: if (mAdded) { final int w = mWinFrame.width(); @@ -7116,6 +7136,14 @@ public final class ViewRootImpl implements ViewParent, mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget(); } + private void dispatchInsetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = insetsState; + args.arg2 = activeControls; + mHandler.obtainMessage(MSG_INSETS_CONTROL_CHANGED, args).sendToTarget(); + } + public void dispatchMoved(int newX, int newY) { if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY); if (mTranslator != null) { @@ -8187,6 +8215,15 @@ public final class ViewRootImpl implements ViewParent, } @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) { + final ViewRootImpl viewAncestor = mViewAncestor.get(); + if (viewAncestor != null) { + viewAncestor.dispatchInsetsControlChanged(insetsState, activeControls); + } + } + + @Override public void moved(int newX, int newY) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index c1e94d8ff97e..58ab817c6faf 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -2410,4 +2410,11 @@ public abstract class Window { public boolean isCloseOnSwipeEnabled() { return mCloseOnSwipeEnabled; } + + /** + * @return The {@link WindowInsetsController} associated with this window + * @see View#getWindowInsetsController() + * @hide pending unhide + */ + public abstract @NonNull WindowInsetsController getInsetsController(); } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index a8debbd623f5..572d33103cf4 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -18,13 +18,17 @@ package android.view; import android.annotation.NonNull; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.graphics.Insets; import android.graphics.Rect; +import android.view.inputmethod.InputMethod; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -807,4 +811,69 @@ public final class WindowInsets { mIsRound, mAlwaysConsumeNavBar, mDisplayCutout); } } + + /** + * Class that defines different types of sources causing window insets. + * @hide pending unhide + */ + public static final class Type { + + static final int TOP_BAR = 0x1; + static final int IME = 0x2; + static final int SIDE_BARS = 0x4; + static final int WINDOW_DECOR = 0x8; + + private Type() { + } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR }) + public @interface InsetType { + } + + /** + * @return An inset type representing the top bar of a window, which can be the status + * bar on handheld-like devices as well as a caption bar. + */ + public static @InsetType int topBar() { + return TOP_BAR; + } + + /** + * @return An inset type representing the window of an {@link InputMethod}. + */ + public static @InsetType int ime() { + return IME; + } + + /** + * @return An inset type representing any system bars that are not {@link #topBar()}. + */ + public static @InsetType int sideBars() { + return SIDE_BARS; + } + + /** + * @return An inset type representing decor that is being app-controlled. + */ + public static @InsetType int windowDecor() { + return WINDOW_DECOR; + } + + /** + * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but + * not {@link #ime()}. + */ + public static @InsetType int systemBars() { + return TOP_BAR | SIDE_BARS; + } + + /** + * @return All inset types combined. + */ + public static @InsetType int all() { + return 0xFFFFFFFF; + } + } } diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java new file mode 100644 index 000000000000..7be5f2e7a0b0 --- /dev/null +++ b/core/java/android/view/WindowInsetsController.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.view.WindowInsets.Type.InsetType; + +/** + * Interface to control windows that generate insets. + * + * TODO Needs more information and examples once the API is more baked. + * @hide pending unhide + */ +public interface WindowInsetsController { + + /** + * Makes a set of windows that cause insets appear on screen. + * <p> + * Note that if the window currently doesn't have control over a certain type, it will apply the + * change as soon as the window gains control. The app can listen to the event by observing + * {@link View#onApplyWindowInsets} and checking visibility with "TODO at method" in + * {@link WindowInsets}. + * + * @param types A bitmask of {@link WindowInsets.Type.InsetType} specifying what windows the app + * would like to make appear on screen. + */ + void show(@InsetType int types); + + /** + * Makes a set of windows causing insets disappear. + * <p> + * Note that if the window currently doesn't have control over a certain type, it will apply the + * change as soon as the window gains control. The app can listen to the event by observing + * {@link View#onApplyWindowInsets} and checking visibility with "TODO at method" in + * {@link WindowInsets}. + * + * @param types A bitmask of {@link WindowInsets.Type.InsetType} specifying what windows the app + * would like to make disappear. + */ + void hide(@InsetType int types); +} diff --git a/core/java/android/view/inspector/ChildTraverser.java b/core/java/android/view/inspector/ChildTraverser.java deleted file mode 100644 index b775de503d98..000000000000 --- a/core/java/android/view/inspector/ChildTraverser.java +++ /dev/null @@ -1,46 +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 android.view.inspector; - -import android.annotation.NonNull; - -/** - * Interface for visiting all the child nodes of an inspectable object. - * - * Inspectable objects may return a collection of children as an array, an {@link Iterable} or an - * {@link java.util.Iterator}. This provides a unified API for traversing across all the children - * of an inspectable node. - * - * This interface is consumed by {@link InspectionHelper#traverseChildren(Object, ChildTraverser)} - * and may be implemented as a lambda. - * - * @see InspectionHelper#traverseChildren(Object, ChildTraverser) - * @hide - */ -@FunctionalInterface -public interface ChildTraverser { - /** - * Visit one child object of a parent inspectable object. - * - * The iteration interface will filter null values out before passing them to this method, but - * some child objects may not be inspectable. It is up to the implementor to determine their - * inspectablity and what to do with them. - * - * @param child A child object, guaranteed not to be null. - */ - void traverseChild(@NonNull Object child); -} diff --git a/core/java/android/view/inspector/InspectableChildren.java b/core/java/android/view/inspector/InspectableChildren.java deleted file mode 100644 index de8fa296e8c5..000000000000 --- a/core/java/android/view/inspector/InspectableChildren.java +++ /dev/null @@ -1,46 +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 android.view.inspector; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Marks a getter for an inspectable node's inspectable children. - * - * This annotation can be applied to any getter that returns a collection of objects, either an - * array, an {@link Iterable} or a {@link java.util.Iterator}. The getter may return null, which - * will be treated as an empty collection. Additionally, the inspector will discard any null - * entries in the collection. - * - * By default, this annotation is inherited. At runtime, the inspector introspects on the class - * hierachy and uses the annotated getter from the bottommost class, if different from any - * annoated getters of the parent class. If a class inherits from a parent class with an annotated - * getter, but does not include this annotation, the child class will be traversed using the - * getter annotated on the parent. This holds true even if the child class overrides the getter. - * - * @see InspectionHelper#traverseChildren(Object, ChildTraverser) - * @see InspectionHelper#hasChildTraversal() - * @hide - */ -@Target({METHOD}) -@Retention(SOURCE) -public @interface InspectableChildren { -} diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java index 716409c9af3a..ea94ad4c5df8 100644 --- a/core/java/android/view/inspector/InspectableNodeName.java +++ b/core/java/android/view/inspector/InspectableNodeName.java @@ -34,7 +34,7 @@ import java.lang.annotation.Target; * This annotation does not inherit. If a class extends an annotated parent class, but does not * annotate itself, its node name will be inferred from its Java name. * - * @see InspectionHelper#getNodeName() + * @see InspectionCompanion#getNodeName() * @hide */ @Target({TYPE}) diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java index b0fd5032ba56..5b95715681fc 100644 --- a/core/java/android/view/inspector/InspectableProperty.java +++ b/core/java/android/view/inspector/InspectableProperty.java @@ -17,8 +17,11 @@ package android.view.inspector; import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.content.res.ResourceId; + import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -31,8 +34,8 @@ import java.lang.annotation.Target; * but on a different getter, the inspector will use the child's getter when inspecting instances * of the child, and the parent's otherwise. * - * @see InspectionHelper#mapProperties(PropertyMapper) - * @see InspectionHelper#readProperties(Object, PropertyReader) + * @see InspectionCompanion#mapProperties(PropertyMapper) + * @see InspectionCompanion#readProperties(Object, PropertyReader) * @hide */ @Target({METHOD}) @@ -46,5 +49,171 @@ public @interface InspectableProperty { * * @return The name of the property. */ - String value() default ""; + String name() default ""; + + /** + * If the property is inflated from XML, the resource ID of its XML attribute. + * + * If left as {ID_NULL}, and {@link #hasAttributeId()} is true, the attribute ID will be + * inferred from {@link #name()}. + * + * @return The attribute ID of the property or {@link ResourceId#ID_NULL} + */ + int attributeId() default ResourceId.ID_NULL; + + /** + * If this property has an attribute ID. + * + * Set to false if the annotated property does not have an attribute ID, that is, it is not + * inflated from an XML attribute. This will prevent the automatic inference of the attribute + * ID if {@link #attributeId()} is set to {@link ResourceId#ID_NULL}. + * + * @return Whether to infer an attribute ID if not supplied + */ + boolean hasAttributeId() default true; + + /** + * Specify how to interpret a value type packed into a primitive integer. + * + * @return A {@link ValueType} + */ + ValueType valueType() default ValueType.INFERRED; + + /** + * For enumerations packed into primitive {int} properties, map the values to string names. + * + * Note that {@link #enumMapping()} cannot be used simultaneously with {@link #flagMapping()}. + * + * @return An array of {@link EnumMap}, empty if not applicable + * @see android.annotation.IntDef + * @see IntEnumMapping + */ + EnumMap[] enumMapping() default {}; + + /** + * For flags packed into primitive {int} properties, model the string names of the flags. + * + * Note that {@link #flagMapping()} cannot be used simultaneously with {@link #enumMapping()}. + * + * @return An array of {@link FlagMap}, empty if not applicable + * @see android.annotation.IntDef + * @see IntFlagMapping + */ + FlagMap[] flagMapping() default {}; + + + /** + * One entry in an enumeration packed into a primitive {int}. + * + * @see IntEnumMapping + * @hide + */ + @Target({TYPE}) + @Retention(SOURCE) + @interface EnumMap { + /** + * The string name of this enumeration value. + * + * @return A string name + */ + String name(); + + /** + * The integer value of this enumeration value. + * + * @return An integer value + */ + int value(); + } + + /** + * One flag value of many that may be packed into a primitive {int}. + * + * @see IntFlagMapping + * @hide + */ + @Target({TYPE}) + @Retention(SOURCE) + @interface FlagMap { + /** + * The string name of this flag. + * + * @return A string name + */ + String name(); + + /** + * A target value that the property's value must equal after masking. + * + * If a mask is not supplied (i.e., {@link #mask()} is 0), the target will be reused as the + * mask. This handles the common case where no flags mutually exclude each other. + * + * @return The target value to compare against + */ + int target(); + + /** + * A mask that the property will be bitwise anded with before comparing to the target. + * + * If set to 0 (the default), the value of {@link #target()} will be used as a mask. Zero + * was chosen as the default since bitwise and with zero is always zero. + * + * @return A mask, or 0 to use the target as a mask + */ + int mask() default 0; + } + + /** + * The type of value packed into a primitive {int}. + * + * @hide + */ + enum ValueType { + /** + * No special handling, property is considered to be a numeric value. + */ + NONE, + + /** + * The default the annotation processor infers the value type from context. + */ + INFERRED, + + /** + * Value packs an enumeration. + * + * This is inferred if {@link #enumMapping()} is specified. + * + * @see EnumMap + */ + INT_ENUM, + + /** + * Value packs flags, of which many may be enabled at once. + * + * This is inferred if {@link #flagMapping()} is specified. + * + * @see FlagMap + */ + INT_FLAG, + + /** + * Value packs color information. + * + * This is inferred from {@link android.annotation.ColorInt}, or + * {@link android.annotation.ColorLong} on the getter method. + * + * @see android.graphics.Color + */ + COLOR, + + /** + * Value packs gravity information. + * + * This type is not inferred, and is non-trivial to represent using {@link FlagMap}. + * + * @see android.view.Gravity + */ + GRAVITY + } } diff --git a/core/java/android/view/inspector/InspectionCompanion.java b/core/java/android/view/inspector/InspectionCompanion.java new file mode 100644 index 000000000000..62d769b6d963 --- /dev/null +++ b/core/java/android/view/inspector/InspectionCompanion.java @@ -0,0 +1,95 @@ +/* + * 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 android.view.inspector; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * An interface for companion objects used to inspect views. + * + * Inspection companions only need to handle the properties and node name of the specific class + * they are defined for, not anything from a parent class. At runtime, the inspector instantiates + * one instance of each inspection companion, and handles visiting them in the correct inheritance + * order for each type it inspects. + * + * Properties are read from the top of the type tree to the bottom, so that classes that override + * a property in their parent class can overwrite it in the reader. In general, properties will + * cleanly inherit through their getters, and the inspector runtime will read the properties of a + * parent class via the parent's inspection companion, and the child companion will only read + * properties added or changed since the parent was defined. + * + * Only one child traversal is considered for each class. If a descendant class defines a + * different child traversal than its parent, only the bottom traversal is used. If a class does + * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's + * traversal will be used. + * + * @param <T> The type of inspectable this is the companion to + */ +public interface InspectionCompanion<T> { + /** + * Map the string names of the properties this companion knows about to integer IDs. + * + * Each companion is responsible for storing the integer IDs of all its properties. This is the + * only method that is allowed to modify the stored IDs. + * + * Calling {@link #readProperties(T, PropertyReader)} before calling this results in + * undefined behavior. + * + * @param propertyMapper A {@link PropertyMapper} maps string names to IDs. + */ + void mapProperties(@NonNull PropertyMapper propertyMapper); + + /** + * Read the values of an instance of this companion's type into a {@link PropertyReader}. + * + * This method needs to return the property IDs stored by + * {@link #mapProperties(PropertyMapper)}. Implementations should track if their properties + * have been mapped and throw a {@link UninitializedPropertyMapException} if this method is + * called before {mapProperties}. + * + * @param inspectable A object of type {T} to read the properties of. + * @param propertyReader An object which receives the property IDs and values. + */ + void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader); + + /** + * Get an optional name to display to developers for inspection nodes of this companion's type. + * + * The default implementation returns null, which will cause the runtime to use the class's + * simple name as defined by {@link Class#getSimpleName()} as the node name. + * + * If the type of this companion is inflated from XML, this method should be overridden to + * return the string used as the tag name for this type in XML. + * + * @return A string to use as the node name, or null to use the simple class name fallback. + */ + @Nullable + default String getNodeName() { + return null; + } + + /** + * Thrown by {@link #readProperties(Object, PropertyReader)} if called before + * {@link #mapProperties(PropertyMapper)}. + */ + class UninitializedPropertyMapException extends RuntimeException { + public UninitializedPropertyMapException() { + super("Unable to read properties of an inspectable before mapping their IDs."); + } + } +} diff --git a/core/java/android/view/inspector/InspectionHelper.java b/core/java/android/view/inspector/InspectionHelper.java deleted file mode 100644 index 27a97040926c..000000000000 --- a/core/java/android/view/inspector/InspectionHelper.java +++ /dev/null @@ -1,145 +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 android.view.inspector; - -import android.annotation.NonNull; -import android.annotation.Nullable; - -/** - * An interface for companion objects used to inspect views. - * - * Inspection helpers only need to handle the properties, name and traversal of the specific class - * they are defined for, not anything from a parent class. At runtime, the inspector instantiates - * one instance of each inspection helper, and handles visiting them in the correct inheritance - * order for each type it inspects. - * - * Properties are read from the top of the type tree to the bottom, so that classes that override - * a property in their parent class can overwrite it in the reader. In general, properties will - * cleanly inherit through their getters, and the inspector runtime will read the properties of a - * parent class via the parent's inspection helper, and the child helper will only read properties - * added or changed since the parent was defined. - * - * Only one child traversal is considered for each class. If a descendant class defines a - * different child traversal than its parent, only the bottom traversal is used. If a class does - * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's - * traversal will be used. - * - * @param <T> The type of inspectable this helper operates on - * @hide - */ -public interface InspectionHelper<T> { - /** - * Map the string names of the properties this helper knows about to integer IDs. - * - * Each helper is responsible for storing the integer IDs of all its properties. This is the - * only method that is allowed to modify the stored IDs. - * - * Calling {@link #readProperties(T, PropertyReader)} before calling this results in - * undefined behavior. - * - * @param propertyMapper A {@link PropertyMapper} or lambda which maps string names to IDs. - */ - void mapProperties(@NonNull PropertyMapper propertyMapper); - - /** - * Read the values of an instance of this helper's type into a {@link PropertyReader}. - * - * This method needs to return the property IDs stored by - * {@link #mapProperties(PropertyMapper)}. Implementations should track if their properties - * have been mapped and throw a {@link UninitializedPropertyMapException} if this method is - * called before {mapProperties}. - * - * @param inspectable A object of type {@link T} to read the properties of. - * @param propertyReader An object which receives the property IDs and values. - */ - void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader); - - /** - * Query if this inspectable type can potentially have child nodes. - * - * E.g.: any descendant of {@link android.view.ViewGroup} can have child nodes, but a leaf - * view like {@link android.widget.ImageView} may not. - * - * The default implementation always returns false. If an implementing class overrides this, it - * should also define {@link #traverseChildren(T, ChildTraverser)}. - * - * @return True if this inspectable type can potentially have child nodes, false otherwise. - */ - default boolean hasChildTraversal() { - return false; - } - - /** - * Traverse the child nodes of an instance of this helper's type into a {@link ChildTraverser}. - * - * This provides the ability to traverse over a variety of collection APIs (e.g.: arrays, - * {@link Iterable}, or {@link java.util.Iterator}) in a uniform fashion. The traversal must be - * in the order defined by this helper's type. If the getter returns null, the helper must - * treat it as an empty collection. - * - * The default implementation throws a {@link NoChildTraversalException}. If - * {@link #hasChildTraversal()} returns is overriden to return true, it is expected that the - * implementing class will also override this method and provide a traversal. - * - * @param inspectable An object of type {@link T} to traverse the child nodes of. - * @param childTraverser A {@link ChildTraverser} or lamba to receive the children in order. - * @throws NoChildTraversalException If there is no defined child traversal - */ - default void traverseChildren( - @NonNull T inspectable, - @SuppressWarnings("unused") @NonNull ChildTraverser childTraverser) { - throw new NoChildTraversalException(inspectable.getClass()); - } - - /** - * Get an optional name to display to developers for inspection nodes of this helper's type. - * - * The default implementation returns null, which will cause the runtime to use the class's - * simple name as defined by {@link Class#getSimpleName()} as the node name. - * - * If the type of this helper is inflated from XML, this method should be overridden to return - * the string used as the tag name for this type in XML. - * - * @return A string to use as the node name, or null to use the simple class name fallback. - */ - @Nullable - default String getNodeName() { - return null; - } - - /** - * Thrown by {@link #readProperties(Object, PropertyReader)} if called before - * {@link #mapProperties(PropertyMapper)}. - */ - class UninitializedPropertyMapException extends RuntimeException { - public UninitializedPropertyMapException() { - super("Unable to read properties of an inspectable before mapping their IDs."); - } - } - - /** - * Thrown by {@link #traverseChildren(Object, ChildTraverser)} if no child traversal exists. - */ - class NoChildTraversalException extends RuntimeException { - public NoChildTraversalException(Class cls) { - super(String.format( - "Class %s does not have a defined child traversal. Cannot traverse children.", - cls.getCanonicalName() - )); - } - } -} diff --git a/core/java/android/view/inspector/IntEnumMapping.java b/core/java/android/view/inspector/IntEnumMapping.java new file mode 100644 index 000000000000..69f6dce94a81 --- /dev/null +++ b/core/java/android/view/inspector/IntEnumMapping.java @@ -0,0 +1,118 @@ +/* + * 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 android.view.inspector; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import java.util.ArrayList; + +/** + * Maps the values of an {int} property to string names for properties that encode enumerations. + * + * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper} + * for enumerations packed into primitive {int} properties. + * + * This class is immutable, and must be constructed by a {@link Builder}. + * + * @see PropertyMapper#mapIntEnum(String, int, IntEnumMapping) + */ +public final class IntEnumMapping { + private final Value[] mValues; + + /** + * Map from a property value to a string name. + * + * @param value The value of a property + * @return The name of the enumeration value, null if the value is not mapped + */ + @Nullable + public String nameOf(int value) { + for (Value valueTuple : mValues) { + if (valueTuple.mValue == value) { + return valueTuple.mName; + } + } + + return null; + } + + /** + * Create a new instance from a builder. + * + * This constructor is private, use {@link Builder#build()} instead. + * + * @param builder A builder to create from + */ + private IntEnumMapping(Builder builder) { + mValues = builder.mValues.toArray(new Value[builder.mValues.size()]); + } + + /** + * A builder for {@link IntEnumMapping} + */ + public static final class Builder { + private final ArrayList<Value> mValues; + + public Builder() { + mValues = new ArrayList<>(); + } + + /** + * Add a new entry to this mapping. + * + * @param name Name of the enumeration value + * @param value Int value of the enumeration value + * @return This builder + */ + @NonNull + public Builder addValue(@NonNull String name, int value) { + mValues.add(new Value(name, value)); + return this; + } + + /** + * Clear the builder, allowing for recycling. + */ + public void clear() { + mValues.clear(); + } + + /** + * Build a new {@link IntEnumMapping} from this builder + * + * @return A new mapping + */ + @NonNull + public IntEnumMapping build() { + return new IntEnumMapping(this); + } + } + + /** + * Inner class that holds the name and value of an enumeration value. + */ + private static final class Value { + @NonNull private final String mName; + private final int mValue; + + private Value(@NonNull String name, int value) { + mName = name; + mValue = value; + } + } +} diff --git a/core/java/android/view/inspector/IntFlagMapping.java b/core/java/android/view/inspector/IntFlagMapping.java new file mode 100644 index 000000000000..dcb87e18ae5e --- /dev/null +++ b/core/java/android/view/inspector/IntFlagMapping.java @@ -0,0 +1,155 @@ +/* + * 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 android.view.inspector; + +import android.annotation.NonNull; + +import java.util.ArrayList; + +/** + * Maps the values of an {int} property to arrays of string for properties that encode flags. + * + * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper} + * for flag values packed into primitive {int} properties. + * + * Each flag has a + * + * This class is immutable, and must be constructed by a {@link Builder}. + * + * @see PropertyMapper#mapIntFlag(String, int, IntFlagMapping) + */ +public final class IntFlagMapping { + private final Flag[] mFlags; + + /** + * Get an array of the names of enabled flags for a given property value. + * + * @param value The value of the property + * @return The names of the enabled flags + */ + @NonNull + public String[] namesOf(int value) { + ArrayList<String> enabledFlagNames = new ArrayList<>(mFlags.length); + + for (Flag flag : mFlags) { + if (flag.isEnabledFor(value)) { + enabledFlagNames.add(flag.mName); + } + } + + return enabledFlagNames.toArray(new String[enabledFlagNames.size()]); + } + + /** + * Create a new instance from a builder. + * + * This constructor is private, use {@link Builder#build()} instead. + * + * @param builder A builder to create from + */ + private IntFlagMapping(Builder builder) { + mFlags = builder.mFlags.toArray(new Flag[builder.mFlags.size()]); + } + + /** + * A builder for {@link IntFlagMapping}. + */ + public static final class Builder { + private ArrayList<Flag> mFlags; + + public Builder() { + mFlags = new ArrayList<>(); + } + + /** + * Add a new flag without a mask. + * + * The target value will be used as a mask, to handle the common case where flag values + * are not mutually exclusive. The flag will be considered enabled for a property value if + * the result of bitwise anding the target and the value equals the target, that is: + * {(value & target) == target}. + * + * @param name The name of the flag + * @param target The value to compare against + * @return This builder + */ + @NonNull + public Builder addFlag(@NonNull String name, int target) { + mFlags.add(new Flag(name, target, target)); + return this; + } + + /** + * Add a new flag with a mask. + * + * The flag will be considered enabled for a property value if the result of bitwise anding + * the value and the mask equals the target, that is: {(value & mask) == target}. + * + * @param name The name of the flag + * @param target The value to compare against + * @param mask A bit mask + * @return This builder + */ + @NonNull + public Builder addFlag(@NonNull String name, int target, int mask) { + mFlags.add(new Flag(name, target, mask)); + return this; + } + + /** + * Clear the builder, allowing for recycling. + */ + public void clear() { + mFlags.clear(); + } + + /** + * Build a new {@link IntFlagMapping} from this builder. + * + * @return A new mapping + */ + @NonNull + public IntFlagMapping build() { + return new IntFlagMapping(this); + } + } + + /** + * Inner class that holds the name, mask, and target value of a flag + */ + private static final class Flag { + @NonNull private final String mName; + private final int mTarget; + private final int mMask; + + private Flag(@NonNull String name, int target, int mask) { + mName = name; + mTarget = target; + mMask = mask; + } + + /** + * Compare the supplied property value against the mask and taget. + * + * @param value The value to check + * @return True if this flag is enabled + */ + private boolean isEnabledFor(int value) { + return (value & mMask) == mTarget; + } + } +} diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java index 35550bd45b30..5fb291b34219 100644 --- a/core/java/android/view/inspector/PropertyMapper.java +++ b/core/java/android/view/inspector/PropertyMapper.java @@ -16,102 +16,160 @@ package android.view.inspector; +import android.annotation.AttrRes; import android.annotation.NonNull; /** * An interface for mapping the string names of inspectable properties to integer identifiers. * - * This interface is consumed by {@link InspectionHelper#mapProperties(PropertyMapper)}. + * This interface is consumed by {@link InspectionCompanion#mapProperties(PropertyMapper)}. * * Mapping properties to IDs enables quick comparisons against shadow copies of inspectable * objects without performing a large number of string comparisons. * - * @see InspectionHelper#mapProperties(PropertyMapper) - * @hide + * @see InspectionCompanion#mapProperties(PropertyMapper) */ public interface PropertyMapper { /** * Map a string name to an integer ID for a primitive boolean property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapBoolean(@NonNull String name); + int mapBoolean(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive byte property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapByte(@NonNull String name); + int mapByte(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive char property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapChar(@NonNull String name); + int mapChar(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive double property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapDouble(@NonNull String name); + int mapDouble(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive float property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapFloat(@NonNull String name); + int mapFloat(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive int property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapInt(@NonNull String name); + int mapInt(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive long property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapLong(@NonNull String name); + int mapLong(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for a primitive short property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapShort(@NonNull String name); + int mapShort(@NonNull String name, @AttrRes int attributeId); /** * Map a string name to an integer ID for an object property. * * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property * @return An integer ID for the property * @throws PropertyConflictException If the property name is already mapped as another type. */ - int mapObject(@NonNull String name); + int mapObject(@NonNull String name, @AttrRes int attributeId); /** + * Map a string name to an integer ID for a color property. + * + * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property + * @return An integer ID for the property + * @throws PropertyConflictException If the property name is already mapped as another type. + * @see android.graphics.Color + */ + int mapColor(@NonNull String name, @AttrRes int attributeId); + + /** + * Map a string name to an integer ID for a gravity property. + * + * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property + * @return An integer ID for the property + * @throws PropertyConflictException If the property name is already mapped as another type. + * @see android.view.Gravity + */ + int mapGravity(@NonNull String name, @AttrRes int attributeId); + + /** + * Map a string name to an integer ID for an enumeration packed into an int property. + * + * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property + * @param mapping A mapping from int to String + * @return An integer ID for the property + * @throws PropertyConflictException If the property name is already mapped as another type. + */ + int mapIntEnum( + @NonNull String name, + @AttrRes int attributeId, + @NonNull IntEnumMapping mapping); + + /** + * Map a string name to an integer ID for a flag set packed into an int property. + * + * @param name The name of the property + * @param attributeId If the property is from an XML attribute, the resource ID of the property + * @param mapping A mapping from int to an array of strings + * @return An integer ID for the property + * @throws PropertyConflictException If the property name is already mapped as another type. + */ + int mapIntFlag( + @NonNull String name, + @AttrRes int attributeId, + @NonNull IntFlagMapping mapping); + /** * Thrown from a map method if a property name is already mapped as different type. */ class PropertyConflictException extends RuntimeException { diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java index df81c102dbad..fd83e8df6c3a 100644 --- a/core/java/android/view/inspector/PropertyReader.java +++ b/core/java/android/view/inspector/PropertyReader.java @@ -16,19 +16,21 @@ package android.view.inspector; +import android.annotation.ColorInt; +import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Color; /** * An interface for reading the properties of an inspectable object. * - * Used as the parameter for {@link InspectionHelper#readProperties(Object, PropertyReader)}. + * Used as the parameter for {@link InspectionCompanion#readProperties(Object, PropertyReader)}. * It has separate methods for all primitive types to avoid autoboxing overhead if a concrete * implementation is able to work with primitives. Implementations should be prepared to accept * {null} as the value of {@link PropertyReader#readObject(int, Object)}. * - * @see InspectionHelper#readProperties(Object, PropertyReader) - * @hide + * @see InspectionCompanion#readProperties(Object, PropertyReader) */ public interface PropertyReader { /** @@ -115,6 +117,60 @@ public interface PropertyReader { void readObject(int id, @Nullable Object value); /** + * Read a color packed into a {@link ColorInt} as a property. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as a color + */ + void readColor(int id, @ColorInt int value); + + /** + * Read a color packed into a {@link ColorLong} as a property. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as a color + */ + void readColor(int id, @ColorLong long value); + + /** + * Read a {@link Color} object as a property. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as a color + */ + void readColor(int id, @Nullable Color value); + + /** + * Read {@link android.view.Gravity} packed into an primitive {int}. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as a gravity property + */ + void readGravity(int id, int value); + + /** + * Read an enumeration packed into a primitive {int}. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as an object + */ + void readIntEnum(int id, int value); + + /** + * Read a flag packed into a primitive {int}. + * + * @param id Identifier of the property from a {@link PropertyMapper} + * @param value Value of the property + * @throws PropertyTypeMismatchException If the property ID is not mapped as an object + */ + void readIntFlag(int id, int value); + + /** * Thrown if a client calls a typed read method for a property of a different type. */ class PropertyTypeMismatchException extends RuntimeException { diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java index befcb55b1f73..f63628105cba 100644 --- a/core/java/android/view/intelligence/ContentCaptureEvent.java +++ b/core/java/android/view/intelligence/ContentCaptureEvent.java @@ -163,7 +163,7 @@ public final class ContentCaptureEvent implements Parcelable { * Gets optional flags associated with the event. * * @return either {@code 0} or - * {@link android.view.intelligence.IntelligenceManager#FLAG_USER_INPUT}. + * {@link android.view.intelligence.ContentCaptureManager#FLAG_USER_INPUT}. */ public int getFlags() { return mFlags; diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/ContentCaptureManager.java index 2f3b4ef56aa1..45518d5e5943 100644 --- a/core/java/android/view/intelligence/IntelligenceManager.java +++ b/core/java/android/view/intelligence/ContentCaptureManager.java @@ -23,7 +23,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.ComponentName; import android.content.Context; @@ -44,13 +43,8 @@ import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.List; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -/** - * TODO(b/111276913): add javadocs / implement - */ /* * NOTE: all methods in this class should return right away, or do the real work in a handler * thread. @@ -58,10 +52,13 @@ import java.util.concurrent.atomic.AtomicBoolean; * Hence, the only field that must be thread-safe is mEnabled, which is called at the beginning * of every method. */ -@SystemService(Context.INTELLIGENCE_MANAGER_SERVICE) -public final class IntelligenceManager { +/** + * TODO(b/111276913): add javadocs / implement + */ +@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE) +public final class ContentCaptureManager { - private static final String TAG = "IntelligenceManager"; + private static final String TAG = "ContentCaptureManager"; // TODO(b/111276913): define a way to dynamically set them(for example, using settings?) private static final boolean VERBOSE = false; @@ -140,7 +137,7 @@ public final class IntelligenceManager { private final Handler mHandler; /** @hide */ - public IntelligenceManager(@NonNull Context context, @Nullable IIntelligenceManager service) { + public ContentCaptureManager(@NonNull Context context, @Nullable IIntelligenceManager service) { mContext = Preconditions.checkNotNull(context, "context cannot be null"); if (VERBOSE) { Log.v(TAG, "Constructor for " + context.getPackageName()); @@ -156,7 +153,7 @@ public final class IntelligenceManager { public void onActivityCreated(@NonNull IBinder token, @NonNull ComponentName componentName) { if (!isContentCaptureEnabled()) return; - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleStartSession, this, + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleStartSession, this, token, componentName)); } @@ -192,7 +189,7 @@ public final class IntelligenceManager { } } - private void handleSessionStarted(int resultCode) { + private void handleSessionStarted(int resultCode) { mState = resultCode; mDisabled.set(mState == STATE_DISABLED); if (VERBOSE) { @@ -264,7 +261,7 @@ public final class IntelligenceManager { Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugName() + ": " + ContentCaptureEvent.getTypeAsString(type)); } - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleSendEvent, this, new ContentCaptureEvent(type), /* forceFlush= */ true)); } @@ -279,7 +276,7 @@ public final class IntelligenceManager { + ", mId=" + mId); } - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleFinishSession, this)); + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleFinishSession, this)); } private void handleFinishSession() { @@ -328,7 +325,7 @@ public final class IntelligenceManager { throw new IllegalArgumentException("Invalid node class: " + node.getClass()); } - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleSendEvent, this, new ContentCaptureEvent(TYPE_VIEW_APPEARED) .setViewNode(((ViewNode.ViewStructureImpl) node).mNode), /* forceFlush= */ false)); @@ -346,7 +343,7 @@ public final class IntelligenceManager { Preconditions.checkNotNull(id); if (!isContentCaptureEnabled()) return; - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleSendEvent, this, new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id), /* forceFlush= */ false)); } @@ -365,7 +362,7 @@ public final class IntelligenceManager { if (!isContentCaptureEnabled()) return; - mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, + mHandler.sendMessage(obtainMessage(ContentCaptureManager::handleSendEvent, this, new ContentCaptureEvent(TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id) .setText(text), /* forceFlush= */ false)); } @@ -396,11 +393,11 @@ public final class IntelligenceManager { } /** - * Returns the component name of the {@code android.service.intelligence.IntelligenceService} - * that is enabled for the current user. + * Returns the component name of the system service that is consuming the captured events for + * the current user. */ @Nullable - public ComponentName getIntelligenceServiceComponentName() { + public ComponentName getServiceComponentName() { //TODO(b/111276913): implement return null; } @@ -422,106 +419,6 @@ public final class IntelligenceManager { //TODO(b/111276913): implement } - /** - * Called by the the service {@link android.service.intelligence.IntelligenceService} - * to define whether content capture should be enabled for activities with such - * {@link android.content.ComponentName}. - * - * <p>Useful to blacklist a particular activity. - * - * @throws UnsupportedOperationException if not called by the UID that owns the - * {@link android.service.intelligence.IntelligenceService} associated with the - * current user. - * - * @hide - */ - @SystemApi - public void setActivityContentCaptureEnabled(@NonNull ComponentName activity, - boolean enabled) { - //TODO(b/111276913): implement - } - - /** - * Called by the the service {@link android.service.intelligence.IntelligenceService} - * to explicitly limit content capture to the given packages and activities. - * - * <p>When the whitelist is set, it overrides the values passed to - * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)} - * and {@link #setPackageContentCaptureEnabled(String, boolean)}. - * - * <p>To reset the whitelist, call it passing {@code null} to both arguments. - * - * <p>Useful when the service wants to restrict content capture to a category of apps, like - * chat apps. For example, if the service wants to support view captures on all activities of - * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2}, - * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"), - * Arrays.asList(new ComponentName("ChatApp2", "act1"), - * new ComponentName("ChatApp2", "act2")));} - * - * @throws UnsupportedOperationException if not called by the UID that owns the - * {@link android.service.intelligence.IntelligenceService} associated with the - * current user. - * - * @hide - */ - @SystemApi - public void setContentCaptureWhitelist(@Nullable List<String> packages, - @Nullable List<ComponentName> activities) { - //TODO(b/111276913): implement - } - - /** - * Called by the the service {@link android.service.intelligence.IntelligenceService} - * to define 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. - * - * @throws UnsupportedOperationException if not called by the UID that owns the - * {@link android.service.intelligence.IntelligenceService} associated with the - * current user. - * - * @hide - */ - @SystemApi - public void setPackageContentCaptureEnabled(@NonNull String packageName, boolean enabled) { - //TODO(b/111276913): implement - } - - /** - * Gets the activities where content capture was disabled by - * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}. - * - * @throws UnsupportedOperationException if not called by the UID that owns the - * {@link android.service.intelligence.IntelligenceService} associated with the - * current user. - * - * @hide - */ - @SystemApi - @NonNull - public Set<ComponentName> getContentCaptureDisabledActivities() { - //TODO(b/111276913): implement - return null; - } - - /** - * Gets the apps where content capture was disabled by - * {@link #setPackageContentCaptureEnabled(String, boolean)}. - * - * @throws UnsupportedOperationException if not called by the UID that owns the - * {@link android.service.intelligence.IntelligenceService} associated with the - * current user. - * - * @hide - */ - @SystemApi - @NonNull - public Set<String> getContentCaptureDisabledPackages() { - //TODO(b/111276913): implement - return null; - } - /** @hide */ public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.println("IntelligenceManager"); @@ -547,7 +444,7 @@ public final class IntelligenceManager { } if (mEvents != null) { final int numberEvents = mEvents.size(); - pw.print(prefix2); pw.print("batched events: "); pw.print(numberEvents); + pw.print(prefix2); pw.print("buffered events: "); pw.print(numberEvents); pw.print('/'); pw.println(MAX_BUFFER_SIZE); if (VERBOSE && numberEvents > 0) { final String prefix3 = prefix2 + " "; diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl index 7518ff53b638..882fb2674bf1 100644 --- a/core/java/android/view/intelligence/IIntelligenceManager.aidl +++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl @@ -28,6 +28,7 @@ import java.util.List; /** * {@hide} */ +// TODO(b/111276913): rename once the final name is defined oneway interface IIntelligenceManager { /** * Starts a session, sending the "remote" sessionId to the receiver. diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7b39efed0c3a..3b916d16b2b4 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -18,6 +18,8 @@ package android.widget; import android.annotation.ColorInt; import android.annotation.DimenRes; +import android.annotation.IntDef; +import android.annotation.LayoutRes; import android.annotation.NonNull; import android.annotation.StyleRes; import android.annotation.UnsupportedAppUsage; @@ -131,6 +133,12 @@ public class RemoteViews implements Parcelable, Filter { static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId"; /** + * The intent extra that contains {@code true} if inflating as dak text theme. + * @hide + */ + static final String EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND = "remoteAdapterOnLightBackground"; + + /** * The intent extra that contains the bounds for all shared elements. */ public static final String EXTRA_SHARED_ELEMENT_BOUNDS = @@ -163,6 +171,36 @@ public class RemoteViews implements Parcelable, Filter { private static final int SET_RIPPLE_DRAWABLE_COLOR_TAG = 21; private static final int SET_INT_TAG_TAG = 22; + /** @hide **/ + @IntDef(flag = true, value = { + FLAG_REAPPLY_DISALLOWED, + FLAG_WIDGET_IS_COLLECTION_CHILD, + FLAG_USE_LIGHT_BACKGROUND_LAYOUT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ApplyFlags {} + /** + * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify + * the layout in a way that isn't recoverable, since views are being removed. + * @hide + */ + public static final int FLAG_REAPPLY_DISALLOWED = 1; + /** + * This flag indicates whether this RemoteViews object is being created from a + * RemoteViewsService for use as a child of a widget collection. This flag is used + * to determine whether or not certain features are available, in particular, + * setting on click extras and setting on click pending intents. The former is enabled, + * and the latter disabled when this flag is true. + * @hide + */ + public static final int FLAG_WIDGET_IS_COLLECTION_CHILD = 2; + /** + * When this flag is set, the views is inflated with {@link #mLightBackgroundLayoutId} instead + * of {link #mLayoutId} + * @hide + */ + public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4; + /** * Application that hosts the remote views. * @@ -178,6 +216,11 @@ public class RemoteViews implements Parcelable, Filter { private final int mLayoutId; /** + * The resource ID of the layout file in dark text mode. (Added to the parcel) + */ + private int mLightBackgroundLayoutId = 0; + + /** * An array of actions to perform on the view tree once it has been * inflated */ @@ -197,12 +240,6 @@ public class RemoteViews implements Parcelable, Filter { private boolean mIsRoot = true; /** - * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify - * the layout in a way that isn't recoverable, since views are being removed. - */ - private boolean mReapplyDisallowed; - - /** * Constants to whether or not this RemoteViews is composed of a landscape and portrait * RemoteViews. */ @@ -218,14 +255,8 @@ public class RemoteViews implements Parcelable, Filter { @UnsupportedAppUsage private RemoteViews mPortrait = null; - /** - * This flag indicates whether this RemoteViews object is being created from a - * RemoteViewsService for use as a child of a widget collection. This flag is used - * to determine whether or not certain features are available, in particular, - * setting on click extras and setting on click pending intents. The former is enabled, - * and the latter disabled when this flag is true. - */ - private boolean mIsWidgetCollectionChild = false; + @ApplyFlags + private int mApplyFlags = 0; /** Class cookies of the Parcel this instance was read from. */ private final Map<Class, Object> mClassCookies; @@ -289,18 +320,15 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - public void setReapplyDisallowed() { - mReapplyDisallowed = true; + public void addFlags(@ApplyFlags int flags) { + mApplyFlags = mApplyFlags | flags; } /** - * @return Whether it is disallowed to reapply another remoteview with the same layout as this - * view. True if this remoteview has actions that destroyed view tree of the base layout. - * * @hide */ - public boolean isReapplyDisallowed() { - return mReapplyDisallowed; + public boolean hasFlags(@ApplyFlags int flag) { + return (mApplyFlags & flag) == flag; } /** @@ -768,7 +796,10 @@ public class RemoteViews implements Parcelable, Filter { // Embed the AppWidget Id for use in RemoteViewsAdapter when connecting to the intent // RemoteViewsService AppWidgetHostView host = (AppWidgetHostView) rootParent; - intent.putExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, host.getAppWidgetId()); + intent.putExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, host.getAppWidgetId()) + .putExtra(EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND, + hasFlags(FLAG_USE_LIGHT_BACKGROUND_LAYOUT)); + if (target instanceof AbsListView) { AbsListView v = (AbsListView) target; v.setRemoteViewsAdapter(intent, isAsync); @@ -829,7 +860,7 @@ public class RemoteViews implements Parcelable, Filter { // If the view is an AdapterView, setting a PendingIntent on click doesn't make // much sense, do they mean to set a PendingIntent template for the // AdapterView's children? - if (mIsWidgetCollectionChild) { + if (hasFlags(FLAG_WIDGET_IS_COLLECTION_CHILD)) { Log.w(LOG_TAG, "Cannot SetOnClickResponse for collection item " + "(id: " + viewId + ")"); ApplicationInfo appInfo = root.getContext().getApplicationInfo(); @@ -843,7 +874,7 @@ public class RemoteViews implements Parcelable, Filter { } target.setTagInternal(R.id.pending_intent_tag, mResponse.mPendingIntent); } else if (mResponse.mFillIntent != null) { - if (!mIsWidgetCollectionChild) { + if (!hasFlags(FLAG_WIDGET_IS_COLLECTION_CHILD)) { Log.e(LOG_TAG, "The method setOnClickFillInIntent is available " + "only from RemoteViewsFactory (ie. on collection items)."); return; @@ -1545,6 +1576,7 @@ public class RemoteViews implements Parcelable, Filter { viewId = parcel.readInt(); mIndex = parcel.readInt(); mNestedViews = new RemoteViews(parcel, bitmapCache, info, depth, classCookies); + mNestedViews.addFlags(mApplyFlags); } public void writeToParcel(Parcel dest, int flags) { @@ -2190,7 +2222,7 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - public RemoteViews(String packageName, int userId, int layoutId) { + public RemoteViews(String packageName, int userId, @LayoutRes int layoutId) { this(getApplicationInfo(packageName, userId), layoutId); } @@ -2203,7 +2235,7 @@ public class RemoteViews implements Parcelable, Filter { * * @hide */ - protected RemoteViews(ApplicationInfo application, int layoutId) { + protected RemoteViews(ApplicationInfo application, @LayoutRes int layoutId) { mApplication = application; mLayoutId = layoutId; mBitmapCache = new BitmapCache(); @@ -2229,7 +2261,8 @@ public class RemoteViews implements Parcelable, Filter { throw new RuntimeException("Both RemoteViews must share the same package and user"); } mApplication = portrait.mApplication; - mLayoutId = portrait.getLayoutId(); + mLayoutId = portrait.mLayoutId; + mLightBackgroundLayoutId = portrait.mLightBackgroundLayoutId; mLandscape = landscape; mPortrait = portrait; @@ -2250,8 +2283,8 @@ public class RemoteViews implements Parcelable, Filter { mApplication = src.mApplication; mIsRoot = src.mIsRoot; mLayoutId = src.mLayoutId; - mIsWidgetCollectionChild = src.mIsWidgetCollectionChild; - mReapplyDisallowed = src.mReapplyDisallowed; + mLightBackgroundLayoutId = src.mLightBackgroundLayoutId; + mApplyFlags = src.mApplyFlags; mClassCookies = src.mClassCookies; if (src.hasLandscapeAndPortraitLayouts()) { @@ -2309,7 +2342,7 @@ public class RemoteViews implements Parcelable, Filter { mApplication = parcel.readInt() == 0 ? info : ApplicationInfo.CREATOR.createFromParcel(parcel); mLayoutId = parcel.readInt(); - mIsWidgetCollectionChild = parcel.readInt() == 1; + mLightBackgroundLayoutId = parcel.readInt(); readActionsFromParcel(parcel, depth); } else { @@ -2318,9 +2351,10 @@ public class RemoteViews implements Parcelable, Filter { mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication, depth, mClassCookies); mApplication = mPortrait.mApplication; - mLayoutId = mPortrait.getLayoutId(); + mLayoutId = mPortrait.mLayoutId; + mLightBackgroundLayoutId = mPortrait.mLightBackgroundLayoutId; } - mReapplyDisallowed = parcel.readInt() == 0; + mApplyFlags = parcel.readInt(); } private void readActionsFromParcel(Parcel parcel, int depth) { @@ -2409,19 +2443,8 @@ public class RemoteViews implements Parcelable, Filter { * @return the layout id. */ public int getLayoutId() { - return mLayoutId; - } - - /* - * This flag indicates whether this RemoteViews object is being created from a - * RemoteViewsService for use as a child of a widget collection. This flag is used - * to determine whether or not certain features are available, in particular, - * setting on click extras and setting on click pending intents. The former is enabled, - * and the latter disabled when this flag is true. - */ - @UnsupportedAppUsage - void setIsWidgetCollectionChild(boolean isWidgetCollectionChild) { - mIsWidgetCollectionChild = isWidgetCollectionChild; + return hasFlags(FLAG_USE_LIGHT_BACKGROUND_LAYOUT) && (mLightBackgroundLayoutId != 0) + ? mLightBackgroundLayoutId : mLayoutId; } /** @@ -3292,6 +3315,33 @@ public class RemoteViews implements Parcelable, Filter { setInt(viewId, "setLabelFor", labeledId); } + /** + * Provides an alternate layout ID, which can be used to inflate this view. This layout will be + * used by the host when the widgets displayed on a light-background where foreground elements + * and text can safely draw using a dark color without any additional background protection. + */ + public void setLightBackgroundLayoutId(@LayoutRes int layoutId) { + mLightBackgroundLayoutId = layoutId; + } + + /** + * If this view supports dark text versions, creates a copy representing that version, + * otherwise returns itself. + * @hide + */ + public RemoteViews getDarkTextViews() { + if (hasFlags(FLAG_USE_LIGHT_BACKGROUND_LAYOUT)) { + return this; + } + + try { + addFlags(FLAG_USE_LIGHT_BACKGROUND_LAYOUT); + return new RemoteViews(this); + } finally { + mApplyFlags &= ~FLAG_USE_LIGHT_BACKGROUND_LAYOUT; + } + } + private RemoteViews getRemoteViewsToApply(Context context) { if (hasLandscapeAndPortraitLayouts()) { int orientation = context.getResources().getConfiguration().orientation; @@ -3652,7 +3702,7 @@ public class RemoteViews implements Parcelable, Filter { mApplication.writeToParcel(dest, flags); } dest.writeInt(mLayoutId); - dest.writeInt(mIsWidgetCollectionChild ? 1 : 0); + dest.writeInt(mLightBackgroundLayoutId); writeActionsToParcel(dest); } else { dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT); @@ -3665,7 +3715,7 @@ public class RemoteViews implements Parcelable, Filter { // Both RemoteViews already share the same package and user mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES); } - dest.writeInt(mReapplyDisallowed ? 1 : 0); + dest.writeInt(mApplyFlags); } private void writeActionsToParcel(Parcel parcel) { diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index d17c7c58ee74..c5cd1a1ece35 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -16,6 +16,9 @@ package android.widget; +import static android.widget.RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID; +import static android.widget.RemoteViews.EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND; + import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; import android.app.IServiceConnection; @@ -97,6 +100,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback private final Context mContext; private final Intent mIntent; private final int mAppWidgetId; + private final boolean mOnLightBackground; private final Executor mAsyncViewLoadExecutor; private OnClickHandler mRemoteViewsOnClickHandler; @@ -817,13 +821,13 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback throw new IllegalArgumentException("Non-null Intent must be specified."); } - mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1); + mAppWidgetId = intent.getIntExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1); mRequestedViews = new RemoteViewsFrameLayoutRefSet(); + mOnLightBackground = intent.getBooleanExtra(EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND, false); // Strip the previously injected app widget id from service intent - if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) { - intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID); - } + intent.removeExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID); + intent.removeExtra(EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND); // Initialize the worker thread mWorkerThread = new HandlerThread("RemoteViewsCache-loader"); @@ -1107,6 +1111,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback } else { layout = new RemoteViewsFrameLayout(parent.getContext(), mCache); layout.setExecutor(mAsyncViewLoadExecutor); + layout.setOnLightBackground(mOnLightBackground); } if (isInCache) { diff --git a/core/java/android/widget/RemoteViewsListAdapter.java b/core/java/android/widget/RemoteViewsListAdapter.java index e490458b38a8..b80fe4871616 100644 --- a/core/java/android/widget/RemoteViewsListAdapter.java +++ b/core/java/android/widget/RemoteViewsListAdapter.java @@ -85,7 +85,7 @@ public class RemoteViewsListAdapter extends BaseAdapter { public View getView(int position, View convertView, ViewGroup parent) { if (position < getCount()) { RemoteViews rv = mRemoteViewsList.get(position); - rv.setIsWidgetCollectionChild(true); + rv.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD); View v; if (convertView != null && rv != null && convertView.getId() == rv.getLayoutId()) { diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java index 2827f634b389..214e5cc01b9e 100644 --- a/core/java/android/widget/RemoteViewsService.java +++ b/core/java/android/widget/RemoteViewsService.java @@ -163,7 +163,7 @@ public abstract class RemoteViewsService extends Service { try { rv = mFactory.getViewAt(position); if (rv != null) { - rv.setIsWidgetCollectionChild(true); + rv.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD); } } catch (Exception ex) { Thread t = Thread.currentThread(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 1deee8af3d75..085f8f1d678f 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -166,7 +166,7 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.intelligence.IntelligenceManager; +import android.view.intelligence.ContentCaptureManager; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationContext; import android.view.textclassifier.TextClassificationManager; @@ -10135,7 +10135,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Notify managers (such as {@link AutofillManager} and {@link IntelligenceManager}) that are + * Notify managers (such as {@link AutofillManager} and {@link ContentCaptureManager}) that are * interested on text changes. */ private void notifyListeningManagersAfterTextChanged() { @@ -10155,10 +10155,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // ContentCapture if (isImportantForContentCapture() && isTextEditable()) { - final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class); - if (im != null && im.isContentCaptureEnabled()) { + final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class); + if (cm != null && cm.isContentCaptureEnabled()) { // TODO(b/111276913): pass flags when edited by user / add CTS test - im.notifyViewTextChanged(getAutofillId(), getText(), /* flags= */ 0); + cm.notifyViewTextChanged(getAutofillId(), getText(), /* flags= */ 0); } } } diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java index 875d7c9ee7a6..a87bbf33ca9e 100644 --- a/core/java/com/android/internal/os/BinderCallsStats.java +++ b/core/java/com/android/internal/os/BinderCallsStats.java @@ -19,6 +19,7 @@ package com.android.internal.os; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Binder; +import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.DateFormat; @@ -78,8 +79,10 @@ public class BinderCallsStats implements BinderInternal.Observer { private final Random mRandom; private long mStartTime = System.currentTimeMillis(); private long mCallStatsCount = 0; + private boolean mAddDebugEntries = false; private CachedDeviceState.Readonly mDeviceState; + private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch; /** Injector for {@link BinderCallsStats}. */ public static class Injector { @@ -93,7 +96,11 @@ public class BinderCallsStats implements BinderInternal.Observer { } public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) { + if (mBatteryStopwatch != null) { + mBatteryStopwatch.close(); + } mDeviceState = deviceState; + mBatteryStopwatch = deviceState.createTimeOnBatteryStopwatch(); } @Override @@ -317,9 +324,30 @@ public class BinderCallsStats implements BinderInternal.Observer { exported.methodName = methodName; } + // Debug entries added to help validate the data. + if (mAddDebugEntries && mBatteryStopwatch != null) { + resultCallStats.add(createDebugEntry("start_time_millis", mStartTime)); + resultCallStats.add(createDebugEntry("end_time_millis", System.currentTimeMillis())); + resultCallStats.add( + createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis())); + } + return resultCallStats; } + private ExportedCallStat createDebugEntry(String variableName, long value) { + final int uid = Process.myUid(); + final ExportedCallStat callStat = new ExportedCallStat(); + callStat.className = ""; + callStat.workSourceUid = uid; + callStat.callingUid = uid; + callStat.recordedCallCount = 1; + callStat.callCount = 1; + callStat.methodName = "__DEBUG_" + variableName; + callStat.maxReplySizeBytes = value; + return callStat; + } + /** @hide */ public ArrayMap<String, Integer> getExportedExceptionStats() { synchronized (mLock) { @@ -341,6 +369,8 @@ public class BinderCallsStats implements BinderInternal.Observer { long totalCpuTime = 0; pw.print("Start time: "); pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartTime)); + pw.print("On battery time (ms): "); + pw.println(mBatteryStopwatch != null ? mBatteryStopwatch.getMillis() : 0); pw.println("Sampling interval period: " + mPeriodicSamplingInterval); final List<UidEntry> entries = new ArrayList<>(); @@ -457,6 +487,10 @@ public class BinderCallsStats implements BinderInternal.Observer { } } + public void setAddDebugEntries(boolean addDebugEntries) { + mAddDebugEntries = addDebugEntries; + } + /** * Sets the maximum number of items to track. */ @@ -496,6 +530,9 @@ public class BinderCallsStats implements BinderInternal.Observer { mUidEntries.clear(); mExceptionCounts.clear(); mStartTime = System.currentTimeMillis(); + if (mBatteryStopwatch != null) { + mBatteryStopwatch.reset(); + } } } diff --git a/core/java/com/android/internal/os/CachedDeviceState.java b/core/java/com/android/internal/os/CachedDeviceState.java index 8c90682ec281..334cca317c30 100644 --- a/core/java/com/android/internal/os/CachedDeviceState.java +++ b/core/java/com/android/internal/os/CachedDeviceState.java @@ -16,8 +16,14 @@ package com.android.internal.os; + +import android.os.SystemClock; + +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import java.util.ArrayList; + /** * Stores the device state (e.g. charging/on battery, screen on/off) to be shared with * the System Server telemetry services. @@ -27,6 +33,9 @@ import com.android.internal.annotations.VisibleForTesting; public class CachedDeviceState { private volatile boolean mScreenInteractive; private volatile boolean mCharging; + private final Object mStopwatchesLock = new Object(); + @GuardedBy("mStopwatchLock") + private final ArrayList<TimeInStateStopwatch> mOnBatteryStopwatches = new ArrayList<>(); public CachedDeviceState() { mCharging = true; @@ -44,7 +53,23 @@ public class CachedDeviceState { } public void setCharging(boolean charging) { - mCharging = charging; + if (mCharging != charging) { + mCharging = charging; + updateStopwatches(/* shouldStart= */ !charging); + } + } + + private void updateStopwatches(boolean shouldStart) { + synchronized (mStopwatchesLock) { + final int size = mOnBatteryStopwatches.size(); + for (int i = 0; i < size; i++) { + if (shouldStart) { + mOnBatteryStopwatches.get(i).start(); + } else { + mOnBatteryStopwatches.get(i).stop(); + } + } + } } public Readonly getReadonlyClient() { @@ -62,5 +87,74 @@ public class CachedDeviceState { public boolean isScreenInteractive() { return mScreenInteractive; } + + /** Creates a {@link TimeInStateStopwatch stopwatch} that tracks the time on battery. */ + public TimeInStateStopwatch createTimeOnBatteryStopwatch() { + synchronized (mStopwatchesLock) { + final TimeInStateStopwatch stopwatch = new TimeInStateStopwatch(); + mOnBatteryStopwatches.add(stopwatch); + if (!mCharging) { + stopwatch.start(); + } + return stopwatch; + } + } + } + + /** Tracks the time the device spent in a given state. */ + public class TimeInStateStopwatch implements AutoCloseable { + private final Object mLock = new Object(); + @GuardedBy("mLock") + private long mStartTimeMillis; + @GuardedBy("mLock") + private long mTotalTimeMillis; + + /** Returns the time in state since the last call to {@link TimeInStateStopwatch#reset}. */ + public long getMillis() { + synchronized (mLock) { + return mTotalTimeMillis + elapsedTime(); + } + } + + /** Resets the time in state to 0 without stopping the timer if it's started. */ + public void reset() { + synchronized (mLock) { + mTotalTimeMillis = 0; + mStartTimeMillis = isRunning() ? SystemClock.elapsedRealtime() : 0; + } + } + + private void start() { + synchronized (mLock) { + if (!isRunning()) { + mStartTimeMillis = SystemClock.elapsedRealtime(); + } + } + } + + private void stop() { + synchronized (mLock) { + if (isRunning()) { + mTotalTimeMillis += elapsedTime(); + mStartTimeMillis = 0; + } + } + } + + private long elapsedTime() { + return isRunning() ? SystemClock.elapsedRealtime() - mStartTimeMillis : 0; + } + + @VisibleForTesting + public boolean isRunning() { + return mStartTimeMillis > 0; + } + + @Override + public void close() { + synchronized (mStopwatchesLock) { + mOnBatteryStopwatches.remove(this); + } + } } } diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java index cf2a297bb6a5..de85c1f35a58 100644 --- a/core/java/com/android/internal/os/LooperStats.java +++ b/core/java/com/android/internal/os/LooperStats.java @@ -49,6 +49,7 @@ public class LooperStats implements Looper.Observer { private final int mEntriesSizeCap; private int mSamplingInterval; private CachedDeviceState.Readonly mDeviceState; + private CachedDeviceState.TimeInStateStopwatch mBatteryStopwatch; private long mStartTime = System.currentTimeMillis(); private boolean mAddDebugEntries = false; @@ -58,7 +59,12 @@ public class LooperStats implements Looper.Observer { } public void setDeviceState(@NonNull CachedDeviceState.Readonly deviceState) { + if (mBatteryStopwatch != null) { + mBatteryStopwatch.close(); + } + mDeviceState = deviceState; + mBatteryStopwatch = deviceState.createTimeOnBatteryStopwatch(); } public void setAddDebugEntries(boolean addDebugEntries) { @@ -148,9 +154,11 @@ public class LooperStats implements Looper.Observer { maybeAddSpecialEntry(exportedEntries, mOverflowEntry); maybeAddSpecialEntry(exportedEntries, mHashCollisionEntry); // Debug entries added to help validate the data. - if (mAddDebugEntries) { + if (mAddDebugEntries && mBatteryStopwatch != null) { exportedEntries.add(createDebugEntry("start_time_millis", mStartTime)); exportedEntries.add(createDebugEntry("end_time_millis", System.currentTimeMillis())); + exportedEntries.add( + createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis())); } return exportedEntries; } @@ -168,6 +176,10 @@ public class LooperStats implements Looper.Observer { return mStartTime; } + public long getBatteryTimeMillis() { + return mBatteryStopwatch != null ? mBatteryStopwatch.getMillis() : 0; + } + private void maybeAddSpecialEntry(List<ExportedEntry> exportedEntries, Entry specialEntry) { synchronized (specialEntry) { if (specialEntry.messageCount > 0 || specialEntry.exceptionCount > 0) { @@ -188,6 +200,9 @@ public class LooperStats implements Looper.Observer { mOverflowEntry.reset(); } mStartTime = System.currentTimeMillis(); + if (mBatteryStopwatch != null) { + mBatteryStopwatch.reset(); + } } public void setSamplingInterval(int samplingInterval) { diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 488b9912ee49..d8ee643e27f0 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -91,6 +91,7 @@ import android.view.ViewParent; import android.view.ViewRootImpl; import android.view.ViewRootImpl.ActivityConfigCallback; import android.view.Window; +import android.view.WindowInsetsController; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; @@ -3877,4 +3878,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mDecor.updateLogTag(params); } } + + @Override + public WindowInsetsController getInsetsController() { + return mDecor.getWindowInsetsController(); + } } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 600b1b324257..53b56f2e937a 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -29,7 +29,7 @@ oneway interface IStatusBar { void setIcon(String slot, in StatusBarIcon icon); void removeIcon(String slot); - void disable(int state1, int state2); + void disable(int displayId, int state1, int state2); void animateExpandNotificationsPanel(); void animateExpandSettingsPanel(String subPanel); void animateCollapsePanels(); @@ -38,8 +38,9 @@ oneway interface IStatusBar void showWirelessChargingAnimation(int batteryLevel); /** - * Notifies the status bar of a System UI visibility flag change. + * Notifies System UI side of a visibility flag change on the specified display. * + * @param displayId the id of the display to notify * @param vis the visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will be reported * separately in fullscreenStackVis and dockedStackVis * @param fullscreenStackVis the flags which only apply in the region of the fullscreen stack, @@ -50,13 +51,13 @@ oneway interface IStatusBar * @param fullscreenBounds the current bounds of the fullscreen stack, in screen coordinates * @param dockedBounds the current bounds of the docked stack, in screen coordinates */ - void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, - in Rect fullscreenBounds, in Rect dockedBounds); + void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis, + int mask, in Rect fullscreenBounds, in Rect dockedBounds); - void topAppWindowChanged(boolean menuVisible); - void setImeWindowStatus(in IBinder token, int vis, int backDisposition, + void topAppWindowChanged(int displayId, boolean menuVisible); + void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition, boolean showImeSwitcher); - void setWindowState(int window, int state); + void setWindowState(int display, int window, int state); void showRecentApps(boolean triggeredFromAltTab); void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); @@ -70,30 +71,38 @@ oneway interface IStatusBar void toggleKeyboardShortcutsMenu(int deviceId); /** - * Notifies the status bar that an app transition is pending to delay applying some flags with - * visual impact until {@link #appTransitionReady} is called. + * Notifies System UI on the specified display that an app transition is pending to delay + * applying some flags with visual impact until {@link #appTransitionReady} is called. + * + * @param displayId the id of the display to notify */ - void appTransitionPending(); + void appTransitionPending(int displayId); /** - * Notifies the status bar that a pending app transition has been cancelled. + * Notifies System UI on the specified display that a pending app transition has been cancelled. + * + * @param displayId the id of the display to notify */ - void appTransitionCancelled(); + void appTransitionCancelled(int displayId); /** - * Notifies the status bar that an app transition is now being executed. + * Notifies System UI on the specified display that an app transition is now being executed. * + * @param displayId the id of the display to notify * @param statusBarAnimationsStartTime the desired start time for all visual animations in the * status bar caused by this app transition in uptime millis * @param statusBarAnimationsDuration the duration for all visual animations in the status * bar caused by this app transition in millis */ - void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration); + void appTransitionStarting(int displayId, long statusBarAnimationsStartTime, + long statusBarAnimationsDuration); /** - * Notifies the status bar that an app transition is done. + * Notifies System UI on the specified display that an app transition is done. + * + * @param displayId the id of the display to notify */ - void appTransitionFinished(); + void appTransitionFinished(int displayId); void showAssistDisclosure(); void startAssist(in Bundle args); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index bf82dc610ad4..5118e5f0473e 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -41,6 +41,7 @@ interface IStatusBarService void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription); void setIconVisibility(String slot, boolean visible); void removeIcon(String slot); + // TODO(b/117478341): support back button change when IME is showing on a external display. void setImeWindowStatus(in IBinder token, int vis, int backDisposition, boolean showImeSwitcher); void expandSettingsPanel(String subPanel); @@ -69,7 +70,7 @@ interface IStatusBarService void onNotificationSmartRepliesAdded(in String key, in int replyCount); void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply, boolean generatedByAssistant); void onNotificationSettingsViewed(String key); - void setSystemUiVisibility(int vis, int mask, String cause); + void setSystemUiVisibility(int displayId, int vis, int mask, String cause); void onGlobalActionsShown(); void onGlobalActionsHidden(); diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 4b662670f5e7..f669e94c1779 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -32,6 +32,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.IntFunction; /** * ArrayUtils contains some methods that you can call to find out @@ -656,4 +657,30 @@ public class ArrayUtils { throw new ArrayIndexOutOfBoundsException("length=" + len + "; index=" + index); } } + + /** + * Returns an array with values from {@code val} minus {@code null} values + * + * @param arrayConstructor typically {@code T[]::new} e.g. {@code String[]::new} + */ + public static <T> T[] filterNotNull(T[] val, IntFunction<T[]> arrayConstructor) { + int nullCount = 0; + int size = size(val); + for (int i = 0; i < size; i++) { + if (val[i] == null) { + nullCount++; + } + } + if (nullCount == 0) { + return val; + } + T[] result = arrayConstructor.apply(size - nullCount); + int outIdx = 0; + for (int i = 0; i < size; i++) { + if (val[i] != null) { + result[outIdx++] = val[i]; + } + } + return result; + } } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 36fe4fc5af49..c8834a889333 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -27,6 +27,7 @@ import android.view.DragEvent; import android.view.IWindow; import android.view.IWindowSession; import android.view.PointerIcon; +import android.view.InsetsSourceControl; import android.view.InsetsState; import com.android.internal.os.IResultReceiver; @@ -58,6 +59,11 @@ public class BaseIWindow extends IWindow.Stub { } @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) throws RemoteException { + } + + @Override public void moved(int newX, int newY) { } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index bdd5f83aa4ea..31bb1d57d702 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -34,7 +34,6 @@ cc_library_shared { ], cppflags: ["-Wno-conversion-null"], - cpp_std: "c++17", srcs: [ "AndroidRuntime.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index bc1d5cc7e1c6..f9879ccc18c9 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1056,12 +1056,18 @@ void AndroidRuntime::start(const char* className, const Vector<String8>& options if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { - LOG_FATAL("No root directory specified, and /android does not exist."); + LOG_FATAL("No root directory specified, and /system does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } + const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT"); + if (runtimeRootDir == NULL) { + LOG_FATAL("No runtime directory specified with ANDROID_RUNTIME_ROOT environment variable."); + return; + } + //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp index dcb787462a13..cfe742d0134d 100644 --- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp +++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp @@ -59,7 +59,7 @@ struct HarfBuzzFontData { static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) { ALOG_ASSERT(codepoint <= 0xFFFF); - paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); + paint->setTextEncoding(kGlyphID_SkTextEncoding); SkScalar skWidth; SkRect skBounds; @@ -84,7 +84,7 @@ static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoin { HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); SkPaint* paint = hbFontData->m_paint; - paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); + paint->setTextEncoding(kUTF32_SkTextEncoding); if (unicode > 0x10ffff) { unicode = 0xfffd; diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index a8b0640c3a73..c249e209b29f 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -71,7 +71,7 @@ static JMetricsID gFontMetricsInt_fieldID; static void defaultSettingsForAndroid(Paint* paint) { // GlyphID encoding is required because we are using Harfbuzz shaping - paint->setTextEncoding(Paint::kGlyphID_TextEncoding); + paint->setTextEncoding(kGlyphID_SkTextEncoding); } namespace PaintGlue { @@ -321,7 +321,7 @@ namespace PaintGlue { x += MinikinUtils::xOffsetForTextAlign(paint, layout); Paint::Align align = paint->getTextAlign(); paint->setTextAlign(Paint::kLeft_Align); - paint->setTextEncoding(Paint::kGlyphID_TextEncoding); + paint->setTextEncoding(kGlyphID_SkTextEncoding); GetTextFunctor f(layout, path, x, y, paint, glyphs, pos); MinikinUtils::forFontRun(layout, paint, f); paint->setTextAlign(align); diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 1ea4ed1b1738..12a8343b4a5c 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -842,6 +842,18 @@ static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env, } // ---------------------------------------------------------------------------- +static jint android_media_AudioRecord_get_port_id(JNIEnv *env, jobject thiz) { + sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); + if (lpRecorder == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioRecord pointer for getId()"); + return (jint)AUDIO_PORT_HANDLE_NONE; + } + return (jint)lpRecorder->getPortId(); +} + + +// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { // name, signature, funcPtr @@ -883,6 +895,7 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioRecord_get_timestamp}, {"native_get_active_microphones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioRecord_get_active_microphones}, + {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id}, }; // field names found in android/media/AudioRecord.java diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 04f0a53dd53b..d927972cf8d3 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -1284,6 +1284,17 @@ static int android_media_AudioTrack_setPresentation( } // ---------------------------------------------------------------------------- +static jint android_media_AudioTrack_get_port_id(JNIEnv *env, jobject thiz) { + sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); + if (lpTrack == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "AudioTrack not initialized"); + return (jint)AUDIO_PORT_HANDLE_NONE; + } + return (jint)lpTrack->getPortId(); +} + +// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { // name, signature, funcPtr @@ -1354,6 +1365,7 @@ static const JNINativeMethod gMethods[] = { "(I)Landroid/media/VolumeShaper$State;", (void *)android_media_AudioTrack_get_volume_shaper_state}, {"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation}, + {"native_getPortId", "()I", (void *)android_media_AudioTrack_get_port_id}, }; @@ -1379,7 +1391,6 @@ bool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const } } - // ---------------------------------------------------------------------------- int register_android_media_AudioTrack(JNIEnv *env) { diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index d917536b1715..4c1fc5c89b0d 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -761,6 +761,13 @@ message GlobalSettingsProto { } optional SmartSelection smart_selection = 108; + message SmartSuggestions { + option (android.msg_privacy).dest = DEST_EXPLICIT; + + optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + optional SmartSuggestions smart_suggestions = 145; + message Sms { option (android.msg_privacy).dest = DEST_EXPLICIT; @@ -869,6 +876,8 @@ message GlobalSettingsProto { // Temperature at which the high temperature warning notification should // be shown. optional SettingProto warning_temperature_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // USB temperature at which the high temperature alarm notification should be shown. + optional SettingProto usb_alarm_temperature_level = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional TemperatureWarning temperature_warning = 119; @@ -991,5 +1000,5 @@ message GlobalSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 145; + // Next tag = 146; } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 6e661e1ce5b2..0e052fe8d4b1 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -234,6 +234,18 @@ message SecureSettingsProto { } optional Location location = 31; + // How frequently will the user be reminded about location permission grants + message LocationAccessCheck { + option (android.msg_privacy).dest = DEST_EXPLICIT; + + // Time in between periodic checks + optional SettingProto interval_millis = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + + // Time in between the user granting a location permission and a check + optional SettingProto delay_millis = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + optional LocationAccessCheck location_access_check = 73; + message LockScreen { option (android.msg_privacy).dest = DEST_EXPLICIT; @@ -515,5 +527,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 73; + // Next tag = 74; } diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 679a1d254cf1..3767ed553181 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -211,7 +211,7 @@ message TaskProto { repeated AppWindowTokenProto app_window_tokens = 3; optional bool fills_parent = 4; optional .android.graphics.RectProto bounds = 5; - optional .android.graphics.RectProto temp_inset_bounds = 6; + optional .android.graphics.RectProto displayed_bounds = 6; optional bool defer_removal = 7; optional int32 surface_width = 8; optional int32 surface_height = 9; diff --git a/core/proto/android/service/runtime.proto b/core/proto/android/service/runtime.proto new file mode 100644 index 000000000000..ecbccef7a94c --- /dev/null +++ b/core/proto/android/service/runtime.proto @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.service.runtime; + +import "frameworks/base/libs/incident/proto/android/privacy.proto"; + +option java_multiple_files = true; +option java_outer_classname = "RuntimeServiceProto"; + +// Represents dumpsys info from RuntimeService. +message RuntimeServiceInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Generic debug information to include. + repeated DebugEntryProto debug_entry = 1; +} + +// A piece of key / value debug information. +message DebugEntryProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string key = 1; + + optional string string_value = 2; +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e6c9b882c39e..3018614fee61 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -655,7 +655,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readContacts" android:description="@string/permdesc_readContacts" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to write the user's contacts data. <p>Protection level: dangerous @@ -686,7 +687,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCalendar" android:description="@string/permdesc_readCalendar" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to write the user's calendar data. <p>Protection level: dangerous @@ -727,7 +729,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveSms" android:description="@string/permdesc_receiveSms" - android:protectionLevel="dangerous"/> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to read SMS messages. <p>Protection level: dangerous @@ -736,7 +739,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readSms" android:description="@string/permdesc_readSms" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to receive WAP push messages. <p>Protection level: dangerous @@ -745,7 +749,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveWapPush" android:description="@string/permdesc_receiveWapPush" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to monitor incoming MMS messages. <p>Protection level: dangerous @@ -754,7 +759,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_receiveMms" android:description="@string/permdesc_receiveMms" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast messages and to register a content observer to get notifications when @@ -772,7 +778,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCellBroadcasts" android:description="@string/permdesc_readCellBroadcasts" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> <!-- Permissions for accessing external storage --> @@ -853,7 +860,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_audioRead" android:description="@string/permdesc_audioRead" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Runtime permission controlling access to the user's shared visual media collection, including images and videos. --> @@ -869,14 +877,16 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_imagesRead" android:description="@string/permdesc_imagesRead" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to read the user's shared video collection. --> <permission android:name="android.permission.READ_MEDIA_VIDEO" android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_videoRead" android:description="@string/permdesc_videoRead" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to access any geographic locations persisted in the user's shared collection. --> @@ -884,7 +894,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_mediaLocation" android:description="@string/permdesc_mediaLocation" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- @hide @SystemApi Allows an application to modify OBB files visible to other apps. --> @@ -916,7 +927,8 @@ android:label="@string/permlab_accessFineLocation" android:description="@string/permdesc_accessFineLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- Allows an app to access approximate location. Alternatively, you might want {@link #ACCESS_FINE_LOCATION}. @@ -927,7 +939,8 @@ android:label="@string/permlab_accessCoarseLocation" android:description="@string/permdesc_accessCoarseLocation" android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- Allows an app to access location in the background. If you are requesting this, you should also request {@link #ACCESS_FINE_LOCATION}. @@ -939,7 +952,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_accessBackgroundLocation" android:description="@string/permdesc_accessBackgroundLocation" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> <!-- Permissions for accessing the call log --> @@ -980,7 +994,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readCallLog" android:description="@string/permdesc_readCallLog" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an application to write (but not read) the user's call log data. @@ -1010,7 +1025,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_processOutgoingCalls" android:description="@string/permdesc_processOutgoingCalls" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> <!-- Permissions for accessing the device telephony --> @@ -1042,7 +1058,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneState" android:description="@string/permdesc_readPhoneState" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities granted by {@link #READ_PHONE_STATE} but is exposed to instant applications. @@ -1051,7 +1068,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_readPhoneNumbers" android:description="@string/permdesc_readPhoneNumbers" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call. @@ -1141,7 +1159,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_recordAudio" android:description="@string/permdesc_recordAudio" - android:protectionLevel="dangerous|instant"/> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> <!-- Permissions for activity recognition --> @@ -1163,7 +1182,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_activityRecognition" android:description="@string/permdesc_activityRecognition" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> <!-- Permissions for accessing the UCE Service --> @@ -1212,7 +1232,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_camera" android:description="@string/permdesc_camera" - android:protectionLevel="dangerous|instant" /> + android:protectionLevel="dangerous|instant" + android:usageInfoRequired="true" /> <!-- ====================================================================== --> @@ -1236,7 +1257,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_bodySensors" android:description="@string/permdesc_bodySensors" - android:protectionLevel="dangerous" /> + android:protectionLevel="dangerous" + android:usageInfoRequired="true" /> <!-- Allows an app to use fingerprint hardware. <p>Protection level: normal @@ -1723,7 +1745,8 @@ android:permissionGroup="android.permission-group.UNDEFINED" android:protectionLevel="dangerous" android:description="@string/permdesc_getAccounts" - android:label="@string/permlab_getAccounts" /> + android:label="@string/permlab_getAccounts" + android:usageInfoRequired="true" /> <uses-permission android:name="android.permission.GET_ACCOUNTS"/> <!-- @SystemApi Allows applications to call into AccountAuthenticators. @@ -3024,12 +3047,12 @@ <permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE" android:protectionLevel="signature" /> - <!-- Must be required by a android.service.intelligence.IntelligenceService, + <!-- Must be required by a android.service.intelligence.SmartSuggestionsService, to ensure that only the system can bind to it. @SystemApi @hide This is not a third-party API (intended for OEMs and system apps). <p>Protection level: signature --> - <permission android:name="android.permission.BIND_INTELLIGENCE_SERVICE" + <permission android:name="android.permission.BIND_SMART_SUGGESTIONS_SERVICE" android:protectionLevel="signature" /> <!-- Must be required by hotword enrollment application, @@ -3364,6 +3387,13 @@ <permission android:name="android.permission.CONTROL_DISPLAY_SATURATION" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to control display color transformations. + <p>Not for use by third-party applications.</p> + @hide + @SystemApi --> + <permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" + android:protectionLevel="signature|privileged" /> + <!-- Allows an application to collect usage infomation about brightness slider changes. <p>Not for use by third-party applications.</p> @hide @@ -4147,6 +4177,11 @@ <permission android:name="android.permission.MANAGE_AUTO_FILL" android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to manage the smart suggestions service. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS" + android:protectionLevel="signature" /> + <!-- Allows an app to set the theme overlay in /vendor/overlay being used. @hide <p>Not for use by third-party applications.</p> --> @@ -4588,6 +4623,13 @@ </intent-filter> </receiver> + <receiver android:name="com.android.server.WallpaperUpdateReceiver" + android:permission="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"> + <intent-filter> + <action android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY"/> + </intent-filter> + </receiver> + <service android:name="android.hardware.location.GeofenceHardwareService" android:permission="android.permission.LOCATION_HARDWARE" android:exported="false" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 244728954aa0..f55e48e5b140 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1915,6 +1915,9 @@ <enum name="KEYCODE_SYSTEM_NAVIGATION_RIGHT" value="283" /> <enum name="KEYCODE_ALL_APPS" value="284" /> <enum name="KEYCODE_REFRESH" value="285" /> + <enum name="KEYCODE_THUMBS_UP" value="286" /> + <enum name="KEYCODE_THUMBS_DOWN" value="287" /> + <enum name="KEYCODE_PROFILE_SWITCH" value="288" /> </attr> <!-- ***************************************************************** --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 1d809613e2b2..c62071bdf552 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2125,6 +2125,9 @@ during initialization when the setting is still null. --> <bool name="config_dozeAlwaysOnEnabled">true</bool> + <!-- If AOD can show an ambient version of the wallpaper --> + <bool name="config_dozeSupportsAodWallpaper">true</bool> + <!-- Whether the display blanks itself when transitioning from a doze to a non-doze state --> <bool name="config_displayBlanksAfterDoze">false</bool> @@ -3347,6 +3350,14 @@ --> <string name="config_defaultTextClassifierPackage" translatable="false"></string> + <!-- The package name for the system's smart suggestion service. + This service must be trusted, as it can be activated without explicit consent of the user. + If no service with the specified name exists on the device, content capture and + smart suggestions will be disabled. + Example: "com.android.intelligence/.SmartSuggestionsService" + --> + <string name="config_defaultSmartSuggestionsService" translatable="false"></string> + <!-- Whether the device uses the default focus highlight when focus state isn't specified. --> <bool name="config_useDefaultFocusHighlight">true</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 783f1f355e87..6854a84e950a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3265,6 +3265,7 @@ <java-symbol type="string" name="notification_channel_do_not_disturb" /> <java-symbol type="string" name="config_defaultAutofillService" /> <java-symbol type="string" name="config_defaultTextClassifierPackage" /> + <java-symbol type="string" name="config_defaultSmartSuggestionsService" /> <java-symbol type="string" name="notification_channel_foreground_service" /> <java-symbol type="string" name="foreground_service_app_in_background" /> @@ -3310,6 +3311,7 @@ <java-symbol type="integer" name="config_autoGroupAtCount" /> <java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" /> <java-symbol type="bool" name="config_dozeAlwaysOnEnabled" /> + <java-symbol type="bool" name="config_dozeSupportsAodWallpaper" /> <java-symbol type="bool" name="config_displayBlanksAfterDoze" /> <java-symbol type="bool" name="config_displayBrightnessBucketsInDoze" /> <java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" /> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 3b650e5ff777..46d4a4773389 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -91,6 +91,8 @@ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> <uses-permission android:name="android.permission.KILL_UID" /> + <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> + <!-- location test permissions --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/> diff --git a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java index c8bc35c976a2..9e1523165925 100644 --- a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java +++ b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java @@ -16,6 +16,10 @@ package android.os; +import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; +import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; +import static android.os.RedactingFileDescriptor.removeRange; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -58,8 +62,8 @@ public class RedactingFileDescriptorTest { @Test public void testSingleByte() throws Exception { - final FileDescriptor fd = RedactingFileDescriptor - .open(mContext, mFile, new long[] { 10, 11 }).getFileDescriptor(); + final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY, + new long[] { 10, 11 }).getFileDescriptor(); final byte[] buf = new byte[1_000]; assertEquals(buf.length, Os.read(fd, buf, 0, buf.length)); @@ -74,8 +78,8 @@ public class RedactingFileDescriptorTest { @Test public void testRanges() throws Exception { - final FileDescriptor fd = RedactingFileDescriptor - .open(mContext, mFile, new long[] { 100, 200, 300, 400 }).getFileDescriptor(); + final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY, + new long[] { 100, 200, 300, 400 }).getFileDescriptor(); final byte[] buf = new byte[10]; assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 90)); @@ -96,8 +100,8 @@ public class RedactingFileDescriptorTest { @Test public void testEntireFile() throws Exception { - final FileDescriptor fd = RedactingFileDescriptor - .open(mContext, mFile, new long[] { 0, 5_000_000 }).getFileDescriptor(); + final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY, + new long[] { 0, 5_000_000 }).getFileDescriptor(); try (FileInputStream in = new FileInputStream(fd)) { int val; @@ -106,4 +110,61 @@ public class RedactingFileDescriptorTest { } } } + + @Test + public void testReadWrite() throws Exception { + final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE, + new long[] { 100, 200, 300, 400 }).getFileDescriptor(); + + // Redacted at first + final byte[] buf = new byte[10]; + assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 95)); + assertArrayEquals(new byte[] { 64, 64, 64, 64, 64, 0, 0, 0, 0, 0 }, buf); + + // But we can see data that we've written + Os.pwrite(fd, new byte[] { 32, 32 }, 0, 2, 102); + assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 95)); + assertArrayEquals(new byte[] { 64, 64, 64, 64, 64, 0, 0, 32, 32, 0 }, buf); + } + + @Test + public void testRemoveRange() throws Exception { + // Removing outside ranges should have no changes + assertArrayEquals(new long[] { 100, 200, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 0, 100)); + assertArrayEquals(new long[] { 100, 200, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 200, 300)); + assertArrayEquals(new long[] { 100, 200, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 400, 500)); + + // Removing full regions + assertArrayEquals(new long[] { 100, 200 }, + removeRange(new long[] { 100, 200, 300, 400 }, 300, 400)); + assertArrayEquals(new long[] { 100, 200 }, + removeRange(new long[] { 100, 200, 300, 400 }, 250, 450)); + assertArrayEquals(new long[] { 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 50, 250)); + assertArrayEquals(new long[] { }, + removeRange(new long[] { 100, 200, 300, 400 }, 0, 5_000_000)); + } + + @Test + public void testRemoveRange_Partial() throws Exception { + assertArrayEquals(new long[] { 150, 200, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 50, 150)); + assertArrayEquals(new long[] { 100, 150, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 150, 250)); + assertArrayEquals(new long[] { 100, 150, 350, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 150, 350)); + assertArrayEquals(new long[] { 100, 150 }, + removeRange(new long[] { 100, 200, 300, 400 }, 150, 500)); + } + + @Test + public void testRemoveRange_Hole() throws Exception { + assertArrayEquals(new long[] { 100, 125, 175, 200, 300, 400 }, + removeRange(new long[] { 100, 200, 300, 400 }, 125, 175)); + assertArrayEquals(new long[] { 100, 200 }, + removeRange(new long[] { 100, 200 }, 150, 150)); + } } diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 305d2af2122d..ed9c3d5b2b70 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -415,6 +415,7 @@ public class SettingsBackupTest { Settings.Global.SHOW_TEMPERATURE_WARNING, Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL, Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL, + Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED, Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS, Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT, @@ -477,6 +478,7 @@ public class SettingsBackupTest { Settings.Global.USER_SWITCHER_ENABLED, Settings.Global.NETWORK_ACCESS_TIMEOUT_MS, Settings.Global.WARNING_TEMPERATURE, + Settings.Global.USB_ALARM_TEMPERATURE, Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY, Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, Settings.Global.WEBVIEW_MULTIPROCESS, @@ -664,7 +666,9 @@ public class SettingsBackupTest { Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE, Settings.Secure.FLASHLIGHT_AVAILABLE, Settings.Secure.FLASHLIGHT_ENABLED, - Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED); + Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED, + Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS, + Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS); @Test public void systemSettingsBackedUpOrBlacklisted() { diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java new file mode 100644 index 000000000000..ed80cd7e375c --- /dev/null +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.view; + +import static android.view.InsetsState.TYPE_TOP_BAR; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; + +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.FlakyTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@FlakyTest(detail = "Promote once confirmed non-flaky") +@RunWith(AndroidJUnit4.class) +public class InsetsControllerTest { + + private InsetsController mController = new InsetsController(); + + private SurfaceSession mSession = new SurfaceSession(); + private SurfaceControl mLeash; + + @Before + public void setup() { + mLeash = new SurfaceControl.Builder(mSession) + .setName("testSurface") + .build(); + } + + @Test + public void testControlsChanged() { + InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash); + mController.onControlsChanged(new InsetsSourceControl[] { control }); + assertEquals(mLeash, + mController.getSourceConsumer(TYPE_TOP_BAR).getControl().getLeash()); + } + + @Test + public void testControlsRevoked() { + InsetsSourceControl control = new InsetsSourceControl(TYPE_TOP_BAR, mLeash); + mController.onControlsChanged(new InsetsSourceControl[] { control }); + mController.onControlsChanged(new InsetsSourceControl[0]); + assertNull(mController.getSourceConsumer(TYPE_TOP_BAR).getControl()); + } +} diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java new file mode 100644 index 000000000000..5a20ba2522b1 --- /dev/null +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.view; + +import static android.view.InsetsState.TYPE_TOP_BAR; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.FlakyTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.SurfaceControl.Transaction; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@Presubmit +@FlakyTest(detail = "Promote once confirmed non-flaky") +@RunWith(AndroidJUnit4.class) +public class InsetsSourceConsumerTest { + + private InsetsSourceConsumer mConsumer; + + private SurfaceSession mSession = new SurfaceSession(); + private SurfaceControl mLeash; + @Mock Transaction mMockTransaction; + @Mock InsetsController mMockController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mLeash = new SurfaceControl.Builder(mSession) + .setName("testSurface") + .build(); + mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(), + () -> mMockTransaction); + mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash)); + } + + @Test + public void testHide() { + mConsumer.hide(); + verify(mMockTransaction).hide(eq(mLeash)); + } + + @Test + public void testShow() { + mConsumer.hide(); + mConsumer.show(); + verify(mMockTransaction, atLeastOnce()).show(eq(mLeash)); + } + + @Test + public void testRestore() { + mConsumer.setControl(null); + reset(mMockTransaction); + mConsumer.hide(); + verifyZeroInteractions(mMockTransaction); + mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash)); + verify(mMockTransaction).hide(eq(mLeash)); + } +} diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java index 8691e73f82fb..02a76f8f78af 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java @@ -17,6 +17,7 @@ package com.android.internal.os; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.os.Binder; import android.platform.test.annotations.Presubmit; @@ -387,8 +388,7 @@ public class BinderCallsStatsTest { @Test public void testNoDataCollectedBeforeInitialDeviceStateSet() { - TestBinderCallsStats bcs = new TestBinderCallsStats(); - bcs.setDeviceState(null); + TestBinderCallsStats bcs = new TestBinderCallsStats(null); bcs.setDetailedTracking(true); Binder binder = new Binder(); CallSession callSession = bcs.callStarted(binder, 1); @@ -613,6 +613,27 @@ public class BinderCallsStatsTest { assertEquals(CALLING_UID, callStats.callingUid); } + @Test + public void testAddsDebugEntries() { + long startTime = System.currentTimeMillis(); + TestBinderCallsStats bcs = new TestBinderCallsStats(); + bcs.setAddDebugEntries(true); + ArrayList<BinderCallsStats.ExportedCallStat> callStats = bcs.getExportedCallStats(); + assertEquals(3, callStats.size()); + BinderCallsStats.ExportedCallStat debugEntry1 = callStats.get(0); + assertEquals("", debugEntry1.className); + assertEquals("__DEBUG_start_time_millis", debugEntry1.methodName); + assertTrue(startTime <= debugEntry1.maxReplySizeBytes); + BinderCallsStats.ExportedCallStat debugEntry2 = callStats.get(1); + assertEquals("", debugEntry2.className); + assertEquals("__DEBUG_end_time_millis", debugEntry2.methodName); + assertTrue(debugEntry1.maxReplySizeBytes <= debugEntry2.maxReplySizeBytes); + BinderCallsStats.ExportedCallStat debugEntry3 = callStats.get(2); + assertEquals("", debugEntry3.className); + assertEquals("__DEBUG_battery_time_millis", debugEntry3.methodName); + assertTrue(debugEntry3.maxReplySizeBytes >= 0); + } + class TestBinderCallsStats extends BinderCallsStats { public int callingUid = CALLING_UID; public int workSourceUid = WORKSOURCE_UID; @@ -620,6 +641,10 @@ public class BinderCallsStatsTest { public long elapsedTime = 0; TestBinderCallsStats() { + this(mDeviceState); + } + + TestBinderCallsStats(CachedDeviceState deviceState) { // Make random generator not random. super(new Injector() { public Random getRandomGenerator() { @@ -633,7 +658,10 @@ public class BinderCallsStatsTest { } }); setSamplingInterval(1); - setDeviceState(mDeviceState.getReadonlyClient()); + setAddDebugEntries(false); + if (deviceState != null) { + setDeviceState(deviceState.getReadonlyClient()); + } } @Override 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 31dde5c79f27..3d7801cbb531 100644 --- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java @@ -273,8 +273,7 @@ public final class LooperStatsTest { @Test public void testDataNotCollectedBeforeDeviceStateSet() { - TestableLooperStats looperStats = new TestableLooperStats(1, 100); - looperStats.setDeviceState(null); + TestableLooperStats looperStats = new TestableLooperStats(1, 100, null); Object token1 = looperStats.messageDispatchStarting(); looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000)); @@ -439,7 +438,7 @@ public final class LooperStatsTest { looperStats.messageDispatched(token, message); List<LooperStats.ExportedEntry> entries = looperStats.getEntries(); - assertThat(entries).hasSize(3); + assertThat(entries).hasSize(4); LooperStats.ExportedEntry debugEntry1 = entries.get(1); assertThat(debugEntry1.handlerClassName).isEqualTo(""); assertThat(debugEntry1.messageName).isEqualTo("__DEBUG_start_time_millis"); @@ -448,6 +447,10 @@ public final class LooperStatsTest { assertThat(debugEntry2.handlerClassName).isEqualTo(""); assertThat(debugEntry2.messageName).isEqualTo("__DEBUG_end_time_millis"); assertThat(debugEntry2.maxDelayMillis).isAtLeast(looperStats.getStartTimeMillis()); + LooperStats.ExportedEntry debugEntry3 = entries.get(3); + assertThat(debugEntry3.handlerClassName).isEqualTo(""); + assertThat(debugEntry3.messageName).isEqualTo("__DEBUG_battery_time_millis"); + assertThat(debugEntry3.maxDelayMillis).isAtLeast(0L); } private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { @@ -468,10 +471,16 @@ public final class LooperStatsTest { private int mSamplingInterval; TestableLooperStats(int samplingInterval, int sizeCap) { + this(samplingInterval, sizeCap, mDeviceState); + } + + TestableLooperStats(int samplingInterval, int sizeCap, CachedDeviceState deviceState) { super(samplingInterval, sizeCap); - this.mSamplingInterval = samplingInterval; - this.setDeviceState(mDeviceState.getReadonlyClient()); - this.setAddDebugEntries(false); + mSamplingInterval = samplingInterval; + setAddDebugEntries(false); + if (deviceState != null) { + setDeviceState(deviceState.getReadonlyClient()); + } } void tickRealtime(long micros) { diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 9e4ea32ed605..f2373446924a 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -281,6 +281,7 @@ applications that come with the platform <permission name="android.permission.WRITE_APN_SETTINGS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> </privapp-permissions> <privapp-permissions package="com.android.settings.intelligence"> @@ -408,6 +409,7 @@ applications that come with the platform <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"/> + <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> </privapp-permissions> <privapp-permissions package="com.android.tv"> diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index bf114b969b67..2227cf5ef2e0 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -1779,6 +1779,36 @@ public abstract class ColorSpace { } /** + * <p>Computes the chromaticity coordinates of a CIE series D illuminant + * from the specified correlated color temperature (CCT). The specified CCT + * must be greater than 0. A meaningful CCT range is [4000, 25000].</p> + * + * <p>The transform is computed using the methods referred to in Kang et + * al., <i>Design of Advanced Color - Temperature Control System for HDTV + * Applications</i>, Journal of Korean Physical Society 41, 865-871 + * (2002).</p> + * + * @param cct The correlated color temperature, in Kelvin + * @return Corresponding XYZ values + * @throws IllegalArgumentException If cct is invalid + */ + @NonNull + @Size(3) + public static float[] cctToIlluminantdXyz(@IntRange(from = 1) int cct) { + if (cct < 1) { + throw new IllegalArgumentException("Temperature must be greater than 0"); + } + + final float icct = 1.0f / cct; + final float icct2 = icct * icct; + final float x = cct <= 7000.0f ? + 0.244063f + 0.09911e3f * icct + 2.9678e6f * icct2 - 4.6070e9f * icct2 * icct : + 0.237040f + 0.24748e3f * icct + 1.9018e6f * icct2 - 2.0064e9f * icct2 * icct; + final float y = -3.0f * x * x + 2.87f * x - 0.275f; + return xyYToXyz(new float[] {x, y}); + } + + /** * <p>Computes the chromatic adaptation transform from the specified * source white point to the specified destination white point.</p> * diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index dbe6e8f4eebb..9b86b77a9384 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -249,7 +249,22 @@ public class Typeface { if (familyBuilder == null) { return Typeface.DEFAULT; } - typeface = new Typeface.CustomFallbackBuilder(familyBuilder.build()).build(); + final FontFamily family = familyBuilder.build(); + final FontStyle normal = new FontStyle(FontStyle.FONT_WEIGHT_NORMAL, + FontStyle.FONT_SLANT_UPRIGHT); + Font bestFont = family.getFont(0); + int bestScore = normal.getMatchScore(bestFont.getStyle()); + for (int i = 1; i < family.getSize(); ++i) { + final Font candidate = family.getFont(i); + final int score = normal.getMatchScore(candidate.getStyle()); + if (score < bestScore) { + bestFont = candidate; + bestScore = score; + } + } + typeface = new Typeface.CustomFallbackBuilder(family) + .setStyle(bestFont.getStyle()) + .build(); } catch (IOException e) { typeface = Typeface.DEFAULT; } diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java index dea2f45e9d33..cb12a7c6ba6b 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -19,6 +19,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; +import android.app.ActivityThread; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -150,11 +151,14 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback */ AdaptiveIconDrawable(@Nullable LayerState state, @Nullable Resources res) { mLayerState = createConstantState(state, res); - - if (sMask == null) { - sMask = PathParser.createPathFromPathData( - Resources.getSystem().getString(R.string.config_icon_mask)); - } + // config_icon_mask from context bound resource may have been chaged using + // OverlayManager. Read that one first. + Resources r = ActivityThread.currentActivityThread() == null + ? Resources.getSystem() + : ActivityThread.currentActivityThread().getApplication().getResources(); + // TODO: either make sMask update only when config_icon_mask changes OR + // get rid of it all-together in layoutlib + sMask = PathParser.createPathFromPathData(r.getString(R.string.config_icon_mask)); mMask = new Path(sMask); mMaskScaleOnly = new Path(mMask); mMaskMatrix = new Matrix(); diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 87402342a3c9..991847ad27fa 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -1571,15 +1571,32 @@ public class GradientDrawable extends Drawable { st.mGradient = a.getInt( R.styleable.GradientDrawableGradient_type, st.mGradient); - // TODO: Update these to be themeable. + final boolean hasGradientColors = st.mGradientColors != null; + final boolean hasGradientCenter = st.hasCenterColor(); + final int prevStart = hasGradientColors ? st.mGradientColors[0] : 0; + final int prevCenter = hasGradientCenter ? st.mGradientColors[1] : 0; + final int prevEnd; + + if (st.hasCenterColor()) { + // if there is a center color, the end color is the last of the 3 values + prevEnd = st.mGradientColors[2]; + } else if (hasGradientColors) { + // if there is not a center color but there are already colors configured, then + // the end color is the 2nd value in the array + prevEnd = st.mGradientColors[1]; + } else { + // otherwise, there isn't a previously configured end color + prevEnd = 0; + } + final int startColor = a.getColor( - R.styleable.GradientDrawableGradient_startColor, 0); + R.styleable.GradientDrawableGradient_startColor, prevStart); final boolean hasCenterColor = a.hasValue( - R.styleable.GradientDrawableGradient_centerColor); + R.styleable.GradientDrawableGradient_centerColor) || hasGradientCenter; final int centerColor = a.getColor( - R.styleable.GradientDrawableGradient_centerColor, 0); + R.styleable.GradientDrawableGradient_centerColor, prevCenter); final int endColor = a.getColor( - R.styleable.GradientDrawableGradient_endColor, 0); + R.styleable.GradientDrawableGradient_endColor, prevEnd); if (hasCenterColor) { st.mGradientColors = new int[3]; @@ -1943,6 +1960,10 @@ public class GradientDrawable extends Drawable { } } + public boolean hasCenterColor() { + return mGradientColors != null && mGradientColors.length == 3; + } + private void applyDensityScaling(int sourceDensity, int targetDensity) { if (mInnerRadius > 0) { mInnerRadius = Drawable.scaleFromDensity( diff --git a/graphics/java/android/graphics/fonts/FontStyle.java b/graphics/java/android/graphics/fonts/FontStyle.java index 82fc7ac01772..af517d623b01 100644 --- a/graphics/java/android/graphics/fonts/FontStyle.java +++ b/graphics/java/android/graphics/fonts/FontStyle.java @@ -18,6 +18,7 @@ package android.graphics.fonts; import android.annotation.IntDef; import android.annotation.IntRange; +import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.util.Preconditions; @@ -232,6 +233,16 @@ public final class FontStyle { return mSlant; } + /** + * Compute the matching score for another style. + * + * The smaller is better. + * @hide + */ + public int getMatchScore(@NonNull FontStyle o) { + return Math.abs((getWeight() - o.getWeight())) / 100 + (getSlant() == o.getSlant() ? 0 : 2); + } + @Override public boolean equals(@Nullable Object o) { if (o == this) { diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 7ab12b1b3167..ad9ec02648b1 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -217,10 +217,19 @@ std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_ ATRACE_NAME("AssetManager::GetResourceConfigurations"); std::set<ResTable_config> configurations; for (const PackageGroup& package_group : package_groups_) { + bool found_system_package = false; for (const ConfiguredPackage& package : package_group.packages_) { if (exclude_system && package.loaded_package_->IsSystem()) { + found_system_package = true; continue; } + + if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) { + // Overlays must appear after the target package to take effect. Any overlay found in the + // same package as a system package is able to overlay system resources. + continue; + } + package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations); } } @@ -232,10 +241,19 @@ std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system, ATRACE_NAME("AssetManager::GetResourceLocales"); std::set<std::string> locales; for (const PackageGroup& package_group : package_groups_) { + bool found_system_package = false; for (const ConfiguredPackage& package : package_group.packages_) { if (exclude_system && package.loaded_package_->IsSystem()) { + found_system_package = true; continue; } + + if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) { + // Overlays must appear after the target package to take effect. Any overlay found in the + // same package as a system package is able to overlay system resources. + continue; + } + package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales); } } diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index 68d216d286cf..c20c720eadbb 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -583,7 +583,65 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, loaded_package->dynamic_package_map_.emplace_back(std::move(package_name), dtohl(entry_iter->packageId)); } + } break; + + case RES_TABLE_OVERLAYABLE_TYPE: { + const ResTable_overlayable_header* header = + child_chunk.header<ResTable_overlayable_header>(); + if (header == nullptr) { + LOG(ERROR) << "RES_TABLE_OVERLAYABLE_TYPE too small."; + return {}; + } + + // Iterate over the overlayable policy chunks + ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); + while (overlayable_iter.HasNext()) { + const Chunk overlayable_child_chunk = overlayable_iter.Next(); + + switch (overlayable_child_chunk.type()) { + case RES_TABLE_OVERLAYABLE_POLICY_TYPE: { + const ResTable_overlayable_policy_header* policy_header = + overlayable_child_chunk.header<ResTable_overlayable_policy_header>(); + if (policy_header == nullptr) { + LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small."; + return {}; + } + + if ((overlayable_child_chunk.data_size() / sizeof(ResTable_ref)) + < dtohl(policy_header->entry_count)) { + LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small to hold entries."; + return {}; + } + + // Retrieve all the ids belonging to this policy + std::unordered_set<uint32_t> ids; + const auto ids_begin = + reinterpret_cast<const ResTable_ref*>(overlayable_child_chunk.data_ptr()); + const auto ids_end = ids_begin + dtohl(policy_header->entry_count); + for (auto id_iter = ids_begin; id_iter != ids_end; ++id_iter) { + ids.insert(dtohl(id_iter->ident)); + } + + // Add the pairing of overlayable properties to resource ids to the package + OverlayableInfo overlayable_info; + overlayable_info.policy_flags = policy_header->policy_flags; + loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids)); + break; + } + + default: + LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); + break; + } + } + if (overlayable_iter.HadError()) { + LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_POLICY_TYPE: %s", + overlayable_iter.GetLastError().c_str()); + if (overlayable_iter.HadFatalError()) { + return {}; + } + } } break; default: diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 2fe98b00f3a2..63b25270f116 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -7076,7 +7076,7 @@ public: } } - const auto& getTypeMapping() const { + const std::map<uint8_t, std::set<std::pair<uint32_t, uint32_t>>>& getTypeMapping() const { return mTypeMapping->mData; } @@ -7137,9 +7137,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, const PackageGroup* packageGroup = mPackageGroups[0]; - // the number of resources overlaid that were not explicitly marked overlayable - size_t forcedOverlayCount = 0u; - // find the resources that exist in both packages auto typeMapping = std::make_unique<IdmapTypeMapping>(); for (size_t typeIndex = 0; typeIndex < packageGroup->types.size(); ++typeIndex) { @@ -7170,11 +7167,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, continue; } - if ((dtohl(typeConfigs->typeSpecFlags[entryIndex]) & - ResTable_typeSpec::SPEC_OVERLAYABLE) == 0) { - ++forcedOverlayCount; - } - typeMapping->add(target_resid, overlay_resid); } } @@ -7243,10 +7235,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, typeData += entryCount * 2; } - if (forcedOverlayCount > 0) { - ALOGW("idmap: overlaid %zu resources not marked overlayable", forcedOverlayCount); - } - return NO_ERROR; } diff --git a/libs/androidfw/include/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h index 99a52dc9244e..a0f23433c676 100644 --- a/libs/androidfw/include/androidfw/Chunk.h +++ b/libs/androidfw/include/androidfw/Chunk.h @@ -89,7 +89,9 @@ class ChunkIterator { len_(len), last_error_(nullptr) { CHECK(next_chunk_ != nullptr) << "data can't be nullptr"; - VerifyNextChunk(); + if (len_ != 0) { + VerifyNextChunk(); + } } Chunk Next(); diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h index 349b379778a6..8c5c3b7d3858 100644 --- a/libs/androidfw/include/androidfw/LoadedArsc.h +++ b/libs/androidfw/include/androidfw/LoadedArsc.h @@ -20,6 +20,7 @@ #include <memory> #include <set> #include <vector> +#include <unordered_set> #include "android-base/macros.h" @@ -76,6 +77,10 @@ struct TypeSpec { // TypeSpecPtr is a managed pointer that knows how to delete itself. using TypeSpecPtr = util::unique_cptr<TypeSpec>; +struct OverlayableInfo { + uint32_t policy_flags; +}; + class LoadedPackage { public: class iterator { @@ -216,6 +221,18 @@ class LoadedPackage { } } + // Retrieve the overlayable properties of the specified resource. If the resource is not + // overlayable, this will return a null pointer. + const OverlayableInfo* GetOverlayableInfo(uint32_t resid) const { + for (const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>& overlayable_info_ids + : overlayable_infos_) { + if (overlayable_info_ids.second.find(resid) != overlayable_info_ids.second.end()) { + return &overlayable_info_ids.first; + } + } + return nullptr; + } + private: DISALLOW_COPY_AND_ASSIGN(LoadedPackage); @@ -233,6 +250,7 @@ class LoadedPackage { ByteBucketArray<TypeSpecPtr> type_specs_; ByteBucketArray<uint32_t> resource_ids_; std::vector<DynamicPackageEntry> dynamic_package_map_; + std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_; }; // Read-only view into a resource table. This class validates all data diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index ad33fcfa2429..91261aa3e4f9 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -234,7 +234,9 @@ enum { RES_TABLE_PACKAGE_TYPE = 0x0200, RES_TABLE_TYPE_TYPE = 0x0201, RES_TABLE_TYPE_SPEC_TYPE = 0x0202, - RES_TABLE_LIBRARY_TYPE = 0x0203 + RES_TABLE_LIBRARY_TYPE = 0x0203, + RES_TABLE_OVERLAYABLE_TYPE = 0x0204, + RES_TABLE_OVERLAYABLE_POLICY_TYPE = 0x0205, }; /** @@ -1354,10 +1356,6 @@ struct ResTable_typeSpec enum : uint32_t { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000u, - - // Additional flag indicating an entry is overlayable at runtime. - // Added in Android-P. - SPEC_OVERLAYABLE = 0x80000000u, }; }; @@ -1607,6 +1605,49 @@ struct ResTable_lib_entry uint16_t packageName[128]; }; +/** + * Specifies the set of resources that are explicitly allowed to be overlaid by RROs. + */ +struct ResTable_overlayable_header +{ + struct ResChunk_header header; +}; + +/** + * Holds a list of resource ids that are protected from being overlaid by a set of policies. If + * the overlay fulfils at least one of the policies, then the overlay can overlay the list of + * resources. + */ +struct ResTable_overlayable_policy_header +{ + struct ResChunk_header header; + + enum PolicyFlags { + // Any overlay can overlay these resources. + POLICY_PUBLIC = 0x00000001, + + // The overlay must reside of the system partition or must have existed on the system partition + // before an upgrade to overlay these resources. + POLICY_SYSTEM_PARTITION = 0x00000002, + + // The overlay must reside of the vendor partition or must have existed on the vendor partition + // before an upgrade to overlay these resources. + POLICY_VENDOR_PARTITION = 0x00000004, + + // The overlay must reside of the product partition or must have existed on the product + // partition before an upgrade to overlay these resources. + POLICY_PRODUCT_PARTITION = 0x00000008, + + // The overlay must reside of the product services partition or must have existed on the product + // services partition before an upgrade to overlay these resources. + POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010, + }; + uint32_t policy_flags; + + // The number of ResTable_ref that follow this header. + uint32_t entry_count; +}; + struct alignas(uint32_t) Idmap_header { // Always 0x504D4449 ('IDMP') uint32_t magic; diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp index ffa48367c252..441356b95d36 100644 --- a/libs/androidfw/tests/LoadedArsc_test.cpp +++ b/libs/androidfw/tests/LoadedArsc_test.cpp @@ -22,12 +22,14 @@ #include "TestHelpers.h" #include "data/basic/R.h" #include "data/libclient/R.h" +#include "data/overlayable/R.h" #include "data/sparse/R.h" #include "data/styles/R.h" namespace app = com::android::app; namespace basic = com::android::basic; namespace libclient = com::android::libclient; +namespace overlayable = com::android::overlayable; namespace sparse = com::android::sparse; using ::android::base::ReadFileToString; @@ -273,10 +275,44 @@ TEST(LoadedArscTest, LoadOverlay) { ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull()); } -// structs with size fields (like Res_value, ResTable_entry) should be -// backwards and forwards compatible (aka checking the size field against -// sizeof(Res_value) might not be backwards compatible. -TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } +TEST(LoadedArscTest, LoadOverlayable) { + std::string contents; + ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk", + "resources.arsc", &contents)); + + std::unique_ptr<const LoadedArsc> loaded_arsc = + LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/, + false /*load_as_shared_library*/); + + ASSERT_THAT(loaded_arsc, NotNull()); + const LoadedPackage* package = loaded_arsc->GetPackageById( + get_package_id(overlayable::R::string::not_overlayable)); + + const OverlayableInfo* info = package->GetOverlayableInfo( + overlayable::R::string::not_overlayable); + ASSERT_THAT(info, IsNull()); + + info = package->GetOverlayableInfo(overlayable::R::string::overlayable1); + ASSERT_THAT(info, NotNull()); + EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC)); + + info = package->GetOverlayableInfo(overlayable::R::string::overlayable2); + ASSERT_THAT(info, NotNull()); + EXPECT_THAT(info->policy_flags, + Eq(ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION + | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); + + info = package->GetOverlayableInfo(overlayable::R::string::overlayable3); + ASSERT_THAT(info, NotNull()); + EXPECT_THAT(info->policy_flags, + Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION + | ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION + | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); + + info = package->GetOverlayableInfo(overlayable::R::string::overlayable4); + ASSERT_THAT(info, NotNull()); + EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC)); +} TEST(LoadedArscTest, ResourceIdentifierIterator) { std::string contents; @@ -326,4 +362,9 @@ TEST(LoadedArscTest, ResourceIdentifierIterator) { ASSERT_EQ(end, iter); } +// structs with size fields (like Res_value, ResTable_entry) should be +// backwards and forwards compatible (aka checking the size field against +// sizeof(Res_value) might not be backwards compatible. +TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } + } // namespace android diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk Binary files differindex 33f961117c44..d37874dcbb40 100644 --- a/libs/androidfw/tests/data/overlay/overlay.apk +++ b/libs/androidfw/tests/data/overlay/overlay.apk diff --git a/packages/SystemUI/res/anim/system_in.xml b/libs/androidfw/tests/data/overlayable/AndroidManifest.xml index 630fd72189cd..abc2a454e845 100644 --- a/packages/SystemUI/res/anim/system_in.xml +++ b/libs/androidfw/tests/data/overlayable/AndroidManifest.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2010 The Android Open Source Project +<!-- 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. @@ -14,9 +14,8 @@ limitations under the License. --> -<set xmlns:android="http://schemas.android.com/apk/res/android" - > - <alpha android:fromAlpha="0.0" android:toAlpha="1.0" - android:duration="@android:integer/config_longAnimTime" - /> -</set> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.overlayable"> + <application> + </application> +</manifest> diff --git a/libs/androidfw/tests/data/overlayable/R.h b/libs/androidfw/tests/data/overlayable/R.h new file mode 100644 index 000000000000..e46e264da318 --- /dev/null +++ b/libs/androidfw/tests/data/overlayable/R.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef TESTS_DATA_OVERLAYABLE_R_H_ +#define TESTS_DATA_OVERLAYABLE_R_H_ + +#include <cstdint> + +namespace com { +namespace android { +namespace overlayable { + +struct R { + struct string { + enum : uint32_t { + not_overlayable = 0x7f010000, + overlayable1 = 0x7f010001, + overlayable2 = 0x7f010002, + overlayable3 = 0x7f010003, + overlayable4 = 0x7f010004, + }; + }; +}; + +} // namespace overlayable +} // namespace android +} // namespace com + +#endif /* TESTS_DATA_OVERLAYABLE_R_H_ */ diff --git a/libs/androidfw/tests/data/overlayable/build b/libs/androidfw/tests/data/overlayable/build new file mode 100755 index 000000000000..98fdc5101160 --- /dev/null +++ b/libs/androidfw/tests/data/overlayable/build @@ -0,0 +1,22 @@ +#!/bin/bash +# +# 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. +# + +set -e + +aapt2 compile --dir res -o compiled.flata +aapt2 link --manifest AndroidManifest.xml -o overlayable.apk compiled.flata +rm compiled.flata diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk Binary files differnew file mode 100644 index 000000000000..85ab4be7a2e5 --- /dev/null +++ b/libs/androidfw/tests/data/overlayable/overlayable.apk diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml new file mode 100644 index 000000000000..11aa7354901d --- /dev/null +++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> +<overlayable> + <!-- Any overlay can overlay the value of @string/overlayable1 --> + <item type="string" name="overlayable1" /> + + <!-- Any overlay on the product or system partition can overlay the value of + @string/overlayable2 --> + <policy type="product|system"> + <item type="string" name="overlayable2" /> + </policy> + + <!-- Any overlay can overlay the value of @string/overlayable4 --> + <policy type="public"> + <item type="string" name="overlayable4" /> + </policy> +</overlayable> + +<overlayable> + <!-- Any overlay on the product_services, vendor, or product partition can overlay the value of + @string/overlayable3 --> + <policy type="product_services|vendor|product"> + <item type="string" name="overlayable3" /> + </policy> +</overlayable> +</resources>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/ic_portrait_to_rotate_arrows_animation.xml b/libs/androidfw/tests/data/overlayable/res/values/public.xml index cdb7890dc170..5676d7cc64c9 100644 --- a/packages/SystemUI/res/anim/ic_portrait_to_rotate_arrows_animation.xml +++ b/libs/androidfw/tests/data/overlayable/res/values/public.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project +<!-- 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. @@ -14,13 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. --> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="616" - android:propertyName="rotation" - android:valueFrom="0.0" - android:valueTo="-221.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> + +<resources> + <public type="string" name="not_overlayable" id="0x7f010000" /> + <public type="string" name="overlayable1" id="0x7f010001" /> + <public type="string" name="overlayable2" id="0x7f010002" /> + <public type="string" name="overlayable3" id="0x7f010003" /> + <public type="string" name="overlayable4" id="0x7f010004" /> +</resources>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/system_out.xml b/libs/androidfw/tests/data/overlayable/res/values/values.xml index 4717e47784b9..a86b31282bc9 100644 --- a/packages/SystemUI/res/anim/system_out.xml +++ b/libs/androidfw/tests/data/overlayable/res/values/values.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2010 The Android Open Source Project +<!-- 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. @@ -14,9 +14,10 @@ limitations under the License. --> -<set xmlns:android="http://schemas.android.com/apk/res/android" - > - <alpha android:toAlpha="0.0" android:fromAlpha="1.0" - android:duration="@android:integer/config_longAnimTime" - /> -</set> +<resources> + <string name="not_overlayable">Not overlayable</string> + <string name="overlayable1">Overlayable One</string> + <string name="overlayable2">Overlayable Two</string> + <string name="overlayable3">Overlayable Three</string> + <string name="overlayable4">Overlayable Four</string> +</resources> diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 4a5b61a2d6cd..da77b99e6e53 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -9,8 +9,6 @@ cc_defaults { "hwui_lto", ], - cpp_std: "c++17", - cflags: [ "-DEGL_EGLEXT_PROTOTYPES", "-DGL_GLEXT_PROTOTYPES", diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp index 06e937ab66f4..0cfaa8c61279 100644 --- a/libs/hwui/CanvasTransform.cpp +++ b/libs/hwui/CanvasTransform.cpp @@ -146,4 +146,4 @@ bool transformPaint(ColorTransform transform, SkPaint* paint, BitmapPalette pale return shouldInvert; } -}; // namespace android::uirenderer
\ No newline at end of file +} // namespace android::uirenderer diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index a952cc23e1ef..dc63e5db4a70 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -31,5 +31,5 @@ typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; */ using DisplayList = skiapipeline::SkiaDisplayList; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/FrameMetricsObserver.h b/libs/hwui/FrameMetricsObserver.h index ba72e937095f..237fc622dd2e 100644 --- a/libs/hwui/FrameMetricsObserver.h +++ b/libs/hwui/FrameMetricsObserver.h @@ -26,5 +26,5 @@ public: virtual void notify(const int64_t* buffer); }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/FrameMetricsReporter.h b/libs/hwui/FrameMetricsReporter.h index d920a99f5ee3..75b8038c5040 100644 --- a/libs/hwui/FrameMetricsReporter.h +++ b/libs/hwui/FrameMetricsReporter.h @@ -56,5 +56,5 @@ private: std::vector<sp<FrameMetricsObserver> > mObservers; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/GlFunctorLifecycleListener.h b/libs/hwui/GlFunctorLifecycleListener.h index 5d07b46919d4..5adc46961c8b 100644 --- a/libs/hwui/GlFunctorLifecycleListener.h +++ b/libs/hwui/GlFunctorLifecycleListener.h @@ -28,5 +28,5 @@ public: virtual void onGlFunctorReleased(Functor* functor) = 0; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 165fc4860fb2..a97c12cad9fd 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -256,4 +256,4 @@ sk_sp<Bitmap> HardwareBitmapUploader::allocateHardwareBitmap(const SkBitmap& sou return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info(), Bitmap::computePalette(bitmap))); } -}; // namespace android::uirenderer +} // namespace android::uirenderer diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h index c0113d81fefb..6298013bd263 100644 --- a/libs/hwui/HardwareBitmapUploader.h +++ b/libs/hwui/HardwareBitmapUploader.h @@ -25,4 +25,4 @@ public: static sk_sp<Bitmap> allocateHardwareBitmap(const SkBitmap& sourceBitmap); }; -}; // namespace android::uirenderer +} // namespace android::uirenderer diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index d0df200d2fa6..a15ff2235db2 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -54,5 +54,5 @@ SkBlendMode Layer::getMode() const { } } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 98600dbf1eea..ea3bfc9e80cb 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -144,5 +144,5 @@ private: }; // struct Layer -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h index 6857999500f0..2c63af6aaab4 100644 --- a/libs/hwui/LayerUpdateQueue.h +++ b/libs/hwui/LayerUpdateQueue.h @@ -50,7 +50,7 @@ private: std::vector<Entry> mEntries; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_LAYER_UPDATE_QUEUE_H diff --git a/libs/hwui/Lighting.h b/libs/hwui/Lighting.h index d972c2181aea..ccfbb93b00ef 100644 --- a/libs/hwui/Lighting.h +++ b/libs/hwui/Lighting.h @@ -34,5 +34,5 @@ struct LightInfo { uint8_t spotShadowAlpha; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index d84ed321a4cb..d0dbff031e99 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -526,5 +526,5 @@ void Matrix4::dump(const char* label) const { ALOGD("]"); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 1b5cb60ca4bd..b33cfe2ec511 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -245,5 +245,5 @@ private: typedef Matrix4 mat4; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/NinePatchUtils.h b/libs/hwui/NinePatchUtils.h index 082e95fb1440..86d3cb9a5b11 100644 --- a/libs/hwui/NinePatchUtils.h +++ b/libs/hwui/NinePatchUtils.h @@ -103,5 +103,5 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice } } -}; // namespace NinePatchUtils -}; // namespace android +} // namespace NinePatchUtils +} // namespace android diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp index ad599e9ec316..808921d344da 100644 --- a/libs/hwui/PathParser.cpp +++ b/libs/hwui/PathParser.cpp @@ -304,5 +304,5 @@ void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, return; } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h index 474eb97b53c6..f5bebce605fb 100644 --- a/libs/hwui/PathParser.h +++ b/libs/hwui/PathParser.h @@ -46,6 +46,6 @@ public: static void validateVerbAndPoints(char verb, size_t points, ParseResult* result); }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_PATHPARSER_H diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 1f5324440477..8067313b2cb2 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -198,5 +198,5 @@ void Properties::overrideRenderPipelineType(RenderPipelineType type) { sRenderPipelineType = type; } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index f94b10861afd..0a7f4e7eb41c 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -257,7 +257,7 @@ private: static RenderPipelineType sRenderPipelineType; }; // class Caches -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_PROPERTIES_H diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index f928de9b92a6..c63e449319dd 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -1028,5 +1028,5 @@ void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { fDL->drawVectorDrawable(tree); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 099e0be433ea..08cfc6266f56 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -216,5 +216,5 @@ private: DisplayListData* fDL; }; -}; // namespace uirenderer -}; // namespace android
\ No newline at end of file +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index 0715187e19ea..d6362ef10aad 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -262,5 +262,5 @@ public: } }; // class Rect -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index ba343841d760..6be7ef72cf5d 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -681,7 +681,7 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } - SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); + SkASSERT(paintCopy.getTextEncoding() == kGlyphID_SkTextEncoding); // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and // older. if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0 && @@ -708,7 +708,7 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } - SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); + SkASSERT(paintCopy.getTextEncoding() == kGlyphID_SkTextEncoding); const int N = end - start; SkAutoSTMalloc<1024, uint8_t> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform))); diff --git a/libs/hwui/UvMapper.h b/libs/hwui/UvMapper.h index b495e3394bc9..833ca4a79ce5 100644 --- a/libs/hwui/UvMapper.h +++ b/libs/hwui/UvMapper.h @@ -124,7 +124,7 @@ private: float mMaxV; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_UV_MAPPER_H diff --git a/libs/hwui/Vector.h b/libs/hwui/Vector.h index d2c15ad872a5..e6eea1c5c0ca 100644 --- a/libs/hwui/Vector.h +++ b/libs/hwui/Vector.h @@ -113,7 +113,7 @@ public: } }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_VECTOR_H diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 6cf04bf5f811..dd62bbbdc84f 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -691,7 +691,7 @@ BitmapPalette Tree::computePalette() { return BitmapPalette::Unknown; } -}; // namespace VectorDrawable +} // namespace VectorDrawable -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index f0912777e3d8..28cabb9be0f1 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -73,7 +73,7 @@ struct TextureVertex { REQUIRE_COMPATIBLE_LAYOUT(TextureVertex); -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_VERTEX_H diff --git a/libs/hwui/VertexBuffer.h b/libs/hwui/VertexBuffer.h index 613cf4af64b2..6543a2251f7a 100644 --- a/libs/hwui/VertexBuffer.h +++ b/libs/hwui/VertexBuffer.h @@ -174,7 +174,7 @@ private: void (*mCleanupIndexMethod)(void*); }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_VERTEX_BUFFER_H diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index e99742bc2eba..a5f21d8e6d73 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -76,8 +76,8 @@ typedef uint32_t Flags; namespace uirenderer { namespace VectorDrawable { class Tree; -}; -}; +} +} typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; typedef std::function<void(uint16_t* text, float* positions)> ReadGlyphFunc; @@ -318,4 +318,4 @@ protected: friend class DrawTextOnPathFunctor; }; -}; // namespace android +} // namespace android diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index 769fce498a70..84292c8768c1 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -43,7 +43,7 @@ MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontDat static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint, const minikin::MinikinPaint& paint, const minikin::FontFakery& fakery) { - skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); + skPaint->setTextEncoding(kGlyphID_SkTextEncoding); skPaint->setTextSize(paint.size); skPaint->setTextScaleX(paint.scaleX); skPaint->setTextSkewX(paint.skewX); diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h index efef6de2a9e1..bf19655825b3 100644 --- a/libs/hwui/pipeline/skia/AnimatedDrawables.h +++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h @@ -79,6 +79,6 @@ private: sp<uirenderer::CanvasPropertyPaint> mPaint; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h index e4ba13da709c..206219426bb0 100644 --- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h +++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h @@ -172,6 +172,6 @@ private: std::string mIdent; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/FunctorDrawable.h b/libs/hwui/pipeline/skia/FunctorDrawable.h index 162d13762e1a..af3a056864a7 100644 --- a/libs/hwui/pipeline/skia/FunctorDrawable.h +++ b/libs/hwui/pipeline/skia/FunctorDrawable.h @@ -48,6 +48,6 @@ protected: const SkRect mBounds; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index 90d5e715f8cd..4a87e7502c6f 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -216,6 +216,6 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { } } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.h b/libs/hwui/pipeline/skia/GLFunctorDrawable.h index b06f7f029f23..215979cba2e3 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.h +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.h @@ -41,6 +41,6 @@ protected: void onDraw(SkCanvas* canvas) override; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp index 9b408fbc95ca..f08ac17e4082 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -145,6 +145,6 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer return layerImage != nullptr; } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h index 5c125908ffb2..95dc6d0cf096 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.h +++ b/libs/hwui/pipeline/skia/LayerDrawable.h @@ -45,6 +45,6 @@ private: sp<DeferredLayerUpdater> mLayerUpdater; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index d80cb6d1ab70..4494cb05df10 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -332,6 +332,6 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S } } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h index d746978b0a61..6ba8e599818c 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h @@ -150,6 +150,6 @@ private: SkiaDisplayList* mProjectedDisplayList = nullptr; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp index dba97fe5ef9f..0a3c8f4347eb 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp @@ -211,6 +211,6 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0); } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h index 26cfa908228c..cfc0f9b258da 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.h @@ -74,6 +74,6 @@ private: StartReorderBarrierDrawable* mStartBarrier; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index 38905138e332..ac6f6a3f776d 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -141,6 +141,6 @@ void SkiaDisplayList::output(std::ostream& output, uint32_t level) { mDisplayList.draw(&canvas); } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index ac7bb7b0950c..d7879e722a29 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -36,7 +36,7 @@ class Outline; namespace VectorDrawable { class Tree; -}; +} typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; namespace skiapipeline { @@ -179,6 +179,6 @@ public: SkMatrix mParentMatrix; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index f5de1c8adfaf..b682ab0256dd 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -259,6 +259,6 @@ double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedIma return 0; } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 988728dfe23e..d6107a9d9969 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -92,6 +92,6 @@ private: PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter); }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index a494e490aea1..3607b23a633e 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -122,8 +122,9 @@ bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior, mVkSurface = nullptr; } + mSurfaceColorSpace = SkColorSpace::MakeSRGB(); if (surface) { - mVkSurface = mVkManager.createSurface(surface, colorMode); + mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace); } if (colorMode == ColorMode::SRGB) { diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp index a594206a2dd9..004a558dd9d0 100644 --- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp @@ -219,6 +219,6 @@ void VkInteropFunctorDrawable::syncFunctor() const { }); } -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h index 3269cfbb8fe3..8fe52c5ef700 100644 --- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h +++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h @@ -51,6 +51,6 @@ private: SkImageInfo mFBInfo; }; -}; // namespace skiapipeline -}; // namespace uirenderer -}; // namespace android +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/private/hwui/DrawGlInfo.h b/libs/hwui/private/hwui/DrawGlInfo.h index efa9da27199d..9e1bb8e8e548 100644 --- a/libs/hwui/private/hwui/DrawGlInfo.h +++ b/libs/hwui/private/hwui/DrawGlInfo.h @@ -83,7 +83,7 @@ struct DrawGlInfo { }; }; // struct DrawGlInfo -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_DRAW_GL_INFO_H diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index f1a522ecd588..6869972b5e7f 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -323,25 +323,6 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy // the deadline for RT animations info.out.canDrawThisFrame = false; } - /* This logic exists to try and recover from a display latch miss, which essentially - * results in the bufferqueue being double-buffered instead of triple-buffered. - * SurfaceFlinger itself now tries to handle & recover from this situation, so this - * logic should no longer be necessary. As it's occasionally triggering when - * undesired disable it. - * TODO: Remove this entirely if the results are solid. - else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3 || - (latestVsync - mLastDropVsync) < 500_ms) { - // It's been several frame intervals, assume the buffer queue is fine - // or the last drop was too recent - info.out.canDrawThisFrame = true; - } else { - info.out.canDrawThisFrame = !isSwapChainStuffed(); - if (!info.out.canDrawThisFrame) { - // dropping frame - mLastDropVsync = mRenderThread.timeLord().latestVsync(); - } - } - */ } else { info.out.canDrawThisFrame = true; } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 6668c5840c3e..d9b789f28f8d 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -49,7 +49,7 @@ enum { Reset = 1 << 1, JankStats = 1 << 2, }; -}; +} /* * RenderProxy is strictly single threaded. All methods must be invoked on the owning diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 9a6df75fedd9..2abb3d5179a0 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -472,8 +472,9 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight); if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) { ColorMode colorMode = surface->mColorMode; + sk_sp<SkColorSpace> colorSpace = surface->mColorSpace; destroySurface(surface); - *surfaceOut = createSurface(window, colorMode); + *surfaceOut = createSurface(window, colorMode, colorSpace); surface = *surfaceOut; } @@ -647,7 +648,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget( mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin, surface->mColorMode == ColorMode::WideColorGamut ? kRGBA_F16_SkColorType - : kRGBA_8888_SkColorType, nullptr, &props); + : kRGBA_8888_SkColorType, surface->mColorSpace, &props); } SkASSERT(mCommandPool != VK_NULL_HANDLE); @@ -744,7 +745,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { surface->mWindowWidth = extent.width; surface->mWindowHeight = extent.height; - uint32_t imageCount = caps.minImageCount + 2; + uint32_t imageCount = std::max<uint32_t>(3, caps.minImageCount); if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) { // Application must settle for fewer images than desired: imageCount = caps.maxImageCount; @@ -833,14 +834,15 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { return true; } -VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode) { +VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode, + sk_sp<SkColorSpace> surfaceColorSpace) { initialize(); if (!window) { return nullptr; } - VulkanSurface* surface = new VulkanSurface(colorMode, window); + VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace); VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo; memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR)); diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 8594a1bd4339..d67d2c81e95c 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -38,8 +38,8 @@ class RenderThread; class VulkanSurface { public: - VulkanSurface(ColorMode colorMode, ANativeWindow* window) - : mColorMode(colorMode), mNativeWindow(window) {} + VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace) + : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace) {} sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; } @@ -79,6 +79,7 @@ private: ANativeWindow* mNativeWindow; int mWindowWidth = 0; int mWindowHeight = 0; + sk_sp<SkColorSpace> mColorSpace; }; // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue, @@ -96,7 +97,8 @@ public: // Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new // VulkanSurface object which is returned. - VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode); + VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode, + sk_sp<SkColorSpace> surfaceColorSpace); // Destroy the VulkanSurface and all associated vulkan objects. void destroySurface(VulkanSurface* surface); diff --git a/libs/hwui/surfacetexture/EGLConsumer.cpp b/libs/hwui/surfacetexture/EGLConsumer.cpp index c8220c6cb0d4..85b3917809fa 100644 --- a/libs/hwui/surfacetexture/EGLConsumer.cpp +++ b/libs/hwui/surfacetexture/EGLConsumer.cpp @@ -672,4 +672,4 @@ EGLImageKHR EGLConsumer::EglImage::createImage(EGLDisplay dpy, return image; } -}; // namespace android +} // namespace android diff --git a/libs/hwui/surfacetexture/EGLConsumer.h b/libs/hwui/surfacetexture/EGLConsumer.h index eccb08298f6f..7dac3ef0f44a 100644 --- a/libs/hwui/surfacetexture/EGLConsumer.h +++ b/libs/hwui/surfacetexture/EGLConsumer.h @@ -308,4 +308,4 @@ protected: sp<EglImage> mReleasedTexImage; }; -}; // namespace android +} // namespace android diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h index 5bab0ef58a9a..f0e55bbf19f8 100644 --- a/libs/hwui/surfacetexture/ImageConsumer.h +++ b/libs/hwui/surfacetexture/ImageConsumer.h @@ -97,4 +97,4 @@ private: ImageSlot mImageSlots[BufferQueueDefs::NUM_BUFFER_SLOTS]; }; -}; /* namespace android */ +} /* namespace android */ diff --git a/libs/hwui/surfacetexture/SurfaceTexture.cpp b/libs/hwui/surfacetexture/SurfaceTexture.cpp index 90f891265572..da094442684d 100644 --- a/libs/hwui/surfacetexture/SurfaceTexture.cpp +++ b/libs/hwui/surfacetexture/SurfaceTexture.cpp @@ -491,4 +491,4 @@ sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, bool* que return image; } -}; // namespace android +} // namespace android diff --git a/libs/hwui/surfacetexture/SurfaceTexture.h b/libs/hwui/surfacetexture/SurfaceTexture.h index 96afd82b0d40..b5d136ff3058 100644 --- a/libs/hwui/surfacetexture/SurfaceTexture.h +++ b/libs/hwui/surfacetexture/SurfaceTexture.h @@ -449,4 +449,4 @@ protected: }; // ---------------------------------------------------------------------------- -}; // namespace android +} // namespace android diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index 8a1bc4d2f7f2..f81202292a49 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -81,7 +81,7 @@ void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint auto utf16 = asciiToUtf16(text); uint32_t length = strlen(text); SkPaint glyphPaint(paint); - glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + glyphPaint.setTextEncoding(kGlyphID_SkTextEncoding); canvas->drawText( utf16.get(), length, // text buffer 0, length, // draw range @@ -94,7 +94,7 @@ void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint const SkPath& path) { auto utf16 = asciiToUtf16(text); SkPaint glyphPaint(paint); - glyphPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + glyphPaint.setTextEncoding(kGlyphID_SkTextEncoding); canvas->drawTextOnPath(utf16.get(), strlen(text), minikin::Bidi::LTR, path, 0, 0, glyphPaint, nullptr); } diff --git a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp index 217d63f9c2e1..41714ebd84b1 100644 --- a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp +++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp @@ -81,5 +81,5 @@ TEST(LayerUpdateQueue, clear) { EXPECT_TRUE(queue.entries().empty()); } -}; -}; +} +} diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp index 02f740cee096..ee6beba847a0 100644 --- a/libs/hwui/tests/unit/VectorDrawableTests.cpp +++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp @@ -406,5 +406,5 @@ TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) { EXPECT_TRUE(shader->unique()); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h index 8faeee6b391a..bb750ca0fa88 100644 --- a/libs/hwui/thread/Barrier.h +++ b/libs/hwui/thread/Barrier.h @@ -48,7 +48,7 @@ private: mutable Condition mCondition; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_BARRIER_H diff --git a/libs/hwui/thread/Future.h b/libs/hwui/thread/Future.h index 45f3102492e3..df53348e58fb 100644 --- a/libs/hwui/thread/Future.h +++ b/libs/hwui/thread/Future.h @@ -53,7 +53,7 @@ private: T mResult; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_FUTURE_H diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h index ffcd4b675a85..6d33ac473ac4 100644 --- a/libs/hwui/thread/Signal.h +++ b/libs/hwui/thread/Signal.h @@ -53,7 +53,7 @@ private: mutable Condition mCondition; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_SIGNAL_H diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h index 276a22f941fe..228ce19a2fd5 100644 --- a/libs/hwui/thread/Task.h +++ b/libs/hwui/thread/Task.h @@ -48,7 +48,7 @@ private: sp<Future<T> > mFuture; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_TASK_H diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp index 54b55e472095..26ff6ebad3b4 100644 --- a/libs/hwui/thread/TaskManager.cpp +++ b/libs/hwui/thread/TaskManager.cpp @@ -129,5 +129,5 @@ void TaskManager::WorkerThread::exit() { mSignal.signal(); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h index 29b4fcdbfde9..c4c1291e755c 100644 --- a/libs/hwui/thread/TaskManager.h +++ b/libs/hwui/thread/TaskManager.h @@ -101,7 +101,7 @@ private: std::vector<sp<WorkerThread> > mThreads; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_TASK_MANAGER_H diff --git a/libs/hwui/utils/Blur.cpp b/libs/hwui/utils/Blur.cpp index 1bc5646993c9..763d1aa177b7 100644 --- a/libs/hwui/utils/Blur.cpp +++ b/libs/hwui/utils/Blur.cpp @@ -178,5 +178,5 @@ void Blur::vertical(float* weights, int32_t radius, const uint8_t* source, uint8 } } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/Blur.h b/libs/hwui/utils/Blur.h index bec3837106e8..d6b41b83def8 100644 --- a/libs/hwui/utils/Blur.h +++ b/libs/hwui/utils/Blur.h @@ -41,7 +41,7 @@ public: int32_t width, int32_t height); }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_HWUI_BLUR_H diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp index 3fb6a31a7d97..dc347f615d98 100644 --- a/libs/hwui/utils/Color.cpp +++ b/libs/hwui/utils/Color.cpp @@ -221,5 +221,5 @@ SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) { static_cast<uint8_t>(rgb.b * 255)); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h index eafe2f13c16d..8cc4d1010ab6 100644 --- a/libs/hwui/utils/FatVector.h +++ b/libs/hwui/utils/FatVector.h @@ -99,7 +99,7 @@ private: typename InlineStdAllocator<T, SIZE>::Allocation mAllocation; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_FAT_VECTOR_H diff --git a/libs/hwui/utils/GLUtils.cpp b/libs/hwui/utils/GLUtils.cpp index fcd036c451e9..c694e93f7e21 100644 --- a/libs/hwui/utils/GLUtils.cpp +++ b/libs/hwui/utils/GLUtils.cpp @@ -76,5 +76,5 @@ const char* GLUtils::getGLFramebufferError() { } } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/LinearAllocator.cpp b/libs/hwui/utils/LinearAllocator.cpp index 3e5021cd45d4..8baa4b770f85 100644 --- a/libs/hwui/utils/LinearAllocator.cpp +++ b/libs/hwui/utils/LinearAllocator.cpp @@ -249,5 +249,5 @@ void LinearAllocator::dumpMemoryStats(const char* prefix) { ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount); } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h index 03f685e8aca8..b401fcf58f76 100644 --- a/libs/hwui/utils/LinearAllocator.h +++ b/libs/hwui/utils/LinearAllocator.h @@ -201,7 +201,7 @@ public: : std::vector<T, LinearStdAllocator<T>>(allocator) {} }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif // ANDROID_LINEARALLOCATOR_H diff --git a/libs/hwui/utils/Pair.h b/libs/hwui/utils/Pair.h index 4bcd57629e0c..76f93cbfeb92 100644 --- a/libs/hwui/utils/Pair.h +++ b/libs/hwui/utils/Pair.h @@ -36,7 +36,7 @@ struct Pair { inline const S& getSecond() const { return second; } }; -}; // namespace uirenderer +} // namespace uirenderer template <typename F, typename S> struct trait_trivial_ctor<uirenderer::Pair<F, S> > { @@ -55,6 +55,6 @@ struct trait_trivial_move<uirenderer::Pair<F, S> > { enum { value = aggregate_traits<F, S>::has_trivial_move }; }; -}; // namespace android +} // namespace android #endif // ANDROID_HWUI_PAIR_H diff --git a/libs/hwui/utils/Result.h b/libs/hwui/utils/Result.h index 7f33f2e3424d..bd20ba66d8a7 100644 --- a/libs/hwui/utils/Result.h +++ b/libs/hwui/utils/Result.h @@ -51,4 +51,4 @@ private: std::variant<R, Error<E>> result; }; -}; // namespace android::uirenderer +} // namespace android::uirenderer diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h index b3e893139cf8..081386a7f671 100644 --- a/libs/hwui/utils/RingBuffer.h +++ b/libs/hwui/utils/RingBuffer.h @@ -61,7 +61,7 @@ private: size_t mCount = 0; }; -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android #endif /* RINGBUFFER_H_ */ diff --git a/libs/hwui/utils/StringUtils.cpp b/libs/hwui/utils/StringUtils.cpp index 5304b762f3dc..304982e8e493 100644 --- a/libs/hwui/utils/StringUtils.cpp +++ b/libs/hwui/utils/StringUtils.cpp @@ -34,5 +34,5 @@ unordered_string_set StringUtils::split(const char* spacedList) { return set; } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/TypeLogic.h b/libs/hwui/utils/TypeLogic.h index dbdad33d8335..1689ccecd6b1 100644 --- a/libs/hwui/utils/TypeLogic.h +++ b/libs/hwui/utils/TypeLogic.h @@ -37,4 +37,4 @@ template <typename D, typename S> struct copy_cv { template <typename D, typename S> using same_cv = copy_cv<std::remove_cv_t<D>, S>; template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type; -}; // namespace android::uirenderer
\ No newline at end of file +} // namespace android::uirenderer diff --git a/media/OWNERS b/media/OWNERS index 0abf9aeb6101..03b751c07c6c 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -1,12 +1,13 @@ +chz@google.com +dwkang@google.com elaurent@google.com etalvala@google.com gkasten@google.com hunga@google.com +jaewan@google.com jmtrivi@google.com +jsharkey@android.com lajos@google.com marcone@google.com sungsoo@google.com wjia@google.com -jaewan@google.com -chz@google.com -dwkang@google.com diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 2a575b626a44..4b2353c992f2 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -16,16 +16,6 @@ package android.media; -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.ref.WeakReference; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.List; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; @@ -39,13 +29,21 @@ import android.os.Message; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; import com.android.internal.annotations.GuardedBy; +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * The AudioRecord class manages the audio resources for Java applications * to record audio from the audio input hardware of the platform. This is @@ -1807,6 +1805,8 @@ public class AudioRecord implements AudioRouting private native final int native_get_active_microphones( ArrayList<MicrophoneInfo> activeMicrophones); + private native int native_getPortId(); + //--------------------------------------------------------- // Utility methods //------------------ diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index c226d49c6af7..2c4ec3a1a0a6 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -2620,7 +2620,8 @@ public class AudioTrack extends PlayerBase * to the audio sink. * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after * queuing as much audio data for playback as possible without blocking. - * @param timestamp The timestamp of the first decodable audio frame in the provided audioData. + * @param timestamp The timestamp, in nanoseconds, of the first decodable audio frame in the + * provided audioData. * @return zero or the positive number of bytes that were written, or one of the following * error codes. * <ul> @@ -3422,6 +3423,8 @@ public class AudioTrack extends PlayerBase private native @Nullable VolumeShaper.State native_getVolumeShaperState(int id); private native final int native_setPresentation(int presentationId, int programId); + private native int native_getPortId(); + //--------------------------------------------------------- // Utility methods //------------------ diff --git a/media/java/android/media/CloseGuard.java b/media/java/android/media/CloseGuard.java new file mode 100644 index 000000000000..20146739fe4c --- /dev/null +++ b/media/java/android/media/CloseGuard.java @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.media; + +import android.util.Log; + +/** + * Note: This file is copied from dalvik.system package with the following modifications: + * - Remove @CorePlatformApi, @IntraCoreApi and @UnsupportedAppUsage annotations. + * - Replace System.logW() with android.util.Log.w(). + * This file should be used only within media mainline module. + * TODO: Remove this file and use dalvik.system.CloseGuard once + * @CorePlatformApi becomes stable or we have a replacement in SDK API. + * b/120419300 + * + * CloseGuard is a mechanism for flagging implicit finalizer cleanup of + * resources that should have been cleaned up by explicit close + * methods (aka "explicit termination methods" in Effective Java). + * <p> + * A simple example: <pre> {@code + * class Foo { + * + * {@literal @}ReachabilitySensitive + * private final CloseGuard guard = CloseGuard.get(); + * + * ... + * + * public Foo() { + * ...; + * guard.open("cleanup"); + * } + * + * public void cleanup() { + * guard.close(); + * ...; + * } + * + * protected void finalize() throws Throwable { + * try { + * // Note that guard could be null if the constructor threw. + * if (guard != null) { + * guard.warnIfOpen(); + * } + * cleanup(); + * } finally { + * super.finalize(); + * } + * } + * } + * }</pre> + * + * In usage where the resource to be explicitly cleaned up is + * allocated after object construction, CloseGuard protection can + * be deferred. For example: <pre> {@code + * class Bar { + * + * {@literal @}ReachabilitySensitive + * private final CloseGuard guard = CloseGuard.get(); + * + * ... + * + * public Bar() { + * ...; + * } + * + * public void connect() { + * ...; + * guard.open("cleanup"); + * } + * + * public void cleanup() { + * guard.close(); + * ...; + * } + * + * protected void finalize() throws Throwable { + * try { + * // Note that guard could be null if the constructor threw. + * if (guard != null) { + * guard.warnIfOpen(); + * } + * cleanup(); + * } finally { + * super.finalize(); + * } + * } + * } + * }</pre> + * + * When used in a constructor, calls to {@code open} should occur at + * the end of the constructor since an exception that would cause + * abrupt termination of the constructor will mean that the user will + * not have a reference to the object to cleanup explicitly. When used + * in a method, the call to {@code open} should occur just after + * resource acquisition. + * + * The @ReachabilitySensitive annotation ensures that finalize() cannot be + * called during the explicit call to cleanup(), prior to the guard.close call. + * There is an extremely small chance that, for code that neglects to call + * cleanup(), finalize() and thus cleanup() will be called while a method on + * the object is still active, but the "this" reference is no longer required. + * If missing cleanup() calls are expected, additional @ReachabilitySensitive + * annotations or reachabilityFence() calls may be required. + * + * @hide + */ +final class CloseGuard { + + /** + * True if collection of call-site information (the expensive operation + * here) and tracking via a Tracker (see below) are enabled. + * Enabled by default so we can diagnose issues early in VM startup. + * Note, however, that Android disables this early in its startup, + * but enables it with DropBoxing for system apps on debug builds. + */ + private static volatile boolean stackAndTrackingEnabled = true; + + /** + * Hook for customizing how CloseGuard issues are reported. + * Bypassed if stackAndTrackingEnabled was false when open was called. + */ + private static volatile Reporter reporter = new DefaultReporter(); + + /** + * Hook for customizing how CloseGuard issues are tracked. + */ + private static volatile Tracker currentTracker = null; // Disabled by default. + + /** + * Returns a CloseGuard instance. {@code #open(String)} can be used to set + * up the instance to warn on failure to close. + */ + public static CloseGuard get() { + return new CloseGuard(); + } + + /** + * Enables/disables stack capture and tracking. A call stack is captured + * during open(), and open/close events are reported to the Tracker, only + * if enabled is true. If a stack trace was captured, the {@link + * #getReporter() reporter} is informed of unclosed resources; otherwise a + * one-line warning is logged. + */ + public static void setEnabled(boolean enabled) { + CloseGuard.stackAndTrackingEnabled = enabled; + } + + /** + * True if CloseGuard stack capture and tracking are enabled. + */ + public static boolean isEnabled() { + return stackAndTrackingEnabled; + } + + /** + * Used to replace default Reporter used to warn of CloseGuard + * violations when stack tracking is enabled. Must be non-null. + */ + public static void setReporter(Reporter rep) { + if (rep == null) { + throw new NullPointerException("reporter == null"); + } + CloseGuard.reporter = rep; + } + + /** + * Returns non-null CloseGuard.Reporter. + */ + public static Reporter getReporter() { + return reporter; + } + + /** + * Sets the {@link Tracker} that is notified when resources are allocated and released. + * The Tracker is invoked only if CloseGuard {@link #isEnabled()} held when {@link #open()} + * was called. A null argument disables tracking. + * + * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so + * MUST NOT be used for any other purposes. + */ + public static void setTracker(Tracker tracker) { + currentTracker = tracker; + } + + /** + * Returns {@link #setTracker(Tracker) last Tracker that was set}, or null to indicate + * there is none. + * + * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so + * MUST NOT be used for any other purposes. + */ + public static Tracker getTracker() { + return currentTracker; + } + + private CloseGuard() {} + + /** + * {@code open} initializes the instance with a warning that the caller + * should have explicitly called the {@code closer} method instead of + * relying on finalization. + * + * @param closer non-null name of explicit termination method. Printed by warnIfOpen. + * @throws NullPointerException if closer is null. + */ + public void open(String closer) { + // always perform the check for valid API usage... + if (closer == null) { + throw new NullPointerException("closer == null"); + } + // ...but avoid allocating an allocation stack if "disabled" + if (!stackAndTrackingEnabled) { + closerNameOrAllocationInfo = closer; + return; + } + String message = "Explicit termination method '" + closer + "' not called"; + Throwable stack = new Throwable(message); + closerNameOrAllocationInfo = stack; + Tracker tracker = currentTracker; + if (tracker != null) { + tracker.open(stack); + } + } + + // We keep either an allocation stack containing the closer String or, when + // in disabled state, just the closer String. + // We keep them in a single field only to minimize overhead. + private Object /* String or Throwable */ closerNameOrAllocationInfo; + + /** + * Marks this CloseGuard instance as closed to avoid warnings on + * finalization. + */ + public void close() { + Tracker tracker = currentTracker; + if (tracker != null && closerNameOrAllocationInfo instanceof Throwable) { + // Invoke tracker on close only if we invoked it on open. Tracker may have changed. + tracker.close((Throwable) closerNameOrAllocationInfo); + } + closerNameOrAllocationInfo = null; + } + + /** + * Logs a warning if the caller did not properly cleanup by calling an + * explicit close method before finalization. If CloseGuard was enabled + * when the CloseGuard was created, passes the stacktrace associated with + * the allocation to the current reporter. If it was not enabled, it just + * directly logs a brief message. + */ + public void warnIfOpen() { + if (closerNameOrAllocationInfo != null) { + if (closerNameOrAllocationInfo instanceof String) { + Log.w("CloseGuard", "A resource failed to call " + + (String) closerNameOrAllocationInfo + ". "); + } else { + String message = + "A resource was acquired at attached stack trace but never released. "; + message += "See java.io.Closeable for information on avoiding resource leaks."; + Throwable stack = (Throwable) closerNameOrAllocationInfo; + reporter.report(message, stack); + } + } + } + + /** + * Interface to allow customization of tracking behaviour. + * + * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so + * MUST NOT be used for any other purposes. + */ + public interface Tracker { + void open(Throwable allocationSite); + void close(Throwable allocationSite); + } + + /** + * Interface to allow customization of reporting behavior. + * @hide + */ + public interface Reporter { + void report(String message, Throwable allocationSite); + } + + /** + * Default Reporter which reports CloseGuard violations to the log. + */ + private static final class DefaultReporter implements Reporter { + private DefaultReporter() {} + + @Override public void report (String message, Throwable allocationSite) { + Log.w("CloseGuard", message, allocationSite); + } + } +} diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 01a0cb619bf0..32c4643adad0 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -2635,13 +2635,18 @@ public class ExifInterface { if (size == 0) { return 0; } - // We don't allow read positions after the available bytes, - // the input stream won't be able to seek back then. - if (position < 0 || position >= in.available()) { + if (position < 0) { return -1; } try { if (mPosition != position) { + // We don't allow seek to positions after the available bytes, + // the input stream won't be able to seek back then. + // However, if we hit an exception before (mPosition set to -1), + // let it try the seek in hope it might recover. + if (mPosition >= 0 && position >= mPosition + in.available()) { + return -1; + } in.seek(position); mPosition = position; } @@ -2649,8 +2654,8 @@ public class ExifInterface { // If the read will cause us to go over the available bytes, // reduce the size so that we stay in the available range. // Otherwise the input stream may not be able to seek back. - if (mPosition + size > in.available()) { - size = in.available() - (int)mPosition; + if (size > in.available()) { + size = in.available(); } int bytesRead = in.read(buffer, offset, size); diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 284e422374aa..b7743c9db4c0 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -17,20 +17,29 @@ package android.media; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; +import java.util.AbstractSet; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** - * Encapsulates the information describing the format of media data, - * be it audio or video. - * - * The format of the media data is specified as string/value pairs. - * + * Encapsulates the information describing the format of media data, be it audio or video, as + * well as optional feature metadata. + * <p> + * The format of the media data is specified as key/value pairs. Keys are strings. Values can + * be integer, long, float, String or ByteBuffer. + * <p> + * The feature metadata is specificed as string/boolean pairs. + * <p> * Keys common to all audio/video formats, <b>all keys not marked optional are mandatory</b>: * * <table> @@ -938,7 +947,6 @@ public final class MediaFormat { */ public static final String KEY_CA_SESSION_ID = "ca-session-id"; - /** * A key describing the private data in the CA_descriptor associated with a media track. * <p> @@ -950,7 +958,7 @@ public final class MediaFormat { */ public static final String KEY_CA_PRIVATE_DATA = "ca-private-data"; - /* package private */ MediaFormat(Map<String, Object> map) { + /* package private */ MediaFormat(@NonNull Map<String, Object> map) { mMap = map; } @@ -969,11 +977,58 @@ public final class MediaFormat { /** * Returns true iff a key of the given name exists in the format. */ - public final boolean containsKey(String name) { + public final boolean containsKey(@NonNull String name) { return mMap.containsKey(name); } /** + * Returns true iff a feature of the given name exists in the format. + */ + public final boolean containsFeature(@NonNull String name) { + return mMap.containsKey(KEY_FEATURE_ + name); + } + + public static final int TYPE_NULL = 0; + public static final int TYPE_INTEGER = 1; + public static final int TYPE_LONG = 2; + public static final int TYPE_FLOAT = 3; + public static final int TYPE_STRING = 4; + public static final int TYPE_BYTE_BUFFER = 5; + + /** @hide */ + @IntDef({ + TYPE_NULL, + TYPE_INTEGER, + TYPE_LONG, + TYPE_FLOAT, + TYPE_STRING, + TYPE_BYTE_BUFFER + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Type {} + + /** + * Returns the value type for a key. If the key does not exist, it returns TYPE_NULL. + */ + public final @Type int getValueTypeForKey(@NonNull String name) { + Object value = mMap.get(name); + if (value == null) { + return TYPE_NULL; + } else if (value instanceof Integer) { + return TYPE_INTEGER; + } else if (value instanceof Long) { + return TYPE_LONG; + } else if (value instanceof Float) { + return TYPE_FLOAT; + } else if (value instanceof String) { + return TYPE_STRING; + } else if (value instanceof ByteBuffer) { + return TYPE_BYTE_BUFFER; + } + throw new RuntimeException("invalid value for key"); + } + + /** * A key prefix used together with a {@link MediaCodecInfo.CodecCapabilities} * feature name describing a required or optional feature for a codec capabilities * query. @@ -989,64 +1044,165 @@ public final class MediaFormat { public static final String KEY_FEATURE_ = "feature-"; /** + * Returns the value of a numeric key. This is provided as a convenience method for keys + * that may take multiple numeric types, such as {@link #KEY_FRAME_RATE}, or {@link + * #KEY_I_FRAME_INTERVAL}. + * + * @return null if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is ByteBuffer or String + */ + public final @Nullable Number getNumber(@NonNull String name) { + return ((Number)mMap.get(name)); + } + + /** + * Returns the value of a numeric key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is ByteBuffer or String + */ + public final @NonNull Number getNumber(@NonNull String name, @NonNull Number defaultValue) { + Number ret = getNumber(name); + return ret == null ? defaultValue : ret; + } + + /** * Returns the value of an integer key. + * + * @throws NullPointerException if the key does not exist or the stored value for the key is + * null + * @throws ClassCastException if the stored value for the key is long, float, ByteBuffer or + * String */ - public final int getInteger(String name) { + public final int getInteger(@NonNull String name) { return ((Integer)mMap.get(name)).intValue(); } /** - * Returns the value of an integer key, or the default value if the - * key is missing or is for another type value. - * @hide + * Returns the value of an integer key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is long, float, ByteBuffer or + * String */ - public final int getInteger(String name, int defaultValue) { + public final int getInteger(@NonNull String name, int defaultValue) { try { return getInteger(name); + } catch (NullPointerException e) { + /* no such field or field is null */ + return defaultValue; } - catch (NullPointerException e) { /* no such field */ } - catch (ClassCastException e) { /* field of different type */ } - return defaultValue; } /** * Returns the value of a long key. + * + * @throws NullPointerException if the key does not exist or the stored value for the key is + * null + * @throws ClassCastException if the stored value for the key is int, float, ByteBuffer or + * String */ - public final long getLong(String name) { + public final long getLong(@NonNull String name) { return ((Long)mMap.get(name)).longValue(); } /** + * Returns the value of an long key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, float, ByteBuffer or + * String + */ + public final long getLong(@NonNull String name, long defaultValue) { + try { + return getLong(name); + } catch (NullPointerException e) { + /* no such field or field is null */ + return defaultValue; + } + } + + /** * Returns the value of a float key. + * + * @throws NullPointerException if the key does not exist or the stored value for the key is + * null + * @throws ClassCastException if the stored value for the key is int, long, ByteBuffer or + * String */ - public final float getFloat(String name) { + public final float getFloat(@NonNull String name) { return ((Float)mMap.get(name)).floatValue(); } /** + * Returns the value of an float key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, long, ByteBuffer or + * String + */ + public final float getFloat(@NonNull String name, float defaultValue) { + try { + return getFloat(name); + } catch (NullPointerException e) { + /* no such field or field is null */ + return defaultValue; + } + } + + /** * Returns the value of a string key. + * + * @return null if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, long, float or ByteBuffer */ - public final String getString(String name) { + public final @Nullable String getString(@NonNull String name) { return (String)mMap.get(name); } /** + * Returns the value of an string key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, long, float or ByteBuffer + */ + public final @NonNull String getString(@NonNull String name, @NonNull String defaultValue) { + String ret = getString(name); + return ret == null ? defaultValue : ret; + } + + /** * Returns the value of a ByteBuffer key. + * + * @return null if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, long, float or String */ - public final ByteBuffer getByteBuffer(String name) { + public final @Nullable ByteBuffer getByteBuffer(@NonNull String name) { return (ByteBuffer)mMap.get(name); } /** + * Returns the value of a ByteBuffer key, or the default value if the key is missing. + * + * @return defaultValue if the key does not exist or the stored value for the key is null + * @throws ClassCastException if the stored value for the key is int, long, float or String + */ + public final @NonNull ByteBuffer getByteBuffer( + @NonNull String name, @NonNull ByteBuffer defaultValue) { + ByteBuffer ret = getByteBuffer(name); + return ret == null ? defaultValue : ret; + } + + /** * Returns whether a feature is to be enabled ({@code true}) or disabled * ({@code false}). * * @param feature the name of a {@link MediaCodecInfo.CodecCapabilities} feature. * * @throws IllegalArgumentException if the feature was neither set to be enabled - * nor to be disabled. + * nor to be disabled. */ - public boolean getFeatureEnabled(String feature) { + public boolean getFeatureEnabled(@NonNull String feature) { Integer enabled = (Integer)mMap.get(KEY_FEATURE_ + feature); if (enabled == null) { throw new IllegalArgumentException("feature is not specified"); @@ -1057,39 +1213,239 @@ public final class MediaFormat { /** * Sets the value of an integer key. */ - public final void setInteger(String name, int value) { + public final void setInteger(@NonNull String name, int value) { mMap.put(name, Integer.valueOf(value)); } /** * Sets the value of a long key. */ - public final void setLong(String name, long value) { + public final void setLong(@NonNull String name, long value) { mMap.put(name, Long.valueOf(value)); } /** * Sets the value of a float key. */ - public final void setFloat(String name, float value) { + public final void setFloat(@NonNull String name, float value) { mMap.put(name, new Float(value)); } /** * Sets the value of a string key. + * <p> + * If value is {@code null}, it sets a null value that behaves similarly to a missing key. + * This could be used prior to API level {@link android os.Build.VERSION_CODES#Q} to effectively + * remove a key. */ - public final void setString(String name, String value) { + public final void setString(@NonNull String name, @Nullable String value) { mMap.put(name, value); } /** * Sets the value of a ByteBuffer key. + * <p> + * If value is {@code null}, it sets a null value that behaves similarly to a missing key. + * This could be used prior to API level {@link android os.Build.VERSION_CODES#Q} to effectively + * remove a key. */ - public final void setByteBuffer(String name, ByteBuffer bytes) { + public final void setByteBuffer(@NonNull String name, @Nullable ByteBuffer bytes) { mMap.put(name, bytes); } /** + * Removes a value of a given key if present. Has no effect if the key is not present. + */ + public final void removeKey(@NonNull String name) { + // exclude feature mappings + if (!name.startsWith(KEY_FEATURE_)) { + mMap.remove(name); + } + } + + /** + * Removes a given feature setting if present. Has no effect if the feature setting is not + * present. + */ + public final void removeFeature(@NonNull String name) { + mMap.remove(KEY_FEATURE_ + name); + } + + /** + * A Partial set view for a portion of the keys in a MediaFormat object. + * + * This class is needed as we want to return a portion of the actual format keys in getKeys() + * and another portion of the keys in getFeatures(), and still allow the view properties. + */ + private abstract class FilteredMappedKeySet extends AbstractSet<String> { + private Set<String> mKeys; + + // Returns true if this set should include this key + abstract protected boolean keepKey(String key); + + // Maps a key from the underlying key set into its new value in this key set + abstract protected String mapKeyToItem(String key); + + // Maps a key from this key set into its original value in the underlying key set + abstract protected String mapItemToKey(String item); + + public FilteredMappedKeySet() { + mKeys = mMap.keySet(); + } + + // speed up contains and remove from abstract implementation (that would iterate + // over each element) + @Override + public boolean contains(Object o) { + if (o instanceof String) { + String key = mapItemToKey((String)o); + return keepKey(key) && mKeys.contains(key); + } + return false; + } + + @Override + public boolean remove(Object o) { + if (o instanceof String) { + String key = mapItemToKey((String)o); + if (keepKey(key) && mKeys.remove(key)) { + mMap.remove(key); + return true; + } + } + return false; + } + + private class KeyIterator implements Iterator<String> { + Iterator<String> mIterator; + String mLast; + + public KeyIterator() { + // We must create a copy of the filtered stream, as remove operation has to modify + // the underlying data structure (mMap), so the iterator's operation is undefined. + // Use a list as it is likely less memory consuming than the other alternative: set. + mIterator = + mKeys.stream().filter(k -> keepKey(k)).collect(Collectors.toList()).iterator(); + } + + @Override + public boolean hasNext() { + return mIterator.hasNext(); + } + + @Override + public String next() { + mLast = mIterator.next(); + return mapKeyToItem(mLast); + } + + @Override + public void remove() { + mIterator.remove(); + mMap.remove(mLast); + } + } + + @Override + public Iterator<String> iterator() { + return new KeyIterator(); + } + + @Override + public int size() { + return (int)mKeys.stream().filter(k -> keepKey(k)).count(); + } + } + + /** + * A Partial set view for a portion of the keys in a MediaFormat object for keys that + * don't start with a prefix, such as "feature-" + */ + private class UnprefixedKeySet extends FilteredMappedKeySet { + private String mPrefix; + + public UnprefixedKeySet(String prefix) { + super(); + mPrefix = prefix; + } + + protected boolean keepKey(String key) { + return !key.startsWith(mPrefix); + } + + protected String mapKeyToItem(String key) { + return key; + } + + protected String mapItemToKey(String item) { + return item; + } + } + + /** + * A Partial set view for a portion of the keys in a MediaFormat object for keys that + * start with a prefix, such as "feature-", with the prefix removed + */ + private class PrefixedKeySetWithPrefixRemoved extends FilteredMappedKeySet { + private String mPrefix; + private int mPrefixLength; + + public PrefixedKeySetWithPrefixRemoved(String prefix) { + super(); + mPrefix = prefix; + mPrefixLength = prefix.length(); + } + + protected boolean keepKey(String key) { + return key.startsWith(mPrefix); + } + + protected String mapKeyToItem(String key) { + return key.substring(mPrefixLength); + } + + protected String mapItemToKey(String item) { + return mPrefix + item; + } + } + + + /** + * Returns a {@link java.util.Set Set} view of the keys contained in this MediaFormat. + * + * The set is backed by the MediaFormat object, so changes to the format are reflected in the + * set, and vice-versa. If the format is modified while an iteration over the set is in progress + * (except through the iterator's own remove operation), the results of the iteration are + * undefined. The set supports element removal, which removes the corresponding mapping from the + * format, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. + * It does not support the add or addAll operations. + */ + public final @NonNull java.util.Set<String> getKeys() { + return new UnprefixedKeySet(KEY_FEATURE_); + } + + /** + * Returns a {@link java.util.Set Set} view of the features contained in this MediaFormat. + * + * The set is backed by the MediaFormat object, so changes to the format are reflected in the + * set, and vice-versa. If the format is modified while an iteration over the set is in progress + * (except through the iterator's own remove operation), the results of the iteration are + * undefined. The set supports element removal, which removes the corresponding mapping from the + * format, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. + * It does not support the add or addAll operations. + */ + public final @NonNull java.util.Set<String> getFeatures() { + return new PrefixedKeySetWithPrefixRemoved(KEY_FEATURE_); + } + + /** + * Create a copy of a media format object. + */ + public MediaFormat(@NonNull MediaFormat other) { + mMap.putAll(other.mMap); + } + + /** * Sets whether a feature is to be enabled ({@code true}) or disabled * ({@code false}). * @@ -1102,7 +1458,7 @@ public final class MediaFormat { * @see MediaCodecList#findEncoderForFormat * @see MediaCodecInfo.CodecCapabilities#isFormatSupported */ - public void setFeatureEnabled(String feature, boolean enabled) { + public void setFeatureEnabled(@NonNull String feature, boolean enabled) { setInteger(KEY_FEATURE_ + feature, enabled ? 1 : 0); } @@ -1112,8 +1468,8 @@ public final class MediaFormat { * @param sampleRate The sampling rate of the content. * @param channelCount The number of audio channels in the content. */ - public static final MediaFormat createAudioFormat( - String mime, + public static final @NonNull MediaFormat createAudioFormat( + @NonNull String mime, int sampleRate, int channelCount) { MediaFormat format = new MediaFormat(); @@ -1132,8 +1488,8 @@ public final class MediaFormat { * in the content. (This will also work if there are multiple language * tracks in the content.) */ - public static final MediaFormat createSubtitleFormat( - String mime, + public static final @NonNull MediaFormat createSubtitleFormat( + @NonNull String mime, String language) { MediaFormat format = new MediaFormat(); format.setString(KEY_MIME, mime); @@ -1148,8 +1504,8 @@ public final class MediaFormat { * @param width The width of the content (in pixels) * @param height The height of the content (in pixels) */ - public static final MediaFormat createVideoFormat( - String mime, + public static final @NonNull MediaFormat createVideoFormat( + @NonNull String mime, int width, int height) { MediaFormat format = new MediaFormat(); @@ -1161,7 +1517,7 @@ public final class MediaFormat { } @Override - public String toString() { + public @NonNull String toString() { return mMap.toString(); } } diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index 111dd0f0b63e..a10b2123a70c 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -48,8 +48,6 @@ import android.view.SurfaceHolder; import com.android.framework.protobuf.InvalidProtocolBufferException; import com.android.internal.annotations.GuardedBy; -import dalvik.system.CloseGuard; - import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 3a64f43f61de..90cfc534877e 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -156,7 +156,8 @@ public class MediaScanner implements AutoCloseable { private static final String NOTIFICATIONS_DIR = "/notifications/"; private static final String ALARMS_DIR = "/alarms/"; private static final String MUSIC_DIR = "/music/"; - private static final String PODCAST_DIR = "/podcasts/"; + private static final String PODCASTS_DIR = "/podcasts/"; + private static final String AUDIOBOOKS_DIR = "/audiobooks/"; public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild"; public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint"; @@ -654,7 +655,7 @@ public class MediaScanner implements AutoCloseable { // rescan for metadata if file was modified since last scan if (entry != null && (entry.mLastModifiedChanged || scanAlways)) { if (noMedia) { - result = endFile(entry, false, false, false, false, false); + result = endFile(entry, false, false, false, false, false, false); } else { boolean isaudio = MediaFile.isAudioMimeType(mMimeType); boolean isvideo = MediaFile.isVideoMimeType(mMimeType); @@ -679,11 +680,13 @@ public class MediaScanner implements AutoCloseable { boolean notifications = mScanSuccess && (lowpath.indexOf(NOTIFICATIONS_DIR) > 0); boolean alarms = mScanSuccess && (lowpath.indexOf(ALARMS_DIR) > 0); - boolean podcasts = mScanSuccess && (lowpath.indexOf(PODCAST_DIR) > 0); + boolean podcasts = mScanSuccess && (lowpath.indexOf(PODCASTS_DIR) > 0); + boolean audiobooks = mScanSuccess && (lowpath.indexOf(AUDIOBOOKS_DIR) > 0); boolean music = mScanSuccess && ((lowpath.indexOf(MUSIC_DIR) > 0) || - (!ringtones && !notifications && !alarms && !podcasts)); + (!ringtones && !notifications && !alarms && !podcasts && !audiobooks)); - result = endFile(entry, ringtones, notifications, alarms, music, podcasts); + result = endFile(entry, ringtones, notifications, alarms, podcasts, + audiobooks, music); } } } catch (RemoteException e) { @@ -957,7 +960,7 @@ public class MediaScanner implements AutoCloseable { @UnsupportedAppUsage private Uri endFile(FileEntry entry, boolean ringtones, boolean notifications, - boolean alarms, boolean music, boolean podcasts) + boolean alarms, boolean podcasts, boolean audiobooks, boolean music) throws RemoteException { // update database @@ -1003,6 +1006,7 @@ public class MediaScanner implements AutoCloseable { values.put(Audio.Media.IS_ALARM, alarms); values.put(Audio.Media.IS_MUSIC, music); values.put(Audio.Media.IS_PODCAST, podcasts); + values.put(Audio.Media.IS_AUDIOBOOK, audiobooks); } else if (MediaFile.isExifMimeType(mMimeType) && !mNoMedia) { ExifInterface exif = null; try { @@ -1011,12 +1015,6 @@ public class MediaScanner implements AutoCloseable { // exif is null } if (exif != null) { - float[] latlng = new float[2]; - if (exif.getLatLong(latlng)) { - values.put(Images.Media.LATITUDE, latlng[0]); - values.put(Images.Media.LONGITUDE, latlng[1]); - } - long time = exif.getGpsDateTime(); if (time != -1) { values.put(Images.Media.DATE_TAKEN, time); diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index a7bdf4f506b2..89a509f64a1b 100644 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -18,11 +18,12 @@ package android.media.audiofx; import android.annotation.UnsupportedAppUsage; import android.app.ActivityThread; -import android.util.Log; -import java.lang.ref.WeakReference; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.util.Log; + +import java.lang.ref.WeakReference; /** * The Visualizer class enables application to retrieve part of the currently playing audio for @@ -455,7 +456,7 @@ public class Visualizer { * <li> Rfk, Ifk are respectively the real and imaginary parts of the kth frequency * component</li> * <li> If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is: - * (k*Fs)/(n/2) </li> + * k * Fs / n </li> * </ul> * <table border="0" cellspacing="0" cellpadding="0"> * <tr><td>Index </p></td> @@ -476,9 +477,23 @@ public class Visualizer { * <td>Rf2 </p></td> * <td>If2 </p></td> * <td>... </p></td> - * <td>Rf(n-1)/2 </p></td> - * <td>If(n-1)/2 </p></td></tr> + * <td>Rf(n/2-1) </p></td> + * <td>If(n/2-1) </p></td></tr> * </table> + * <p>In order to obtain magnitude and phase values the following code can + * be used: + * <pre class="prettyprint"> + * int n = fft.size(); + * float[] magnitudes = new float[n / 2 + 1]; + * float[] phases = new float[n / 2 + 1]; + * magnitudes[0] = (float)Math.abs(fft[0]); // DC + * magnitudes[n / 2] = (float)Math.abs(fft[1]); // Nyquist + * phases[0] = phases[n / 2] = 0; + * for (int k = 1; k < n / 2; k++) { + * int i = k * 2; + * magnitudes[k] = (float)Math.hypot(fft[i], fft[i + 1]); + * phases[k] = (float)Math.atan2(fft[i + 1], fft[i]); + * }</pre> * @param fft array of bytes where the FFT should be returned * @return {@link #SUCCESS} in case of success, * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} @@ -561,25 +576,11 @@ public class Visualizer { * <p>Data in the fft buffer is valid only within the scope of the callback. * Applications which need access to the fft data after returning from the callback * should make a copy of the data instead of holding a reference. + * <p>For the explanation of the fft data array layout, and the example + * code for processing it, please see the documentation for {@link #getFft(byte[])} method. * - * <p>In order to obtain magnitude and phase values the following formulas can - * be used: - * <pre class="prettyprint"> - * for (int i = 0; i < fft.size(); i += 2) { - * float magnitude = (float)Math.hypot(fft[i], fft[i + 1]); - * float phase = (float)Math.atan2(fft[i + 1], fft[i]); - * }</pre> * @param visualizer Visualizer object on which the listener is registered. * @param fft array of bytes containing the frequency representation. - * The fft array only contains the first half of the actual - * FFT spectrum (frequencies up to Nyquist frequency), exploiting - * the symmetry of the spectrum. For each frequencies bin <code>i</code>: - * <ul> - * <li>the element at index <code>2*i</code> in the array contains - * the real part of a complex number,</li> - * <li>the element at index <code>2*i+1</code> contains the imaginary - * part of the complex number.</li> - * </ul> * @param samplingRate sampling rate of the visualized audio. */ void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate); diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 8215779d2b13..d91cf8732674 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -96,9 +96,15 @@ public final class MediaSessionManager { * @return The binder object from the system * @hide */ + @SystemApi public @NonNull ISession createSession(@NonNull MediaSession.CallbackStub cbStub, - @NonNull String tag, int userId) throws RemoteException { - return mService.createSession(mContext.getPackageName(), cbStub, tag, userId); + @NonNull String tag, int userId) { + try { + return mService.createSession(mContext.getPackageName(), cbStub, tag, userId); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return null; } /** diff --git a/native/webview/plat_support/draw_gl.h b/native/webview/plat_support/draw_gl.h index c8434b61eba5..de13ed0dec6f 100644 --- a/native/webview/plat_support/draw_gl.h +++ b/native/webview/plat_support/draw_gl.h @@ -43,9 +43,9 @@ struct AwDrawGLInfo { // Input: tells the draw function what action to perform. enum Mode { kModeDraw = 0, - kModeProcess, - kModeProcessNoContext, - kModeSync, + kModeProcess = 1, + kModeProcessNoContext = 2, + kModeSync = 3, } mode; // Input: current clip rect in surface coordinates. Reflects the current state @@ -93,9 +93,9 @@ typedef void (AwDrawGLFunction)(long view_context, AwDrawGLInfo* draw_info, void* spare); enum AwMapMode { - MAP_READ_ONLY, - MAP_WRITE_ONLY, - MAP_READ_WRITE, + MAP_READ_ONLY = 0, + MAP_WRITE_ONLY = 1, + MAP_READ_WRITE = 2, }; // Called to create a GraphicBuffer diff --git a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_down.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_down.xml index 74f38d4f9946..74f38d4f9946 100644 --- a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_down.xml +++ b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_down.xml diff --git a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_up.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_up.xml index 0f28297f0214..0f28297f0214 100644 --- a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_up.xml +++ b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_up.xml diff --git a/packages/SystemUI/res/anim/car_arrow_fade_out.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_out.xml index e6757d2862b1..e6757d2862b1 100644 --- a/packages/SystemUI/res/anim/car_arrow_fade_out.xml +++ b/packages/CarSystemUI/res/anim/car_arrow_fade_out.xml diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_animation.xml index ed637a7adcbf..6f12338d8db8 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_icon_animation.xml index 227c981cb72a..9f8c12ef16b5 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_icon_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_name_animation.xml index 5901ff41735c..adc1f720e91b 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_name_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_pages_animation.xml index 41cbe4b104c3..dec5c05dbce8 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_pages_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_pod_animation.xml index 341e7e0cdfe9..986a9cb06459 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_pod_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_open_animation.xml index 6ae74131584d..80b38b388aed 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_open_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_open_icon_animation.xml index 06ac9e359b57..721376cae960 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_open_icon_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_open_name_animation.xml index 4baefb83a4ef..246099ef7b35 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_open_name_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_open_pages_animation.xml index 2d0deb95da59..9a1c642363d0 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_open_pages_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_open_pod_animation.xml index 3315220a60ef..1414b6688c8f 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_open_pod_animation.xml @@ -1,4 +1,4 @@ -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/drawable/car_add_circle_round.xml b/packages/CarSystemUI/res/drawable/car_add_circle_round.xml index 13c7dd12f940..13c7dd12f940 100644 --- a/packages/SystemUI/res/drawable/car_add_circle_round.xml +++ b/packages/CarSystemUI/res/drawable/car_add_circle_round.xml diff --git a/packages/SystemUI/res/drawable/car_ic_add_white.xml b/packages/CarSystemUI/res/drawable/car_ic_add_white.xml index d6818607ec08..d6818607ec08 100644 --- a/packages/SystemUI/res/drawable/car_ic_add_white.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_add_white.xml diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/CarSystemUI/res/drawable/car_ic_arrow.xml index d400ed8c7707..cfacbf98354f 100644 --- a/packages/SystemUI/res/drawable/car_ic_arrow.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_arrow.xml @@ -1,5 +1,5 @@ <!-- - ~ Copyright (C) 2017 The Android Open Source Project + ~ 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. diff --git a/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml b/packages/CarSystemUI/res/drawable/car_ic_arrow_drop_up.xml index 33a512e31675..81e7262c7cea 100644 --- a/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_arrow_drop_up.xml @@ -1,5 +1,5 @@ <!-- - ~ Copyright (C) 2015 The Android Open Source Project + ~ 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. diff --git a/packages/SystemUI/res/drawable/car_ic_hvac.xml b/packages/CarSystemUI/res/drawable/car_ic_hvac.xml index bdc44b38a176..bdc44b38a176 100644 --- a/packages/SystemUI/res/drawable/car_ic_hvac.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_hvac.xml diff --git a/packages/SystemUI/res/drawable/car_ic_keyboard_arrow_down.xml b/packages/CarSystemUI/res/drawable/car_ic_keyboard_arrow_down.xml index 3709aa546766..3709aa546766 100644 --- a/packages/SystemUI/res/drawable/car_ic_keyboard_arrow_down.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_keyboard_arrow_down.xml diff --git a/packages/SystemUI/res/drawable/car_ic_navigation.xml b/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml index 328efa08abdd..eb501e5c26eb 100644 --- a/packages/SystemUI/res/drawable/car_ic_navigation.xml +++ b/packages/CarSystemUI/res/drawable/car_rounded_bg_bottom.xml @@ -14,15 +14,14 @@ ~ 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="32dp" - android:height="37dp" - android:viewportWidth="32.0" - android:viewportHeight="37.0"> - <path - android:pathData="M16.62,0.61L31.33,35.21C31.55,35.72 31.31,36.3 30.8,36.52C30.48,36.66 30.12,36.62 29.83,36.42L15.7,26.44L1.58,36.42C1.13,36.73 0.5,36.63 0.18,36.18C-0.02,35.89 -0.06,35.53 0.08,35.21L14.78,0.61C15,0.1 15.59,-0.14 16.1,0.08C16.33,0.18 16.52,0.37 16.62,0.61Z" - android:strokeColor="#00000000" - android:fillType="evenOdd" - android:fillColor="@color/car_grey_50" - android:strokeWidth="1"/> -</vector>
\ No newline at end of file + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="?android:attr/colorBackgroundFloating" /> + <corners + android:bottomLeftRadius="@dimen/car_radius_3" + android:topLeftRadius="0dp" + android:bottomRightRadius="@dimen/car_radius_3" + android:topRightRadius="0dp" + /> +</shape> diff --git a/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml b/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml new file mode 100644 index 000000000000..34578fe252d4 --- /dev/null +++ b/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml @@ -0,0 +1,28 @@ +<!-- +Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="17dp" + android:height="17dp" + android:viewportWidth="18.0" + android:viewportHeight="18.0"> + <group + android:translateY="0.5" + android:translateX="0.5" > + <path + android:pathData="M9.57,8.5l2.79,-2.78c0.3,-0.3 0.3,-0.8 0,-1.1L9.04,1.29L9.02,1.27C8.7,0.98 8.21,1 7.91,1.31C7.78,1.45 7.71,1.64 7.71,1.84v4.79L4.69,3.61c-0.3,-0.3 -0.79,-0.3 -1.09,0s-0.3,0.79 0,1.09L7.39,8.5L3.6,12.29c-0.3,0.3 -0.3,0.79 0,1.09s0.79,0.3 1.09,0l3.01,-3.01v4.8c0,0.42 0.35,0.77 0.77,0.77c0.19,0 0.39,-0.07 0.53,-0.21l0.04,-0.04l3.32,-3.32c0.3,-0.3 0.3,-0.8 0,-1.1L9.57,8.5zM9.19,6.77v-3.2l1.6,1.6L9.19,6.77zM9.19,13.42v-3.2l1.6,1.6L9.19,13.42zM4.03,9.29c-0.44,0.44 -1.15,0.44 -1.58,0C2.02,8.86 2.02,8.16 2.45,7.72l0.01,-0.01C2.89,7.27 3.59,7.27 4.02,7.7l0.01,0.01C4.47,8.15 4.47,8.85 4.03,9.29zM14.44,7.71c0.44,0.44 0.44,1.15 0,1.58c-0.44,0.44 -1.15,0.44 -1.58,0c-0.44,-0.43 -0.44,-1.13 -0.01,-1.57l0.01,-0.01C13.3,7.28 14,7.27 14.43,7.7C14.44,7.7 14.44,7.71 14.44,7.71z" + android:fillColor="#FFFFFF"/> + </group> +</vector> diff --git a/packages/CarSystemUI/res/drawable/ic_mic_white.xml b/packages/CarSystemUI/res/drawable/ic_mic_white.xml index f5a91b5ded32..e1e389d7f472 100644 --- a/packages/CarSystemUI/res/drawable/ic_mic_white.xml +++ b/packages/CarSystemUI/res/drawable/ic_mic_white.xml @@ -1,3 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" diff --git a/packages/SystemUI/res/layout/car_facet_button.xml b/packages/CarSystemUI/res/layout/car_facet_button.xml index ad8604935628..8e7ebad7d7ec 100644 --- a/packages/SystemUI/res/layout/car_facet_button.xml +++ b/packages/CarSystemUI/res/layout/car_facet_button.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2017, The Android Open Source Project +** 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. diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/CarSystemUI/res/layout/car_fullscreen_user_pod.xml index ee8d357a0b80..1d6728689933 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml +++ b/packages/CarSystemUI/res/layout/car_fullscreen_user_pod.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (C) 2015 The Android Open Source Project + 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. diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml index c9f51486e983..6cd70d62b4f7 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml +++ b/packages/CarSystemUI/res/layout/car_fullscreen_user_switcher.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2015 The Android Open Source Project + 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. diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml index 02be45788761..141b28a9ae28 100644 --- a/packages/SystemUI/res/layout/car_left_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2016, The Android Open Source Project +** 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. diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml index 708f5955f306..708f5955f306 100644 --- a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml +++ b/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml diff --git a/packages/SystemUI/res/layout/car_navigation_button.xml b/packages/CarSystemUI/res/layout/car_navigation_button.xml index 4062eb8068fa..6d8cca990fa1 100644 --- a/packages/SystemUI/res/layout/car_navigation_button.xml +++ b/packages/CarSystemUI/res/layout/car_navigation_button.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2016, The Android Open Source Project +** 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. diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/CarSystemUI/res/layout/car_qs_footer.xml index 3afd4ea33039..6f19cfcfa345 100644 --- a/packages/SystemUI/res/layout/car_qs_footer.xml +++ b/packages/CarSystemUI/res/layout/car_qs_footer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/CarSystemUI/res/layout/car_qs_panel.xml index e7413de342fa..dfa48c30b0c8 100644 --- a/packages/SystemUI/res/layout/car_qs_panel.xml +++ b/packages/CarSystemUI/res/layout/car_qs_panel.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project +<!-- 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. diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml index 91ba02622e9a..141b28a9ae28 100644 --- a/packages/SystemUI/res/layout/car_right_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2016, The Android Open Source Project +** 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. @@ -58,7 +58,6 @@ android:paddingTop="30dp" android:paddingBottom="30dp" /> - </LinearLayout> <LinearLayout @@ -79,7 +78,6 @@ android:alpha="0.7" /> - <com.android.systemui.statusbar.policy.Clock android:id="@+id/clock" android:textAppearance="@style/TextAppearance.StatusBar.Clock" diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml index 708f5955f306..708f5955f306 100644 --- a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml +++ b/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml diff --git a/packages/SystemUI/res/values/colors_car.xml b/packages/CarSystemUI/res/values/colors_car.xml index 49bfb250acab..2f720f5aba65 100644 --- a/packages/SystemUI/res/values/colors_car.xml +++ b/packages/CarSystemUI/res/values/colors_car.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- /* - * Copyright 2017, The Android Open Source Project + * 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. diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/CarSystemUI/res/values/dimens_car.xml index afbe17632346..c027f81eb8bd 100644 --- a/packages/SystemUI/res/values/dimens_car.xml +++ b/packages/CarSystemUI/res/values/dimens_car.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - * Copyright (c) 2016, The Android Open Source Project + * 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. diff --git a/packages/SystemUI/res/values/ids_car.xml b/packages/CarSystemUI/res/values/ids_car.xml index 27ed2e250d9f..27ed2e250d9f 100644 --- a/packages/SystemUI/res/values/ids_car.xml +++ b/packages/CarSystemUI/res/values/ids_car.xml diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml index fc3623cb69fb..472c957ab568 100644 --- a/packages/SystemUI/res/values/integers_car.xml +++ b/packages/CarSystemUI/res/values/integers_car.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (c) 2017, The Android Open Source Project + 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. diff --git a/packages/SystemUI/res/values/strings_car.xml b/packages/CarSystemUI/res/values/strings_car.xml index 2890cf275b37..83e91c57ccc3 100644 --- a/packages/SystemUI/res/values/strings_car.xml +++ b/packages/CarSystemUI/res/values/strings_car.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- /** - * Copyright (c) 2016, The Android Open Source Project + * 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. diff --git a/packages/CarSystemUI/res/xml/car_volume_items.xml b/packages/CarSystemUI/res/xml/car_volume_items.xml index 8715946aac26..922b1a79d45a 100644 --- a/packages/CarSystemUI/res/xml/car_volume_items.xml +++ b/packages/CarSystemUI/res/xml/car_volume_items.xml @@ -23,8 +23,8 @@ car:icon="@drawable/car_ic_music"/> <item car:usage="media" car:icon="@drawable/car_ic_music"/> - <item car:usage="voice_communication" - car:icon="@*android:drawable/ic_audio_ring_notif"/> + <item car:usage="assistance_navigation_guidance" + car:icon="@drawable/car_ic_navigation"/> <item car:usage="voice_communication_signalling" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="alarm" @@ -43,8 +43,8 @@ car:icon="@drawable/car_ic_notification"/> <item car:usage="assistance_accessibility" car:icon="@drawable/car_ic_notification"/> - <item car:usage="assistance_navigation_guidance" - car:icon="@drawable/car_ic_navigation"/> + <item car:usage="voice_communication" + car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistance_sonification" car:icon="@drawable/car_ic_notification"/> <item car:usage="game" diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java index dfe57044e4e0..f57f26db118c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java @@ -28,6 +28,8 @@ import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager; import com.android.systemui.statusbar.car.hvac.HvacController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.volume.CarVolumeDialogComponent; +import com.android.systemui.volume.VolumeDialogComponent; /** * Class factory to provide car specific SystemUI components. @@ -39,6 +41,10 @@ public class CarSystemUIFactory extends SystemUIFactory { return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils); } + public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) { + return new CarVolumeDialogComponent(systemUi, context); + } + @Override public void injectDependencies(ArrayMap<Object, DependencyProvider> providers, Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java index 50fefe948aa8..0563418e5fb9 100644 --- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -11,8 +11,9 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ + package com.android.systemui.car; import android.content.Context; diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFooter.java index 0389030a17b2..b74f1998bf9e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java +++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFooter.java @@ -1,16 +1,19 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.qs.car; import android.content.Context; diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java index 3e82c54dc811..41c37d3bbc19 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarQSFragment.java @@ -1,16 +1,19 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.qs.car; import android.animation.Animator; @@ -223,7 +226,7 @@ public class CarQSFragment extends Fragment implements QS { private void animateHeightChange(boolean opening) { // Animation in progress; cancel it to avoid contention. - if (mAnimatorSet != null){ + if (mAnimatorSet != null) { mAnimatorSet.cancel(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java index 083a7471c3c1..d5dd3c3eaca0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java +++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java @@ -1,16 +1,19 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.qs.car; import android.content.Context; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java index fc39648b7ac0..58f80a4ed968 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java @@ -58,28 +58,31 @@ public class CarBatteryController extends BroadcastReceiver implements BatteryCo private final Context mContext; private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); - private BluetoothHeadsetClient mBluetoothHeadsetClient; - private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); + private BluetoothHeadsetClient mBluetoothHeadsetClient; + private final ServiceListener mHfpServiceListener = new ServiceListener() { + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (profile == BluetoothProfile.HEADSET_CLIENT) { + mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; + } + } + @Override + public void onServiceDisconnected(int profile) { + if (profile == BluetoothProfile.HEADSET_CLIENT) { + mBluetoothHeadsetClient = null; + } + } + }; private int mLevel; - - /** - * An interface indicating the container of a View that will display what the information - * in the {@link CarBatteryController}. - */ - public interface BatteryViewHandler { - void hideBatteryView(); - void showBatteryView(); - } - private BatteryViewHandler mBatteryViewHandler; public CarBatteryController(Context context) { mContext = context; if (mAdapter == null) { - return; + return; } mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener, @@ -159,7 +162,7 @@ public class CarBatteryController extends BroadcastReceiver implements BatteryCo } BluetoothDevice device = - (BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE); + (BluetoothDevice) intent.getExtra(BluetoothDevice.EXTRA_DEVICE); updateBatteryIcon(device, newState); } } @@ -261,20 +264,14 @@ public class CarBatteryController extends BroadcastReceiver implements BatteryCo } } - private final ServiceListener mHfpServiceListener = new ServiceListener() { - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET_CLIENT) { - mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; - } - } + /** + * An interface indicating the container of a View that will display what the information + * in the {@link CarBatteryController}. + */ + public interface BatteryViewHandler { + void hideBatteryView(); - @Override - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET_CLIENT) { - mBluetoothHeadsetClient = null; - } - } - }; + void showBatteryView(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java index 20986adbfe9f..56db242f1eb9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.systemui.statusbar.car; import android.app.ActivityManager; @@ -34,7 +50,6 @@ public class CarFacetButtonController { * Add facet button to this controller. The expected use is for the facet button * to get a reference to this controller via {@link com.android.systemui.Dependency} * and self add. - * @param facetButton */ public void addFacetButton(CarFacetButton facetButton) { String[] categories = facetButton.getCategories(); @@ -70,15 +85,16 @@ public class CarFacetButtonController { * They will then be compared with the supplied StackInfo list. * The StackInfo is expected to be supplied in order of recency and StackInfo will only be used * for consideration if it has the same displayId as the CarFacetButtons. - * @param taskInfo of the currently running application + * + * @param stackInfoList of the currently running application */ public void taskChanged(List<ActivityManager.StackInfo> stackInfoList) { int displayId = getDisplayId(); ActivityManager.StackInfo validStackInfo = null; - for (ActivityManager.StackInfo stackInfo :stackInfoList) { + for (ActivityManager.StackInfo stackInfo : stackInfoList) { // If the display id is unknown or it matches the stack, it's valid for use - if ((displayId == -1 || displayId == stackInfo.displayId) && - stackInfo.topActivity != null) { + if ((displayId == -1 || displayId == stackInfo.displayId) + && stackInfo.topActivity != null) { validStackInfo = stackInfo; break; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java index 81f7846b357d..81f7846b357d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java index 084c136fc555..e640baa4327a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.systemui.statusbar.car; import android.content.Context; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 4bff5ba3de7f..2d90f8f0afd9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * 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. @@ -35,6 +35,8 @@ import com.android.systemui.R; import com.android.systemui.classifier.FalsingLog; import com.android.systemui.classifier.FalsingManager; import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.plugins.qs.QS; +import com.android.systemui.qs.car.CarQSFragment; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.StatusBarState; @@ -252,6 +254,11 @@ public class CarStatusBar extends StatusBar implements addTemperatureViewToController(mStatusBarWindow); } + @Override + protected QS createDefaultQSFragment() { + return new CarQSFragment(); + } + private BatteryController createBatteryController() { mCarBatteryController = new CarBatteryController(mContext); mCarBatteryController.addBatteryViewHandler(this); @@ -549,7 +556,7 @@ public class CarStatusBar extends StatusBar implements */ public void dismissKeyguard() { executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */, - true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */); + true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java index d0f06296545b..8c6b9b0107a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.systemui.statusbar.car; import android.content.Context; @@ -16,13 +32,13 @@ public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManage ViewMediatorCallback callback, LockPatternUtils lockPatternUtils) { super(context, callback, lockPatternUtils); - mShouldHideNavBar =context.getResources() + mShouldHideNavBar = context.getResources() .getBoolean(R.bool.config_hideNavWhenKeyguardBouncerShown); } @Override protected void updateNavigationBarVisibility(boolean navBarVisible) { - if(!mShouldHideNavBar) { + if (!mShouldHideNavBar) { return; } CarStatusBar statusBar = (CarStatusBar) mStatusBar; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java index f2923f7df248..3288927bf730 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.systemui.statusbar.car; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG; @@ -29,7 +45,7 @@ import com.android.systemui.statusbar.policy.BluetoothController; */ public class ConnectedDeviceSignalController extends BroadcastReceiver implements BluetoothController.Callback { - private final static String TAG = "DeviceSignalCtlr"; + private static final String TAG = "DeviceSignalCtlr"; /** * The value that indicates if a network is unavailable. This value is according ot the @@ -70,6 +86,21 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement private final SignalDrawable mSignalDrawable; private BluetoothHeadsetClient mBluetoothHeadsetClient; + private final ServiceListener mHfpServiceListener = new ServiceListener() { + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (profile == BluetoothProfile.HEADSET_CLIENT) { + mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; + } + } + + @Override + public void onServiceDisconnected(int profile) { + if (profile == BluetoothProfile.HEADSET_CLIENT) { + mBluetoothHeadsetClient = null; + } + } + }; public ConnectedDeviceSignalController(Context context, View signalsView) { mContext = context; @@ -87,7 +118,7 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement new ScalingDrawableWrapper(mSignalDrawable, mIconScaleFactor)); if (mAdapter == null) { - return; + return; } mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener, @@ -236,20 +267,4 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement mSignalsView.setVisibility(View.GONE); } } - - private final ServiceListener mHfpServiceListener = new ServiceListener() { - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET_CLIENT) { - mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy; - } - } - - @Override - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET_CLIENT) { - mBluetoothHeadsetClient = null; - } - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java index 47941bf22941..730c3e3440ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java @@ -124,4 +124,4 @@ public class DrivingStateHelper { Log.d(TAG, message); } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 2ebf5eb39bf6..23fe5944573e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * 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. @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.systemui.statusbar.car; @@ -44,7 +44,7 @@ public class FullscreenUserSwitcher { // Initialize user grid. mUserGridView = container.findViewById(R.id.user_grid); GridLayoutManager layoutManager = new GridLayoutManager(context, - context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); + context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col)); mUserGridView.getRecyclerView().setLayoutManager(layoutManager); mUserGridView.buildAdapter(); mUserGridView.setUserSelectionListener(this::onUserSelected); @@ -54,7 +54,7 @@ public class FullscreenUserSwitcher { hide(); mShortAnimDuration = container.getResources() - .getInteger(android.R.integer.config_shortAnimTime); + .getInteger(android.R.integer.config_shortAnimTime); } /** @@ -108,4 +108,4 @@ public class FullscreenUserSwitcher { }); } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java index 0c91cba43390..0c91cba43390 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java index d802ed8d6e3a..fb2b57b6d490 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ package com.android.systemui.statusbar.car; @@ -210,7 +210,7 @@ public class UserGridRecyclerView extends PagedListView implements public void onBindViewHolder(UserAdapterViewHolder holder, int position) { UserRecord userRecord = mUsers.get(position); RoundedBitmapDrawable circleIcon = RoundedBitmapDrawableFactory.create(mRes, - getUserRecordIcon(userRecord)); + getUserRecordIcon(userRecord)); circleIcon.setCircular(true); holder.mUserAvatarImageView.setImageDrawable(circleIcon); holder.mUserNameTextView.setText(userRecord.mInfo.name); @@ -254,13 +254,13 @@ public class UserGridRecyclerView extends PagedListView implements private void showMaxUserLimitReachedDialog() { AlertDialog maxUsersDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert) - .setTitle(R.string.user_limit_reached_title) - .setMessage(getResources().getQuantityString( - R.plurals.user_limit_reached_message, - mCarUserManagerHelper.getMaxSupportedRealUsers(), - mCarUserManagerHelper.getMaxSupportedRealUsers())) - .setPositiveButton(android.R.string.ok, null) - .create(); + .setTitle(R.string.user_limit_reached_title) + .setMessage(getResources().getQuantityString( + R.plurals.user_limit_reached_message, + mCarUserManagerHelper.getMaxSupportedRealUsers(), + mCarUserManagerHelper.getMaxSupportedRealUsers())) + .setPositiveButton(android.R.string.ok, null) + .create(); // Sets window flags for the SysUI dialog SystemUIDialog.applyFlags(maxUsersDialog); maxUsersDialog.show(); @@ -268,17 +268,17 @@ public class UserGridRecyclerView extends PagedListView implements private void showConfirmAddUserDialog() { String message = mRes.getString(R.string.user_add_user_message_setup) - .concat(System.getProperty("line.separator")) - .concat(System.getProperty("line.separator")) - .concat(mRes.getString(R.string.user_add_user_message_update)); + .concat(System.getProperty("line.separator")) + .concat(System.getProperty("line.separator")) + .concat(mRes.getString(R.string.user_add_user_message_update)); AlertDialog addUserDialog = new Builder(mContext, R.style.Theme_Car_Dark_Dialog_Alert) - .setTitle(R.string.user_add_user_title) - .setMessage(message) - .setNegativeButton(android.R.string.cancel, this) - .setPositiveButton(android.R.string.ok, this) - .setOnCancelListener(this) - .create(); + .setTitle(R.string.user_add_user_title) + .setMessage(message) + .setNegativeButton(android.R.string.cancel, this) + .setPositiveButton(android.R.string.ok, this) + .setOnCancelListener(this) + .create(); // Sets window flags for the SysUI dialog SystemUIDialog.applyFlags(addUserDialog); addUserDialog.show(); @@ -298,7 +298,7 @@ public class UserGridRecyclerView extends PagedListView implements if (userRecord.mIsAddUser) { return UserIcons.convertToBitmap(mContext - .getDrawable(R.drawable.car_add_circle_round)); + .getDrawable(R.drawable.car_add_circle_round)); } return mCarUserManagerHelper.getUserIcon(userRecord.mInfo); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java index 6c924e3c2c16..aec31ee4bfdd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java @@ -41,31 +41,58 @@ import java.util.Objects; public class HvacController { public static final String TAG = "HvacController"; - public final static int BIND_TO_HVAC_RETRY_DELAY = 5000; + public static final int BIND_TO_HVAC_RETRY_DELAY = 5000; private Context mContext; private Handler mHandler; private Car mCar; private CarHvacManager mHvacManager; private HashMap<HvacKey, List<TemperatureView>> mTempComponents = new HashMap<>(); - - public HvacController(Context context) { - mContext = context; - } - /** - * Create connection to the Car service. Note: call backs from the Car service - * ({@link CarHvacManager}) will happen on the same thread this method was called from. + * Callback for getting changes from {@link CarHvacManager} and setting the UI elements to + * match. */ - public void connectToCarService() { - mHandler = new Handler(); - mCar = Car.createCar(mContext, mServiceConnection, mHandler); - if (mCar != null) { - // note: this connect call handles the retries - mCar.connect(); + private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() { + @Override + public void onChangeEvent(final CarPropertyValue val) { + try { + int areaId = val.getAreaId(); + int propertyId = val.getPropertyId(); + List<TemperatureView> temperatureViews = mTempComponents.get( + new HvacKey(propertyId, areaId)); + if (temperatureViews != null && !temperatureViews.isEmpty()) { + float value = (float) val.getValue(); + for (TemperatureView tempView : temperatureViews) { + tempView.setTemp(value); + } + } // else the data is not of interest + } catch (Exception e) { + // catch all so we don't take down the sysui if a new data type is + // introduced. + Log.e(TAG, "Failed handling hvac change event", e); + } } - } + @Override + public void onErrorEvent(final int propertyId, final int zone) { + Log.d(TAG, "HVAC error event, propertyId: " + propertyId + + " zone: " + zone); + } + }; + /** + * If the connection to car service goes away then restart it. + */ + private final IBinder.DeathRecipient mRestart = new IBinder.DeathRecipient() { + @Override + public void binderDied() { + Log.d(TAG, "Death of HVAC triggering a restart"); + if (mCar != null) { + mCar.disconnect(); + } + destroyHvacManager(); + mHandler.postDelayed(() -> mCar.connect(), BIND_TO_HVAC_RETRY_DELAY); + } + }; /** * Registers callbacks and initializes components upon connection. */ @@ -88,6 +115,23 @@ public class HvacController { } }; + public HvacController(Context context) { + mContext = context; + } + + /** + * Create connection to the Car service. Note: call backs from the Car service + * ({@link CarHvacManager}) will happen on the same thread this method was called from. + */ + public void connectToCarService() { + mHandler = new Handler(); + mCar = Car.createCar(mContext, mServiceConnection, mHandler); + if (mCar != null) { + // note: this connect call handles the retries + mCar.connect(); + } + } + private void destroyHvacManager() { if (mHvacManager != null) { mHvacManager.unregisterCallback(mHardwareCallback); @@ -96,23 +140,7 @@ public class HvacController { } /** - * If the connection to car service goes away then restart it. - */ - private final IBinder.DeathRecipient mRestart = new IBinder.DeathRecipient() { - @Override - public void binderDied() { - Log.d(TAG, "Death of HVAC triggering a restart"); - if (mCar != null) { - mCar.disconnect(); - } - destroyHvacManager(); - mHandler.postDelayed(() -> mCar.connect(), BIND_TO_HVAC_RETRY_DELAY); - } - }; - - /** * Add component to list and initialize it if the connection is up. - * @param temperatureView */ public void addHvacTextView(TemperatureView temperatureView) { @@ -136,7 +164,6 @@ public class HvacController { } } - private void initComponent(TemperatureView view) { int id = view.getPropertyId(); int zone = view.getAreaId(); @@ -153,38 +180,6 @@ public class HvacController { } /** - * Callback for getting changes from {@link CarHvacManager} and setting the UI elements to - * match. - */ - private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() { - @Override - public void onChangeEvent(final CarPropertyValue val) { - try { - int areaId = val.getAreaId(); - int propertyId = val.getPropertyId(); - List<TemperatureView> temperatureViews = mTempComponents.get( - new HvacKey(propertyId, areaId)); - if (temperatureViews != null && !temperatureViews.isEmpty()) { - float value = (float) val.getValue(); - for (TemperatureView tempView : temperatureViews) { - tempView.setTemp(value); - } - } // else the data is not of interest - } catch (Exception e) { - // catch all so we don't take down the sysui if a new data type is - // introduced. - Log.e(TAG, "Failed handling hvac change event", e); - } - } - - @Override - public void onErrorEvent(final int propertyId, final int zone) { - Log.d(TAG, "HVAC error event, propertyId: " + propertyId + - " zone: " + zone); - } - }; - - /** * Removes all registered components. This is useful if you need to rebuild the UI since * components self register. */ @@ -200,7 +195,7 @@ public class HvacController { int mPropertyId; int mAreaId; - public HvacKey(int propertyId, int areaId) { + private HvacKey(int propertyId, int areaId) { mPropertyId = propertyId; mAreaId = areaId; } @@ -210,8 +205,8 @@ public class HvacController { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; HvacKey hvacKey = (HvacKey) o; - return mPropertyId == hvacKey.mPropertyId && - mAreaId == hvacKey.mAreaId; + return mPropertyId == hvacKey.mPropertyId + && mAreaId == hvacKey.mAreaId; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java index 4d8ce4348319..507c60f87b1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureTextView.java @@ -40,7 +40,7 @@ public class TemperatureTextView extends TextView implements TemperatureView { public TemperatureTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TemperatureView); - mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId,-1); + mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId, -1); mPropertyId = typedArray.getInt(R.styleable.TemperatureView_hvacPropertyId, -1); String format = typedArray.getString(R.styleable.TemperatureView_hvacTempFormat); mTempFormat = (format == null) ? "%.1f\u00B0" : format; @@ -48,6 +48,7 @@ public class TemperatureTextView extends TextView implements TemperatureView { /** * Formats the float for display + * * @param temp - The current temp or NaN */ @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java index 7651356f98a3..7651356f98a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java new file mode 100644 index 000000000000..71cc19b63ac1 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogComponent.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume; + +import android.content.Context; + +import com.android.systemui.SystemUI; +import com.android.systemui.plugins.VolumeDialog; + +/** + * Allows for adding car specific dialog when the volume dialog is created. + */ +public class CarVolumeDialogComponent extends VolumeDialogComponent { + + public CarVolumeDialogComponent(SystemUI sysui, Context context) { + super(sysui, context); + } + + protected VolumeDialog createDefault() { + return new CarVolumeDialogImpl(mContext); + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java new file mode 100644 index 000000000000..12df263ffede --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java @@ -0,0 +1,602 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.volume; + +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; +import android.annotation.DrawableRes; +import android.annotation.Nullable; +import android.app.Dialog; +import android.app.KeyguardManager; +import android.car.Car; +import android.car.CarNotConnectedException; +import android.car.media.CarAudioManager; +import android.car.media.ICarVolumeCallback; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.ServiceConnection; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.media.AudioManager; +import android.os.Debug; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.util.SparseArray; +import android.util.Xml; +import android.view.ContextThemeWrapper; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; + +import androidx.car.widget.ListItem; +import androidx.car.widget.ListItemAdapter; +import androidx.car.widget.ListItemAdapter.BackgroundStyle; +import androidx.car.widget.ListItemProvider.ListProvider; +import androidx.car.widget.PagedListView; +import androidx.car.widget.SeekbarListItem; + +import com.android.systemui.R; +import com.android.systemui.plugins.VolumeDialog; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Car version of the volume dialog. + * + * Methods ending in "H" must be called on the (ui) handler. + */ +public class CarVolumeDialogImpl implements VolumeDialog { + + private static final String TAG = Util.logTag(CarVolumeDialogImpl.class); + + private static final String XML_TAG_VOLUME_ITEMS = "carVolumeItems"; + private static final String XML_TAG_VOLUME_ITEM = "item"; + private static final int HOVERING_TIMEOUT = 16000; + private static final int NORMAL_TIMEOUT = 3000; + private static final int LISTVIEW_ANIMATION_DURATION_IN_MILLIS = 250; + private static final int DISMISS_DELAY_IN_MILLIS = 50; + private static final int ARROW_FADE_IN_START_DELAY_IN_MILLIS = 100; + + private final Context mContext; + private final H mHandler = new H(); + // All the volume items. + private final SparseArray<VolumeItem> mVolumeItems = new SparseArray<>(); + // Available volume items in car audio manager. + private final List<VolumeItem> mAvailableVolumeItems = new ArrayList<>(); + // Volume items in the PagedListView. + private final List<ListItem> mVolumeLineItems = new ArrayList<>(); + private final KeyguardManager mKeyguard; + private Window mWindow; + private CustomDialog mDialog; + private PagedListView mListView; + private ListItemAdapter mPagedListAdapter; + private Car mCar; + private CarAudioManager mCarAudioManager; + private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() { + @Override + public void onGroupVolumeChanged(int groupId, int flags) { + VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); + int value = getSeekbarValue(mCarAudioManager, groupId); + // Do not update the progress if it is the same as before. When car audio manager sets + // its group volume caused by the seekbar progress changed, it also triggers this + // callback. Updating the seekbar at the same time could block the continuous seeking. + if (value != volumeItem.progress) { + volumeItem.listItem.setProgress(value); + volumeItem.progress = value; + } + if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { + mHandler.obtainMessage(H.SHOW, Events.SHOW_REASON_VOLUME_CHANGED).sendToTarget(); + } + } + + @Override + public void onMasterMuteChanged(int flags) { + // ignored + } + }; + private boolean mHovering; + private boolean mShowing; + private boolean mExpanded; + private final ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + try { + mExpanded = false; + mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE); + int volumeGroupCount = mCarAudioManager.getVolumeGroupCount(); + // Populates volume slider items from volume groups to UI. + for (int groupId = 0; groupId < volumeGroupCount; groupId++) { + VolumeItem volumeItem = getVolumeItemForUsages( + mCarAudioManager.getUsagesForVolumeGroupId(groupId)); + mAvailableVolumeItems.add(volumeItem); + // The first one is the default item. + if (groupId == 0) { + volumeItem.defaultItem = true; + addSeekbarListItem(volumeItem, groupId, + R.drawable.car_ic_keyboard_arrow_down, + new ExpandIconListener()); + } + } + + // If list is already initiated, update its content. + if (mPagedListAdapter != null) { + mPagedListAdapter.notifyDataSetChanged(); + } + mCarAudioManager.registerVolumeCallback(mVolumeChangeCallback.asBinder()); + } catch (CarNotConnectedException e) { + Log.e(TAG, "Car is not connected!", e); + } + } + + /** + * This does not get called when service is properly disconnected. + * So we need to also handle cleanups in destroy(). + */ + @Override + public void onServiceDisconnected(ComponentName name) { + cleanupAudioManager(); + } + }; + + public CarVolumeDialogImpl(Context context) { + mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); + mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + mCar = Car.createCar(mContext, mServiceConnection); + } + + private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { + try { + return carAudioManager.getGroupVolume(volumeGroupId); + } catch (CarNotConnectedException e) { + Log.e(TAG, "Car is not connected!", e); + } + return 0; + } + + private static int getMaxSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { + try { + return carAudioManager.getGroupMaxVolume(volumeGroupId); + } catch (CarNotConnectedException e) { + Log.e(TAG, "Car is not connected!", e); + } + return 0; + } + + /** + * Build the volume window and connect to the CarService which registers with car audio + * manager. + */ + @Override + public void init(int windowType, Callback callback) { + initDialog(); + + mCar.connect(); + } + + @Override + public void destroy() { + mHandler.removeCallbacksAndMessages(null); + + cleanupAudioManager(); + // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup + // audio manager beforehand. + mCar.disconnect(); + } + + private void initDialog() { + loadAudioUsageItems(); + mVolumeLineItems.clear(); + mDialog = new CustomDialog(mContext); + + mHovering = false; + mShowing = false; + mExpanded = false; + mWindow = mDialog.getWindow(); + mWindow.requestFeature(Window.FEATURE_NO_TITLE); + mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); + mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); + mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); + final WindowManager.LayoutParams lp = mWindow.getAttributes(); + lp.format = PixelFormat.TRANSLUCENT; + lp.setTitle(VolumeDialogImpl.class.getSimpleName()); + lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; + lp.windowAnimations = -1; + mWindow.setAttributes(lp); + mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + mDialog.setCanceledOnTouchOutside(true); + mDialog.setContentView(R.layout.car_volume_dialog); + mDialog.setOnShowListener(dialog -> { + mListView.setTranslationY(-mListView.getHeight()); + mListView.setAlpha(0); + mListView.animate() + .alpha(1) + .translationY(0) + .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) + .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) + .start(); + }); + mListView = (PagedListView) mWindow.findViewById(R.id.volume_list); + mListView.setOnHoverListener((v, event) -> { + int action = event.getActionMasked(); + mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) + || (action == MotionEvent.ACTION_HOVER_MOVE); + rescheduleTimeoutH(); + return true; + }); + + mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems), + BackgroundStyle.PANEL); + mListView.setAdapter(mPagedListAdapter); + mListView.setMaxPages(PagedListView.UNLIMITED_PAGES); + } + + + private void showH(int reason) { + if (D.BUG) { + Log.d(TAG, "showH r=" + Events.DISMISS_REASONS[reason]); + } + + mHandler.removeMessages(H.SHOW); + mHandler.removeMessages(H.DISMISS); + rescheduleTimeoutH(); + // Refresh the data set before showing. + mPagedListAdapter.notifyDataSetChanged(); + if (mShowing) { + return; + } + mShowing = true; + + mDialog.show(); + Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); + } + + private void rescheduleTimeoutH() { + mHandler.removeMessages(H.DISMISS); + final int timeout = computeTimeoutH(); + mHandler.sendMessageDelayed(mHandler + .obtainMessage(H.DISMISS, Events.DISMISS_REASON_TIMEOUT), timeout); + + if (D.BUG) { + Log.d(TAG, "rescheduleTimeout " + timeout + " " + Debug.getCaller()); + } + } + + private int computeTimeoutH() { + return mHovering ? HOVERING_TIMEOUT : NORMAL_TIMEOUT; + } + + private void dismissH(int reason) { + if (D.BUG) { + Log.d(TAG, "dismissH r=" + Events.DISMISS_REASONS[reason]); + } + + mHandler.removeMessages(H.DISMISS); + mHandler.removeMessages(H.SHOW); + if (!mShowing) { + return; + } + + mListView.animate().cancel(); + + mListView.setTranslationY(0); + mListView.setAlpha(1); + mListView.animate() + .alpha(0) + .translationY(-mListView.getHeight()) + .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) + .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator()) + .withEndAction(() -> mHandler.postDelayed(() -> { + if (D.BUG) { + Log.d(TAG, "mDialog.dismiss()"); + } + mDialog.dismiss(); + mShowing = false; + }, DISMISS_DELAY_IN_MILLIS)) + .start(); + + Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason); + } + + private void loadAudioUsageItems() { + try (XmlResourceParser parser = mContext.getResources().getXml(R.xml.car_volume_items)) { + AttributeSet attrs = Xml.asAttributeSet(parser); + int type; + // Traverse to the first start tag + while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT + && type != XmlResourceParser.START_TAG) { + // Do Nothing (moving parser to start element) + } + + if (!XML_TAG_VOLUME_ITEMS.equals(parser.getName())) { + throw new RuntimeException("Meta-data does not start with carVolumeItems tag"); + } + int outerDepth = parser.getDepth(); + int rank = 0; + while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT + && (type != XmlResourceParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlResourceParser.END_TAG) { + continue; + } + if (XML_TAG_VOLUME_ITEM.equals(parser.getName())) { + TypedArray item = mContext.getResources().obtainAttributes( + attrs, R.styleable.carVolumeItems_item); + int usage = item.getInt(R.styleable.carVolumeItems_item_usage, -1); + if (usage >= 0) { + VolumeItem volumeItem = new VolumeItem(); + volumeItem.rank = rank; + volumeItem.icon = item.getResourceId(R.styleable.carVolumeItems_item_icon, + 0); + mVolumeItems.put(usage, volumeItem); + rank++; + } + item.recycle(); + } + } + } catch (XmlPullParserException | IOException e) { + Log.e(TAG, "Error parsing volume groups configuration", e); + } + } + + private VolumeItem getVolumeItemForUsages(int[] usages) { + int rank = Integer.MAX_VALUE; + VolumeItem result = null; + for (int usage : usages) { + VolumeItem volumeItem = mVolumeItems.get(usage); + if (volumeItem.rank < rank) { + rank = volumeItem.rank; + result = volumeItem; + } + } + return result; + } + + private SeekbarListItem addSeekbarListItem(VolumeItem volumeItem, + int volumeGroupId, + int supplementalIconId, + @Nullable View.OnClickListener supplementalIconOnClickListener) { + SeekbarListItem listItem = new SeekbarListItem(mContext); + listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); + int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); + int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); + listItem.setProgress(progress); + listItem.setOnSeekBarChangeListener(new CarVolumeDialogImpl + .VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); + Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); + primaryIcon.mutate().setTint(color); + listItem.setPrimaryActionIcon(primaryIcon); + if (supplementalIconId != 0) { + Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); + supplementalIcon.mutate().setTint(color); + listItem.setSupplementalIcon(supplementalIcon, true); + listItem.setSupplementalIconListener(supplementalIconOnClickListener); + } else { + listItem.setSupplementalEmptyIcon(true); + listItem.setSupplementalIconListener(null); + } + + mVolumeLineItems.add(listItem); + volumeItem.listItem = listItem; + volumeItem.progress = progress; + return listItem; + } + + private VolumeItem findVolumeItem(SeekbarListItem targetItem) { + for (int i = 0; i < mVolumeItems.size(); ++i) { + VolumeItem volumeItem = mVolumeItems.valueAt(i); + if (volumeItem.listItem == targetItem) { + return volumeItem; + } + } + return null; + } + + private void cleanupAudioManager() { + try { + mCarAudioManager.unregisterVolumeCallback(mVolumeChangeCallback.asBinder()); + } catch (CarNotConnectedException e) { + Log.e(TAG, "Car is not connected!", e); + } + mVolumeLineItems.clear(); + mCarAudioManager = null; + } + + /** + * Wrapper class which contains information of each volume group. + */ + private static class VolumeItem { + + private int rank; + private boolean defaultItem = false; + private @DrawableRes int icon; + private SeekbarListItem listItem; + private int progress; + } + + private final class H extends Handler { + + private static final int SHOW = 1; + private static final int DISMISS = 2; + + private H() { + super(Looper.getMainLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case SHOW: + showH(msg.arg1); + break; + case DISMISS: + dismissH(msg.arg1); + break; + default: + } + } + } + + private final class CustomDialog extends Dialog implements DialogInterface { + + private CustomDialog(Context context) { + super(context, com.android.systemui.R.style.qs_theme); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + rescheduleTimeoutH(); + return super.dispatchTouchEvent(ev); + } + + @Override + protected void onStart() { + super.setCanceledOnTouchOutside(true); + super.onStart(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isShowing()) { + if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { + mHandler.obtainMessage( + H.DISMISS, Events.DISMISS_REASON_TOUCH_OUTSIDE).sendToTarget(); + return true; + } + } + return false; + } + } + + private final class ExpandIconListener implements View.OnClickListener { + + @Override + public void onClick(final View v) { + mExpanded = !mExpanded; + Animator inAnimator; + if (mExpanded) { + for (int groupId = 0; groupId < mAvailableVolumeItems.size(); ++groupId) { + // Adding the items which are not coming from the default item. + VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); + if (volumeItem.defaultItem) { + // Set progress here due to the progress of seekbar may not be updated. + volumeItem.listItem.setProgress(volumeItem.progress); + } else { + addSeekbarListItem(volumeItem, groupId, 0, null); + } + } + inAnimator = AnimatorInflater.loadAnimator( + mContext, R.anim.car_arrow_fade_in_rotate_up); + } else { + // Only keeping the default stream if it is not expended. + Iterator itr = mVolumeLineItems.iterator(); + while (itr.hasNext()) { + SeekbarListItem seekbarListItem = (SeekbarListItem) itr.next(); + VolumeItem volumeItem = findVolumeItem(seekbarListItem); + if (!volumeItem.defaultItem) { + itr.remove(); + } else { + // Set progress here due to the progress of seekbar may not be updated. + seekbarListItem.setProgress(volumeItem.progress); + } + } + inAnimator = AnimatorInflater.loadAnimator( + mContext, R.anim.car_arrow_fade_in_rotate_down); + } + + Animator outAnimator = AnimatorInflater.loadAnimator( + mContext, R.anim.car_arrow_fade_out); + inAnimator.setStartDelay(ARROW_FADE_IN_START_DELAY_IN_MILLIS); + AnimatorSet animators = new AnimatorSet(); + animators.playTogether(outAnimator, inAnimator); + animators.setTarget(v); + animators.start(); + mPagedListAdapter.notifyDataSetChanged(); + } + } + + private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener { + + private final int mVolumeGroupId; + private final CarAudioManager mCarAudioManager; + + private VolumeSeekBarChangeListener(int volumeGroupId, CarAudioManager carAudioManager) { + mVolumeGroupId = volumeGroupId; + mCarAudioManager = carAudioManager; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) { + // For instance, if this event is originated from AudioService, + // we can ignore it as it has already been handled and doesn't need to be + // sent back down again. + return; + } + try { + if (mCarAudioManager == null) { + Log.w(TAG, "Ignoring volume change event because the car isn't connected"); + return; + } + mAvailableVolumeItems.get(mVolumeGroupId).progress = progress; + mCarAudioManager.setGroupVolume(mVolumeGroupId, progress, 0); + } catch (CarNotConnectedException e) { + Log.e(TAG, "Car is not connected!", e); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + } +} diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS index 7057ce6cb6fe..aef6a3cdf5c8 100644 --- a/packages/CarrierDefaultApp/OWNERS +++ b/packages/CarrierDefaultApp/OWNERS @@ -9,4 +9,5 @@ jackyu@google.com jminjie@google.com satk@google.com shuoq@google.com -refuhoo@google.com
\ No newline at end of file +refuhoo@google.com +nazaninb@google.com
\ No newline at end of file diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java index 4b212c25c89e..0cad5af00267 100644 --- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java +++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java @@ -19,8 +19,7 @@ package android.ext.services.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.service.notification.Adjustment.KEY_IMPORTANCE; -import static android.service.notification.NotificationListenerService.Ranking - .USER_SENTIMENT_NEGATIVE; +import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -241,7 +240,7 @@ public class Assistant extends NotificationAssistantService { signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies); } if (Settings.Secure.getInt(getContentResolver(), - Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) == 1) { + Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) == 1) { if (mNotificationCategorizer.shouldSilence(entry)) { final int importance = entry.getImportance() < IMPORTANCE_LOW ? entry.getImportance() : IMPORTANCE_LOW; diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java index b2fc41783516..892267b22058 100644 --- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java +++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java @@ -48,7 +48,7 @@ public class SmartActionsHelper { | Notification.FLAG_NO_CLEAR; private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400; private static final int MAX_ACTIONS_PER_LINK = 1; - private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS; + private static final int MAX_SMART_ACTIONS = 3; private static final int MAX_SUGGESTED_REPLIES = 3; private static final ConversationActions.TypeConfig TYPE_CONFIG = @@ -81,12 +81,9 @@ public class SmartActionsHelper { if (tcm == null) { return EMPTY_ACTION_LIST; } - Notification.Action[] actions = entry.getNotification().actions; - int numOfExistingActions = actions == null ? 0: actions.length; - int maxSmartActions = MAX_SMART_ACTIONS - numOfExistingActions; return suggestActionsFromText( tcm, - getMostSalientActionText(entry.getNotification()), maxSmartActions); + getMostSalientActionText(entry.getNotification()), MAX_SMART_ACTIONS); } ArrayList<CharSequence> suggestReplies( diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml index 91e23ddeaedf..03eafc4ab836 100644 --- a/packages/PrintSpooler/AndroidManifest.xml +++ b/packages/PrintSpooler/AndroidManifest.xml @@ -34,15 +34,23 @@ <uses-permission android:name="com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"/> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.READ_PRINT_SERVICES" /> <uses-permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" + android:dataSentOffDevice="no" + android:dataSharedWithThirdParty="no" + android:dataUsedForMonetization="no" + android:dataRetentionTime="unlimited"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" + android:dataSentOffDevice="no" + android:dataSharedWithThirdParty="no" + android:dataUsedForMonetization="no" + android:dataRetentionTime="unlimited"/> + <application android:allowClearUserData="true" android:label="@string/app_label" - android:allowBackup= "false" android:supportsRtl="true"> <service diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml index 0ccf13e23aaf..9e16f5ef40a7 100644 --- a/packages/PrintSpooler/res/layout/print_activity.xml +++ b/packages/PrintSpooler/res/layout/print_activity.xml @@ -107,7 +107,7 @@ android:layout_height="wrap_content" android:layout_marginStart="16dip" android:elevation="@dimen/preview_controls_elevation" - android:tint="?android:attr/textColorPrimaryInverse" + android:tint="@android:color/white" android:background="@drawable/print_button"> </ImageButton> diff --git a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml new file mode 100644 index 000000000000..1a47afc81d55 --- /dev/null +++ b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<!-- Based off preference_material_settings.xml except that ripple on only on the left side. --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:gravity="center_vertical" + android:background="@android:color/transparent" + android:clipToPadding="false"> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:background="?android:attr/selectableItemBackground" + android:gravity="start|center_vertical" + android:clipToPadding="false" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + <LinearLayout + android:id="@+id/checkbox_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="start|center_vertical" + android:minWidth="56dp" + android:orientation="horizontal" + android:clipToPadding="false" + android:paddingTop="4dp" + android:paddingBottom="4dp"> + <include layout="@layout/preference_widget_checkbox" /> + </LinearLayout> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:paddingTop="16dp" + android:paddingBottom="16dp"> + + <TextView + android:id="@android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem" + android:ellipsize="marquee" /> + + <TextView + android:id="@android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@android:id/title" + android:layout_alignStart="@android:id/title" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" + android:textColor="?android:attr/textColorSecondary" + android:maxLines="10" /> + + </RelativeLayout> + + </LinearLayout> + + <include layout="@layout/preference_two_target_divider" /> + + <!-- Preference should place its actual preference widget here. --> + <LinearLayout + android:id="@android:id/widget_frame" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:minWidth="64dp" + android:gravity="center" + android:orientation="vertical" /> + +</LinearLayout>
\ No newline at end of file diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java index 92fd86894d56..12b8efb1461c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java @@ -53,6 +53,8 @@ public final class CategoryKey { "com.android.settings.category.ia.night_display"; public static final String CATEGORY_PRIVACY = "com.android.settings.category.ia.privacy"; + public static final String CATEGORY_ENTERPRISE_PRIVACY = + "com.android.settings.category.ia.enterprise_privacy"; public static final Map<String, String> KEY_COMPAT_MAP; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java deleted file mode 100644 index e9c523881373..000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settingslib.net; - -import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.TAG_NONE; -import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; -import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; -import static android.text.format.DateUtils.HOUR_IN_MILLIS; - -import android.content.Context; -import android.net.INetworkStatsSession; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.os.Bundle; -import android.os.RemoteException; - -import androidx.loader.content.AsyncTaskLoader; - -import com.android.settingslib.AppItem; - -/** - * Loader for historical chart data for both network and UID details. - * - * Deprecated in favor of {@link NetworkCycleChartDataLoader} and - * {@link NetworkCycleDataForUidLoader} - * - * @deprecated - */ -@Deprecated -public class ChartDataLoaderCompat extends AsyncTaskLoader<ChartData> { - private static final String KEY_TEMPLATE = "template"; - private static final String KEY_APP = "app"; - private static final String KEY_FIELDS = "fields"; - - private final INetworkStatsSession mSession; - private final Bundle mArgs; - - public static Bundle buildArgs(NetworkTemplate template, AppItem app) { - return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES); - } - - public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) { - final Bundle args = new Bundle(); - args.putParcelable(KEY_TEMPLATE, template); - args.putParcelable(KEY_APP, app); - args.putInt(KEY_FIELDS, fields); - return args; - } - - public ChartDataLoaderCompat(Context context, INetworkStatsSession session, Bundle args) { - super(context); - mSession = session; - mArgs = args; - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - forceLoad(); - } - - @Override - public ChartData loadInBackground() { - final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); - final AppItem app = mArgs.getParcelable(KEY_APP); - final int fields = mArgs.getInt(KEY_FIELDS); - - try { - return loadInBackground(template, app, fields); - } catch (RemoteException e) { - // since we can't do much without history, and we don't want to - // leave with half-baked UI, we bail hard. - throw new RuntimeException("problem reading network stats", e); - } - } - - private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields) - throws RemoteException { - final ChartData data = new ChartData(); - data.network = mSession.getHistoryForNetwork(template, fields); - - if (app != null) { - // load stats for current uid and template - final int size = app.uids.size(); - for (int i = 0; i < size; i++) { - final int uid = app.uids.keyAt(i); - data.detailDefault = collectHistoryForUid( - template, uid, SET_DEFAULT, data.detailDefault); - data.detailForeground = collectHistoryForUid( - template, uid, SET_FOREGROUND, data.detailForeground); - } - - if (size > 0) { - data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration()); - data.detail.recordEntireHistory(data.detailDefault); - data.detail.recordEntireHistory(data.detailForeground); - } else { - data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS); - data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS); - data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS); - } - } - - return data; - } - - @Override - protected void onStopLoading() { - super.onStopLoading(); - cancelLoad(); - } - - @Override - protected void onReset() { - super.onReset(); - cancelLoad(); - } - - /** - * Collect {@link NetworkStatsHistory} for the requested UID, combining with - * an existing {@link NetworkStatsHistory} if provided. - */ - private NetworkStatsHistory collectHistoryForUid( - NetworkTemplate template, int uid, int set, NetworkStatsHistory existing) - throws RemoteException { - final NetworkStatsHistory history = mSession.getHistoryForUid( - template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES); - - if (existing != null) { - existing.recordEntireHistory(history); - return existing; - } else { - return history; - } - } -} diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index 183d4856ac6f..180b77e7503b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -32,30 +32,24 @@ import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.NetworkPolicy; import android.net.NetworkPolicyManager; -import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.format.DateUtils; -import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Range; import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; import java.time.ZonedDateTime; -import java.util.Date; import java.util.Iterator; import java.util.Locale; public class DataUsageController { private static final String TAG = "DataUsageController"; - @VisibleForTesting - static final String DATA_USAGE_V2 = "settings_data_usage_v2"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES; private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50); @@ -95,21 +89,6 @@ public class DataUsageController { * mContext.getResources().getInteger(R.integer.default_data_warning_level_mb); } - @VisibleForTesting - @Deprecated - INetworkStatsSession getSession() { - if (mSession == null) { - try { - mSession = mStatsService.openSession(); - } catch (RemoteException e) { - Log.w(TAG, "Failed to open stats session", e); - } catch (RuntimeException e) { - Log.w(TAG, "Failed to open stats session", e); - } - } - return mSession; - } - public void setCallback(Callback callback) { mCallback = callback; } @@ -149,13 +128,7 @@ public class DataUsageController { end = now; start = now - DateUtils.WEEK_IN_MILLIS * 4; } - final long totalBytes; - final long callStart = System.currentTimeMillis(); - if (FeatureFlagUtils.isEnabled(mContext, DATA_USAGE_V2)) { - totalBytes = getUsageLevel(template, start, end); - } else { - totalBytes = getUsageLevel(template, start, end, now); - } + final long totalBytes = getUsageLevel(template, start, end); if (totalBytes < 0L) { return warn("no entry data"); } @@ -185,32 +158,7 @@ public class DataUsageController { * retrieving the data. */ public long getHistoricalUsageLevel(NetworkTemplate template) { - if (FeatureFlagUtils.isEnabled(mContext, DATA_USAGE_V2)) { - return getUsageLevel(template, 0L /* start */, System.currentTimeMillis() /* end */); - } else { - final long now = System.currentTimeMillis(); - return getUsageLevel(template, 0L /* start */, now /* end */, now); - } - } - - @Deprecated - private long getUsageLevel(NetworkTemplate template, long start, long end, long now) { - final INetworkStatsSession session = getSession(); - if (session != null) { - try { - final NetworkStatsHistory history = - session.getHistoryForNetwork(template, FIELDS); - final NetworkStatsHistory.Entry entry = history.getValues( - start, end, System.currentTimeMillis() /* now */, null /* recycle */); - if (entry != null) { - return entry.rxBytes + entry.txBytes; - } - Log.w(TAG, "Failed to get data usage, no entry data"); - } catch (RemoteException e) { - Log.w(TAG, "Failed to get data usage, remote call failed"); - } - } - return -1L; + return getUsageLevel(template, 0L /* start */, System.currentTimeMillis() /* end */); } private long getUsageLevel(NetworkTemplate template, long start, long end) { @@ -241,20 +189,6 @@ public class DataUsageController { return null; } - @Deprecated - private static String historyEntryToString(NetworkStatsHistory.Entry entry) { - return entry == null ? null : new StringBuilder("Entry[") - .append("bucketDuration=").append(entry.bucketDuration) - .append(",bucketStart=").append(entry.bucketStart) - .append(",activeTime=").append(entry.activeTime) - .append(",rxBytes=").append(entry.rxBytes) - .append(",rxPackets=").append(entry.rxPackets) - .append(",txBytes=").append(entry.txBytes) - .append(",txPackets=").append(entry.txPackets) - .append(",operations=").append(entry.operations) - .append(']').toString(); - } - private static String statsBucketToString(Bucket bucket) { return bucket == null ? null : new StringBuilder("Entry[") .append("bucketDuration=").append(bucket.getEndTimeStamp() - bucket.getStartTimeStamp()) diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java deleted file mode 100644 index 82bb0115c66f..000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settingslib.net; - -import android.content.Context; -import android.net.INetworkStatsSession; -import android.net.NetworkStats; -import android.net.NetworkTemplate; -import android.os.Bundle; -import android.os.RemoteException; - -import androidx.loader.content.AsyncTaskLoader; - -/** - * Deprecated in favor of {@link NetworkStatsDetailLoader} - * - * @deprecated - */ -@Deprecated -public class SummaryForAllUidLoaderCompat extends AsyncTaskLoader<NetworkStats> { - private static final String KEY_TEMPLATE = "template"; - private static final String KEY_START = "start"; - private static final String KEY_END = "end"; - - private final INetworkStatsSession mSession; - private final Bundle mArgs; - - public static Bundle buildArgs(NetworkTemplate template, long start, long end) { - final Bundle args = new Bundle(); - args.putParcelable(KEY_TEMPLATE, template); - args.putLong(KEY_START, start); - args.putLong(KEY_END, end); - return args; - } - - public SummaryForAllUidLoaderCompat(Context context, INetworkStatsSession session, - Bundle args) { - super(context); - mSession = session; - mArgs = args; - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - forceLoad(); - } - - @Override - public NetworkStats loadInBackground() { - final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); - final long start = mArgs.getLong(KEY_START); - final long end = mArgs.getLong(KEY_END); - - try { - return mSession.getSummaryForAllUid(template, start, end, false); - } catch (RemoteException e) { - return null; - } - } - - @Override - protected void onStopLoading() { - super.onStopLoading(); - cancelLoad(); - } - - @Override - protected void onReset() { - super.onReset(); - cancelLoad(); - } -} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java index 72ed5e123add..acf99a24e96c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java @@ -18,7 +18,6 @@ package com.android.settingslib.net; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; @@ -35,12 +34,10 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.INetworkStatsSession; import android.net.NetworkStatsHistory; -import android.net.NetworkStatsHistory.Entry; import android.net.NetworkTemplate; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.format.DateUtils; -import android.util.FeatureFlagUtils; import org.junit.Before; import org.junit.Test; @@ -48,7 +45,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class DataUsageControllerTest { @@ -61,16 +57,18 @@ public class DataUsageControllerTest { private TelephonyManager mTelephonyManager; @Mock private NetworkStatsManager mNetworkStatsManager; - + @Mock private Context mContext; + private DataUsageController mController; private NetworkStatsHistory mNetworkStatsHistory; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mController = spy(new DataUsageController(mContext)); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); + mController = new DataUsageController(mContext); mNetworkStatsHistory = spy( new NetworkStatsHistory(DateUtils.DAY_IN_MILLIS /* bucketDuration */)); doReturn(mNetworkStatsHistory) @@ -79,75 +77,25 @@ public class DataUsageControllerTest { } @Test - public void getHistoricalUsageLevel_v1_noNetworkSession_shouldReturnNegative1() { - FeatureFlagUtils.setEnabled(mContext, DataUsageController.DATA_USAGE_V2, false); - doReturn(null).when(mController).getSession(); - - assertThat(mController.getHistoricalUsageLevel(null /* template */)).isEqualTo(-1L); - } - - @Test - public void getHistoriclUsageLevel_v1_noUsageData_shouldReturn0() { - FeatureFlagUtils.setEnabled(mContext, DataUsageController.DATA_USAGE_V2, false); - doReturn(mSession).when(mController).getSession(); + public void getHistoricalUsageLevel_shouldQuerySummaryForDevice() throws Exception { - assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) - .isEqualTo(0L); - } - - @Test - public void getHistoricalUsageLevel_v1_hasUsageData_shouldReturnTotalUsage() { - FeatureFlagUtils.setEnabled(mContext, DataUsageController.DATA_USAGE_V2, false); - doReturn(mSession).when(mController).getSession(); - final long receivedBytes = 743823454L; - final long transmittedBytes = 16574289L; - final Entry entry = new Entry(); - entry.bucketStart = 1521583200000L; - entry.rxBytes = receivedBytes; - entry.txBytes = transmittedBytes; - when(mNetworkStatsHistory.getValues(eq(0L), anyLong(), anyLong(), nullable(Entry.class))) - .thenReturn(entry); - - assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) - .isEqualTo(receivedBytes + transmittedBytes); - } - - @Test - public void getHistoricalUsageLevel_v2_shouldQuerySummaryForDevice() throws Exception { - final Context context = mock(Context.class); - FeatureFlagUtils.setEnabled(context, DataUsageController.DATA_USAGE_V2, true); - when(context.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - when(context.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); - final DataUsageController controller = new DataUsageController(context); - - controller.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()); + mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()); verify(mNetworkStatsManager).querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI), eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */); } @Test - public void getHistoricalUsageLevel_v2NoUsageData_shouldReturn0() throws Exception { - final Context context = mock(Context.class); - FeatureFlagUtils.setEnabled(context, DataUsageController.DATA_USAGE_V2, true); - when(context.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - when(context.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); + public void getHistoricalUsageLevel_noUsageData_shouldReturn0() throws Exception { when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI), eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */)) .thenReturn(mock(NetworkStats.Bucket.class)); - final DataUsageController controller = new DataUsageController(context); - - assertThat(controller.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) + assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) .isEqualTo(0L); } @Test - public void getHistoricalUsageLevel_v2HasUsageData_shouldReturnTotalUsage() - throws Exception { - final Context context = mock(Context.class); - FeatureFlagUtils.setEnabled(context, DataUsageController.DATA_USAGE_V2, true); - when(context.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); - when(context.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); + public void getHistoricalUsageLevel_hasUsageData_shouldReturnTotalUsage() throws Exception { final long receivedBytes = 743823454L; final long transmittedBytes = 16574289L; final NetworkStats.Bucket bucket = mock(NetworkStats.Bucket.class); @@ -155,9 +103,8 @@ public class DataUsageControllerTest { when(bucket.getTxBytes()).thenReturn(transmittedBytes); when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI), eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */)).thenReturn(bucket); - final DataUsageController controller = new DataUsageController(context); - assertThat(controller.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) + assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) .isEqualTo(receivedBytes + transmittedBytes); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index b2c12b277dc0..df5b1467f9d9 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1165,6 +1165,12 @@ class SettingsProtoDumpUtil { GlobalSettingsProto.SmartSelection.UPDATE_METADATA_URL); p.end(smartSelectToken); + final long smartSuggestionsToken = p.start(GlobalSettingsProto.SMART_SUGGESTIONS); + dumpSetting(s, p, + Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED, + GlobalSettingsProto.SmartSuggestions.SERVICE_EXPLICITLY_ENABLED); + p.end(smartSuggestionsToken); + final long smsToken = p.start(GlobalSettingsProto.SMS); dumpSetting(s, p, Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS, @@ -1306,6 +1312,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.WARNING_TEMPERATURE, GlobalSettingsProto.TemperatureWarning.WARNING_TEMPERATURE_LEVEL); + dumpSetting(s, p, + Settings.Global.USB_ALARM_TEMPERATURE, + GlobalSettingsProto.TemperatureWarning.USB_ALARM_TEMPERATURE_LEVEL); p.end(tempWarningToken); final long tetherToken = p.start(GlobalSettingsProto.TETHER); @@ -1914,6 +1923,15 @@ class SettingsProtoDumpUtil { SecureSettingsProto.Location.CHANGER); p.end(locationToken); + final long locationAccessCheckToken = p.start(SecureSettingsProto.LOCATION_ACCESS_CHECK); + dumpSetting(s, p, + Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS, + SecureSettingsProto.LocationAccessCheck.INTERVAL_MILLIS); + dumpSetting(s, p, + Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS, + SecureSettingsProto.LocationAccessCheck.DELAY_MILLIS); + p.end(locationAccessCheckToken); + final long lockScreenToken = p.start(SecureSettingsProto.LOCK_SCREEN); // Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated. // Settings.Secure.LOCK_PATTERN_ENABLED intentionally excluded since it's deprecated. diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index cb552318b908..83e83693375b 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -130,6 +130,7 @@ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="android.permission.MANAGE_AUTO_FILL" /> + <uses-permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS" /> <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.SET_TIME" /> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 0b9b27f238d7..7d53c2f78151 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -223,6 +223,9 @@ <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" /> + <!-- Permission to change the display color --> + <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> + <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_1.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_1.xml deleted file mode 100644 index 3cc98d8f7ed9..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_1.xml +++ /dev/null @@ -1,22 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="500" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M 0,0 c 31.33333,0 156.66667,0 188,0 " - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_2.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_2.xml deleted file mode 100644 index eda843d03ba2..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_2.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="33" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M -12,18 L -12,18" /> - <objectAnimator - android:duration="500" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M -12,18 c 31.33333,0 156.66667,0 188,0 " - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_3.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_3.xml deleted file mode 100644 index cab3d5cc2367..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_3.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="67" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M -24,36 L -24,36" /> - <objectAnimator - android:duration="500" - android:propertyXName="translateX" - android:propertyYName="translateY" - android:pathData="M -24,36 c 31.33333,0 156.66667,0 188,0 " - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1.xml deleted file mode 100644 index e435d9a9a69e..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1.xml +++ /dev/null @@ -1,31 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="150" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="100" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="0" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_1.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_1.xml deleted file mode 100644 index e31a7dbcebc5..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_1.xml +++ /dev/null @@ -1,31 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="183" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="100" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="0" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_2.xml b/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_2.xml deleted file mode 100644 index 2409612cb250..000000000000 --- a/packages/SystemUI/res/anim/dismiss_all_shape_animation_rectangle_path_1_2.xml +++ /dev/null @@ -1,31 +0,0 @@ -<!-- Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="217" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="100" - android:propertyName="fillAlpha" - android:valueFrom="1" - android:valueTo="0" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/fab_elevation.xml b/packages/SystemUI/res/anim/fab_elevation.xml deleted file mode 100644 index 2c76a865a470..000000000000 --- a/packages/SystemUI/res/anim/fab_elevation.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_enabled="true" android:state_pressed="true"> - <set> - <objectAnimator - android:duration="@android:integer/config_shortAnimTime" - android:propertyName="translationZ" - android:valueTo="@dimen/fab_press_translation_z" - android:valueType="floatType" /> - </set> - </item> - <item> - <set> - <objectAnimator - android:duration="@android:integer/config_shortAnimTime" - android:propertyName="translationZ" - android:valueTo="0" - android:valueType="floatType" /> - </set> - </item> -</selector> diff --git a/packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml deleted file mode 100644 index 8fdad809f0d1..000000000000 --- a/packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="616" - android:propertyName="rotation" - android:valueFrom="-90.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml deleted file mode 100644 index 3c3c131ef16b..000000000000 --- a/packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="50" - android:propertyName="fillAlpha" - android:valueFrom="0.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="83" - android:propertyName="fillAlpha" - android:valueFrom="0.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml deleted file mode 100644 index 57132e19dcc5..000000000000 --- a/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="466" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="0.909" - android:valueType="floatType" - android:interpolator="@interpolator/ic_landscape_to_rotate_animation_interpolator_0" /> - <objectAnimator - android:duration="466" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="0.909" - android:valueType="floatType" - android:interpolator="@interpolator/ic_landscape_to_rotate_animation_interpolator_0" /> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="50" - android:propertyName="rotation" - android:valueFrom="0.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="400" - android:propertyName="rotation" - android:valueFrom="0.0" - android:valueTo="45.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_portrait_to_rotate_arrows_0_animation.xml b/packages/SystemUI/res/anim/ic_portrait_to_rotate_arrows_0_animation.xml deleted file mode 100644 index ad2a5fad5268..000000000000 --- a/packages/SystemUI/res/anim/ic_portrait_to_rotate_arrows_0_animation.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="333" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="0.9" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="333" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="0.9" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_portrait_to_rotate_bottom_merged_animation.xml b/packages/SystemUI/res/anim/ic_portrait_to_rotate_bottom_merged_animation.xml deleted file mode 100644 index 46100b407831..000000000000 --- a/packages/SystemUI/res/anim/ic_portrait_to_rotate_bottom_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="400" - android:propertyName="fillAlpha" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="83" - android:propertyName="fillAlpha" - android:valueFrom="1.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_0_animation.xml b/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_0_animation.xml deleted file mode 100644 index 8f6d24d0d61d..000000000000 --- a/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_0_animation.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="400" - android:propertyName="rotation" - android:valueFrom="0.0" - android:valueTo="-135.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_merged_animation.xml b/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_merged_animation.xml deleted file mode 100644 index 300ed53052a8..000000000000 --- a/packages/SystemUI/res/anim/ic_portrait_to_rotate_device_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="66" - android:propertyName="pathData" - android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z" - android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="216" - android:propertyName="pathData" - android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z" - android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml deleted file mode 100644 index ad2a5fad5268..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="333" - android:propertyName="scaleX" - android:valueFrom="1.0" - android:valueTo="0.9" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="333" - android:propertyName="scaleY" - android:valueFrom="1.0" - android:valueTo="0.9" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml deleted file mode 100644 index c1521520c427..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="616" - android:propertyName="rotation" - android:valueFrom="0.0" - android:valueTo="-180.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml deleted file mode 100644 index b2c1eb8b93a3..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="200" - android:propertyName="fillAlpha" - android:valueFrom="1.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="83" - android:propertyName="fillAlpha" - android:valueFrom="1.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml deleted file mode 100644 index 2a9bbe32975e..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleX" - android:valueFrom="0.909" - android:valueTo="0.909" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleX" - android:valueFrom="0.909" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_rotate_to_landscape_animation_interpolator_0" /> - </set> - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="116" - android:propertyName="scaleY" - android:valueFrom="0.909" - android:valueTo="0.909" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="166" - android:propertyName="scaleY" - android:valueFrom="0.909" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_rotate_to_landscape_animation_interpolator_0" /> - </set> - <objectAnimator - android:duration="616" - android:propertyName="rotation" - android:valueFrom="45.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_0_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_0_animation.xml deleted file mode 100644 index ce267704dac5..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_0_animation.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="466" - android:propertyName="scaleX" - android:valueFrom="0.9" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_rotate_to_portrait_animation_interpolator_0" /> - <objectAnimator - android:duration="466" - android:propertyName="scaleY" - android:valueFrom="0.9" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@interpolator/ic_rotate_to_portrait_animation_interpolator_0" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_animation.xml deleted file mode 100644 index 6e8941d608cd..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_portrait_arrows_animation.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <objectAnimator - android:duration="616" - android:propertyName="rotation" - android:valueFrom="-221.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_portrait_bottom_merged_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_portrait_bottom_merged_animation.xml deleted file mode 100644 index 3c3c131ef16b..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_portrait_bottom_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="50" - android:propertyName="fillAlpha" - android:valueFrom="0.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="83" - android:propertyName="fillAlpha" - android:valueFrom="0.0" - android:valueTo="1.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_0_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_0_animation.xml deleted file mode 100644 index fd8e4f881160..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_0_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="50" - android:propertyName="rotation" - android:valueFrom="-135.0" - android:valueTo="-135.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="400" - android:propertyName="rotation" - android:valueFrom="-135.0" - android:valueTo="0.0" - android:valueType="floatType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_merged_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_merged_animation.xml deleted file mode 100644 index a77a536e46c0..000000000000 --- a/packages/SystemUI/res/anim/ic_rotate_to_portrait_device_merged_animation.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<set - xmlns:android="http://schemas.android.com/apk/res/android" > - <set - android:ordering="sequentially" > - <objectAnimator - android:duration="50" - android:propertyName="pathData" - android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z" - android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/linear" /> - <objectAnimator - android:duration="500" - android:propertyName="pathData" - android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z" - android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z" - android:valueType="pathType" - android:interpolator="@android:interpolator/fast_out_slow_in" /> - </set> -</set> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_1.xml b/packages/SystemUI/res/anim/ic_signal_blink_1.xml deleted file mode 100644 index 64580d189c0d..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_blink_1.xml +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:anim/linear_interpolator" - android:duration="@integer/carrier_network_change_anim_time" - android:repeatCount="-1"> - - <propertyValuesHolder - android:propertyName="fillColor" - android:valueType="colorType"> - <keyframe - android:fraction="0.0" - android:value="?attr/fillColor"/> - <keyframe - android:fraction="0.32" - android:value="?attr/fillColor"/> - <keyframe - android:fraction="0.33" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="1.0" - android:value="?attr/backgroundColor"/> - </propertyValuesHolder> - -</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_2.xml b/packages/SystemUI/res/anim/ic_signal_blink_2.xml deleted file mode 100644 index f055cd078558..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_blink_2.xml +++ /dev/null @@ -1,44 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:anim/linear_interpolator" - android:duration="@integer/carrier_network_change_anim_time" - android:repeatCount="-1"> - - <propertyValuesHolder - android:propertyName="fillColor" - android:valueType="colorType"> - <keyframe - android:fraction="0.0" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="0.32" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="0.33" - android:value="?attr/fillColor"/> - <keyframe - android:fraction="0.66" - android:value="?attr/fillColor"/> - <keyframe - android:fraction="0.67" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="1.0" - android:value="?attr/backgroundColor"/> - </propertyValuesHolder> - -</objectAnimator> diff --git a/packages/SystemUI/res/anim/ic_signal_blink_3.xml b/packages/SystemUI/res/anim/ic_signal_blink_3.xml deleted file mode 100644 index abcd77410220..000000000000 --- a/packages/SystemUI/res/anim/ic_signal_blink_3.xml +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" - android:interpolator="@android:anim/linear_interpolator" - android:duration="@integer/carrier_network_change_anim_time" - android:repeatCount="-1"> - - <propertyValuesHolder - android:propertyName="fillColor" - android:valueType="colorType"> - <keyframe - android:fraction="0.0" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="0.66" - android:value="?attr/backgroundColor"/> - <keyframe - android:fraction="0.67" - android:value="?attr/fillColor"/> - <keyframe - android:fraction="1.0" - android:value="?attr/fillColor"/> - </propertyValuesHolder> - -</objectAnimator> diff --git a/packages/SystemUI/res/drawable/car_ic_music.xml b/packages/SystemUI/res/drawable/car_ic_music.xml deleted file mode 100644 index f90cd69c1b39..000000000000 --- a/packages/SystemUI/res/drawable/car_ic_music.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 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="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:fillAlpha=".1" - android:strokeAlpha=".1" - android:pathData="M0 0h48v48H0z" /> - <path - android:fillColor="@color/car_grey_50" - android:pathData="M24 2C14.06 2 6 10.06 6 20v14c0 3.31 2.69 6 6 6h6V24h-8v-4c0-7.73 6.27-14 -14-14s14 6.27 14 14v4h-8v16h6c3.31 0 6-2.69 6-6V20c0-9.94-8.06-18-18-18z" /> -</vector> diff --git a/packages/SystemUI/res/drawable/car_ic_notification.xml b/packages/SystemUI/res/drawable/car_ic_notification.xml deleted file mode 100644 index 61d937b90d04..000000000000 --- a/packages/SystemUI/res/drawable/car_ic_notification.xml +++ /dev/null @@ -1,28 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:fillColor="#FFFFFF" - android:pathData="M24 44c2.21 0 4-1.79 4-4h-8c0 2.21 1.79 4 4 -4zm12-12V22c0-6.15-3.27-11.28-9-12.64V8c0-1.66-1.34-3-3-3s-3 1.34-3 3v1.36c-5.73 -1.36-9 6.49-9 12.64v10l-4 4v2h32v-2l-4-4zm-4 2H16V22c0-4.97 3.03-9 8-9s8 4.03 8 -9v12z" /> -</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/car_ic_overview.xml b/packages/SystemUI/res/drawable/car_ic_overview.xml deleted file mode 100644 index 4651dcb3a229..000000000000 --- a/packages/SystemUI/res/drawable/car_ic_overview.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 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="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:pathData="M0 0h48v48H0z" /> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm0 36c-8.82 -0-16-7.18-16-16S15.18 8 24 8s16 7.18 16 16-7.18 16-16 16z" /> -</vector> diff --git a/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml b/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml deleted file mode 100644 index 25b449ab3a8a..000000000000 --- a/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <solid android:color="?android:attr/colorBackgroundFloating" /> - <corners - android:bottomLeftRadius="@dimen/car_radius_3" - android:topLeftRadius="0dp" - android:bottomRightRadius="@dimen/car_radius_3" - android:topRightRadius="0dp" - /> -</shape> diff --git a/packages/SystemUI/res/drawable/dismiss_all_shape_animation.xml b/packages/SystemUI/res/drawable/dismiss_all_shape_animation.xml deleted file mode 100644 index 9e71cbeebea4..000000000000 --- a/packages/SystemUI/res/drawable/dismiss_all_shape_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - android:drawable="@drawable/dismiss_all_shape" > - <target - android:name="3" - android:animation="@anim/dismiss_all_shape_animation_3" /> - <target - android:name="rectangle_path_1_2" - android:animation="@anim/dismiss_all_shape_animation_rectangle_path_1_2" /> - <target - android:name="2" - android:animation="@anim/dismiss_all_shape_animation_2" /> - <target - android:name="rectangle_path_1_1" - android:animation="@anim/dismiss_all_shape_animation_rectangle_path_1_1" /> - <target - android:name="1" - android:animation="@anim/dismiss_all_shape_animation_1" /> - <target - android:name="rectangle_path_1" - android:animation="@anim/dismiss_all_shape_animation_rectangle_path_1" /> -</animated-vector> diff --git a/packages/SystemUI/res/layout/car_navigation_bar.xml b/packages/SystemUI/res/layout/car_navigation_bar.xml deleted file mode 100644 index d568d0d3c179..000000000000 --- a/packages/SystemUI/res/layout/car_navigation_bar.xml +++ /dev/null @@ -1,98 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** Copyright 2016, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<com.android.systemui.statusbar.car.CarNavigationBarView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:systemui="http://schemas.android.com/apk/res-auto" - android:layout_height="match_parent" - android:layout_width="match_parent" - android:background="@drawable/system_bar_background"> - - <LinearLayout - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:orientation="horizontal" - android:id="@+id/nav_buttons" - android:gravity="left" - android:paddingLeft="30dp" - android:layout_weight="1" - android:animateLayoutChanges="true"> - - <com.android.systemui.statusbar.car.CarNavigationButton - android:id="@+id/home" - android:layout_height="match_parent" - android:layout_width="wrap_content" - systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end" - android:src="@drawable/car_ic_overview" - android:background="?android:attr/selectableItemBackground" - android:paddingLeft="30dp" - android:paddingRight="30dp" - /> - - <com.android.systemui.statusbar.car.CarNavigationButton - android:id="@+id/hvac" - android:layout_height="match_parent" - android:layout_width="wrap_content" - systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end" - systemui:broadcast="true" - android:src="@drawable/car_ic_hvac" - android:background="?android:attr/selectableItemBackground" - android:paddingLeft="30dp" - android:paddingRight="30dp" - /> - </LinearLayout> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_weight="1" - android:gravity="right" - android:orientation="horizontal"> - - <com.android.keyguard.AlphaOptimizedImageButton - android:id="@+id/notifications" - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:src="@drawable/car_ic_notification" - android:background="?android:attr/selectableItemBackground" - android:paddingLeft="20dp" - android:paddingRight="20dp" - android:alpha="0.7" - /> - - <com.android.systemui.statusbar.policy.Clock - android:id="@+id/clock" - android:textAppearance="@style/TextAppearance.StatusBar.Clock" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:singleLine="true" - android:paddingStart="@dimen/status_bar_clock_starting_padding" - android:paddingEnd="@dimen/status_bar_clock_end_padding" - android:gravity="center_vertical" - android:paddingRight="20dp" - /> - - <Space - android:layout_width="10dp" - android:layout_height="match_parent"/> - - </LinearLayout> - -</com.android.systemui.statusbar.car.CarNavigationBarView> - diff --git a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml deleted file mode 100644 index 4ba6c06d80a1..000000000000 --- a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml +++ /dev/null @@ -1,61 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** 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. -*/ ---> - -<com.android.systemui.statusbar.car.CarNavigationBarView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:systemui="http://schemas.android.com/apk/res-auto" - android:layout_height="match_parent" - android:layout_width="match_parent" - android:background="@drawable/system_bar_background"> - - <LinearLayout - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:orientation="horizontal" - android:id="@+id/nav_buttons" - android:gravity="left" - android:paddingLeft="30dp" - android:layout_weight="1" - android:animateLayoutChanges="true"> - - <com.android.systemui.statusbar.car.CarNavigationButton - android:id="@+id/home" - android:layout_height="match_parent" - android:layout_width="wrap_content" - systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end" - android:src="@drawable/car_ic_overview" - android:background="?android:attr/selectableItemBackground" - android:paddingLeft="30dp" - android:paddingRight="30dp" - /> - - <com.android.systemui.statusbar.car.CarNavigationButton - android:id="@+id/hvac" - android:layout_height="match_parent" - android:layout_width="wrap_content" - systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end" - systemui:broadcast="true" - android:src="@drawable/car_ic_hvac" - android:background="?android:attr/selectableItemBackground" - android:paddingLeft="30dp" - android:paddingRight="30dp" - /> - </LinearLayout> -</com.android.systemui.statusbar.car.CarNavigationBarView> - diff --git a/packages/SystemUI/res/layout/car_status_bar_header.xml b/packages/SystemUI/res/layout/car_status_bar_header.xml deleted file mode 100644 index f2ef30180bc0..000000000000 --- a/packages/SystemUI/res/layout/car_status_bar_header.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<!-- Extends LinearLayout --> -<com.android.systemui.qs.car.CarStatusBarHeader - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:systemui="http://schemas.android.com/apk/res-auto" - android:id="@+id/header" - android:layout_width="match_parent" - android:layout_height="@dimen/car_qs_header_system_icons_area_height" - android:paddingStart="8dp" - android:paddingEnd="8dp" > - - <include layout="@layout/system_icons" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical|end" - android:layout_weight="1" - /> - - <com.android.systemui.statusbar.policy.Clock - android:id="@+id/clock" - android:textAppearance="@style/TextAppearance.StatusBar.Clock" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:singleLine="true" - android:paddingStart="@dimen/status_bar_clock_starting_padding" - android:paddingEnd="@dimen/status_bar_clock_end_padding" - android:gravity="center_vertical|end" - /> -</com.android.systemui.qs.car.CarStatusBarHeader> diff --git a/packages/SystemUI/res/layout/car_top_navigation_bar.xml b/packages/SystemUI/res/layout/car_top_navigation_bar.xml deleted file mode 100644 index e16014bb8945..000000000000 --- a/packages/SystemUI/res/layout/car_top_navigation_bar.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** -** 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. -*/ ---> - -<com.android.systemui.statusbar.car.CarNavigationBarView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="match_parent" - android:layout_width="match_parent" - android:background="@drawable/system_bar_background"> - - <com.android.systemui.statusbar.policy.Clock - android:id="@+id/clock" - android:textAppearance="@style/TextAppearance.StatusBar.Clock" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:singleLine="true" - android:paddingStart="@dimen/status_bar_clock_starting_padding" - android:paddingEnd="@dimen/status_bar_clock_end_padding" - android:gravity="center_vertical" - /> - -</com.android.systemui.statusbar.car.CarNavigationBarView> - diff --git a/packages/SystemUI/res/layout/car_volume_dialog.xml b/packages/SystemUI/res/layout/car_volume_dialog.xml deleted file mode 100644 index a6beaa15a4bf..000000000000 --- a/packages/SystemUI/res/layout/car_volume_dialog.xml +++ /dev/null @@ -1,31 +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. ---> -<androidx.car.widget.PagedListView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:background="@drawable/car_card_rounded_background" - android:id="@+id/volume_list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/car_margin" - android:layout_marginEnd="@dimen/car_margin" - android:minWidth="@dimen/volume_dialog_panel_width" - android:theme="@style/Theme.Car.NoActionBar" - app:dividerStartMargin="@dimen/car_keyline_1" - app:dividerEndMargin="@dimen/car_keyline_1" - app:gutter="none" - app:showPagedListViewDivider="true" - app:scrollBarEnabled="false" /> diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 0cc3c9eb55dc..34c208ab81aa 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -56,11 +56,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - <ViewStub android:id="@+id/fullscreen_user_switcher_stub" - android:layout="@layout/car_fullscreen_user_switcher" - android:layout_width="match_parent" - android:layout_height="match_parent"/> - <include layout="@layout/status_bar_expanded" android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index b0a519c00943..8e0bfb65428e 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -881,6 +881,7 @@ <dimen name="smart_reply_button_stroke_width">1dp</dimen> <dimen name="smart_reply_button_font_size">14sp</dimen> <dimen name="smart_reply_button_line_spacing_extra">6sp</dimen> <!-- Total line height 20sp. --> + <dimen name="smart_action_button_icon_size">24dp</dimen> <dimen name="smart_action_button_icon_padding">10dp</dimen> <!-- A reasonable upper bound for the height of the smart reply button. The measuring code diff --git a/packages/SystemUI/res/xml/car_volume_items.xml b/packages/SystemUI/res/xml/car_volume_items.xml deleted file mode 100644 index 742dfdda73c8..000000000000 --- a/packages/SystemUI/res/xml/car_volume_items.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * - * 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. -*/ ---> - -<!-- - Defines all possible items on car volume settings UI, keyed by usage. - - This enables the CarSettings UI to associate VolumeGroups surfaced by - CarAudioManager.getVolumeGroupCount with renderable assets (ie: title, icon) - for presentation. - - Order matters in this configuration. If one volume group contains multiple - audio usages, the first one appears in this file would be picked to be - presented on UI. - - When overriding this configuration, please consult also the - car_volume_groups.xml, which is read by car audio service. ---> -<carVolumeItems xmlns:car="http://schemas.android.com/apk/res-auto"> - <item car:usage="unknown" - car:icon="@drawable/car_ic_music"/> - <item car:usage="media" - car:icon="@drawable/car_ic_music"/> - <item car:usage="voice_communication" - car:icon="@*android:drawable/ic_audio_ring_notif"/> - <item car:usage="voice_communication_signalling" - car:icon="@*android:drawable/ic_audio_ring_notif"/> - <item car:usage="alarm" - car:icon="@*android:drawable/ic_audio_alarm"/> - <item car:usage="notification" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="notification_ringtone" - car:icon="@*android:drawable/ic_audio_ring_notif"/> - <item car:usage="notification_communication_request" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="notification_communication_instant" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="notification_communication_delayed" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="notification_event" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="assistance_accessibility" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="assistance_navigation_guidance" - car:icon="@drawable/car_ic_navigation"/> - <item car:usage="assistance_sonification" - car:icon="@drawable/car_ic_notification"/> - <item car:usage="game" - car:icon="@drawable/car_ic_music"/> - <item car:usage="assistant" - car:icon="@drawable/car_ic_music"/> -</carVolumeItems> - diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 417d5168641d..867c9175d308 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -62,6 +62,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.SmartReplyConstants; +import com.android.systemui.volume.VolumeDialogComponent; import java.util.function.Consumer; @@ -132,6 +133,10 @@ public class SystemUIFactory { return new QSTileHost(context, statusBar, iconController); } + public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) { + return new VolumeDialogComponent(systemUi, context); + } + public void injectDependencies(ArrayMap<Object, DependencyProvider> providers, Context context) { providers.put(StatusBarStateController.class, StatusBarStateController::new); diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java deleted file mode 100644 index 09c000b469a7..000000000000 --- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.car; - -import android.content.Context; -import android.util.ArrayMap; - -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.Dependency.DependencyProvider; -import com.android.systemui.SystemUIFactory; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.car.CarFacetButtonController; -import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager; -import com.android.systemui.statusbar.car.hvac.HvacController; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; - -/** - * Class factory to provide car specific SystemUI components. - */ -public class CarSystemUIFactory extends SystemUIFactory { - - public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context, - ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) { - return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils); - } - - @Override - public void injectDependencies(ArrayMap<Object, DependencyProvider> providers, - Context context) { - super.injectDependencies(providers, context); - providers.put(NotificationEntryManager.class, - () -> new CarNotificationEntryManager(context)); - providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context)); - providers.put(HvacController.class, () -> new HvacController(context)); - providers.put(NotificationMediaManager.class, - () -> new CarNotificationMediaManager(context)); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java index 2c61da343763..1718cff4e62b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java @@ -108,7 +108,7 @@ public class FalsingManager implements SensorEventListener { UserHandle.USER_ALL); updateConfiguration(); - Dependency.get(StatusBarStateController.class).addListener(mStateListener); + Dependency.get(StatusBarStateController.class).addCallback(mStateListener); } public static FalsingManager getInstance(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index bf8e04db976b..7e778437b7d7 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -401,7 +401,9 @@ public class DozeSensors { } mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY, event.values); - updateListener(); // reregister, this sensor only fires once + if (!mRegistered) { + updateListener(); // reregister, this sensor only fires once + } })); } @@ -440,7 +442,9 @@ public class DozeSensors { mRegistered = false; mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1, event.getValues()); - updateListener(); // reregister, this sensor only fires once + if (!mRegistered) { + updateListener(); // reregister, this sensor only fires once + } })); }; @@ -487,7 +491,6 @@ public class DozeSensors { } return sb.append(']').toString(); } - } public interface Callback { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index bad01480d677..afe9a74da48a 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -184,6 +184,7 @@ public class DozeTriggers implements DozeMachine.Part { if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch); mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch); } + if (far && (paused || pausing)) { if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD"); mMachine.requestState(DozeMachine.State.DOZE_AOD); @@ -205,13 +206,13 @@ public class DozeTriggers implements DozeMachine.Part { // In pocket, drop event. return; } - if (pausing || paused) { + if (mMachine.getState() == DozeMachine.State.DOZE) { mMachine.requestState(DozeMachine.State.DOZE_AOD); } }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP); } else { if (!pausing && !paused) { - mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING); + mMachine.requestState(DozeMachine.State.DOZE); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java index a5e7f04be281..8821679aadf1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AmbientPulseManager.java @@ -33,7 +33,7 @@ import com.android.systemui.statusbar.notification.row.NotificationInflater.Infl * dozing and/or in AOD. The pulse uses the notification's ambient view and pops in briefly * before automatically dismissing the alert. */ -public final class AmbientPulseManager extends AlertingNotificationManager { +public class AmbientPulseManager extends AlertingNotificationManager { protected final ArraySet<OnAmbientChangedListener> mListeners = new ArraySet<>(); @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 8b9399536969..b55027436b91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -223,7 +223,9 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void disable(int state1, int state2) { + // TODO(b/117478341): Add multi-display support. + @Override + public void disable(int displayId, int state1, int state2) { disable(state1, state2, true); } @@ -266,8 +268,10 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, - int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { + // TODO(b/117478341): Add multi-display support. + @Override + public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, + int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { synchronized (mLock) { // Don't coalesce these, since it might have one time flags set such as // STATUS_BAR_UNHIDE which might get lost. @@ -282,7 +286,9 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void topAppWindowChanged(boolean menuVisible) { + // TODO(b/117478341): Add multi-display support. + @Override + public void topAppWindowChanged(int displayId, boolean menuVisible) { synchronized (mLock) { mHandler.removeMessages(MSG_TOP_APP_WINDOW_CHANGED); mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, menuVisible ? 1 : 0, 0, @@ -290,7 +296,9 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void setImeWindowStatus(IBinder token, int vis, int backDisposition, + // TODO(b/117478341): Add multi-display support. + @Override + public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { synchronized (mLock) { mHandler.removeMessages(MSG_SHOW_IME_BUTTON); @@ -371,7 +379,9 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void setWindowState(int window, int state) { + // TODO(b/117478341): Add multi-display support. + @Override + public void setWindowState(int displayId, int window, int state) { synchronized (mLock) { // don't coalesce these mHandler.obtainMessage(MSG_SET_WINDOW_STATE, window, state, null).sendToTarget(); @@ -385,7 +395,9 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void appTransitionPending() { + // TODO(b/117478341): Add multi-display support. + @Override + public void appTransitionPending(int displayId) { appTransitionPending(false /* forced */); } @@ -395,13 +407,17 @@ public class CommandQueue extends IStatusBar.Stub { } } - public void appTransitionCancelled() { + // TODO(b/117478341): Add multi-display support. + @Override + public void appTransitionCancelled(int displayId) { synchronized (mLock) { mHandler.sendEmptyMessage(MSG_APP_TRANSITION_CANCELLED); } } - public void appTransitionStarting(long startTime, long duration) { + // TODO(b/117478341): Add multi-display support. + @Override + public void appTransitionStarting(int displayId, long startTime, long duration) { appTransitionStarting(startTime, duration, false /* forced */); } @@ -412,8 +428,9 @@ public class CommandQueue extends IStatusBar.Stub { } } + // TODO(b/117478341): Add multi-display support. @Override - public void appTransitionFinished() { + public void appTransitionFinished(int displayId) { synchronized (mLock) { mHandler.sendEmptyMessage(MSG_APP_TRANSITION_FINISHED); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 960d22185652..7d1b640f7e40 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -156,7 +156,7 @@ public class KeyguardIndicationController implements StateListener { new IntentFilter(Intent.ACTION_TIME_TICK), null, Dependency.get(Dependency.TIME_TICK_HANDLER)); - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } /** @@ -167,7 +167,7 @@ public class KeyguardIndicationController implements StateListener { */ public void destroy() { mContext.unregisterReceiver(mTickReceiver); - Dependency.get(StatusBarStateController.class).removeListener(this); + Dependency.get(StatusBarStateController.class).removeCallback(this); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index b0724b1e014b..bba4369b5e01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -165,7 +165,7 @@ public class NotificationLockscreenUserManagerImpl implements mCurrentUserId = ActivityManager.getCurrentUser(); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); mLockPatternUtils = new LockPatternUtils(context); mKeyguardManager = context.getSystemService(KeyguardManager.class); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 7be5461f0afa..ecadf96dfbfc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -141,7 +141,7 @@ public class NotificationRemoteInputManager implements Dumpable { ActivityManager.getService().resumeAppSwitches(); } catch (RemoteException e) { } - return mCallback.handleRemoteViewClick(pendingIntent, () -> { + return mCallback.handleRemoteViewClick(view, pendingIntent, () -> { Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view); options.second.setLaunchWindowingMode( WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); @@ -666,11 +666,13 @@ public class NotificationRemoteInputManager implements Dumpable { * Performs any special handling for a remote view click. The default behaviour can be * called through the defaultHandler parameter. * + * @param view * @param pendingIntent * @param defaultHandler * @return true iff the click was handled */ - boolean handleRemoteViewClick(PendingIntent pendingIntent, ClickHandler defaultHandler); + boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, + ClickHandler defaultHandler); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index e7b4904a8ba5..6cec36a81e5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -121,13 +121,13 @@ public class NotificationShelf extends ActivatableNotificationView implements protected void onAttachedToWindow() { super.onAttachedToWindow(); Dependency.get(StatusBarStateController.class) - .addListener(mStateListener, StatusBarStateController.RANK_SHELF); + .addCallback(mStateListener, StatusBarStateController.RANK_SHELF); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - Dependency.get(StatusBarStateController.class).removeListener(mStateListener); + Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); } public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) { @@ -225,7 +225,7 @@ public class NotificationShelf extends ActivatableNotificationView implements } viewState.hasItemsInStableShelf = lastViewState.inShelf; viewState.hidden = !mAmbientState.isShadeExpanded() - || mAmbientState.isQsCustomizerShowing(); + || mAmbientState.isQsCustomizerShowing() || mAmbientState.isFullyDark(); viewState.maxShelfEnd = maxShelfEnd; } else { viewState.hidden = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index daa2fd45b142..dc3a60786ce2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -129,7 +129,7 @@ public class NotificationViewHierarchyManager { res.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications); mStatusBarStateListener = new StatusBarStateListener(mBubbleController); mEntryManager.setStatusBarStateListener(mStatusBarStateListener); - Dependency.get(StatusBarStateController.class).addListener(mStatusBarStateListener); + Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener); } public void setUpWithPresenter(NotificationPresenter presenter, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java index eaf52cb357fe..3f84416ad575 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java @@ -26,8 +26,10 @@ import android.view.animation.Interpolator; import com.android.internal.annotations.GuardedBy; import com.android.systemui.Interpolators; +import com.android.systemui.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.policy.CallbackController; import java.lang.annotation.Retention; import java.util.ArrayList; @@ -36,7 +38,7 @@ import java.util.Comparator; /** * Tracks and reports on {@link StatusBarState}. */ -public class StatusBarStateController { +public class StatusBarStateController implements CallbackController<StateListener> { private static final String TAG = "SbStateController"; private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER; @@ -228,7 +230,7 @@ public class StatusBarStateController { return mLastState == StatusBarState.SHADE_LOCKED; } - public void addListener(StateListener listener) { + public void addCallback(StateListener listener) { synchronized (mListeners) { addListenerInternalLocked(listener, Integer.MAX_VALUE); } @@ -244,7 +246,7 @@ public class StatusBarStateController { * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking * (i.e., they are non-dependent on the order of operations of StatusBarState listeners). */ - public void addListener(StateListener listener, @SbStateListenerRank int rank) { + public void addCallback(StateListener listener, @SbStateListenerRank int rank) { synchronized (mListeners) { addListenerInternalLocked(listener, rank); } @@ -264,7 +266,7 @@ public class StatusBarStateController { mListeners.sort(mComparator); } - public void removeListener(StateListener listener) { + public void removeCallback(StateListener listener) { synchronized (mListeners) { mListeners.removeIf((it) -> it.listener.equals(listener)); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java deleted file mode 100644 index bd328567fb46..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.android.systemui.statusbar.car; - -import android.content.Context; -import android.content.Intent; -import android.content.res.TypedArray; -import android.os.UserHandle; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import com.android.keyguard.AlphaOptimizedImageButton; -import com.android.systemui.Dependency; -import com.android.systemui.R; - -/** - * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined - * category. It can also render a indicator impling that there are more options of apps to launch - * using this component. This is done with a "More icon" currently an arrow as defined in the layout - * file. The class is to serve as an example. - * Usage example: A button that allows a user to select a music app and indicate that there are - * other music apps installed. - */ -public class CarFacetButton extends LinearLayout { - private static final String FACET_FILTER_DELIMITER = ";"; - /** - * Extra information to be sent to a helper to make the decision of what app to launch when - * clicked. - */ - private static final String EXTRA_FACET_CATEGORIES = "categories"; - private static final String EXTRA_FACET_PACKAGES = "packages"; - private static final String EXTRA_FACET_ID = "filter_id"; - private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker"; - - private Context mContext; - private AlphaOptimizedImageButton mIcon; - private AlphaOptimizedImageButton mMoreIcon; - private boolean mSelected = false; - private String[] mComponentNames; - /** App categories that are to be used with this widget */ - private String[] mFacetCategories; - /** App packages that are allowed to be used with this widget */ - private String[] mFacetPackages; - private int mIconResourceId; - /** - * If defined in the xml this will be the icon that's rendered when the button is marked as - * selected - */ - private int mSelectedIconResourceId; - private boolean mUseMoreIcon = true; - private float mSelectedAlpha = 1f; - private float mUnselectedAlpha = 1f; - - - public CarFacetButton(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - View.inflate(context, R.layout.car_facet_button, this); - - // extract custom attributes - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton); - setupIntents(typedArray); - setupIcons(typedArray); - CarFacetButtonController carFacetButtonController = Dependency.get( - CarFacetButtonController.class); - carFacetButtonController.addFacetButton(this); - - } - - /** - * Reads the custom attributes to setup click handlers for this component. - */ - private void setupIntents(TypedArray typedArray) { - String intentString = typedArray.getString(R.styleable.CarFacetButton_intent); - String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent); - String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories); - String packageString = typedArray.getString(R.styleable.CarFacetButton_packages); - String componentNameString = - typedArray.getString(R.styleable.CarFacetButton_componentNames); - try { - final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME); - intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId())); - - if (packageString != null) { - mFacetPackages = packageString.split(FACET_FILTER_DELIMITER); - intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages); - } - if (categoryString != null) { - mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER); - intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories); - } - if (componentNameString != null) { - mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER); - } - - setOnClickListener(v -> { - intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - }); - - if (longPressIntentString != null) { - final Intent longPressIntent = Intent.parseUri(longPressIntentString, - Intent.URI_INTENT_SCHEME); - setOnLongClickListener(v -> { - mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT); - return true; - }); - } - } catch (Exception e) { - throw new RuntimeException("Failed to attach intent", e); - } - } - - - private void setupIcons(TypedArray styledAttributes) { - mSelectedAlpha = styledAttributes.getFloat( - R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha); - mUnselectedAlpha = styledAttributes.getFloat( - R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha); - mIcon = findViewById(R.id.car_nav_button_icon); - mIcon.setScaleType(ImageView.ScaleType.CENTER); - mIcon.setClickable(false); - mIcon.setAlpha(mUnselectedAlpha); - mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0); - mIcon.setImageResource(mIconResourceId); - mSelectedIconResourceId = styledAttributes.getResourceId( - R.styleable.CarFacetButton_selectedIcon, mIconResourceId); - - mMoreIcon = findViewById(R.id.car_nav_button_more_icon); - mMoreIcon.setClickable(false); - mMoreIcon.setAlpha(mSelectedAlpha); - mMoreIcon.setVisibility(GONE); - mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true); - } - - /** - * @return The app categories the component represents - */ - public String[] getCategories() { - if (mFacetCategories == null) { - return new String[0]; - } - return mFacetCategories; - } - - /** - * @return The valid packages that should be considered. - */ - public String[] getFacetPackages() { - if (mFacetPackages == null) { - return new String[0]; - } - return mFacetPackages; - } - - public String[] getComponentName() { - if (mComponentNames == null) { - return new String[0]; - } - return mComponentNames; - } - - /** - * Updates the alpha of the icons to "selected" and shows the "More icon" - * @param selected true if the view must be selected, false otherwise - */ - public void setSelected(boolean selected) { - super.setSelected(selected); - setSelected(selected, selected); - } - - /** - * Updates the visual state to let the user know if it's been selected. - * @param selected true if should update the alpha of the icon to selected, false otherwise - * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this - * is ignored if the attribute useMoreIcon is set to false - */ - public void setSelected(boolean selected, boolean showMoreIcon) { - mSelected = selected; - mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha); - mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId); - if (mUseMoreIcon) { - mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE); - } - } -} 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 f506753379a4..f899863dcc6b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java @@ -299,6 +299,10 @@ public class ActivityLaunchAnimator { return top; } + public int getBottom() { + return bottom; + } + public int getWidth() { return right - left; } 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 1616b6dc53de..70d144e006f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -952,10 +952,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. // Has a copy of the current UI adjustments. ArrayMap<String, NotificationUiAdjustment> oldAdjustments = new ArrayMap<>(); + ArrayMap<String, Integer> oldImportances = new ArrayMap<>(); for (NotificationData.Entry entry : entries) { NotificationUiAdjustment adjustment = NotificationUiAdjustment.extractFromNotificationEntry(entry); oldAdjustments.put(entry.key, adjustment); + oldImportances.put(entry.key, entry.importance); } // Populate notification entries from the new rankings. @@ -978,6 +980,11 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. // Once the RowInflaterTask is done, it will pick up the updated entry, so // no-op here. } + } else if (oldImportances.containsKey(entry.key) + && entry.importance != oldImportances.get(entry.key)) { + if (entry.rowExists()) { + entry.getRow().onNotificationRankingUpdated(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java index 1f48c15e63c0..09eb8a1030ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java @@ -75,6 +75,6 @@ public class NotificationUtils { /** Returns the value of the new interruption model setting. */ public static boolean useNewInterruptionModel(Context context) { return Settings.Secure.getInt(context.getContentResolver(), - NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) != 0; + NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) != 0; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java index 87313b8a0393..9f02e543b6e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java @@ -149,7 +149,7 @@ public class NotificationLogger implements StateListener { mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); // Not expected to be destroyed, don't need to unsubscribe - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } public void setUpWithContainer(NotificationListContainer listContainer) { 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 d4d45ea52a85..69e698ffcd39 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 @@ -588,6 +588,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView updateRippleAllowed(); } + /** Called when the notification's ranking was changed (but nothing else changed). */ + public void onNotificationRankingUpdated() { + if (mMenuRow != null) { + mMenuRow.onNotificationUpdated(mStatusBarNotification); + } + } + @VisibleForTesting void updateShelfIconColor() { StatusBarIconView expandedIcon = mEntry.expandedIcon; @@ -2001,7 +2008,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView float interpolation = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(params.getProgress()); int startClipTopAmount = params.getStartClipTopAmount(); if (mNotificationParent != null) { - top -= mNotificationParent.getTranslationY(); + float parentY = mNotificationParent.getTranslationY(); + top -= parentY; mNotificationParent.setTranslationZ(translationZ); int parentStartClipTopAmount = params.getParentStartClipTopAmount(); if (startClipTopAmount != 0) { @@ -2011,8 +2019,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mNotificationParent.setClipTopAmount(clipTopAmount); } mNotificationParent.setExtraWidthForClipping(extraWidthForClipping); - mNotificationParent.setMinimumHeightForClipping(params.getHeight() - + mNotificationParent.getActualHeight()); + float clipBottom = Math.max(params.getBottom(), + parentY + mNotificationParent.getActualHeight() + - mNotificationParent.getClipBottomAmount()); + float clipTop = Math.min(params.getTop(), parentY); + int minimumHeightForClipping = (int) (clipBottom - clipTop); + mNotificationParent.setMinimumHeightForClipping(minimumHeightForClipping); } else if (startClipTopAmount != 0) { int clipTopAmount = (int) MathUtils.lerp(startClipTopAmount, 0, interpolation); setClipTopAmount(clipTopAmount); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java index 7086025836cb..ef343fac5afa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java @@ -697,7 +697,7 @@ public class NotificationInflater { && newView.getPackage() != null && newView.getPackage().equals(oldView.getPackage()) && newView.getLayoutId() == oldView.getLayoutId() - && !oldView.isReapplyDisallowed()); + && !oldView.hasFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED)); } public void setInflationCallback(InflationCallback callback) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java index 948d2a5e2a18..50564e386e4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java @@ -267,7 +267,9 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl } else { mRightMenuItems.add(mInfoItem); mRightMenuItems.add(mAppOpsItem); - mRightMenuItems.add(mSnoozeItem); + if (!isForeground) { + mRightMenuItems.add(mSnoozeItem); + } } populateMenuViews(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 626e68850c12..eca1a1411212 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator .ExpandAnimationParameters; +import static com.android.systemui.statusbar.notification.stack.StackStateAnimator + .ANIMATION_DURATION_SWIPE; import static com.android.systemui.statusbar.phone.NotificationIconAreaController.LOW_PRIORITY; import android.animation.Animator; @@ -616,7 +618,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd protected void onAttachedToWindow() { super.onAttachedToWindow(); Dependency.get(StatusBarStateController.class) - .addListener(mStateListener, StatusBarStateController.RANK_STACK_SCROLLER); + .addCallback(mStateListener, StatusBarStateController.RANK_STACK_SCROLLER); Dependency.get(ConfigurationController.class).addCallback(this); } @@ -624,7 +626,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - Dependency.get(StatusBarStateController.class).removeListener(mStateListener); + Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); Dependency.get(ConfigurationController.class).removeCallback(this); } @@ -5093,7 +5095,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd if (i == 0) { endRunnable = animationFinishAction; } - dismissViewAnimated(view, endRunnable, totalDelay, 260); + dismissViewAnimated(view, endRunnable, totalDelay, ANIMATION_DURATION_SWIPE); currentDelay = Math.max(50, currentDelay - rowDelayDecrement); totalDelay += currentDelay; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index fef28cf1393e..d6905478a043 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -44,6 +44,7 @@ public class StackStateAnimator { public static final int ANIMATION_DURATION_WAKEUP = 500; public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448; public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464; + public static final int ANIMATION_DURATION_SWIPE = 260; public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220; public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150; public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index 3b13fe96fe42..8418cba4c7b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -121,14 +121,14 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public void onResume() { super.onResume(); mCommandQueue.addCallbacks(this); - mStatusBarStateController.addListener(this); + mStatusBarStateController.addCallback(this); } @Override public void onPause() { super.onPause(); mCommandQueue.removeCallbacks(this); - mStatusBarStateController.removeListener(this); + mStatusBarStateController.removeCallback(this); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index 94b2cdeea898..cfa751cec613 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -88,7 +88,7 @@ public class DozeScrimController implements StateListener { public DozeScrimController(DozeParameters dozeParameters) { mDozeParameters = dozeParameters; //Never expected to be destroyed - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 9faada05294b..aa0b7b656e1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -129,7 +129,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, updateTouchableRegionListener(); } }); - Dependency.get(StatusBarStateController.class).addListener(mStateListener); + Dependency.get(StatusBarStateController.class).addCallback(mStateListener); mBubbleController.setBubbleStateChangeListener((hasBubbles) -> { if (!hasBubbles) { mBubbleGoingAway = true; @@ -143,7 +143,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } public void destroy() { - Dependency.get(StatusBarStateController.class).removeListener(mStateListener); + Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); } private void initResources() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java index b29889dac6f8..1c6d2924bb93 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java @@ -74,14 +74,14 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, mStatusBarStateController = Dependency.get(StatusBarStateController.class); SysUiServiceProvider.getComponent(context, CommandQueue.class) .addCallbacks(this); - mStatusBarStateController.addListener(this); + mStatusBarStateController.addCallback(this); mDozeAmount = mStatusBarStateController.getDozeAmount(); } public void destroy(Context context) { SysUiServiceProvider.getComponent(context, CommandQueue.class) .removeCallbacks(this); - mStatusBarStateController.removeListener(this); + mStatusBarStateController.removeCallback(this); } public void saveState(Bundle outState) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index 12a0cc882a81..3984405f8e09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -24,7 +24,6 @@ import android.util.SparseArray; import android.view.Display; import android.view.IWallpaperVisibilityListener; import android.view.IWindowManager; -import android.view.MotionEvent; import android.view.View; import com.android.internal.statusbar.IStatusBarService; @@ -165,23 +164,4 @@ public final class NavigationBarTransitions extends BarTransitions { } mView.onDarkIntensityChange(darkIntensity); } - - private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - // even though setting the systemUI visibility below will turn these views - // on, we need them to come up faster so that they can catch this motion - // event - applyLightsOut(false, false, false); - - try { - mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE, - "LightsOutListener"); - } catch (android.os.RemoteException ex) { - } - } - return false; - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java index 83067f6cff87..a8d00c454548 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java @@ -127,6 +127,15 @@ public abstract class NavigationGestureAction { } /** + * Decide if the controller should not send the current motion event to launcher via + * {@link OverviewProxyService} + * @return if controller should not proxy + */ + public boolean disableProxyEvents() { + return false; + } + + /** * Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings * if the action is disabled for a particular gesture. For example a back action can be enabled * however if there is nothing to back to then {@link #canPerformAction()} should return false. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java index 3e31fa06ef27..2a68fa598603 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java @@ -82,7 +82,7 @@ public class NotificationGroupAlertTransferHelper implements OnGroupChangeListen private boolean mIsDozing; public NotificationGroupAlertTransferHelper() { - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java index 448b5c38da51..8f4369a98b17 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java @@ -55,7 +55,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, private boolean mIsUpdatingUnchangedGroup; public NotificationGroupManager() { - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 33d176a580da..a2a11bbfd650 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -366,7 +366,7 @@ public class NotificationPanelView extends PanelView implements protected void onAttachedToWindow() { super.onAttachedToWindow(); FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener); - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); Dependency.get(ZenModeController.class).addCallback(this); Dependency.get(ConfigurationController.class).addCallback(this); } @@ -375,7 +375,7 @@ public class NotificationPanelView extends PanelView implements protected void onDetachedFromWindow() { super.onDetachedFromWindow(); FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener); - Dependency.get(StatusBarStateController.class).removeListener(this); + Dependency.get(StatusBarStateController.class).removeCallback(this); Dependency.get(ZenModeController.class).removeCallback(this); Dependency.get(ConfigurationController.class).removeCallback(this); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java index 74744f1408fb..2b202eb83431 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java @@ -212,6 +212,11 @@ public class QuickScrubAction extends NavigationGestureAction { } @Override + public boolean disableProxyEvents() { + return true; + } + + @Override protected void onGestureStart(MotionEvent event) { updateHighlight(); ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this, 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 43e86d66b8be..4983618ba414 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -185,6 +185,7 @@ public class QuickStepController implements GestureHelper { // Requires proxy and an active gesture or able to perform any gesture to continue if (mOverviewEventSender.getProxy() == null + || !mOverviewEventSender.shouldShowSwipeUpUI() || (mCurrentAction == null && !canPerformAnyAction())) { return deadZoneConsumed; } @@ -275,25 +276,21 @@ public class QuickStepController implements GestureHelper { if (mDragVPositive ? (posV < touchDownV) : (posV > touchDownV)) { // Swiping up gesture tryToStartGesture(mGestureActions[ACTION_SWIPE_UP_INDEX], - false /* alignedWithNavBar */, false /* positiveDirection */, - event); + false /* alignedWithNavBar */, event); } else { // Swiping down gesture tryToStartGesture(mGestureActions[ACTION_SWIPE_DOWN_INDEX], - false /* alignedWithNavBar */, true /* positiveDirection */, - event); + false /* alignedWithNavBar */, event); } } else if (exceededSwipeHorizontalTouchSlop) { if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) { // Swiping left (ltr) gesture tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX], - true /* alignedWithNavBar */, false /* positiveDirection */, - event); + true /* alignedWithNavBar */, event); } else { // Swiping right (ltr) gesture tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX], - true /* alignedWithNavBar */, true /* positiveDirection */, - event); + true /* alignedWithNavBar */, event); } } } @@ -306,7 +303,6 @@ public class QuickStepController implements GestureHelper { case MotionEvent.ACTION_UP: if (mCurrentAction != null) { mCurrentAction.endGesture(); - mCurrentAction = null; } // Return the hit target back to its original position @@ -329,6 +325,11 @@ public class QuickStepController implements GestureHelper { if (shouldProxyEvents(action)) { proxyMotionEvents(event); } + + // Clear action when gesture and event proxy finishes + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + mCurrentAction = null; + } return mCurrentAction != null || deadZoneConsumed; } @@ -354,8 +355,7 @@ public class QuickStepController implements GestureHelper { private boolean shouldProxyEvents(int action) { final boolean actionValid = (mCurrentAction == null - || (mGestureActions[ACTION_SWIPE_UP_INDEX] != null - && mGestureActions[ACTION_SWIPE_UP_INDEX].isActive())); + || !mCurrentAction.disableProxyEvents()); if (actionValid && !mIsInScreenPinning) { // Allow down, cancel and up events, move and other events are passed if notifications // are not showing and disabled gestures (such as long press) are not executed @@ -455,7 +455,7 @@ public class QuickStepController implements GestureHelper { } private void tryToStartGesture(NavigationGestureAction action, boolean alignedWithNavBar, - boolean positiveDirection, MotionEvent event) { + MotionEvent event) { if (action == null) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index cfd53be8979b..58b9de4ebe27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -161,7 +161,6 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.Snoo import com.android.systemui.qs.QSFragment; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTileHost; -import com.android.systemui.qs.car.CarQSFragment; import com.android.systemui.recents.Recents; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -474,8 +473,10 @@ public class StatusBar extends SystemUI implements DemoMode, return; } WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT); - final boolean supportsAmbientMode = info != null && - info.supportsAmbientMode(); + final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dozeSupportsAodWallpaper); + final boolean supportsAmbientMode = deviceSupportsAodWallpaper + && info != null && info.supportsAmbientMode(); mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); @@ -626,7 +627,7 @@ public class StatusBar extends SystemUI implements DemoMode, mBubbleController.setExpandListener(mBubbleExpandListener); mColorExtractor.addOnColorsChangedListener(this); - mStatusBarStateController.addListener(this, StatusBarStateController.RANK_STATUS_BAR); + mStatusBarStateController.addCallback(this, StatusBarStateController.RANK_STATUS_BAR); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mDreamManager = IDreamManager.Stub.asInterface( @@ -918,8 +919,7 @@ public class StatusBar extends SystemUI implements DemoMode, Dependency.get(ExtensionController.class) .newExtension(QS.class) .withPlugin(QS.class) - .withFeature(PackageManager.FEATURE_AUTOMOTIVE, CarQSFragment::new) - .withDefault(QSFragment::new) + .withDefault(this::createDefaultQSFragment) .build()); final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, mIconController); @@ -1007,6 +1007,10 @@ public class StatusBar extends SystemUI implements DemoMode, ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } + protected QS createDefaultQSFragment() { + return new QSFragment(); + } + protected void setUpPresenter() { // Set up the initial notification state. mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel, @@ -2885,7 +2889,7 @@ public class StatusBar extends SystemUI implements DemoMode, mContext.unregisterReceiver(mDemoReceiver); mAssistManager.destroy(); mHeadsUpManager.destroy(); - mStatusBarStateController.removeListener(this); + mStatusBarStateController.removeCallback(this); if (mQSPanel != null && mQSPanel.getHost() != null) { mQSPanel.getHost().destroy(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 484fe110b28a..0f8970f1069f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -151,7 +151,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mLockPatternUtils = lockPatternUtils; mStatusBarWindowController = Dependency.get(StatusBarWindowController.class); KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback); - Dependency.get(StatusBarStateController.class).addListener(this); + Dependency.get(StatusBarStateController.class).addCallback(this); } public void registerStatusBar(StatusBar statusBar, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index a743d41e8d3a..3f1e826eb67b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -70,7 +70,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks { mContext = context; mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL, new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null); - mStatusBarStateController.addListener(mStateListener); + mStatusBarStateController.addCallback(mStateListener); mKeyguardManager = context.getSystemService(KeyguardManager.class); mCommandQueue = getComponent(context, CommandQueue.class); mCommandQueue.addCallbacks(this); @@ -206,7 +206,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks { } @Override - public boolean handleRemoteViewClick(PendingIntent pendingIntent, + public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) { final boolean isActivity = pendingIntent.isActivity(); if (isActivity) { 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 158ee8ae8fbd..986a86d13958 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -92,7 +92,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); mDozeParameters = dozeParameters; mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze(); - Dependency.get(StatusBarStateController.class).addListener( + Dependency.get(StatusBarStateController.class).addCallback( mStateListener, StatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER); Dependency.get(ConfigurationController.class).addCallback(this); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 978a72dcb4b7..53e461db3dd1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -49,6 +49,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; +import android.view.WindowInsetsController; import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; @@ -785,6 +786,11 @@ public class StatusBarWindowView extends FrameLayout { @Override public void reportActivityRelaunched() { } + + @Override + public WindowInsetsController getInsetsController() { + return null; + } }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index 8517d9086fc7..c2af95e66fe9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -165,7 +165,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C mClockVisibleByUser = bundle.getBoolean(VISIBLE_BY_USER, true); mShowSeconds = bundle.getBoolean(SHOW_SECONDS, false); if (bundle.containsKey(VISIBILITY)) { - setVisibility(bundle.getInt(VISIBILITY)); + super.setVisibility(bundle.getInt(VISIBILITY)); } } @@ -203,6 +203,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C // Make sure we update to the current time updateClock(); + updateClockVisibility(); updateShowSeconds(); } @@ -247,6 +248,15 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C } }; + @Override + public void setVisibility(int visibility) { + if (visibility == View.VISIBLE && !shouldBeVisible()) { + return; + } + + super.setVisibility(visibility); + } + public void setClockVisibleByUser(boolean visible) { mClockVisibleByUser = visible; updateClockVisibility(); @@ -257,11 +267,15 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C updateClockVisibility(); } + private boolean shouldBeVisible() { + return mClockVisibleByPolicy && mClockVisibleByUser; + } + private void updateClockVisibility() { - boolean visible = mClockVisibleByPolicy && mClockVisibleByUser; + boolean visible = shouldBeVisible(); Dependency.get(IconLogger.class).onIconVisibility("clock", visible); int visibility = visible ? View.VISIBLE : View.GONE; - setVisibility(visibility); + super.setVisibility(visibility); } final void updateClock() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java index 639e50cf4e58..9c099f91bc8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EncryptionHelper.java @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.policy; -import android.os.SystemProperties; +import android.sysprop.VoldProperties; /** * Helper for determining whether the phone is decrypted yet. @@ -26,7 +26,7 @@ public class EncryptionHelper { public static final boolean IS_DATA_ENCRYPTED = isDataEncrypted(); private static boolean isDataEncrypted() { - String voldState = SystemProperties.get("vold.decrypt"); + String voldState = VoldProperties.decrypt().orElse(""); return "1".equals(voldState) || "trigger_restart_min_framework".equals(voldState); } } 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 f36066ce3794..2a4336e809a0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -21,7 +21,6 @@ import android.text.TextPaint; import android.text.method.TransformationMethod; import android.util.AttributeSet; import android.util.Log; -import android.util.Size; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -41,6 +40,7 @@ import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import java.text.BreakIterator; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.PriorityQueue; @@ -282,9 +282,9 @@ public class SmartReplyView extends ViewGroup { Drawable iconDrawable = action.getIcon().loadDrawable(context); // Add the action icon to the Smart Action button. - Size newIconSize = calculateIconSizeFromSingleLineButton(context, root, - new Size(iconDrawable.getIntrinsicWidth(), iconDrawable.getIntrinsicHeight())); - iconDrawable.setBounds(0, 0, newIconSize.getWidth(), newIconSize.getHeight()); + int newIconSize = context.getResources().getDimensionPixelSize( + R.dimen.smart_action_button_icon_size); + iconDrawable.setBounds(0, 0, newIconSize, newIconSize); button.setCompoundDrawables(iconDrawable, null, null, null); button.setOnClickListener(view -> @@ -295,30 +295,12 @@ public class SmartReplyView extends ViewGroup { // TODO(b/119010281): handle accessibility + // Mark this as an Action button + final LayoutParams lp = (LayoutParams) button.getLayoutParams(); + lp.buttonType = SmartButtonType.ACTION; return button; } - private static Size calculateIconSizeFromSingleLineButton(Context context, ViewGroup root, - Size originalIconSize) { - Button button = (Button) LayoutInflater.from(context).inflate( - R.layout.smart_action_button, root, false); - // Add simple text here to ensure the button displays one line of text. - button.setText("a"); - return calculateIconSizeFromButtonHeight(button, originalIconSize); - } - - // Given a button with text on a single line - we want to add an icon to that button. This - // method calculates the icon height to use to avoid making the button grow in height. - private static Size calculateIconSizeFromButtonHeight(Button button, Size originalIconSize) { - // A completely permissive measure spec should make the button text single-line. - button.measure(MEASURE_SPEC_ANY_LENGTH, MEASURE_SPEC_ANY_LENGTH); - int buttonHeight = button.getMeasuredHeight(); - int newIconHeight = buttonHeight / 2; - int newIconWidth = (int) (originalIconSize.getWidth() - * ((double) newIconHeight) / originalIconSize.getHeight()); - return new Size(newIconWidth, newIconHeight); - } - @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(mContext, attrs); @@ -352,18 +334,26 @@ public class SmartReplyView extends ViewGroup { int displayedChildCount = 0; int buttonPaddingHorizontal = mSingleLineButtonPaddingHorizontal; - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); + // Set up a list of suggestions where actions come before replies. Note that the Buttons + // themselves have already been added to the view hierarchy in an order such that Smart + // Replies are shown before Smart Actions. The order of the list below determines which + // suggestions will be shown at all - only the first X elements are shown (where X depends + // on how much space each suggestion button needs). + List<View> smartActions = filterActionsOrReplies(SmartButtonType.ACTION); + List<View> smartReplies = filterActionsOrReplies(SmartButtonType.REPLY); + List<View> smartSuggestions = new ArrayList<>(smartActions); + smartSuggestions.addAll(smartReplies); + List<View> coveredSuggestions = new ArrayList<>(); + + for (View child : smartSuggestions) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (child.getVisibility() != View.VISIBLE || !(child instanceof Button)) { - continue; - } child.setPadding(buttonPaddingHorizontal, child.getPaddingTop(), buttonPaddingHorizontal, child.getPaddingBottom()); child.measure(MEASURE_SPEC_ANY_LENGTH, heightMeasureSpec); + coveredSuggestions.add(child); + final int lineCount = ((Button) child).getLineCount(); if (lineCount < 1 || lineCount > 2) { // If smart reply has no text, or more than two lines, then don't show it. @@ -417,7 +407,8 @@ public class SmartReplyView extends ViewGroup { // Mark all buttons from the last squeezing round as "failed to squeeze", so // that they're re-measured without squeezing later. - markButtonsWithPendingSqueezeStatusAs(LayoutParams.SQUEEZE_STATUS_FAILED, i); + markButtonsWithPendingSqueezeStatusAs( + LayoutParams.SQUEEZE_STATUS_FAILED, coveredSuggestions); // The current button doesn't fit, so there's no point in measuring further // buttons. @@ -426,7 +417,8 @@ public class SmartReplyView extends ViewGroup { // The current button fits, so mark all squeezed buttons as "successfully squeezed" // to prevent them from being un-squeezed in a subsequent squeezing round. - markButtonsWithPendingSqueezeStatusAs(LayoutParams.SQUEEZE_STATUS_SUCCESSFUL, i); + markButtonsWithPendingSqueezeStatusAs( + LayoutParams.SQUEEZE_STATUS_SUCCESSFUL, coveredSuggestions); } lp.show = true; @@ -445,6 +437,22 @@ public class SmartReplyView extends ViewGroup { mPaddingTop + maxChildHeight + mPaddingBottom), heightMeasureSpec)); } + private List<View> filterActionsOrReplies(SmartButtonType buttonType) { + List<View> actions = new ArrayList<>(); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (child.getVisibility() != View.VISIBLE || !(child instanceof Button)) { + continue; + } + if (lp.buttonType == buttonType) { + actions.add(child); + } + } + return actions; + } + private void resetButtonsLayoutParams() { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -615,9 +623,9 @@ public class SmartReplyView extends ViewGroup { } } - private void markButtonsWithPendingSqueezeStatusAs(int squeezeStatus, int maxChildIndex) { - for (int i = 0; i <= maxChildIndex; i++) { - final View child = getChildAt(i); + private void markButtonsWithPendingSqueezeStatusAs( + int squeezeStatus, List<View> coveredChildren) { + for (View child : coveredChildren) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp.squeezeStatus == LayoutParams.SQUEEZE_STATUS_PENDING) { lp.squeezeStatus = squeezeStatus; @@ -712,6 +720,11 @@ public class SmartReplyView extends ViewGroup { return mActivityStarter; } + private enum SmartButtonType { + REPLY, + ACTION + } + @VisibleForTesting static class LayoutParams extends ViewGroup.LayoutParams { @@ -737,6 +750,7 @@ public class SmartReplyView extends ViewGroup { private boolean show = false; private int squeezeStatus = SQUEEZE_STATUS_NONE; + private SmartButtonType buttonType = SmartButtonType.REPLY; private LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java deleted file mode 100644 index 9b616e00a72f..000000000000 --- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.volume; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.animation.AnimatorSet; -import android.annotation.DrawableRes; -import android.annotation.Nullable; -import android.app.Dialog; -import android.app.KeyguardManager; -import android.car.Car; -import android.car.CarNotConnectedException; -import android.car.media.CarAudioManager; -import android.car.media.ICarVolumeCallback; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.ServiceConnection; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.graphics.Color; -import android.graphics.PixelFormat; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.media.AudioAttributes; -import android.media.AudioManager; -import android.os.Debug; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseArray; -import android.util.Xml; -import android.view.ContextThemeWrapper; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import androidx.car.widget.ListItem; -import androidx.car.widget.ListItemAdapter; -import androidx.car.widget.ListItemAdapter.BackgroundStyle; -import androidx.car.widget.ListItemProvider.ListProvider; -import androidx.car.widget.PagedListView; -import androidx.car.widget.SeekbarListItem; - -import com.android.systemui.R; -import com.android.systemui.plugins.VolumeDialog; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Car version of the volume dialog. - * - * Methods ending in "H" must be called on the (ui) handler. - */ -public class CarVolumeDialogImpl implements VolumeDialog { - private static final String TAG = Util.logTag(CarVolumeDialogImpl.class); - - private static final String XML_TAG_VOLUME_ITEMS = "carVolumeItems"; - private static final String XML_TAG_VOLUME_ITEM = "item"; - private static final int HOVERING_TIMEOUT = 16000; - private static final int NORMAL_TIMEOUT = 3000; - private static final int LISTVIEW_ANIMATION_DURATION_IN_MILLIS = 250; - private static final int DISMISS_DELAY_IN_MILLIS = 50; - private static final int ARROW_FADE_IN_START_DELAY_IN_MILLIS = 100; - - private final Context mContext; - private final H mHandler = new H(); - - private Window mWindow; - private CustomDialog mDialog; - private PagedListView mListView; - private ListItemAdapter mPagedListAdapter; - // All the volume items. - private final SparseArray<VolumeItem> mVolumeItems = new SparseArray<>(); - // Available volume items in car audio manager. - private final List<VolumeItem> mAvailableVolumeItems = new ArrayList<>(); - // Volume items in the PagedListView. - private final List<ListItem> mVolumeLineItems = new ArrayList<>(); - private final KeyguardManager mKeyguard; - - private Car mCar; - private CarAudioManager mCarAudioManager; - - private boolean mHovering; - private boolean mShowing; - private boolean mExpanded; - - public CarVolumeDialogImpl(Context context) { - mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); - mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); - mCar = Car.createCar(mContext, mServiceConnection); - } - - public void init(int windowType, Callback callback) { - initDialog(); - - mCar.connect(); - } - - @Override - public void destroy() { - mHandler.removeCallbacksAndMessages(null); - - cleanupAudioManager(); - // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup - // audio manager beforehand. - mCar.disconnect(); - } - - private void initDialog() { - loadAudioUsageItems(); - mVolumeLineItems.clear(); - mDialog = new CustomDialog(mContext); - - mHovering = false; - mShowing = false; - mExpanded = false; - mWindow = mDialog.getWindow(); - mWindow.requestFeature(Window.FEATURE_NO_TITLE); - mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND - | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); - mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); - mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); - final WindowManager.LayoutParams lp = mWindow.getAttributes(); - lp.format = PixelFormat.TRANSLUCENT; - lp.setTitle(VolumeDialogImpl.class.getSimpleName()); - lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; - lp.windowAnimations = -1; - mWindow.setAttributes(lp); - mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - - mDialog.setCanceledOnTouchOutside(true); - mDialog.setContentView(R.layout.car_volume_dialog); - mDialog.setOnShowListener(dialog -> { - mListView.setTranslationY(-mListView.getHeight()); - mListView.setAlpha(0); - mListView.animate() - .alpha(1) - .translationY(0) - .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) - .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) - .start(); - }); - mListView = (PagedListView) mWindow.findViewById(R.id.volume_list); - mListView.setOnHoverListener((v, event) -> { - int action = event.getActionMasked(); - mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) - || (action == MotionEvent.ACTION_HOVER_MOVE); - rescheduleTimeoutH(); - return true; - }); - - mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems), - BackgroundStyle.PANEL); - mListView.setAdapter(mPagedListAdapter); - mListView.setMaxPages(PagedListView.UNLIMITED_PAGES); - } - - public void show(int reason) { - mHandler.obtainMessage(H.SHOW, reason).sendToTarget(); - } - - public void dismiss(int reason) { - mHandler.obtainMessage(H.DISMISS, reason).sendToTarget(); - } - - private void showH(int reason) { - if (D.BUG) { - Log.d(TAG, "showH r=" + Events.DISMISS_REASONS[reason]); - } - - mHandler.removeMessages(H.SHOW); - mHandler.removeMessages(H.DISMISS); - rescheduleTimeoutH(); - // Refresh the data set before showing. - mPagedListAdapter.notifyDataSetChanged(); - if (mShowing) { - return; - } - mShowing = true; - - mDialog.show(); - Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); - } - - protected void rescheduleTimeoutH() { - mHandler.removeMessages(H.DISMISS); - final int timeout = computeTimeoutH(); - mHandler.sendMessageDelayed(mHandler - .obtainMessage(H.DISMISS, Events.DISMISS_REASON_TIMEOUT), timeout); - - if (D.BUG) { - Log.d(TAG, "rescheduleTimeout " + timeout + " " + Debug.getCaller()); - } - } - - private int computeTimeoutH() { - return mHovering ? HOVERING_TIMEOUT : NORMAL_TIMEOUT; - } - - protected void dismissH(int reason) { - if (D.BUG) { - Log.d(TAG, "dismissH r=" + Events.DISMISS_REASONS[reason]); - } - - mHandler.removeMessages(H.DISMISS); - mHandler.removeMessages(H.SHOW); - if (!mShowing) { - return; - } - - mListView.animate().cancel(); - - mListView.setTranslationY(0); - mListView.setAlpha(1); - mListView.animate() - .alpha(0) - .translationY(-mListView.getHeight()) - .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) - .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator()) - .withEndAction(() -> mHandler.postDelayed(() -> { - if (D.BUG) { - Log.d(TAG, "mDialog.dismiss()"); - } - mDialog.dismiss(); - mShowing = false; - }, DISMISS_DELAY_IN_MILLIS)) - .start(); - - Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason); - } - - public void dump(PrintWriter writer) { - writer.println(VolumeDialogImpl.class.getSimpleName() + " state:"); - writer.print(" mShowing: "); writer.println(mShowing); - } - - private void loadAudioUsageItems() { - try (XmlResourceParser parser = mContext.getResources().getXml(R.xml.car_volume_items)) { - AttributeSet attrs = Xml.asAttributeSet(parser); - int type; - // Traverse to the first start tag - while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT - && type != XmlResourceParser.START_TAG) { - } - - if (!XML_TAG_VOLUME_ITEMS.equals(parser.getName())) { - throw new RuntimeException("Meta-data does not start with carVolumeItems tag"); - } - int outerDepth = parser.getDepth(); - int rank = 0; - while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT - && (type != XmlResourceParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlResourceParser.END_TAG) { - continue; - } - if (XML_TAG_VOLUME_ITEM.equals(parser.getName())) { - TypedArray item = mContext.getResources().obtainAttributes( - attrs, R.styleable.carVolumeItems_item); - int usage = item.getInt(R.styleable.carVolumeItems_item_usage, -1); - if (usage >= 0) { - VolumeItem volumeItem = new VolumeItem(); - volumeItem.usage = usage; - volumeItem.rank = rank; - volumeItem.icon = item.getResourceId(R.styleable.carVolumeItems_item_icon, 0); - mVolumeItems.put(usage, volumeItem); - rank++; - } - item.recycle(); - } - } - } catch (XmlPullParserException | IOException e) { - Log.e(TAG, "Error parsing volume groups configuration", e); - } - } - - private VolumeItem getVolumeItemForUsages(int[] usages) { - int rank = Integer.MAX_VALUE; - VolumeItem result = null; - for (int usage : usages) { - VolumeItem volumeItem = mVolumeItems.get(usage); - if (volumeItem.rank < rank) { - rank = volumeItem.rank; - result = volumeItem; - } - } - return result; - } - - private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { - try { - return carAudioManager.getGroupVolume(volumeGroupId); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - return 0; - } - - private static int getMaxSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { - try { - return carAudioManager.getGroupMaxVolume(volumeGroupId); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - return 0; - } - - private SeekbarListItem addSeekbarListItem(VolumeItem volumeItem, int volumeGroupId, - int supplementalIconId, @Nullable View.OnClickListener supplementalIconOnClickListener) { - SeekbarListItem listItem = new SeekbarListItem(mContext); - listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); - int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); - int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); - listItem.setProgress(progress); - listItem.setOnSeekBarChangeListener( - new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); - Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); - primaryIcon.mutate().setTint(color); - listItem.setPrimaryActionIcon(primaryIcon); - if (supplementalIconId != 0) { - Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); - supplementalIcon.mutate().setTint(color); - listItem.setSupplementalIcon(supplementalIcon, true); - listItem.setSupplementalIconListener(supplementalIconOnClickListener); - } else { - listItem.setSupplementalEmptyIcon(true); - listItem.setSupplementalIconListener(null); - } - - mVolumeLineItems.add(listItem); - volumeItem.listItem = listItem; - volumeItem.progress = progress; - return listItem; - } - - private VolumeItem findVolumeItem(SeekbarListItem targetItem) { - for (int i = 0; i < mVolumeItems.size(); ++i) { - VolumeItem volumeItem = mVolumeItems.valueAt(i); - if (volumeItem.listItem == targetItem) { - return volumeItem; - } - } - return null; - } - - private void cleanupAudioManager() { - try { - mCarAudioManager.unregisterVolumeCallback(mVolumeChangeCallback.asBinder()); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - mVolumeLineItems.clear(); - mCarAudioManager = null; - } - - private final class H extends Handler { - private static final int SHOW = 1; - private static final int DISMISS = 2; - - public H() { - super(Looper.getMainLooper()); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case SHOW: - showH(msg.arg1); - break; - case DISMISS: - dismissH(msg.arg1); - break; - default: - } - } - } - - private final class CustomDialog extends Dialog implements DialogInterface { - public CustomDialog(Context context) { - super(context, com.android.systemui.R.style.qs_theme); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - rescheduleTimeoutH(); - return super.dispatchTouchEvent(ev); - } - - @Override - protected void onStart() { - super.setCanceledOnTouchOutside(true); - super.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isShowing()) { - if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { - mHandler.obtainMessage( - H.DISMISS, Events.DISMISS_REASON_TOUCH_OUTSIDE).sendToTarget(); - return true; - } - } - return false; - } - } - - private final class ExpandIconListener implements View.OnClickListener { - @Override - public void onClick(final View v) { - mExpanded = !mExpanded; - Animator inAnimator; - if (mExpanded) { - for (int groupId = 0; groupId < mAvailableVolumeItems.size(); ++groupId) { - // Adding the items which are not coming from the default item. - VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - if (volumeItem.defaultItem) { - // Set progress here due to the progress of seekbar may not be updated. - volumeItem.listItem.setProgress(volumeItem.progress); - } else { - addSeekbarListItem(volumeItem, groupId, 0, null); - } - } - inAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_in_rotate_up); - } else { - // Only keeping the default stream if it is not expended. - Iterator itr = mVolumeLineItems.iterator(); - while (itr.hasNext()) { - SeekbarListItem seekbarListItem = (SeekbarListItem) itr.next(); - VolumeItem volumeItem = findVolumeItem(seekbarListItem); - if (!volumeItem.defaultItem) { - itr.remove(); - } else { - // Set progress here due to the progress of seekbar may not be updated. - seekbarListItem.setProgress(volumeItem.progress); - } - } - inAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_in_rotate_down); - } - - Animator outAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_out); - inAnimator.setStartDelay(ARROW_FADE_IN_START_DELAY_IN_MILLIS); - AnimatorSet animators = new AnimatorSet(); - animators.playTogether(outAnimator, inAnimator); - animators.setTarget(v); - animators.start(); - mPagedListAdapter.notifyDataSetChanged(); - } - } - - private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener { - private final int mVolumeGroupId; - private final CarAudioManager mCarAudioManager; - - private VolumeSeekBarChangeListener(int volumeGroupId, CarAudioManager carAudioManager) { - mVolumeGroupId = volumeGroupId; - mCarAudioManager = carAudioManager; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (!fromUser) { - // For instance, if this event is originated from AudioService, - // we can ignore it as it has already been handled and doesn't need to be - // sent back down again. - return; - } - try { - if (mCarAudioManager == null) { - Log.w(TAG, "Ignoring volume change event because the car isn't connected"); - return; - } - mAvailableVolumeItems.get(mVolumeGroupId).progress = progress; - mCarAudioManager.setGroupVolume(mVolumeGroupId, progress, 0); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) {} - - @Override - public void onStopTrackingTouch(SeekBar seekBar) {} - } - - private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() { - @Override - public void onGroupVolumeChanged(int groupId, int flags) { - VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - int value = getSeekbarValue(mCarAudioManager, groupId); - // Do not update the progress if it is the same as before. When car audio manager sets its - // group volume caused by the seekbar progress changed, it also triggers this callback. - // Updating the seekbar at the same time could block the continuous seeking. - if (value != volumeItem.progress) { - volumeItem.listItem.setProgress(value); - volumeItem.progress = value; - } - if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { - show(Events.SHOW_REASON_VOLUME_CHANGED); - } - } - - @Override - public void onMasterMuteChanged(int flags) { - // ignored - } - }; - - private final ServiceConnection mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - try { - mExpanded = false; - mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE); - int volumeGroupCount = mCarAudioManager.getVolumeGroupCount(); - // Populates volume slider items from volume groups to UI. - for (int groupId = 0; groupId < volumeGroupCount; groupId++) { - VolumeItem volumeItem = getVolumeItemForUsages( - mCarAudioManager.getUsagesForVolumeGroupId(groupId)); - mAvailableVolumeItems.add(volumeItem); - // The first one is the default item. - if (groupId == 0) { - volumeItem.defaultItem = true; - addSeekbarListItem(volumeItem, groupId, R.drawable.car_ic_keyboard_arrow_down, - new ExpandIconListener()); - } - } - - // If list is already initiated, update its content. - if (mPagedListAdapter != null) { - mPagedListAdapter.notifyDataSetChanged(); - } - mCarAudioManager.registerVolumeCallback(mVolumeChangeCallback.asBinder()); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - } - - /** - * This does not get called when service is properly disconnected. - * So we need to also handle cleanups in destroy(). - */ - @Override - public void onServiceDisconnected(ComponentName name) { - cleanupAudioManager(); - } - }; - - /** - * Wrapper class which contains information of each volume group. - */ - private static class VolumeItem { - private @AudioAttributes.AttributeUsage int usage; - private int rank; - private boolean defaultItem = false; - private @DrawableRes int icon; - private SeekbarListItem listItem; - private int progress; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index 2861dffe5460..080567739be7 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -19,12 +19,10 @@ package com.android.systemui.volume; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; import android.content.res.Configuration; import android.media.AudioManager; import android.media.VolumePolicy; import android.os.Bundle; -import android.os.Handler; import android.view.WindowManager.LayoutParams; import com.android.settingslib.applications.InterestingConfigChanges; @@ -57,7 +55,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false; private final SystemUI mSysui; - private final Context mContext; + protected final Context mContext; private final VolumeDialogControllerImpl mController; private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE @@ -70,7 +68,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna 400 // vibrateToSilentDebounce ); - public VolumeDialogComponent(SystemUI sysui, Context context, Handler handler) { + public VolumeDialogComponent(SystemUI sysui, Context context) { mSysui = sysui; mContext = context; mController = (VolumeDialogControllerImpl) Dependency.get(VolumeDialogController.class); @@ -81,7 +79,6 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna Dependency.get(ExtensionController.class).newExtension(VolumeDialog.class) .withPlugin(VolumeDialog.class) .withDefault(this::createDefault) - .withFeature(PackageManager.FEATURE_AUTOMOTIVE, this::createCarDefault) .withCallback(dialog -> { if (mDialog != null) { mDialog.destroy(); @@ -94,7 +91,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna VOLUME_SILENT_DO_NOT_DISTURB); } - private VolumeDialog createDefault() { + protected VolumeDialog createDefault() { VolumeDialogImpl impl = new VolumeDialogImpl(mContext); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); @@ -102,10 +99,6 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna return impl; } - private VolumeDialog createCarDefault() { - return new CarVolumeDialogImpl(mContext); - } - @Override public void onTuningChanged(String key, String newValue) { if (VOLUME_DOWN_SILENT.equals(key)) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index e4f37decdf35..f8cf79322b40 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -22,6 +22,7 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.SystemUIFactory; import com.android.systemui.qs.tiles.DndTile; import java.io.FileDescriptor; @@ -43,7 +44,9 @@ public class VolumeUI extends SystemUI { mContext.getResources().getBoolean(R.bool.enable_safety_warning); mEnabled = enableVolumeUi || enableSafetyWarning; if (!mEnabled) return; - mVolumeComponent = new VolumeDialogComponent(this, mContext, null); + + mVolumeComponent = SystemUIFactory.getInstance() + .createVolumeDialogComponent(this, mContext); mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning); putComponent(VolumeComponent.class, getVolumeComponent()); setDefaultVolumeController(); diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index b32bf99ad53d..83ec33c69629 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -38,8 +38,6 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ android.test.base \ - android.car \ - android.car.userlib LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java deleted file mode 100644 index f89a93264b0c..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package com.android.systemui.qs.car; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; - -import android.content.Context; -import android.support.test.filters.SmallTest; -import android.testing.AndroidTestingRunner; -import android.testing.LayoutInflaterBuilder; -import android.testing.TestableLooper; -import android.testing.TestableLooper.RunWithLooper; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.keyguard.CarrierText; -import com.android.systemui.Dependency; -import com.android.systemui.SysuiBaseFragmentTest; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.policy.Clock; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for {@link CarQSFragment}. - */ -@RunWith(AndroidTestingRunner.class) -@RunWithLooper(setAsMainLooper = true) -@SmallTest -@Ignore -public class CarQsFragmentTest extends SysuiBaseFragmentTest { - public CarQsFragmentTest() { - super(CarQSFragment.class); - } - - @Before - public void initDependencies() { - mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, - new LayoutInflaterBuilder(mContext) - .replace("com.android.systemui.statusbar.policy.SplitClockView", - FrameLayout.class) - .replace("TextClock", View.class) - .replace(CarrierText.class, View.class) - .replace(Clock.class, View.class) - .build()); - mSysuiContext.putComponent(CommandQueue.class, mock(CommandQueue.class)); - mDependency.injectTestDependency(Dependency.BG_LOOPER, - TestableLooper.get(this).getLooper()); - } - - @Test - @Ignore("Flaky") - public void testLayoutInflation() { - CarQSFragment fragment = (CarQSFragment) mFragment; - mFragments.dispatchResume(); - - assertNotNull(fragment.getHeader()); - assertNotNull(fragment.getFooter()); - } - - @Test - @Ignore("Flaky") - public void testListening() { - CarQSFragment qs = (CarQSFragment) mFragment; - mFragments.dispatchResume(); - processAllMessages(); - - qs.setListening(true); - processAllMessages(); - - qs.setListening(false); - processAllMessages(); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 8ae3cd8d6acd..a4fe52d46f56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -14,6 +14,8 @@ package com.android.systemui.statusbar; +import static android.view.Display.DEFAULT_DISPLAY; + import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -64,11 +66,12 @@ public class CommandQueueTest extends SysuiTestCase { verify(mCallbacks).removeIcon(eq(slot)); } + // TODO(b/117478341): add test case for multi-display @Test public void testDisable() { int state1 = 14; int state2 = 42; - mCommandQueue.disable(state1, state2); + mCommandQueue.disable(DEFAULT_DISPLAY, state1, state2); waitForIdleSync(); verify(mCallbacks).disable(eq(state1), eq(state2), eq(true)); } @@ -95,24 +98,27 @@ public class CommandQueueTest extends SysuiTestCase { verify(mCallbacks).animateExpandSettingsPanel(eq(panel)); } + // TODO(b/117478341): add test case for multi-display @Test public void testSetSystemUiVisibility() { Rect r = new Rect(); - mCommandQueue.setSystemUiVisibility(1, 2, 3, 4, null, r); + mCommandQueue.setSystemUiVisibility(DEFAULT_DISPLAY, 1, 2, 3, 4, null, r); waitForIdleSync(); verify(mCallbacks).setSystemUiVisibility(eq(1), eq(2), eq(3), eq(4), eq(null), eq(r)); } + // TODO(b/117478341): add test case for multi-display @Test public void testTopAppWindowChanged() { - mCommandQueue.topAppWindowChanged(true); + mCommandQueue.topAppWindowChanged(DEFAULT_DISPLAY, true); waitForIdleSync(); verify(mCallbacks).topAppWindowChanged(eq(true)); } + // TODO(b/117478341): add test case for multi-display @Test public void testShowImeButton() { - mCommandQueue.setImeWindowStatus(null, 1, 2, true); + mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true); waitForIdleSync(); verify(mCallbacks).setImeWindowStatus(eq(null), eq(1), eq(2), eq(true)); } @@ -166,9 +172,10 @@ public class CommandQueueTest extends SysuiTestCase { verify(mCallbacks).toggleKeyboardShortcutsMenu(eq(1)); } + // TODO(b/117478341): add test case for multi-display @Test public void testSetWindowState() { - mCommandQueue.setWindowState(1, 2); + mCommandQueue.setWindowState(DEFAULT_DISPLAY, 1, 2); waitForIdleSync(); verify(mCallbacks).setWindowState(eq(1), eq(2)); } @@ -180,30 +187,34 @@ public class CommandQueueTest extends SysuiTestCase { verify(mCallbacks).showScreenPinningRequest(eq(1)); } + // TODO(b/117478341): add test case for multi-display @Test public void testAppTransitionPending() { - mCommandQueue.appTransitionPending(); + mCommandQueue.appTransitionPending(DEFAULT_DISPLAY); waitForIdleSync(); verify(mCallbacks).appTransitionPending(eq(false)); } + // TODO(b/117478341): add test case for multi-display @Test public void testAppTransitionCancelled() { - mCommandQueue.appTransitionCancelled(); + mCommandQueue.appTransitionCancelled(DEFAULT_DISPLAY); waitForIdleSync(); verify(mCallbacks).appTransitionCancelled(); } + // TODO(b/117478341): add test case for multi-display @Test public void testAppTransitionStarting() { - mCommandQueue.appTransitionStarting(1, 2); + mCommandQueue.appTransitionStarting(DEFAULT_DISPLAY, 1, 2); waitForIdleSync(); verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L), eq(false)); } + // TODO(b/117478341): add test case for multi-display @Test public void testAppTransitionFinished() { - mCommandQueue.appTransitionFinished(); + mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY); waitForIdleSync(); verify(mCallbacks).appTransitionFinished(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java index 906e718f19d9..51492da11d02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java @@ -25,7 +25,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.Notification; +import android.app.NotificationChannel; import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; @@ -35,6 +35,7 @@ import android.testing.ViewUtils; import android.view.ViewGroup; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; +import com.android.systemui.statusbar.notification.NotificationData; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; @@ -43,19 +44,26 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; @RunWith(AndroidTestingRunner.class) -@RunWithLooper() +@RunWithLooper(setAsMainLooper = true) @SmallTest public class NotificationMenuRowTest extends LeakCheckedTest { + private ExpandableNotificationRow mRow; + @Before public void setup() { injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); + mRow = mock(ExpandableNotificationRow.class); + NotificationData.Entry entry = new NotificationData.Entry( + mock(StatusBarNotification.class)); + entry.channel = mock(NotificationChannel.class); + when(mRow.getEntry()).thenReturn(entry); } @Test public void testAttachDetach() { NotificationMenuRowPlugin row = new NotificationMenuRow(mContext); - row.createMenu(null, null); + row.createMenu(mRow, null); ViewUtils.attachView(row.getMenuView()); TestableLooper.get(this).processAllMessages(); ViewUtils.detachView(row.getMenuView()); @@ -65,9 +73,9 @@ public class NotificationMenuRowTest extends LeakCheckedTest { @Test public void testRecreateMenu() { NotificationMenuRowPlugin row = new NotificationMenuRow(mContext); - row.createMenu(null, null); + row.createMenu(mRow, null); assertTrue(row.getMenuView() != null); - row.createMenu(null, null); + row.createMenu(mRow, null); assertTrue(row.getMenuView() != null); } @@ -81,12 +89,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest { @Test public void testNoAppOpsInSlowSwipe() { NotificationMenuRow row = new NotificationMenuRow(mContext); - Notification n = mock(Notification.class); - StatusBarNotification sbn = mock(StatusBarNotification.class); - when(sbn.getNotification()).thenReturn(n); - ExpandableNotificationRow parent = mock(ExpandableNotificationRow.class); - when(parent.getStatusBarNotification()).thenReturn(sbn); - row.createMenu(parent, null); + row.createMenu(mRow, null); ViewGroup container = (ViewGroup) row.getMenuView(); // one for snooze and one for noti blocking 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 4177cd16c8bf..1783d0cf2519 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 @@ -38,12 +38,12 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.content.Context; import com.android.systemui.R; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.SysuiTestCase; +import android.content.Context; import android.content.res.Resources; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; @@ -78,6 +78,7 @@ public class QuickStepControllerTest extends SysuiTestCase { mProxyService = mock(OverviewProxyService.class); mProxy = mock(IOverviewProxy.Stub.class); doReturn(mProxy).when(mProxyService).getProxy(); + doReturn(true).when(mProxyService).shouldShowSwipeUpUI(); mDependency.injectTestDependency(OverviewProxyService.class, mProxyService); mStatusBar = mock(StatusBar.class); @@ -106,6 +107,18 @@ public class QuickStepControllerTest extends SysuiTestCase { } @Test + public void testNoGesturesWhenSwipeUpDisabled() throws Exception { + doReturn(false).when(mProxyService).shouldShowSwipeUpUI(); + mController.setGestureActions(mockAction(true), null /* swipeDownAction */, + null /* swipeLeftAction */, null /* swipeRightAction */); + + MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1); + assertFalse(mController.onInterceptTouchEvent(ev)); + verify(mNavigationBarView, never()).requestUnbufferedDispatch(ev); + assertNull(mController.getCurrentAction()); + } + + @Test public void testHasActionDetectGesturesTouchdown() throws Exception { MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1); @@ -395,6 +408,7 @@ public class QuickStepControllerTest extends SysuiTestCase { verify(mProxy, times(1)).onQuickScrubStart(); verify(mProxyService, times(1)).notifyQuickScrubStarted(); verify(mNavigationBarView, times(1)).updateSlippery(); + verify(mProxy, never()).onMotionEvent(moveEvent1); // Move again for scrub MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, 200, y); @@ -402,6 +416,7 @@ public class QuickStepControllerTest extends SysuiTestCase { assertEquals(action, mController.getCurrentAction()); verify(action, times(1)).onGestureMove(200, y); verify(mProxy, times(1)).onQuickScrubProgress(1f / 2); + verify(mProxy, never()).onMotionEvent(moveEvent2); // Action up MotionEvent upEvent = event(MotionEvent.ACTION_UP, 1, y); @@ -409,6 +424,7 @@ public class QuickStepControllerTest extends SysuiTestCase { assertNull(mController.getCurrentAction()); verify(action, times(1)).onGestureEnd(); verify(mProxy, times(1)).onQuickScrubEnd(); + verify(mProxy, never()).onMotionEvent(upEvent); } @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 df7aeab2ed38..506fa974944a 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 @@ -801,4 +801,55 @@ public class SmartReplyViewTest extends SysuiTestCase { assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(1)); assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(2)); } + + @Test + public void testMeasure_choicesAndActionsPrioritizeActionsOnlyActions() { + String[] choices = new String[] {"Reply"}; + String[] actions = new String[] {"Looooooong actioooon", "second action", "third action"}; + + // All actions should be displayed as DOUBLE-line smart action buttons. + ViewGroup expectedView = buildExpectedView(new String[0], 2, + createActions(new String[] { + "Looooooong \nactioooon", "second \naction", "third \naction"})); + expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + + setSmartRepliesAndActions(choices, actions); + mView.measure( + MeasureSpec.makeMeasureSpec(expectedView.getMeasuredWidth(), MeasureSpec.AT_MOST), + MeasureSpec.UNSPECIFIED); + + assertEqualMeasures(expectedView, mView); + // smart replies + assertReplyButtonHidden(mView.getChildAt(0)); + // smart actions + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(1)); + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(2)); + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(3)); + } + + @Test + public void testMeasure_choicesAndActionsPrioritizeActions() { + String[] choices = new String[] {"Short", "longer reply"}; + String[] actions = new String[] {"Looooooong actioooon", "second action"}; + + // All actions should be displayed as DOUBLE-line smart action buttons. + ViewGroup expectedView = buildExpectedView(new String[] {"Short"}, 2, + createActions(new String[] {"Looooooong \nactioooon", "second \naction"})); + expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + + setSmartRepliesAndActions(choices, actions); + mView.measure( + MeasureSpec.makeMeasureSpec(expectedView.getMeasuredWidth(), MeasureSpec.AT_MOST), + MeasureSpec.UNSPECIFIED); + + Button firstAction = ((Button) mView.getChildAt(1)); + + assertEqualMeasures(expectedView, mView); + // smart replies + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0)); + assertReplyButtonHidden(mView.getChildAt(1)); + // smart actions + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(2)); + assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(3)); + } } diff --git a/packages/overlays/AdaptiveIconChangeOverlay/Android.mk b/packages/overlays/AdaptiveIconChangeOverlay/Android.mk new file mode 100644 index 000000000000..6e3b8cbbcf2f --- /dev/null +++ b/packages/overlays/AdaptiveIconChangeOverlay/Android.mk @@ -0,0 +1,30 @@ +# +# 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := SquareIcon +LOCAL_CERTIFICATE := platform + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := SquareIconOverlay +LOCAL_SDK_VERSION := current + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/AdaptiveIconChangeOverlay/AndroidManifest.xml b/packages/overlays/AdaptiveIconChangeOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..33da51047bf0 --- /dev/null +++ b/packages/overlays/AdaptiveIconChangeOverlay/AndroidManifest.xml @@ -0,0 +1,27 @@ +<!-- +/** + * 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.theme.icon.square" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="android" + android:category="android.theme.customization.adaptive_icon_shape" + android:priority="1"/> + + <application android:label="@string/square_icon_overlay" android:hasCode="false"/> +</manifest> diff --git a/packages/SystemUI/res/values/arrays_car.xml b/packages/overlays/AdaptiveIconChangeOverlay/res/values/config.xml index 8c760fc45e72..54623f5c9fb0 100644 --- a/packages/SystemUI/res/values/arrays_car.xml +++ b/packages/overlays/AdaptiveIconChangeOverlay/res/values/config.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -** -** Copyright 2015, The Android Open Source Project +/* +** 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. @@ -16,15 +16,11 @@ ** limitations under the License. */ --> -<resources> - <!-- These should be overriden in an overlay. The default implementation is empty. - There needs to be correspondence per index between these arrays, which means that if there - isn't a longpress action associated with a shortcut item, put in an empty item to make - sure everything lines up. - --> - <array name="car_facet_icons" /> - <array name="car_facet_intent_uris" /> - <array name="car_facet_longpress_intent_uris" /> - <array name="car_facet_package_filters"/> - <array name="car_facet_category_filters"/> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. --> + <string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string> + <!-- Flag indicating whether round icons should be parsed from the application manifest. --> + <bool name="config_useRoundIcon">false</bool> + </resources> + diff --git a/packages/overlays/AdaptiveIconChangeOverlay/res/values/strings.xml b/packages/overlays/AdaptiveIconChangeOverlay/res/values/strings.xml new file mode 100644 index 000000000000..64b7d0dc16b5 --- /dev/null +++ b/packages/overlays/AdaptiveIconChangeOverlay/res/values/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Square icon overlay [DO NOT TRANSLATE] --> + <string name="square_icon_overlay">Square Icons</string> + +</resources> diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index c56f31efd953..0da07ae52857 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -175,10 +175,6 @@ public final class AutofillManagerService } }; - // TODO(b/117779333): move to superclass / create super-class for ShellCommand - @GuardedBy("mLock") - private boolean mAllowInstantService; - /** * Supported modes for Augmented Autofill Smart Suggestions. */ @@ -271,6 +267,11 @@ public final class AutofillManagerService addCompatibilityModeRequestsLocked(service, userId); } + @Override // from AbstractMasterSystemService + protected void enforceCallingPermissionForManagement() { + getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + } + @Override // from SystemService public void onStart() { publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub()); @@ -290,7 +291,7 @@ public final class AutofillManagerService // Called by Shell command. void destroySessions(@UserIdInt int userId, IResultReceiver receiver) { Slog.i(TAG, "destroySessions() for userId " + userId); - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); synchronized (mLock) { if (userId != UserHandle.USER_ALL) { @@ -313,7 +314,7 @@ public final class AutofillManagerService // Called by Shell command. void listSessions(int userId, IResultReceiver receiver) { Slog.i(TAG, "listSessions() for userId " + userId); - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); final Bundle resultData = new Bundle(); final ArrayList<String> sessions = new ArrayList<>(); @@ -340,7 +341,7 @@ public final class AutofillManagerService // Called by Shell command. void reset() { Slog.i(TAG, "reset()"); - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); synchronized (mLock) { visitServicesLocked((s) -> s.destroyLocked()); @@ -351,7 +352,7 @@ public final class AutofillManagerService // Called by Shell command. void setLogLevel(int level) { Slog.i(TAG, "setLogLevel(): " + level); - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); final long token = Binder.clearCallingIdentity(); try { @@ -388,7 +389,7 @@ public final class AutofillManagerService // Called by Shell command. int getLogLevel() { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); synchronized (mLock) { if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE; @@ -399,7 +400,7 @@ public final class AutofillManagerService // Called by Shell command. int getMaxPartitions() { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); synchronized (mLock) { return sPartitionMaxCount; @@ -408,8 +409,8 @@ public final class AutofillManagerService // Called by Shell command. void setMaxPartitions(int max) { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); Slog.i(TAG, "setMaxPartitions(): " + max); + enforceCallingPermissionForManagement(); final long token = Binder.clearCallingIdentity(); try { @@ -433,7 +434,7 @@ public final class AutofillManagerService // Called by Shell command. int getMaxVisibleDatasets() { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); synchronized (sLock) { return sVisibleDatasetsMaxCount; @@ -442,8 +443,8 @@ public final class AutofillManagerService // Called by Shell command. void setMaxVisibleDatasets(int max) { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); Slog.i(TAG, "setMaxVisibleDatasets(): " + max); + enforceCallingPermissionForManagement(); final long token = Binder.clearCallingIdentity(); try { @@ -480,7 +481,7 @@ public final class AutofillManagerService // Called by Shell command. void getScore(@Nullable String algorithmName, @NonNull String value1, @NonNull String value2, @NonNull RemoteCallback callback) { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); final FieldClassificationStrategy strategy = new FieldClassificationStrategy(getContext(), UserHandle.USER_CURRENT); @@ -491,33 +492,16 @@ public final class AutofillManagerService // Called by Shell command. Boolean getFullScreenMode() { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); return sFullScreenMode; } // Called by Shell command. void setFullScreenMode(@Nullable Boolean mode) { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); + enforceCallingPermissionForManagement(); sFullScreenMode = mode; } - // Called by Shell command. - boolean getAllowInstantService() { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); - synchronized (mLock) { - return mAllowInstantService; - } - } - - // Called by Shell command. - void setAllowInstantService(boolean mode) { - getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG); - Slog.i(TAG, "setAllowInstantService(): " + mode); - synchronized (mLock) { - mAllowInstantService = mode; - } - } - private void setLoggingLevelsLocked(boolean debug, boolean verbose) { com.android.server.autofill.Helper.sDebug = debug; android.view.autofill.Helper.sDebug = debug; @@ -1218,7 +1202,6 @@ public final class AutofillManagerService mAutofillCompatState.dump(prefix, pw); pw.print("from settings: "); pw.println(getWhitelistedCompatModePackagesFromSettings()); - pw.print("Allow instant service: "); pw.println(mAllowInstantService); if (mSupportedSmartSuggestionModes != 0) { pw.print("Smart Suggestion modes: "); pw.println(smartSuggestionFlagsToString(mSupportedSmartSuggestionModes)); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 0df99d4b6642..18bc856700f7 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -190,6 +190,11 @@ final class AutofillManagerServiceImpl return mInfo.getServiceInfo(); } + @Override // from PerUserSystemService + protected String getDefaultComponentName() { + return getComponentNameFromSettings(); + } + @Nullable String[] getUrlBarResourceIdsForCompatMode(@NonNull String packageName) { return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId); @@ -369,7 +374,7 @@ final class AutofillManagerServiceImpl final long identity = Binder.clearCallingIdentity(); try { - final String autoFillService = getComponentNameFromSettings(); + final String autoFillService = getComponentNameLocked(); final ComponentName componentName = serviceInfo.getComponentName(); if (componentName.equals(ComponentName.unflattenFromString(autoFillService))) { mMetricsLogger.action(MetricsEvent.AUTOFILL_SERVICE_DISABLED_SELF, diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 9aa9d7c52818..af6575954842 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -40,9 +40,9 @@ import android.service.autofill.SaveRequest; import android.text.format.DateUtils; import android.util.Slog; -import com.android.server.AbstractRemoteService; +import com.android.server.AbstractSinglePendingRequestRemoteService; -final class RemoteFillService extends AbstractRemoteService { +final class RemoteFillService extends AbstractSinglePendingRequestRemoteService<RemoteFillService> { private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS; @@ -69,8 +69,8 @@ final class RemoteFillService extends AbstractRemoteService { mCallbacks = callbacks; } - @Override - protected void onConnectedStateChanged(boolean state) { + @Override // from AbstractRemoteService + protected void handleOnConnectedStateChanged(boolean state) { if (mAutoFillService == null) { Slog.w(mTag, "onConnectedStateChanged(): null service"); return; @@ -82,18 +82,18 @@ final class RemoteFillService extends AbstractRemoteService { } } - @Override + @Override // from AbstractRemoteService protected IInterface getServiceInterface(IBinder service) { mAutoFillService = IAutoFillService.Stub.asInterface(service); return mAutoFillService; } - @Override + @Override // from AbstractRemoteService protected long getTimeoutIdleBindMillis() { return TIMEOUT_IDLE_BIND_MILLIS; } - @Override + @Override // from AbstractRemoteService protected long getRemoteRequestMillis() { return TIMEOUT_REMOTE_REQUEST_MILLIS; } @@ -136,6 +136,19 @@ final class RemoteFillService extends AbstractRemoteService { scheduleRequest(new PendingSaveRequest(request, this)); } + private boolean handleResponseCallbackCommon( + @NonNull PendingRequest<RemoteFillService> pendingRequest) { + if (isDestroyed()) return false; + + if (mPendingRequest == pendingRequest) { + mPendingRequest = null; + } + if (mPendingRequest == null) { + scheduleUnbind(); + } + return true; + } + private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest, @Nullable FillResponse response, int requestFlags) { mHandler.post(() -> { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 8676f7f5bea0..4c645076eb95 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -902,7 +902,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // VultureCallback @Override - public void onServiceDied(AbstractRemoteService service) { + public void onServiceDied(AbstractRemoteService<? extends AbstractRemoteService<?>> service) { Slog.w(TAG, "removing session because service died"); forceRemoveSelfLocked(); } diff --git a/services/core/java/com/android/server/AbstractMasterSystemService.java b/services/core/java/com/android/server/AbstractMasterSystemService.java index 9c1e3cdec5b1..76010b346a3b 100644 --- a/services/core/java/com/android/server/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/AbstractMasterSystemService.java @@ -39,6 +39,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.util.List; @@ -93,6 +94,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem public boolean debug = false; /** + * Whether the service is allowed to bind to an instant-app. + */ + @GuardedBy("mLock") + protected boolean mAllowInstantService; + + /** * Users disabled due to {@link UserManager} restrictions, or {@code null} if the service cannot * be disabled through {@link UserManager}. */ @@ -176,6 +183,107 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } /** + * Gets whether the service is allowed to bind to an instant-app. + * + * <p>Typically called by {@code ShellCommand} during CTS tests. + * + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + public final boolean getAllowInstantService() { + enforceCallingPermissionForManagement(); + synchronized (mLock) { + return mAllowInstantService; + } + } + + /** + * Sets whether the service is allowed to bind to an instant-app. + * + * <p>Typically called by {@code ShellCommand} during CTS tests. + * + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + public final void setAllowInstantService(boolean mode) { + Slog.i(mTag, "setAllowInstantService(): " + mode); + enforceCallingPermissionForManagement(); + synchronized (mLock) { + mAllowInstantService = mode; + } + } + + /** + * Temporary sets the service implementation. + * + * <p>Typically used by Shell command and/or CTS tests. + * + * @param componentName name of the new component + * @param durationMs how long the change will be valid (the service will be automatically reset + * to the default component after this timeout expires). + * @throws SecurityException if caller is not allowed to manage this service's settings. + * @throws IllegalArgumentException if value of {@code durationMs} is higher than + * {@link #getMaximumTemporaryServiceDurationMs()}. + */ + public final void setTemporaryService(@UserIdInt int userId, @NonNull String componentName, + int durationMs) { + Slog.i(mTag, "setTemporaryService(" + userId + ") to " + componentName + " for " + + durationMs + "ms"); + enforceCallingPermissionForManagement(); + + Preconditions.checkNotNull(componentName); + final int maxDurationMs = getMaximumTemporaryServiceDurationMs(); + if (durationMs > maxDurationMs) { + throw new IllegalArgumentException( + "Max duration is " + maxDurationMs + " (called with " + durationMs + ")"); + } + + synchronized (mLock) { + final S service = getServiceForUserLocked(userId); + if (service != null) { + service.setTemporaryServiceLocked(componentName, durationMs); + } + } + } + + /** + * Gets the maximum time the service implementation can be changed. + * + * @throws UnsupportedOperationException if subclass doesn't override it. + */ + protected int getMaximumTemporaryServiceDurationMs() { + throw new UnsupportedOperationException("Not implemented by " + getClass()); + } + + /** + * Resets the temporary service implementation to the default component. + * + * <p>Typically used by Shell command and/or CTS tests. + * + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + public final void resetTemporaryService(@UserIdInt int userId) { + Slog.i(mTag, "resetTemporaryService(): " + userId); + enforceCallingPermissionForManagement(); + synchronized (mLock) { + final S service = getServiceForUserLocked(userId); + if (service != null) { + service.resetTemporaryServiceLocked(); + } + } + } + + /** + * Asserts that the caller has permissions to manage this service. + * + * <p>Typically called by {@code ShellCommand} implementations. + * + * @throws UnsupportedOperationException if subclass doesn't override it. + * @throws SecurityException if caller is not allowed to manage this service's settings. + */ + protected void enforceCallingPermissionForManagement() { + throw new UnsupportedOperationException("Not implemented by " + getClass()); + } + + /** * Creates a new service that will be added to the cache. * * @param resolvedUserId the resolved user id for the service. @@ -362,6 +470,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem pw.print(prefix); pw.print("Debug: "); pw.print(realDebug); pw.print(" Verbose: "); pw.println(realVerbose); pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers); + pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService); pw.print(prefix); pw.print("Settings property: "); pw.println( getServiceSettingsProperty()); pw.print(prefix); pw.print("Cached services: "); diff --git a/services/core/java/com/android/server/AbstractMultiplePendingRequestsRemoteService.java b/services/core/java/com/android/server/AbstractMultiplePendingRequestsRemoteService.java new file mode 100644 index 000000000000..f532b22cb8d4 --- /dev/null +++ b/services/core/java/com/android/server/AbstractMultiplePendingRequestsRemoteService.java @@ -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. + */ + +package com.android.server; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Context; +import android.util.Slog; + +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * Base class representing a remote service that can queue multiple pending requests while not + * bound. + * + * @param <S> the concrete remote service class + * + * @hide + */ +public abstract class AbstractMultiplePendingRequestsRemoteService< + S extends AbstractMultiplePendingRequestsRemoteService<S>> + extends AbstractRemoteService<S> { + + private final int mInitialCapacity; + + protected ArrayList<PendingRequest<S>> mPendingRequests; + + public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context, + @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, + @NonNull VultureCallback callback, boolean bindInstantServiceAllowed, boolean verbose, + int initialCapacity) { + super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed, + verbose); + mInitialCapacity = initialCapacity; + } + + @Override // from AbstractRemoteService + void handlePendingRequests() { + if (mPendingRequests != null) { + final int size = mPendingRequests.size(); + if (mVerbose) Slog.v(mTag, "Sending " + size + " pending requests"); + for (int i = 0; i < size; i++) { + mPendingRequests.get(i).run(); + } + mPendingRequests = null; + } + } + + @Override // from AbstractRemoteService + protected void handleOnDestroy() { + if (mPendingRequests != null) { + final int size = mPendingRequests.size(); + if (mVerbose) Slog.v(mTag, "Canceling " + size + " pending requests"); + for (int i = 0; i < size; i++) { + mPendingRequests.get(i).cancel(); + } + mPendingRequests = null; + } + } + + @Override // from AbstractRemoteService + public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { + super.dump(prefix, pw); + + pw.append(prefix).append("initialCapacity=").append(String.valueOf(mInitialCapacity)) + .println(); + final int size = mPendingRequests == null ? 0 : mPendingRequests.size(); + pw.append(prefix).append("pendingRequests=").append(String.valueOf(size)).println(); + } + + @Override // from AbstractRemoteService + void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) { + if (mPendingRequests == null) { + mPendingRequests = new ArrayList<>(mInitialCapacity); + } + mPendingRequests.add(pendingRequest); + if (mVerbose) { + Slog.v(mTag, "queued " + mPendingRequests.size() + " requests; last=" + pendingRequest); + } + } +} diff --git a/services/core/java/com/android/server/AbstractPerUserSystemService.java b/services/core/java/com/android/server/AbstractPerUserSystemService.java index 71d261c7f5b5..a26102d57297 100644 --- a/services/core/java/com/android/server/AbstractPerUserSystemService.java +++ b/services/core/java/com/android/server/AbstractPerUserSystemService.java @@ -26,12 +26,17 @@ import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.SystemClock; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; +import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -49,6 +54,9 @@ import java.io.PrintWriter; public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSystemService<S, M>, M extends AbstractMasterSystemService<M, S>> { + /** Handler message to {@link #resetTemporaryServiceLocked()} */ + private static final int MSG_RESET_TEMPORARY_SERVICE = 0; + protected final @UserIdInt int mUserId; protected final Object mLock; protected final String mTag = getClass().getSimpleName(); @@ -70,6 +78,26 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst @GuardedBy("mLock") private ServiceInfo mServiceInfo; + /** + * Temporary service name set by {@link #setTemporaryServiceLocked(String, int)}. + * + * <p>Typically used by Shell command and/or CTS tests. + */ + @GuardedBy("mLock") + private String mTemporaryServiceName; + + /** + * When the temporary service will expire (and reset back to the default). + */ + @GuardedBy("mLock") + private long mTemporaryServiceExpiration; + + /** + * Handler used to reset the temporary service name. + */ + @GuardedBy("mLock") + private Handler mTemporaryHandler; + protected AbstractPerUserSystemService(@NonNull M master, @NonNull Object lock, @UserIdInt int userId) { mMaster = master; @@ -108,7 +136,8 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst * <p>Typically called when the service {@link Settings} property or {@link UserManager} * restriction changed, which includes the initial creation of the service. * - * <p>Subclasses can extend this method to provide extra initialization. + * <p>Subclasses can extend this method to provide extra initialization, like clearing up + * previous state. * * @param disabled whether the service is disabled (due to {@link UserManager} restrictions). * @@ -129,7 +158,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst mDisabled = disabled; ComponentName serviceComponent = null; ServiceInfo serviceInfo = null; - final String componentName = getComponentNameFromSettings(); + final String componentName = getComponentNameLocked(); if (!TextUtils.isEmpty(componentName)) { try { serviceComponent = ComponentName.unflattenFromString(componentName); @@ -190,6 +219,29 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst } /** + * Gets the current name of the service, which is either the + * {@link #getDefaultComponentName() default service} or the + * {@link #setTemporaryServiceLocked(String, int) temporary one}. + */ + protected final String getComponentNameLocked() { + if (mTemporaryServiceName != null) { + // Always log it, as it should only be used on CTS or during development + Slog.w(mTag, "getComponentName(): using temporary name " + mTemporaryServiceName); + return mTemporaryServiceName; + } + return getDefaultComponentName(); + } + + /** + * Gets the name of the default component for the service. + * + * <p>Typically implemented by returning {@link #getComponentNameFromSettings()} or by using + * a string from the system resources. + */ + @Nullable + protected abstract String getDefaultComponentName(); + + /** * Gets this name of the remote service this service binds to as defined by {@link Settings}. */ @Nullable @@ -200,6 +252,66 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst } /** + * Checks whether the current service for the user was temporarily set. + */ + public final boolean isTemporaryServiceSetLocked() { + return mTemporaryServiceName != null; + } + + /** + * Temporary sets the service implementation. + * + * @param componentName name of the new component + * @param durationMs how long the change will be valid (the service will be automatically reset + * to the default component after this timeout expires). + */ + protected final void setTemporaryServiceLocked(@NonNull String componentName, int durationMs) { + mTemporaryServiceName = componentName; + + if (mTemporaryHandler == null) { + mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_RESET_TEMPORARY_SERVICE) { + synchronized (mLock) { + resetTemporaryServiceLocked(); + } + } else { + Slog.wtf(mTag, "invalid handler msg: " + msg); + } + } + }; + } else { + removeResetTemporaryServiceMessageLocked(); + } + mTemporaryServiceExpiration = SystemClock.elapsedRealtime() + durationMs; + mTemporaryHandler.sendEmptyMessageDelayed(MSG_RESET_TEMPORARY_SERVICE, durationMs); + + updateLocked(mDisabled); + } + + private void removeResetTemporaryServiceMessageLocked() { + if (mMaster.verbose) { + Slog.v(mTag, "setTemporaryServiceLocked(): removing old message"); + } + // NOTE: caller should already have checked it + mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE); + } + + /** + * Resets the temporary service implementation to the default component. + */ + protected final void resetTemporaryServiceLocked() { + Slog.i(mTag, "resetting temporary service from " + mTemporaryServiceName); + mTemporaryServiceName = null; + if (mTemporaryHandler != null) { + removeResetTemporaryServiceMessageLocked(); + mTemporaryHandler = null; + } + updateLocked(mDisabled); + } + + /** * Gets the {@link ComponentName} of the remote service this service binds to, or {@code null} * if the service is disabled. */ @@ -289,12 +401,14 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst pw.print(prefix); pw.print("Service UID: "); pw.println(mServiceInfo.applicationInfo.uid); } - final String componentName = getComponentNameFromSettings(); - if (componentName != null) { - pw.print(prefix); pw.print("Service name: "); - pw.println(componentName); + if (mTemporaryServiceName != null) { + pw.print(prefix); pw.print("Temporary service name: "); pw.print(mTemporaryServiceName); + final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime(); + pw.print(" (expires in "); TimeUtils.formatDuration(ttl, pw); pw.println(")"); + pw.print(prefix); pw.print(prefix); + pw.print("Default service name: "); pw.println(getDefaultComponentName()); } else { - pw.println("No service package set"); + pw.print(prefix); pw.print("Service name: "); pw.println(getDefaultComponentName()); } } } diff --git a/services/core/java/com/android/server/AbstractRemoteService.java b/services/core/java/com/android/server/AbstractRemoteService.java index 0d4cf6b01ba8..f636487c666b 100644 --- a/services/core/java/com/android/server/AbstractRemoteService.java +++ b/services/core/java/com/android/server/AbstractRemoteService.java @@ -45,13 +45,20 @@ import java.lang.ref.WeakReference; * * <p>All state of this class is modified on a handler thread. * + * <p><b>NOTE: </b>this class should not be extended directly, you should extend either + * {@link AbstractSinglePendingRequestRemoteService} or + * {@link AbstractMultiplePendingRequestsRemoteService}. + * * <p>See {@code com.android.server.autofill.RemoteFillService} for a concrete * (no pun intended) example of how to use it. * + * @param <S> the concrete remote service class + * * @hide */ //TODO(b/117779333): improve javadoc above instead of using Autofill as an example -public abstract class AbstractRemoteService implements DeathRecipient { +public abstract class AbstractRemoteService<S extends AbstractRemoteService<S>> + implements DeathRecipient { private static final int MSG_UNBIND = 1; @@ -64,8 +71,6 @@ public abstract class AbstractRemoteService implements DeathRecipient { protected final Handler mHandler; protected final ComponentName mComponentName; - protected PendingRequest<? extends AbstractRemoteService> mPendingRequest; - private final Context mContext; private final Intent mIntent; private final VultureCallback mVultureCallback; @@ -88,10 +93,11 @@ public abstract class AbstractRemoteService implements DeathRecipient { * * @param service service that died! */ - void onServiceDied(AbstractRemoteService service); + void onServiceDied(AbstractRemoteService<? extends AbstractRemoteService<?>> service); } - public AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface, + // NOTE: must be package-protected so this class is not extend outside + AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, @NonNull VultureCallback callback, boolean bindInstantServiceAllowed, boolean verbose) { mContext = context; @@ -118,12 +124,25 @@ public abstract class AbstractRemoteService implements DeathRecipient { return mDestroyed; } + private void handleOnConnectedStateChangedInternal(boolean connected) { + if (connected) { + handlePendingRequests(); + } + handleOnConnectedStateChanged(connected); + } + + /** + * Handles the pending requests when the connection it bounds to the remote service. + */ + abstract void handlePendingRequests(); + /** - * Callback called when the system connected / disconnected to the service. + * Callback called when the system connected / disconnected to the service and the pending + * requests have been handled. * * @param state {@code true} when connected, {@code false} when disconnected. */ - protected void onConnectedStateChanged(boolean state) { + protected void handleOnConnectedStateChanged(boolean state) { } /** @@ -144,14 +163,18 @@ public abstract class AbstractRemoteService implements DeathRecipient { private void handleDestroy() { if (checkIfDestroyed()) return; - if (mPendingRequest != null) { - mPendingRequest.cancel(); - mPendingRequest = null; - } - ensureUnbound(); + handleOnDestroy(); + handleEnsureUnbound(); mDestroyed = true; } + /** + * Clears the state when this object is destroyed. + * + * <p>Typically used to cancel the pending requests. + */ + protected abstract void handleOnDestroy(); + @Override // from DeathRecipient public void binderDied() { mHandler.sendMessage(obtainMessage(AbstractRemoteService::handleBinderDied, this)); @@ -183,9 +206,7 @@ public abstract class AbstractRemoteService implements DeathRecipient { pw.append(prefix).append(tab).append("destroyed=") .append(String.valueOf(mDestroyed)).println(); pw.append(prefix).append(tab).append("bound=") - .append(String.valueOf(isBound())).println(); - pw.append(prefix).append(tab).append("hasPendingRequest=") - .append(String.valueOf(mPendingRequest != null)).println(); + .append(String.valueOf(handleIsBound())).println(); pw.append(prefix).append("mBindInstantServiceAllowed=").println(mBindInstantServiceAllowed); pw.append(prefix).append("idleTimeout=") .append(Long.toString(getTimeoutIdleBindMillis() / 1000)).append("s").println(); @@ -194,7 +215,7 @@ public abstract class AbstractRemoteService implements DeathRecipient { pw.println(); } - protected void scheduleRequest(PendingRequest<? extends AbstractRemoteService> pendingRequest) { + protected void scheduleRequest(@NonNull PendingRequest<S> pendingRequest) { mHandler.sendMessage(obtainMessage( AbstractRemoteService::handlePendingRequest, this, pendingRequest)); } @@ -215,19 +236,20 @@ public abstract class AbstractRemoteService implements DeathRecipient { private void handleUnbind() { if (checkIfDestroyed()) return; - ensureUnbound(); + handleEnsureUnbound(); } - private void handlePendingRequest( - PendingRequest<? extends AbstractRemoteService> pendingRequest) { + /** + * Handles a request, either processing it right now when bound, or saving it to be handled when + * bound. + */ + protected final void handlePendingRequest(@NonNull PendingRequest<S> pendingRequest) { if (checkIfDestroyed() || mCompleted) return; - if (!isBound()) { - if (mPendingRequest != null) { - mPendingRequest.cancel(); - } - mPendingRequest = pendingRequest; - ensureBound(); + if (!handleIsBound()) { + if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing" + pendingRequest); + handlePendingRequestWhileUnBound(pendingRequest); + handleEnsureBound(); } else { if (mVerbose) Slog.v(mTag, "handlePendingRequest(): " + pendingRequest); pendingRequest.run(); @@ -237,12 +259,17 @@ public abstract class AbstractRemoteService implements DeathRecipient { } } - private boolean isBound() { + /** + * Defines what to do with a request that arrives while not bound to the service. + */ + abstract void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest); + + private boolean handleIsBound() { return mServiceInterface != null; } - private void ensureBound() { - if (isBound() || mBinding) return; + private void handleEnsureBound() { + if (handleIsBound() || mBinding) return; if (mVerbose) Slog.v(mTag, "ensureBound()"); mBinding = true; @@ -265,13 +292,13 @@ public abstract class AbstractRemoteService implements DeathRecipient { } } - private void ensureUnbound() { - if (!isBound() && !mBinding) return; + private void handleEnsureUnbound() { + if (!handleIsBound() && !mBinding) return; if (mVerbose) Slog.v(mTag, "ensureUnbound()"); mBinding = false; - if (isBound()) { - onConnectedStateChanged(false); + if (handleIsBound()) { + handleOnConnectedStateChangedInternal(false); if (mServiceInterface != null) { mServiceInterface.asBinder().unlinkToDeath(this, 0); mServiceInterface = null; @@ -283,6 +310,7 @@ public abstract class AbstractRemoteService implements DeathRecipient { private class RemoteServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { + if (mVerbose) Slog.v(mTag, "onServiceConnected()"); if (mDestroyed || !mBinding) { // This is abnormal. Unbinding the connection has been requested already. Slog.wtf(mTag, "onServiceConnected() was dispatched after unbindService."); @@ -296,15 +324,7 @@ public abstract class AbstractRemoteService implements DeathRecipient { handleBinderDied(); return; } - onConnectedStateChanged(true); - - if (mPendingRequest != null) { - final PendingRequest<? extends AbstractRemoteService> pendingRequest = - mPendingRequest; - mPendingRequest = null; - handlePendingRequest(pendingRequest); - } - + handleOnConnectedStateChangedInternal(true); mServiceDied = false; } @@ -325,25 +345,12 @@ public abstract class AbstractRemoteService implements DeathRecipient { return mDestroyed; } - protected boolean handleResponseCallbackCommon( - PendingRequest<? extends AbstractRemoteService> pendingRequest) { - if (isDestroyed()) return false; - - if (mPendingRequest == pendingRequest) { - mPendingRequest = null; - } - if (mPendingRequest == null) { - scheduleUnbind(); - } - return true; - } - /** * Base class for the requests serviced by the remote service. * * @param <S> the remote service class */ - public abstract static class PendingRequest<S extends AbstractRemoteService> + public abstract static class PendingRequest<S extends AbstractRemoteService<S>> implements Runnable { protected final String mTag = getClass().getSimpleName(); protected final Object mLock = new Object(); diff --git a/services/core/java/com/android/server/AbstractSinglePendingRequestRemoteService.java b/services/core/java/com/android/server/AbstractSinglePendingRequestRemoteService.java new file mode 100644 index 000000000000..8e1f540a4d5e --- /dev/null +++ b/services/core/java/com/android/server/AbstractSinglePendingRequestRemoteService.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Context; +import android.util.Slog; + +import java.io.PrintWriter; + +/** + * Base class representing a remote service that can have only one pending requests while not bound. + * + * <p>If another request is received while not bound, the previous one will be canceled. + * + * @param <S> the concrete remote service class + * + * @hide + */ +public abstract class AbstractSinglePendingRequestRemoteService< + S extends AbstractSinglePendingRequestRemoteService<S>> extends AbstractRemoteService<S> { + + protected PendingRequest<S> mPendingRequest; + + public AbstractSinglePendingRequestRemoteService(@NonNull Context context, + @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, + @NonNull VultureCallback callback, boolean bindInstantServiceAllowed, + boolean verbose) { + super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed, + verbose); + } + + @Override // from AbstractRemoteService + void handlePendingRequests() { + if (mPendingRequest != null) { + final PendingRequest<S> pendingRequest = mPendingRequest; + mPendingRequest = null; + handlePendingRequest(pendingRequest); + } + } + + @Override // from AbstractRemoteService + protected void handleOnDestroy() { + if (mPendingRequest != null) { + mPendingRequest.cancel(); + mPendingRequest = null; + } + } + + @Override // from AbstractRemoteService + public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { + super.dump(prefix, pw); + pw.append(prefix).append("hasPendingRequest=") + .append(String.valueOf(mPendingRequest != null)).println(); + } + + @Override // from AbstractRemoteService + void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) { + if (mPendingRequest != null) { + if (mVerbose) { + Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest); + } + mPendingRequest.cancel(); + } + mPendingRequest = pendingRequest; + } +} diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java index 98203213e996..81f0259bfd71 100644 --- a/services/core/java/com/android/server/BinderCallsStatsService.java +++ b/services/core/java/com/android/server/BinderCallsStatsService.java @@ -98,7 +98,7 @@ public class BinderCallsStatsService extends Binder { mBinderCallsStats.setSamplingInterval(mParser.getInt( SETTINGS_SAMPLING_INTERVAL_KEY, BinderCallsStats.PERIODIC_SAMPLING_INTERVAL_DEFAULT)); - mBinderCallsStats.setSamplingInterval(mParser.getInt( + mBinderCallsStats.setMaxBinderCallStats(mParser.getInt( SETTINGS_MAX_CALL_STATS_KEY, BinderCallsStats.MAX_BINDER_CALL_STATS_COUNT_DEFAULT)); @@ -116,6 +116,7 @@ public class BinderCallsStatsService extends Binder { } mEnabled = enabled; mBinderCallsStats.reset(); + mBinderCallsStats.setAddDebugEntries(enabled); } } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 7ee3d3b3bdc7..126bf6556538 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1236,7 +1236,8 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(sockFd, callingUid); + mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner( + new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); @@ -1696,7 +1697,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), + socket, callingUid, direction, c.getSourceAddress(), @@ -1715,7 +1716,7 @@ public class IpSecService extends IIpSecService.Stub { throws RemoteException { mSrvConfig .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); + .ipSecRemoveTransportModeTransform(socket); } /** diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java index c563ad224da6..fa3babad639d 100644 --- a/services/core/java/com/android/server/LooperStatsService.java +++ b/services/core/java/com/android/server/LooperStatsService.java @@ -94,6 +94,8 @@ public class LooperStatsService extends Binder { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; pw.print("Start time: "); pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStats.getStartTimeMillis())); + pw.print("On battery time (ms): "); + pw.println(mStats.getBatteryTimeMillis()); final List<LooperStats.ExportedEntry> entries = mStats.getEntries(); entries.sort(Comparator .comparing((LooperStats.ExportedEntry entry) -> entry.workSourceUid) diff --git a/services/core/java/com/android/server/RuntimeService.java b/services/core/java/com/android/server/RuntimeService.java new file mode 100644 index 000000000000..ccfac80d22a7 --- /dev/null +++ b/services/core/java/com/android/server/RuntimeService.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.Context; +import android.os.Binder; +import android.service.runtime.DebugEntryProto; +import android.service.runtime.RuntimeServiceInfoProto; +import android.util.Slog; +import android.util.proto.ProtoOutputStream; + +import libcore.timezone.TimeZoneDataFiles; +import libcore.util.CoreLibraryDebug; +import libcore.util.DebugInfo; + +import com.android.internal.util.DumpUtils; +import com.android.timezone.distro.DistroException; +import com.android.timezone.distro.DistroVersion; +import com.android.timezone.distro.FileUtils; +import com.android.timezone.distro.TimeZoneDistro; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * This service exists only as a "dumpsys" target which reports information about the status of the + * runtime and related libraries. + */ +public class RuntimeService extends Binder { + + private static final String TAG = "RuntimeService"; + + private final Context mContext; + + public RuntimeService(Context context) { + mContext = context; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) { + return; + } + + boolean protoFormat = hasOption(args, "--proto"); + ProtoOutputStream proto = null; + + DebugInfo coreLibraryDebugInfo = CoreLibraryDebug.getDebugInfo(); + addTimeZoneApkDebugInfo(coreLibraryDebugInfo); + + if (protoFormat) { + proto = new ProtoOutputStream(fd); + reportTimeZoneInfoProto(coreLibraryDebugInfo, proto); + } else { + reportTimeZoneInfo(coreLibraryDebugInfo, pw); + } + + if (protoFormat) { + proto.flush(); + } + } + + /** Returns {@code true} if {@code args} contains {@code arg}. */ + private static boolean hasOption(String[] args, String arg) { + for (String opt : args) { + if (arg.equals(opt)) { + return true; + } + } + return false; + } + + /** + * Add information to {@link DebugInfo} about the time zone data supplied by the + * "Time zone updates via APK" feature. + */ + private static void addTimeZoneApkDebugInfo(DebugInfo coreLibraryDebugInfo) { + // Add /data tz data set using the DistroVersion class (which libcore cannot use). + // This update mechanism will be removed after the time zone APEX is launched so this + // untidiness will disappear with it. + String debugKeyPrefix = "core_library.timezone.data_"; + String versionFileName = TimeZoneDataFiles.getDataTimeZoneFile( + TimeZoneDistro.DISTRO_VERSION_FILE_NAME); + addDistroVersionDebugInfo(versionFileName, debugKeyPrefix, coreLibraryDebugInfo); + } + + /** + * Prints {@code coreLibraryDebugInfo} to {@code pw}. + * + * <p>If you change this method, make sure to modify + * {@link #reportTimeZoneInfoProto(DebugInfo, ProtoOutputStream)} as well. + */ + private static void reportTimeZoneInfo(DebugInfo coreLibraryDebugInfo, + PrintWriter pw) { + pw.println("Core Library Debug Info: "); + for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) { + pw.print(debugEntry.getKey()); + pw.print(": \""); + pw.print(debugEntry.getStringValue()); + pw.println("\""); + } + } + + /** + * Adds {@code coreLibraryDebugInfo} to {@code protoStream}. + * + * <p>If you change this method, make sure to modify + * {@link #reportTimeZoneInfo(DebugInfo, PrintWriter)}. + */ + private static void reportTimeZoneInfoProto( + DebugInfo coreLibraryDebugInfo, ProtoOutputStream protoStream) { + for (DebugInfo.DebugEntry debugEntry : coreLibraryDebugInfo.getDebugEntries()) { + long entryToken = protoStream.start(RuntimeServiceInfoProto.DEBUG_ENTRY); + protoStream.write(DebugEntryProto.KEY, debugEntry.getKey()); + protoStream.write(DebugEntryProto.STRING_VALUE, debugEntry.getStringValue()); + protoStream.end(entryToken); + } + } + + /** + * Adds version information to {@code debugInfo} from the distro_version file that may exist + * at {@code distroVersionFileName}. If the file does not exist or cannot be read this is + * reported as debug information too. + */ + private static void addDistroVersionDebugInfo(String distroVersionFileName, + String debugKeyPrefix, DebugInfo debugInfo) { + File file = new File(distroVersionFileName); + String statusKey = debugKeyPrefix + "status"; + if (file.exists()) { + try { + byte[] versionBytes = + FileUtils.readBytes(file, DistroVersion.DISTRO_VERSION_FILE_LENGTH); + DistroVersion distroVersion = DistroVersion.fromBytes(versionBytes); + String formatVersionString = distroVersion.formatMajorVersion + "." + + distroVersion.formatMinorVersion; + debugInfo.addStringEntry(statusKey, "OK") + .addStringEntry(debugKeyPrefix + "formatVersion", formatVersionString) + .addStringEntry(debugKeyPrefix + "rulesVersion", + distroVersion.rulesVersion) + .addStringEntry(debugKeyPrefix + "revision", + distroVersion.revision); + } catch (IOException | DistroException e) { + debugInfo.addStringEntry(statusKey, "ERROR"); + debugInfo.addStringEntry(debugKeyPrefix + "exception_class", + e.getClass().getName()); + debugInfo.addStringEntry(debugKeyPrefix + "exception_msg", e.getMessage()); + logMessage("Error reading " + file, e); + } + } else { + debugInfo.addStringEntry(statusKey, "NOT_FOUND"); + } + } + + private static void logMessage(String msg, Throwable t) { + Slog.v(TAG, msg, t); + } +} diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index e933bd0bc7ff..390126c63ab8 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -99,6 +99,7 @@ import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; import android.provider.MediaStore; import android.provider.Settings; +import android.sysprop.VoldProperties; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -1015,7 +1016,7 @@ class StorageManagerService extends IStorageManager.Stub // On an encrypted device we can't see system properties yet, so pull // the system locale out of the mount service. - if ("".equals(SystemProperties.get("vold.encrypt_progress"))) { + if ("".equals(VoldProperties.encrypt_progress().orElse(""))) { copyLocaleFromMountService(); } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index f0b472be1472..a2cbfaa02bfb 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -47,6 +47,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.emergency.EmergencyNumber; import android.util.LocalLog; import android.util.StatsLog; @@ -1664,6 +1665,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override + public void notifyEmergencyNumberList(List<EmergencyNumber> emergencyNumberList) { + // TODO checkPermission, modify Listener constent documentation + // TODO implement multisim emergency number list update in listener + // TODO implement PhoneStateListenerTest + } + + + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); diff --git a/services/core/java/com/android/server/WallpaperUpdateReceiver.java b/services/core/java/com/android/server/WallpaperUpdateReceiver.java new file mode 100644 index 000000000000..629e88250a11 --- /dev/null +++ b/services/core/java/com/android/server/WallpaperUpdateReceiver.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.ActivityThread; +import android.app.WallpaperManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.util.Slog; + +/** + * Receiver responsible for updating the wallpaper when the device + * configuration has changed. + * + * @hide + */ +public class WallpaperUpdateReceiver extends BroadcastReceiver { + + private static final String TAG = "WallpaperUpdateReceiver"; + private static final boolean DEBUG = false; + + @Override + public void onReceive(final Context context, final Intent intent) { + if (DEBUG) Slog.d(TAG, "onReceive: " + intent); + + if (intent != null && Intent.ACTION_DEVICE_CUSTOMIZATION_READY.equals(intent.getAction())) { + AsyncTask.execute(this::updateWallpaper); + } + } + + private void updateWallpaper() { + try { + ActivityThread currentActivityThread = ActivityThread.currentActivityThread(); + Context uiContext = currentActivityThread.getSystemUiContext(); + WallpaperManager wallpaperManager = WallpaperManager.getInstance(uiContext); + if (DEBUG) Slog.d(TAG, "Set customized default_wallpaper."); + Bitmap blank = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); + // set a blank wallpaper to force a redraw of default_wallpaper + wallpaperManager.setBitmap(blank); + wallpaperManager.setResource(com.android.internal.R.drawable.default_wallpaper); + } catch (Exception e) { + Slog.w(TAG, "Failed to customize system wallpaper." + e); + } + } +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0e354d515eef..8842f4198206 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -272,6 +272,7 @@ import android.os.UserManager; import android.os.WorkSource; import android.os.storage.StorageManager; import android.provider.Settings; +import android.sysprop.VoldProperties; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.style.SuggestionSpan; @@ -666,16 +667,50 @@ public class ActivityManagerService extends IActivityManager.Stub final class PidMap { private final SparseArray<ProcessRecord> mPidMap = new SparseArray<>(); + /** + * Puts the process record in the map. + * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this + * method. + */ void put(int key, ProcessRecord value) { - mPidMap.put(key, value); + synchronized (this) { + mPidMap.put(key, value); + } mAtmInternal.onProcessMapped(key, value.getWindowProcessController()); } + /** + * Removes the process record from the map. + * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this + * method. + */ void remove(int pid) { - mPidMap.remove(pid); + synchronized (this) { + mPidMap.remove(pid); + } mAtmInternal.onProcessUnMapped(pid); } + /** + * Removes the process record from the map if it has a thread. + * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this + * method. + */ + boolean removeIfNoThread(int pid) { + boolean removed = false; + synchronized (this) { + final ProcessRecord app = get(pid); + if (app != null && app.thread == null) { + mPidMap.remove(pid); + removed = true; + } + } + if (removed) { + mAtmInternal.onProcessUnMapped(pid); + } + return removed; + } + ProcessRecord get(int pid) { return mPidMap.get(pid); } @@ -1889,9 +1924,7 @@ public class ActivityManagerService extends IActivityManager.Stub app.getWindowProcessController().setPid(MY_PID); app.maxAdj = ProcessList.SYSTEM_ADJ; app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); - synchronized (mPidsSelfLocked) { - mPidsSelfLocked.put(app.pid, app); - } + mPidsSelfLocked.put(app.pid, app); mProcessList.updateLruProcessLocked(app, false, null); updateOomAdjLocked(); } @@ -4254,14 +4287,7 @@ public class ActivityManagerService extends IActivityManager.Stub private final void processStartTimedOutLocked(ProcessRecord app) { final int pid = app.pid; - boolean gone = false; - synchronized (mPidsSelfLocked) { - ProcessRecord knownApp = mPidsSelfLocked.get(pid); - if (knownApp != null && knownApp.thread == null) { - mPidsSelfLocked.remove(pid); - gone = true; - } - } + boolean gone = mPidsSelfLocked.removeIfNoThread(pid); if (gone) { Slog.w(TAG, "Process " + app + " failed to attach"); @@ -4782,8 +4808,8 @@ public class ActivityManagerService extends IActivityManager.Stub SystemProperties.set("sys.boot_completed", "1"); // And trigger dev.bootcomplete if we are not showing encryption progress - if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt")) - || "".equals(SystemProperties.get("vold.encrypt_progress"))) { + if (!"trigger_restart_min_framework".equals(VoldProperties.decrypt().orElse("")) + || "".equals(VoldProperties.encrypt_progress().orElse(""))) { SystemProperties.set("dev.bootcomplete", "1"); } mUserController.sendBootCompleted( @@ -13113,11 +13139,8 @@ public class ActivityManagerService extends IActivityManager.Stub return true; } else if (app.pid > 0 && app.pid != MY_PID) { // Goodbye! - boolean removed; - synchronized (mPidsSelfLocked) { - mPidsSelfLocked.remove(app.pid); - mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); - } + mPidsSelfLocked.remove(app.pid); + mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid); if (app.isolated) { mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 2541352b6daa..24543b7974df 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -25,10 +25,12 @@ import android.net.wifi.IWifiManager; import android.net.wifi.WifiActivityEnergyInfo; import android.os.BatteryStats; import android.os.Parcelable; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SynchronousResultReceiver; import android.os.SystemClock; +import android.os.ThreadLocalWorkSource; import android.telephony.ModemActivityInfo; import android.telephony.TelephonyManager; import android.util.IntArray; @@ -43,11 +45,9 @@ import com.android.internal.util.function.pooled.PooledLambda; import libcore.util.EmptyArray; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -74,7 +74,12 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { private final ScheduledExecutorService mExecutorService = Executors.newSingleThreadScheduledExecutor( (ThreadFactory) r -> { - Thread t = new Thread(r, "batterystats-worker"); + Thread t = new Thread( + () -> { + ThreadLocalWorkSource.setUid(Process.myUid()); + r.run(); + }, + "batterystats-worker"); t.setPriority(Thread.NORM_PRIORITY); return t; }); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 7991783e08c8..62f100926581 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -1246,10 +1246,8 @@ public final class ProcessList { long startTime = SystemClock.elapsedRealtime(); if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) { checkSlow(startTime, "startProcess: removing from pids map"); - synchronized (mService.mPidsSelfLocked) { - mService.mPidsSelfLocked.remove(app.pid); - mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); - } + mService.mPidsSelfLocked.remove(app.pid); + mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); checkSlow(startTime, "startProcess: done removing from pids map"); app.setPid(0); } @@ -1767,8 +1765,8 @@ public final class ProcessList { mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1, true /*replacingPid*/); } + mService.mPidsSelfLocked.put(pid, app); synchronized (mService.mPidsSelfLocked) { - mService.mPidsSelfLocked.put(pid, app); if (!procAttached) { Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; @@ -1928,10 +1926,8 @@ public final class ProcessList { .pendingStart)) { int pid = app.pid; if (pid > 0) { - synchronized (mService.mPidsSelfLocked) { - mService.mPidsSelfLocked.remove(pid); - mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); - } + mService.mPidsSelfLocked.remove(pid); + mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid); if (app.isolated) { mService.mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid); diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index c2f4406c615d..bf95210195b7 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -313,6 +313,7 @@ public class NetworkMonitor extends StateMachine { private final State mCaptivePortalState = new CaptivePortalState(); private final State mEvaluatingPrivateDnsState = new EvaluatingPrivateDnsState(); private final State mProbingState = new ProbingState(); + private final State mWaitingForNextProbeState = new WaitingForNextProbeState(); private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null; @@ -368,6 +369,7 @@ public class NetworkMonitor extends StateMachine { addState(mMaybeNotifyState, mDefaultState); addState(mEvaluatingState, mMaybeNotifyState); addState(mProbingState, mEvaluatingState); + addState(mWaitingForNextProbeState, mEvaluatingState); addState(mCaptivePortalState, mMaybeNotifyState); addState(mEvaluatingPrivateDnsState, mDefaultState); addState(mValidatedState, mDefaultState); @@ -877,6 +879,11 @@ public class NetworkMonitor extends StateMachine { @Override public void enter() { + if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) { + //Don't continue to blame UID forever. + TrafficStats.clearThreadStatsUid(); + } + final int token = ++mProbeToken; mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE, token, 0, isCaptivePortal()))); @@ -904,29 +911,16 @@ public class NetworkMonitor extends StateMachine { mLastPortalProbeResult = probeResult; transitionTo(mCaptivePortalState); } else { - final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0); - sendMessageDelayed(msg, mReevaluateDelayMs); logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED); notifyNetworkTestResultInvalid(probeResult.redirectUrl); - if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) { - // Don't continue to blame UID forever. - TrafficStats.clearThreadStatsUid(); - } - mReevaluateDelayMs *= 2; - if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) { - mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS; - } + transitionTo(mWaitingForNextProbeState); } return HANDLED; - case CMD_REEVALUATE: - // Leave the event to EvaluatingState. Defer this message will result in reset - // of mReevaluateDelayMs and mEvaluateAttempts. - case CMD_NETWORK_DISCONNECTED: case EVENT_DNS_NOTIFICATION: + // Leave the event to DefaultState to record correct dns timestamp. return NOT_HANDLED; default: - // TODO: Some events may able to handle in this state, instead of deferring to - // next state. + // Wait for probe result and defer events to next state by default. deferMessage(message); return HANDLED; } @@ -941,6 +935,29 @@ public class NetworkMonitor extends StateMachine { } } + // Being in the WaitingForNextProbeState indicates that evaluating probes failed and state is + // transited from ProbingState. This ensures that the state machine is only in ProbingState + // while a probe is in progress, not while waiting to perform the next probe. That allows + // ProbingState to defer most messages until the probe is complete, which keeps the code simple + // and matches the pre-Q behaviour where probes were a blocking operation performed on the state + // machine thread. + private class WaitingForNextProbeState extends State { + @Override + public void enter() { + final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0); + sendMessageDelayed(msg, mReevaluateDelayMs); + mReevaluateDelayMs *= 2; + if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) { + mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS; + } + } + + @Override + public boolean processMessage(Message message) { + return NOT_HANDLED; + } + } + // Limits the list of IP addresses returned by getAllByName or tried by openConnection to at // most one per address family. This ensures we only wait up to 20 seconds for TCP connections // to complete, regardless of how many IP addresses a host has. diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java index 0b6786cf8c07..521fa236cf7d 100644 --- a/services/core/java/com/android/server/display/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/ColorDisplayService.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TypeEvaluator; @@ -29,8 +31,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; +import android.hardware.display.IColorDisplayManager; import android.net.Uri; import android.opengl.Matrix; +import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; @@ -39,6 +43,7 @@ import android.util.MathUtils; import android.util.Slog; import android.view.animation.AnimationUtils; +import com.android.internal.R; import com.android.internal.app.ColorDisplayController; import com.android.server.SystemService; import com.android.server.twilight.TwilightListener; @@ -49,12 +54,8 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; -import com.android.internal.R; - -import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; - /** - * Tints the display at night. + * Controls the display's color transforms. */ public final class ColorDisplayService extends SystemService implements ColorDisplayController.Callback { @@ -101,7 +102,7 @@ public final class ColorDisplayService extends SystemService @Override public void onStart() { - // Nothing to publish. + publishBinderService(Context.COLOR_DISPLAY_SERVICE, new BinderService()); } @Override @@ -171,7 +172,7 @@ public final class ColorDisplayService extends SystemService } }; cr.registerContentObserver(Secure.getUriFor(Secure.USER_SETUP_COMPLETE), - false /* notifyForDescendents */, mUserSetupObserver, mCurrentUser); + false /* notifyForDescendants */, mUserSetupObserver, mCurrentUser); } else if (mBootCompleted) { setUp(); } @@ -405,8 +406,8 @@ public final class ColorDisplayService extends SystemService } /** - * Returns the first date time corresponding to the local time that occurs before the - * provided date time. + * Returns the first date time corresponding to the local time that occurs before the provided + * date time. * * @param compareTime the LocalDateTime to compare against * @return the prior LocalDateTime corresponding to this local time @@ -420,8 +421,8 @@ public final class ColorDisplayService extends SystemService } /** - * Returns the first date time corresponding to this local time that occurs after the - * provided date time. + * Returns the first date time corresponding to this local time that occurs after the provided + * date time. * * @param compareTime the LocalDateTime to compare against * @return the next LocalDateTime corresponding to this local time @@ -434,6 +435,11 @@ public final class ColorDisplayService extends SystemService return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt; } + private boolean isDeviceColorManagedInternal() { + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + return dtm.isDeviceColorManaged(); + } + private abstract class AutoMode implements ColorDisplayController.Callback { public abstract void onStart(); @@ -616,4 +622,16 @@ public final class ColorDisplayService extends SystemService return mResultMatrix; } } + + private final class BinderService extends IColorDisplayManager.Stub { + @Override + public boolean isDeviceColorManaged() { + final long token = Binder.clearCallingIdentity(); + try { + return isDeviceColorManagedInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } } diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java index d6931e006479..5ca1755131ab 100644 --- a/services/core/java/com/android/server/display/DisplayTransformManager.java +++ b/services/core/java/com/android/server/display/DisplayTransformManager.java @@ -16,7 +16,6 @@ package com.android.server.display; -import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.opengl.Matrix; import android.os.IBinder; @@ -27,8 +26,10 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import android.util.SparseArray; + import com.android.internal.annotations.GuardedBy; import com.android.internal.app.ColorDisplayController; + import java.util.Arrays; /** @@ -59,10 +60,6 @@ public class DisplayTransformManager { private static final int SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX = 1015; private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014; - - private static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation"; - private static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode"; - /** * SurfaceFlinger global saturation factor. */ @@ -71,6 +68,10 @@ public class DisplayTransformManager { * SurfaceFlinger display color (managed, unmanaged, etc.). */ private static final int SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR = 1023; + private static final int SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR = 1030; + + private static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation"; + private static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode"; private static final float COLOR_SATURATION_NATURAL = 1.0f; private static final float COLOR_SATURATION_BOOSTED = 1.1f; @@ -269,6 +270,29 @@ public class DisplayTransformManager { } /** + * Returns whether the screen is wide color gamut via SurfaceFlinger's + * {@link #SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR}. + */ + public boolean isDeviceColorManaged() { + final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER); + if (flinger != null) { + final Parcel data = Parcel.obtain(); + final Parcel reply = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + try { + flinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_WIDE_COLOR, data, reply, 0); + return reply.readBoolean(); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to query wide color support", ex); + } finally { + data.recycle(); + reply.recycle(); + } + } + return false; + } + + /** * Propagates the provided saturation to the SurfaceFlinger. */ private void applySaturation(float saturation) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index b148a2f3fff5..c0d3fdfb8f91 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -980,7 +980,7 @@ public class HdmiControlService extends SystemService { * @param sourceAddress a logical address of source device where sends polling message * @param pickStrategy strategy how to pick polling candidates * @param retryCount the number of retry used to send polling message to remote devices - * @throw IllegalArgumentException if {@code pickStrategy} is invalid value + * @throws IllegalArgumentException if {@code pickStrategy} is invalid value */ @ServiceThreadOnly void pollDevices(DevicePollingCallback callback, int sourceAddress, int pickStrategy, diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java index 6fe632459eaa..d5be26ac3389 100644 --- a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java +++ b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java @@ -27,12 +27,13 @@ import android.view.autofill.IAutoFillManagerClient; * * @hide Only for use within the system server. */ +//TODO(b/111276913): rename once the final name is defined public abstract class IntelligenceManagerInternal { /** * Checks whether the given {@code uid} owns the - * {@link android.service.intelligence.IntelligenceService} implementation associated with the - * given {@code userId}. + * {@link android.service.intelligence.SmartSuggestionsService} implementation associated with + * the given {@code userId}. */ public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 6c2549e9b04d..25a1626df865 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -428,6 +428,7 @@ public class NotificationManagerService extends SystemService { private GroupHelper mGroupHelper; private int mAutoGroupAtCount; private boolean mIsTelevision; + private boolean mIsAutomotive; private MetricsLogger mMetricsLogger; private Predicate<String> mAllowedManagedServicePackages; @@ -1388,6 +1389,11 @@ public class NotificationManagerService extends SystemService { } @VisibleForTesting + void setIsAutomotive(boolean isAutomotive) { + mIsAutomotive = isAutomotive; + } + + @VisibleForTesting void setIsTelevision(boolean isTelevision) { mIsTelevision = isTelevision; } @@ -1543,6 +1549,9 @@ public class NotificationManagerService extends SystemService { mIsTelevision = mPackageManagerClient.hasSystemFeature(FEATURE_LEANBACK) || mPackageManagerClient.hasSystemFeature(FEATURE_TELEVISION); + + mIsAutomotive = + mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0); } @Override @@ -5131,7 +5140,9 @@ public class NotificationManagerService extends SystemService { // Should this notification make noise, vibe, or use the LED? final boolean aboveThreshold = - record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; + mIsAutomotive + ? record.getImportance() > NotificationManager.IMPORTANCE_DEFAULT + : record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT; // Remember if this notification already owns the notification channels. boolean wasBeep = key != null && key.equals(mSoundNotificationKey); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8abb5000d544..dab4e79e141c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -58,6 +58,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY; import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; import static android.content.pm.PackageManager.INSTALL_INTERNAL; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; @@ -10299,12 +10300,21 @@ public class PackageManagerService extends IPackageManager.Stub compareSignatures( signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures, pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) { - // Treat mismatched signatures on system packages using a shared UID as - // fatal for the system overall, rather than just failing to install - // whichever package happened to be scanned later. - throw new IllegalStateException( - "Signature mismatch on system package " + pkg.packageName - + " for shared user " + pkgSetting.sharedUser); + if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 28) { + // Mismatched signatures is an error and silently skipping system + // packages will likely break the device in unforeseen ways. However, + // we allow the device to boot anyway because, prior to P, vendors were + // not expecting the platform to crash in this situation. + throw new PackageManagerException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, + "Signature mismatch for shared user: " + pkgSetting.sharedUser); + } else { + // Treat mismatched signatures on system packages using a shared UID as + // fatal for the system overall, rather than just failing to install + // whichever package happened to be scanned later. + throw new IllegalStateException("Signature mismatch on system package " + + pkg.packageName + " for shared user " + pkgSetting.sharedUser); + } } signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index 68fe1d8a05f8..51619cf940a8 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -46,7 +46,6 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; import android.permission.PermissionManager; @@ -1059,6 +1058,17 @@ public final class DefaultPermissionGrantPolicy { return; } + // Intersect the requestedPermissions for a factory image with that of its current update + // in case the latter one removed a <uses-permission> + String[] requestedByNonSystemPackage = getPackageInfo(pkg.packageName).requestedPermissions; + int size = requestedPermissions.length; + for (int i = 0; i < size; i++) { + if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) { + requestedPermissions[i] = null; + } + } + requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new); + PackageManager pm = mContext.getPackageManager(); final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits); ApplicationInfo applicationInfo = pkg.applicationInfo; diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java index 79e2688c6429..07bebad8e190 100644 --- a/services/core/java/com/android/server/power/ThermalManagerService.java +++ b/services/core/java/com/android/server/power/ThermalManagerService.java @@ -29,8 +29,12 @@ import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.IThermalStatusListener; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.os.ShellCommand; import android.os.Temperature; import android.util.ArrayMap; import android.util.Slog; @@ -77,6 +81,10 @@ public class ThermalManagerService extends SystemService { @GuardedBy("mLock") private int mStatus; + /** If override status takes effect*/ + @GuardedBy("mLock") + private boolean mIsStatusOverride; + /** Current thermal map, key as name */ @GuardedBy("mLock") private ArrayMap<String, Temperature> mTemperatureMap = new ArrayMap<>(); @@ -184,13 +192,19 @@ public class ThermalManagerService extends SystemService { newStatus = t.getStatus(); } } + // Do not update if override from shell + if (!mIsStatusOverride) { + setStatusLocked(newStatus); + } + } + + private void setStatusLocked(int newStatus) { if (newStatus != mStatus) { mStatus = newStatus; notifyStatusListenersLocked(); } } - private void postEventListenerCurrentTemperatures(IThermalEventListener listener, @Nullable Integer type) { synchronized (mLock) { @@ -241,12 +255,7 @@ public class ThermalManagerService extends SystemService { // Thermal Shutdown for Skin temperature if (temperature.getStatus() == Temperature.THROTTLING_SHUTDOWN && temperature.getType() == Temperature.TYPE_SKIN) { - final long token = Binder.clearCallingIdentity(); - try { - mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false); - } finally { - Binder.restoreCallingIdentity(token); - } + mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false); } Temperature old = mTemperatureMap.put(temperature.getName(), temperature); @@ -263,8 +272,14 @@ public class ThermalManagerService extends SystemService { } } + /* HwBinder callback **/ private void onTemperatureChangedCallback(Temperature temperature) { - onTemperatureChanged(temperature, true); + final long token = Binder.clearCallingIdentity(); + try { + onTemperatureChanged(temperature, true); + } finally { + Binder.restoreCallingIdentity(token); + } } private void dumpTemperaturesLocked(PrintWriter pw, String prefix, @@ -393,7 +408,7 @@ public class ThermalManagerService extends SystemService { } @Override - public int getCurrentStatus() { + public int getCurrentThermalStatus() { synchronized (mLock) { final long token = Binder.clearCallingIdentity(); try { @@ -434,8 +449,93 @@ public class ThermalManagerService extends SystemService { Binder.restoreCallingIdentity(token); } } + + private boolean isCallerShell() { + final int callingUid = Binder.getCallingUid(); + return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; + } + + @Override + public void onShellCommand(FileDescriptor in, FileDescriptor out, + FileDescriptor err, String[] args, ShellCallback callback, + ResultReceiver resultReceiver) { + if (!isCallerShell()) { + Slog.w(TAG, "Only shell is allowed to call thermalservice shell commands"); + return; + } + (new ThermalShellCommand()).exec( + this, in, out, err, args, callback, resultReceiver); + } + }; + class ThermalShellCommand extends ShellCommand { + @Override + public int onCommand(String cmd) { + switch(cmd != null ? cmd : "") { + case "override-status": + return runOverrideStatus(); + case "reset": + return runReset(); + default: + return handleDefaultCommands(cmd); + } + } + + private int runReset() { + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + mIsStatusOverride = false; + onTemperatureMapChangedLocked(); + return 0; + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private int runOverrideStatus() { + final long token = Binder.clearCallingIdentity(); + try { + final PrintWriter pw = getOutPrintWriter(); + int status; + try { + status = Integer.parseInt(getNextArgRequired()); + } catch (RuntimeException ex) { + pw.println("Error: " + ex.toString()); + return -1; + } + if (!Temperature.isValidStatus(status)) { + pw.println("Invalid status: " + Integer.toString(status)); + return -1; + } + synchronized (mLock) { + mIsStatusOverride = true; + setStatusLocked(status); + } + return 0; + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void onHelp() { + final PrintWriter pw = getOutPrintWriter(); + pw.println("Thermal service (thermalservice) commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(""); + pw.println(" override-status STATUS"); + pw.println(" sets and locks the thermal status of the device to STATUS."); + pw.println(" status code is defined in android.os.Temperature."); + pw.println(" reset"); + pw.println(" unlocks the thermal status of the device."); + pw.println(); + } + } + abstract static class ThermalHalWrapper { protected static final String TAG = ThermalHalWrapper.class.getSimpleName(); diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index b065470fe98c..b5ad2352896d 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -55,6 +55,7 @@ import java.io.FileDescriptor; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -106,7 +107,7 @@ public class RoleManagerService extends SystemService { intentFilter.addAction(Intent.ACTION_USER_REMOVED); getContext().registerReceiverAsUser(new BroadcastReceiver() { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(@NonNull Context context, @NonNull Intent intent) { if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); onRemoveUser(userId); @@ -129,10 +130,11 @@ public class RoleManagerService extends SystemService { userState = getUserStateLocked(userId); } String packagesHash = computeComponentStateHash(userId); - boolean needGrant; + String lastGrantPackagesHash; synchronized (mLock) { - needGrant = !packagesHash.equals(userState.getLastGrantPackagesHashLocked()); + lastGrantPackagesHash = userState.getLastGrantPackagesHashLocked(); } + boolean needGrant = !Objects.equals(packagesHash, lastGrantPackagesHash); if (needGrant) { // Some vital packages state has changed since last role grant // Run grants again @@ -144,7 +146,6 @@ public class RoleManagerService extends SystemService { public void onSuccess() { result.complete(null); } - @Override public void onFailure() { result.completeExceptionally(new RuntimeException()); @@ -163,7 +164,8 @@ public class RoleManagerService extends SystemService { } } - private String computeComponentStateHash(int userId) { + @Nullable + private String computeComponentStateHash(@UserIdInt int userId) { PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -198,8 +200,7 @@ public class RoleManagerService extends SystemService { private RoleUserState getUserStateLocked(@UserIdInt int userId) { RoleUserState userState = mUserStates.get(userId); if (userState == null) { - userState = new RoleUserState(userId); - userState.readSyncLocked(); + userState = RoleUserState.newInstanceLocked(userId); mUserStates.put(userId, userState); } return userState; @@ -386,11 +387,11 @@ public class RoleManagerService extends SystemService { } @Override - public void onShellCommand(FileDescriptor in, FileDescriptor out, - FileDescriptor err, String[] args, ShellCallback callback, - ResultReceiver resultReceiver) { - (new RoleManagerShellCommand(this)).exec( - this, in, out, err, args, callback, resultReceiver); + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, @NonNull String[] args, + @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) { + new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback, + resultReceiver); } } } diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleManagerShellCommand.java index e1977ef083b4..336b311723a9 100644 --- a/services/core/java/com/android/server/role/RoleManagerShellCommand.java +++ b/services/core/java/com/android/server/role/RoleManagerShellCommand.java @@ -16,6 +16,8 @@ package com.android.server.role; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.role.IRoleManager; import android.app.role.IRoleManagerCallback; import android.os.RemoteException; @@ -27,13 +29,17 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; class RoleManagerShellCommand extends ShellCommand { + + @NonNull private final IRoleManager mRoleManager; - RoleManagerShellCommand(IRoleManager roleManager) { + RoleManagerShellCommand(@NonNull IRoleManager roleManager) { mRoleManager = roleManager; } private class Callback extends IRoleManagerCallback.Stub { + + @NonNull private final CompletableFuture<Void> mResult = new CompletableFuture<>(); public int waitForResult() { @@ -58,7 +64,7 @@ class RoleManagerShellCommand extends ShellCommand { } @Override - public int onCommand(String cmd) { + public int onCommand(@Nullable String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java index f218d3a5834b..3e3e1566b2dd 100644 --- a/services/core/java/com/android/server/role/RoleUserState.java +++ b/services/core/java/com/android/server/role/RoleUserState.java @@ -47,6 +47,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Objects; /** * Stores the state of roles for a user. @@ -70,25 +71,41 @@ public class RoleUserState { private final int mUserId; @GuardedBy("RoleManagerService.mLock") - private int mVersion; + private int mVersion = VERSION_UNDEFINED; @GuardedBy("RoleManagerService.mLock") - private String mLastGrantPackagesHash = null; + @Nullable + private String mLastGrantPackagesHash; /** * Maps role names to its holders' package names. The values should never be null. */ @GuardedBy("RoleManagerService.mLock") - @Nullable - private ArrayMap<String, ArraySet<String>> mRoles = null; + @NonNull + private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>(); @GuardedBy("RoleManagerService.mLock") private boolean mDestroyed; + @NonNull private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper()); - public RoleUserState(@UserIdInt int userId) { + private RoleUserState(@UserIdInt int userId) { mUserId = userId; + + readSyncLocked(); + } + + /** + * Create a new instance of user state, and read its state from disk if previously persisted. + * + * @param userId the user id for the new user state + * + * @return the new user state + */ + @GuardedBy("RoleManagerService.mLock") + public static RoleUserState newInstanceLocked(@UserIdInt int userId) { + return new RoleUserState(userId); } /** @@ -116,7 +133,9 @@ public class RoleUserState { } /** - * Get the hash representing the state of packages during the last time initial grants was run + * Get the hash representing the state of packages during the last time initial grants was run. + * + * @return the hash representing the state of packages */ @GuardedBy("RoleManagerService.mLock") public String getLastGrantPackagesHashLocked() { @@ -124,10 +143,16 @@ public class RoleUserState { } /** - * Set the hash representing the state of packages during the last time initial grants was run + * Set the hash representing the state of packages during the last time initial grants was run. + * + * @param lastGrantPackagesHash the hash representing the state of packages */ @GuardedBy("RoleManagerService.mLock") - public void setLastGrantPackagesHashLocked(String lastGrantPackagesHash) { + public void setLastGrantPackagesHashLocked(@Nullable String lastGrantPackagesHash) { + throwIfDestroyedLocked(); + if (Objects.equals(mLastGrantPackagesHash, lastGrantPackagesHash)) { + return; + } mLastGrantPackagesHash = lastGrantPackagesHash; writeAsyncLocked(); } @@ -250,9 +275,9 @@ public class RoleUserState { * Schedule writing the state to file. */ @GuardedBy("RoleManagerService.mLock") - void writeAsyncLocked() { + private void writeAsyncLocked() { throwIfDestroyedLocked(); - int version = mVersion; + ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>(); for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) { String roleName = mRoles.keyAt(i); @@ -260,15 +285,16 @@ public class RoleUserState { roleHolders = new ArraySet<>(roleHolders); roles.put(roleName, roleHolders); } + mWriteHandler.removeCallbacksAndMessages(null); // TODO: Throttle writes. - mWriteHandler.sendMessage(PooledLambda.obtainMessage( - RoleUserState::writeSync, this, version, roles, mLastGrantPackagesHash)); + mWriteHandler.sendMessage(PooledLambda.obtainMessage(RoleUserState::writeSync, this, + mVersion, mLastGrantPackagesHash, roles)); } @WorkerThread - private void writeSync(int version, @NonNull ArrayMap<String, ArraySet<String>> roles, - String packagesHash) { + private void writeSync(int version, @Nullable String packagesHash, + @NonNull ArrayMap<String, ArraySet<String>> roles) { AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId); FileOutputStream out = null; try { @@ -280,7 +306,7 @@ public class RoleUserState { "http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startDocument(null, true); - serializeRoles(serializer, version, roles, packagesHash); + serializeRoles(serializer, version, packagesHash, roles); serializer.endDocument(); atomicFile.finishWrite(out); @@ -296,19 +322,26 @@ public class RoleUserState { @WorkerThread private void serializeRoles(@NonNull XmlSerializer serializer, int version, - @NonNull ArrayMap<String, ArraySet<String>> roles, String packagesHash) + @Nullable String packagesHash, @NonNull ArrayMap<String, ArraySet<String>> roles) throws IOException { serializer.startTag(null, TAG_ROLES); + serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version)); - serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash); + + if (packagesHash != null) { + serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash); + } + for (int i = 0, size = roles.size(); i < size; ++i) { String roleName = roles.keyAt(i); ArraySet<String> roleHolders = roles.valueAt(i); + serializer.startTag(null, TAG_ROLE); serializer.attribute(null, ATTRIBUTE_NAME, roleName); serializeRoleHolders(serializer, roleHolders); serializer.endTag(null, TAG_ROLE); } + serializer.endTag(null, TAG_ROLES); } @@ -317,6 +350,7 @@ public class RoleUserState { @NonNull ArraySet<String> roleHolders) throws IOException { for (int i = 0, size = roleHolders.size(); i < size; ++i) { String roleHolder = roleHolders.valueAt(i); + serializer.startTag(null, TAG_HOLDER); serializer.attribute(null, ATTRIBUTE_NAME, roleHolder); serializer.endTag(null, TAG_HOLDER); @@ -327,11 +361,7 @@ public class RoleUserState { * Read the state from file. */ @GuardedBy("RoleManagerService.mLock") - public void readSyncLocked() { - if (mRoles != null) { - throw new IllegalStateException("This RoleUserState has already read the roles.xml"); - } - + private void readSyncLocked() { File file = getFile(mUserId); try (FileInputStream in = new AtomicFile(file).openRead()) { XmlPullParser parser = Xml.newPullParser(); @@ -339,8 +369,6 @@ public class RoleUserState { parseXmlLocked(parser); } catch (FileNotFoundException e) { Slog.i(LOG_TAG, "roles.xml not found"); - mRoles = new ArrayMap<>(); - mVersion = VERSION_UNDEFINED; } catch (XmlPullParserException | IOException e) { throw new IllegalStateException("Failed to parse roles.xml: " + file, e); } @@ -362,13 +390,14 @@ public class RoleUserState { return; } } + Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml"); } private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION)); mLastGrantPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH); - mRoles = new ArrayMap<>(); + mRoles.clear(); int type; int depth; diff --git a/services/core/java/com/android/server/signedconfig/SignedConfigApplicator.java b/services/core/java/com/android/server/signedconfig/SignedConfigApplicator.java new file mode 100644 index 000000000000..7ce071faab04 --- /dev/null +++ b/services/core/java/com/android/server/signedconfig/SignedConfigApplicator.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.signedconfig; + +import android.content.Context; + +class SignedConfigApplicator { + + static void applyConfig(Context context, String config, String signature) { + //TODO verify signature + //TODO parse & apply config + } + +} diff --git a/services/core/java/com/android/server/signedconfig/SignedConfigService.java b/services/core/java/com/android/server/signedconfig/SignedConfigService.java new file mode 100644 index 000000000000..148568628397 --- /dev/null +++ b/services/core/java/com/android/server/signedconfig/SignedConfigService.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.signedconfig; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; +import android.net.Uri; +import android.os.Bundle; +import android.util.Slog; + +import com.android.server.LocalServices; + +/** + * Signed config service. This is not an Android Service, but just owns a broadcast receiver for + * receiving package install and update notifications from the package manager. + */ +public class SignedConfigService { + + private static final boolean DBG = false; + private static final String TAG = "SignedConfig"; + + // TODO should these be elsewhere? In a public API? + private static final String KEY_CONFIG = "android.signedconfig"; + private static final String KEY_CONFIG_SIGNATURE = "android.signedconfig.signature"; + + private static class UpdateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + new SignedConfigService(context).handlePackageBroadcast(intent); + } + } + + private final Context mContext; + private final PackageManagerInternal mPacMan; + + public SignedConfigService(Context context) { + mContext = context; + mPacMan = LocalServices.getService(PackageManagerInternal.class); + } + + void handlePackageBroadcast(Intent intent) { + if (DBG) Slog.d(TAG, "handlePackageBroadcast " + intent); + Uri packageData = intent.getData(); + String packageName = packageData == null ? null : packageData.getSchemeSpecificPart(); + if (DBG) Slog.d(TAG, "handlePackageBroadcast package=" + packageName); + if (packageName == null) { + return; + } + int userId = mContext.getUser().getIdentifier(); + PackageInfo pi = mPacMan.getPackageInfo(packageName, PackageManager.GET_META_DATA, + android.os.Process.SYSTEM_UID, userId); + if (pi == null) { + Slog.w(TAG, "Got null PackageInfo for " + packageName + "; user " + userId); + return; + } + Bundle metaData = pi.applicationInfo.metaData; + if (metaData == null) { + if (DBG) Slog.d(TAG, "handlePackageBroadcast: no metadata"); + return; + } + if (metaData.containsKey(KEY_CONFIG) + && metaData.containsKey(KEY_CONFIG_SIGNATURE)) { + String config = metaData.getString(KEY_CONFIG); + String signature = metaData.getString(KEY_CONFIG_SIGNATURE); + if (DBG) { + Slog.d(TAG, "Got signed config: " + config); + Slog.d(TAG, "Got config signature: " + signature); + } + SignedConfigApplicator.applyConfig(mContext, config, signature); + } else { + if (DBG) Slog.d(TAG, "Package has no config/signature."); + } + } + + /** + * Register to receive broadcasts from the package manager. + */ + public static void registerUpdateReceiver(Context context) { + if (DBG) Slog.d(TAG, "Registering receiver"); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addDataScheme("package"); + context.registerReceiver(new UpdateReceiver(), filter); + } +} diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index e645b84e83a0..6e4c00eed181 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -17,6 +17,7 @@ package com.android.server.statusbar; import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS; +import static android.view.Display.DEFAULT_DISPLAY; import android.app.ActivityThread; import android.app.Notification; @@ -25,6 +26,8 @@ import android.content.ComponentName; import android.content.Context; import android.graphics.Rect; import android.hardware.biometrics.IBiometricServiceReceiverInternal; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManager.DisplayListener; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -40,7 +43,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; -import android.view.Display; +import android.util.SparseArray; import com.android.internal.R; import com.android.internal.statusbar.IStatusBar; @@ -63,7 +66,7 @@ import java.util.List; * A note on locking: We rely on the fact that calls onto mBar are oneway or * if they are local, that they just enqueue messages to not deadlock. */ -public class StatusBarManagerService extends IStatusBarService.Stub { +public class StatusBarManagerService extends IStatusBarService.Stub implements DisplayListener { private static final String TAG = "StatusBarManagerService"; private static final boolean SPEW = false; @@ -79,24 +82,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub { private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener; private IBinder mSysUiVisToken = new Binder(); - private int mDisabled1 = 0; - private int mDisabled2 = 0; private final Object mLock = new Object(); private final DeathRecipient mDeathRecipient = new DeathRecipient(); - // encompasses lights-out mode and other flags defined on View - private int mSystemUiVisibility = 0; - private int mFullscreenStackSysUiVisibility; - private int mDockedStackSysUiVisibility; - private final Rect mFullscreenStackBounds = new Rect(); - private final Rect mDockedStackBounds = new Rect(); - private boolean mMenuVisible = false; - private int mImeWindowVis = 0; - private int mImeBackDisposition; - private boolean mShowImeSwitcher; - private IBinder mImeToken = null; private int mCurrentUserId; + private SparseArray<UiState> mDisplayUiState = new SparseArray<>(); + private class DeathRecipient implements IBinder.DeathRecipient { public void binderDied() { mBar.asBinder().unlinkToDeath(this,0); @@ -185,8 +177,29 @@ public class StatusBarManagerService extends IStatusBarService.Stub { LocalServices.addService(StatusBarManagerInternal.class, mInternalService); LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider); + + // We always have a default display. + final UiState state = new UiState(); + mDisplayUiState.put(DEFAULT_DISPLAY, state); + + final DisplayManager displayManager = + (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + displayManager.registerDisplayListener(this, mHandler); } + @Override + public void onDisplayAdded(int displayId) {} + + @Override + public void onDisplayRemoved(int displayId) { + synchronized (mLock) { + mDisplayUiState.remove(displayId); + } + } + + @Override + public void onDisplayChanged(int displayId) {} + /** * Private API used by NotificationManagerService. */ @@ -240,22 +253,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub { @Override public void topAppWindowChanged(int displayId, boolean menuVisible) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } - StatusBarManagerService.this.topAppWindowChanged(menuVisible); + StatusBarManagerService.this.topAppWindowChanged(displayId, menuVisible); } @Override public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds, String cause) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } - StatusBarManagerService.this.setSystemUiVisibility(vis, fullscreenStackVis, + StatusBarManagerService.this.setSystemUiVisibility(displayId, vis, fullscreenStackVis, dockedStackVis, mask, fullscreenBounds, dockedBounds, cause); } @@ -272,13 +277,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub { @Override public void appTransitionFinished(int displayId) { enforceStatusBarService(); - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } if (mBar != null) { try { - mBar.appTransitionFinished(); + mBar.appTransitionFinished(displayId); } catch (RemoteException ex) {} } } @@ -374,39 +375,27 @@ public class StatusBarManagerService extends IStatusBarService.Stub { @Override public void setWindowState(int displayId, int window, int state) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } if (mBar != null) { try { - mBar.setWindowState(window, state); + mBar.setWindowState(displayId, window, state); } catch (RemoteException ex) {} } } @Override public void appTransitionPending(int displayId) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } if (mBar != null) { try { - mBar.appTransitionPending(); + mBar.appTransitionPending(displayId); } catch (RemoteException ex) {} } } @Override public void appTransitionCancelled(int displayId) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } if (mBar != null) { try { - mBar.appTransitionCancelled(); + mBar.appTransitionCancelled(displayId); } catch (RemoteException ex) {} } } @@ -414,14 +403,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub { @Override public void appTransitionStarting(int displayId, long statusBarAnimationsStartTime, long statusBarAnimationsDuration) { - if (displayId != Display.DEFAULT_DISPLAY) { - // TODO (b/117478341): Resolve one status bar/ navigation bar assumption - return; - } if (mBar != null) { try { mBar.appTransitionStarting( - statusBarAnimationsStartTime, statusBarAnimationsDuration); + displayId, statusBarAnimationsStartTime, statusBarAnimationsDuration); } catch (RemoteException ex) {} } } @@ -449,6 +434,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { return false; } + // TODO(b/118592525): support it per display if necessary. @Override public void onProposedRotationChanged(int rotation, boolean isValid) { if (mBar != null){ @@ -462,7 +448,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub { private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() { @Override public boolean isGlobalActionsDisabled() { - return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0; + // TODO(b/118592525): support global actions for multi-display. + final int disabled2 = mDisplayUiState.get(DEFAULT_DISPLAY).getDisabled2(); + return (disabled2 & DISABLE2_GLOBAL_ACTIONS) != 0; } @Override @@ -664,20 +652,23 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } + // TODO(b/117478341): make it aware of multi-display if needed. @Override public void disable(int what, IBinder token, String pkg) { disableForUser(what, token, pkg, mCurrentUserId); } + // TODO(b/117478341): make it aware of multi-display if needed. @Override public void disableForUser(int what, IBinder token, String pkg, int userId) { enforceStatusBar(); synchronized (mLock) { - disableLocked(userId, what, token, pkg, 1); + disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 1); } } + // TODO(b/117478341): make it aware of multi-display if needed. /** * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. * To re-enable everything, pass {@link #DISABLE_NONE}. @@ -689,6 +680,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { disable2ForUser(what, token, pkg, mCurrentUserId); } + // TODO(b/117478341): make it aware of multi-display if needed. /** * Disable additional status bar features for a given user. Pass the bitwise-or of the * DISABLE2_* flags. To re-enable everything, pass {@link #DISABLE_NONE}. @@ -700,11 +692,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub { enforceStatusBar(); synchronized (mLock) { - disableLocked(userId, what, token, pkg, 2); + disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 2); } } - private void disableLocked(int userId, int what, IBinder token, String pkg, int whichFlag) { + private void disableLocked(int displayId, int userId, int what, IBinder token, String pkg, + int whichFlag) { // It's important that the the callback and the call to mBar get done // in the same order when multiple threads are calling this function // so they are paired correctly. The messages on the handler will be @@ -723,22 +716,19 @@ public class StatusBarManagerService extends IStatusBarService.Stub { disabledData += " ([" + i + "] " + tok + "), "; } disabledData += " }"; - Log.d(TAG, "disabledlocked (b/113914868): net1=" + net1 + ", mDisabled1=" + mDisabled1 - + ", token=" + token + ", mDisableRecords=" + mDisableRecords.size() + " => " - + disabledData); - } + final UiState state = getUiState(displayId); - if (net1 != mDisabled1 || net2 != mDisabled2) { - mDisabled1 = net1; - mDisabled2 = net2; - mHandler.post(new Runnable() { - public void run() { - mNotificationDelegate.onSetDisabled(net1); - } - }); + Log.d(TAG, "disabledlocked (b/113914868): displayId=" + displayId + "net1=" + net1 + + ", mDisabled1=" + state.mDisabled1 + ", token=" + token + + ", mDisableRecords=" + mDisableRecords.size() + " => " + disabledData); + } + final UiState state = getUiState(displayId); + if (state.disableEquals(net1, net2)) { + state.setDisabled(net1, net2); + mHandler.post(() -> mNotificationDelegate.onSetDisabled(net1)); if (mBar != null) { try { - mBar.disable(net1, net2); + mBar.disable(displayId, net1, net2); } catch (RemoteException ex) { } } @@ -808,26 +798,27 @@ public class StatusBarManagerService extends IStatusBarService.Stub { * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}. */ - private void topAppWindowChanged(final boolean menuVisible) { + private void topAppWindowChanged(int displayId, final boolean menuVisible) { enforceStatusBar(); - if (SPEW) Slog.d(TAG, (menuVisible?"showing":"hiding") + " MENU key"); - + if (SPEW) { + Slog.d(TAG, "display#" + displayId + ": " + + (menuVisible ? "showing" : "hiding") + " MENU key"); + } synchronized(mLock) { - mMenuVisible = menuVisible; - mHandler.post(new Runnable() { - public void run() { - if (mBar != null) { - try { - mBar.topAppWindowChanged(menuVisible); - } catch (RemoteException ex) { - } + getUiState(displayId).setMenuVisible(menuVisible); + mHandler.post(() -> { + if (mBar != null) { + try { + mBar.topAppWindowChanged(displayId, menuVisible); + } catch (RemoteException ex) { } } }); } } + // TODO(b/117478341): support back button change when IME is showing on a external display. @Override public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition, final boolean showImeSwitcher) { @@ -841,39 +832,42 @@ public class StatusBarManagerService extends IStatusBarService.Stub { // In case of IME change, we need to call up setImeWindowStatus() regardless of // mImeWindowVis because mImeWindowVis may not have been set to false when the // previous IME was destroyed. - mImeWindowVis = vis; - mImeBackDisposition = backDisposition; - mImeToken = token; - mShowImeSwitcher = showImeSwitcher; - mHandler.post(new Runnable() { - public void run() { - if (mBar != null) { - try { - mBar.setImeWindowStatus(token, vis, backDisposition, showImeSwitcher); - } catch (RemoteException ex) { - } - } - } + // TODO(b/117478341): support back button change when IME is showing on a external + // display. + getUiState(DEFAULT_DISPLAY) + .setImeWindowState(vis, backDisposition, showImeSwitcher, token); + + mHandler.post(() -> { + if (mBar == null) return; + try { + // TODO(b/117478341): support back button change when IME is showing on a + // external display. + mBar.setImeWindowStatus( + DEFAULT_DISPLAY, token, vis, backDisposition, showImeSwitcher); + } catch (RemoteException ex) { } }); } } @Override - public void setSystemUiVisibility(int vis, int mask, String cause) { - setSystemUiVisibility(vis, 0, 0, mask, mFullscreenStackBounds, mDockedStackBounds, cause); + public void setSystemUiVisibility(int displayId, int vis, int mask, String cause) { + final UiState state = getUiState(displayId); + setSystemUiVisibility(displayId, vis, 0, 0, mask, + state.mFullscreenStackBounds, state.mDockedStackBounds, cause); } - private void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, - Rect fullscreenBounds, Rect dockedBounds, String cause) { + private void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, + int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds, String cause) { // also allows calls from window manager which is in this process. enforceStatusBarService(); if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")"); synchronized (mLock) { - updateUiVisibilityLocked(vis, fullscreenStackVis, dockedStackVis, mask, + updateUiVisibilityLocked(displayId, vis, fullscreenStackVis, dockedStackVis, mask, fullscreenBounds, dockedBounds); disableLocked( + displayId, mCurrentUserId, vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken, @@ -881,30 +875,107 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } - private void updateUiVisibilityLocked(final int vis, + private void updateUiVisibilityLocked(final int displayId, final int vis, final int fullscreenStackVis, final int dockedStackVis, final int mask, final Rect fullscreenBounds, final Rect dockedBounds) { - if (mSystemUiVisibility != vis - || mFullscreenStackSysUiVisibility != fullscreenStackVis - || mDockedStackSysUiVisibility != dockedStackVis - || !mFullscreenStackBounds.equals(fullscreenBounds) - || !mDockedStackBounds.equals(dockedBounds)) { + final UiState state = getUiState(displayId); + if (!state.systemUiStateEquals(vis, fullscreenStackVis, dockedStackVis, + fullscreenBounds, dockedBounds)) { + state.setSystemUiState(vis, fullscreenStackVis, dockedStackVis, fullscreenBounds, + dockedBounds); + mHandler.post(() -> { + if (mBar != null) { + try { + mBar.setSystemUiVisibility(displayId, vis, fullscreenStackVis, + dockedStackVis, mask, fullscreenBounds, dockedBounds); + } catch (RemoteException ex) { + Log.w(TAG, "Can not get StatusBar!"); + } + } + }); + } + } + + /** + * @return {@link UiState} specified by {@code displayId}. + * + * <p> + * Note: If {@link UiState} specified by {@code displayId} does not exist, {@link UiState} + * will be allocated and {@code mDisplayUiState} will be updated accordingly. + * <p/> + */ + private UiState getUiState(int displayId) { + UiState state = mDisplayUiState.get(displayId); + if (state == null) { + state = new UiState(); + mDisplayUiState.put(displayId, state); + } + return state; + } + + private class UiState { + private int mSystemUiVisibility = 0; + private int mFullscreenStackSysUiVisibility = 0; + private int mDockedStackSysUiVisibility = 0; + private final Rect mFullscreenStackBounds = new Rect(); + private final Rect mDockedStackBounds = new Rect(); + private boolean mMenuVisible = false; + private int mDisabled1 = 0; + private int mDisabled2 = 0; + private int mImeWindowVis = 0; + private int mImeBackDisposition = 0; + private boolean mShowImeSwitcher = false; + private IBinder mImeToken = null; + + private int getDisabled1() { + return mDisabled1; + } + + private int getDisabled2() { + return mDisabled2; + } + + private void setDisabled(int disabled1, int disabled2) { + mDisabled1 = disabled1; + mDisabled2 = disabled2; + } + + private boolean isMenuVisible() { + return mMenuVisible; + } + + private void setMenuVisible(boolean menuVisible) { + mMenuVisible = menuVisible; + } + + private boolean disableEquals(int disabled1, int disabled2) { + return mDisabled1 == disabled1 && mDisabled2 == disabled2; + } + + private void setSystemUiState(final int vis, final int fullscreenStackVis, + final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds) { mSystemUiVisibility = vis; mFullscreenStackSysUiVisibility = fullscreenStackVis; mDockedStackSysUiVisibility = dockedStackVis; mFullscreenStackBounds.set(fullscreenBounds); mDockedStackBounds.set(dockedBounds); - mHandler.post(new Runnable() { - public void run() { - if (mBar != null) { - try { - mBar.setSystemUiVisibility(vis, fullscreenStackVis, dockedStackVis, - mask, fullscreenBounds, dockedBounds); - } catch (RemoteException ex) { - } - } - } - }); + } + + private boolean systemUiStateEquals(final int vis, final int fullscreenStackVis, + final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds) { + return mSystemUiVisibility == vis + && mFullscreenStackSysUiVisibility == fullscreenStackVis + && mDockedStackSysUiVisibility == dockedStackVis + && mFullscreenStackBounds.equals(fullscreenBounds) + && mDockedStackBounds.equals(dockedBounds); + } + + private void setImeWindowState(final int vis, final int backDisposition, + final boolean showImeSwitcher, final IBinder token) { + mImeWindowVis = vis; + mImeBackDisposition = backDisposition; + mShowImeSwitcher = showImeSwitcher; + mImeToken = token; } } @@ -939,6 +1010,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { // ================================================================================ // Callbacks from the status bar service. // ================================================================================ + // TODO(b/118592525): refactor it as an IStatusBar API. @Override public void registerStatusBar(IStatusBar bar, List<String> iconSlots, List<StatusBarIcon> iconList, int switches[], List<IBinder> binders, @@ -956,18 +1028,21 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } synchronized (mLock) { + // TODO(b/118592525): Currently, status bar only works on the default display. + // Make it aware of multi-display if needed. + final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY); switches[0] = gatherDisableActionsLocked(mCurrentUserId, 1); - switches[1] = mSystemUiVisibility; - switches[2] = mMenuVisible ? 1 : 0; - switches[3] = mImeWindowVis; - switches[4] = mImeBackDisposition; - switches[5] = mShowImeSwitcher ? 1 : 0; + switches[1] = state.mSystemUiVisibility; + switches[2] = state.mMenuVisible ? 1 : 0; + switches[3] = state.mImeWindowVis; + switches[4] = state.mImeBackDisposition; + switches[5] = state.mShowImeSwitcher ? 1 : 0; switches[6] = gatherDisableActionsLocked(mCurrentUserId, 2); - switches[7] = mFullscreenStackSysUiVisibility; - switches[8] = mDockedStackSysUiVisibility; - binders.add(mImeToken); - fullscreenStackBounds.set(mFullscreenStackBounds); - dockedStackBounds.set(mDockedStackBounds); + switches[7] = state.mFullscreenStackSysUiVisibility; + switches[8] = state.mDockedStackSysUiVisibility; + binders.add(state.mImeToken); + fullscreenStackBounds.set(state.mFullscreenStackBounds); + dockedStackBounds.set(state.mDockedStackBounds); } } @@ -1309,8 +1384,13 @@ public class StatusBarManagerService extends IStatusBarService.Stub { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; synchronized (mLock) { - pw.println(" mDisabled1=0x" + Integer.toHexString(mDisabled1)); - pw.println(" mDisabled2=0x" + Integer.toHexString(mDisabled2)); + for (int i = 0; i < mDisplayUiState.size(); i++) { + final int key = mDisplayUiState.keyAt(i); + final UiState state = mDisplayUiState.get(key); + pw.println(" displayId=" + key); + pw.println(" mDisabled1=0x" + Integer.toHexString(state.getDisabled1())); + pw.println(" mDisabled2=0x" + Integer.toHexString(state.getDisabled2())); + } final int N = mDisableRecords.size(); pw.println(" mDisableRecords.size=" + N); for (int i=0; i<N; i++) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index cfec8effeede..64ff9cf21ba0 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2822,8 +2822,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub IoUtils.closeQuietly(stream); if (!success) { - wpdData.mWidth = -1; - wpdData.mHeight = -1; wallpaper.cropHint.set(0, 0, 0, 0); wpdData.mPadding.set(0, 0, 0, 0); wallpaper.name = ""; @@ -2839,6 +2837,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY); ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY); WallpaperData lockWallpaper = mLockWallpaperMap.get(userId); if (lockWallpaper != null) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 25399ef165a5..255a003bb542 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2543,7 +2543,7 @@ final class ActivityRecord extends ConfigurationContainer { // Bounds changed...update configuration to match. if (!matchParentBounds()) { - task.computeOverrideConfiguration(mTmpConfig, updatedBounds, null /* insetBounds */, + task.computeOverrideConfiguration(mTmpConfig, updatedBounds, false /* overrideWidth */, false /* overrideHeight */); } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index d40a4faf9d21..3ccede02c430 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4944,9 +4944,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - mTmpBounds.put(task.taskId, task.getOverrideBounds()); - if (tempTaskInsetBounds != null) { - mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds); + if (task.hasDisplayedBounds()) { + mTmpBounds.put(task.taskId, task.getDisplayedBounds()); + mTmpInsetBounds.put(task.taskId, task.getOverrideBounds()); + } else { + mTmpBounds.put(task.taskId, task.getOverrideBounds()); + mTmpInsetBounds.put(task.taskId, null); } } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index fb93d39b33d4..c458c94b59e2 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -2178,9 +2178,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree final TaskStack stack = getStack(); final Task task = getTask(); if (task != null && task.inFreeformWindowingMode()) { - task.getRelativePosition(outPosition); + task.getRelativeDisplayedPosition(outPosition); } else if (stack != null) { - stack.getRelativePosition(outPosition); + stack.getRelativeDisplayedPosition(outPosition); } // Always use stack bounds in order to have the ability to animate outside the task region. @@ -2193,6 +2193,18 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree outBounds.offsetTo(0, 0); } + @Override + Rect getDisplayedBounds() { + final Task task = getTask(); + if (task != null) { + final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds(); + if (!overrideDisplayedBounds.isEmpty()) { + return overrideDisplayedBounds; + } + } + return getBounds(); + } + boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f1d77b9961cf..581cec928334 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -2834,6 +2834,9 @@ public class DisplayPolicy { return 0; } + mDisplayContent.getInsetsStateController().onBarControllingWindowChanged( + mTopFullscreenOpaqueWindowState); + int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java index e3ddadc7f70e..a667d679ee94 100644 --- a/services/core/java/com/android/server/wm/DragDropController.java +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -31,13 +31,12 @@ import android.util.Slog; import android.view.Display; import android.view.IWindow; import android.view.SurfaceControl; -import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.View; import com.android.internal.util.Preconditions; -import android.view.InputWindowHandle; import com.android.server.wm.WindowManagerInternal.IDragDropCallback; + import java.util.concurrent.atomic.AtomicReference; /** @@ -71,7 +70,7 @@ class DragDropController { new IDragDropCallback() {}); boolean dragDropActiveLocked() { - return mDragState != null; + return mDragState != null && !mDragState.isClosing(); } void showInputSurface(SurfaceControl.Transaction t, int displayId) { diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 8f6ed85d122d..607ee767869f 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -31,25 +31,24 @@ import android.animation.ValueAnimator; import android.annotation.Nullable; import android.content.ClipData; import android.content.ClipDescription; -import android.content.Context; -import android.graphics.Rect; import android.graphics.Point; +import android.graphics.Rect; import android.hardware.input.InputManager; -import android.os.Build; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; -import android.os.IUserManager; import android.os.UserManagerInternal; import android.util.Slog; import android.view.Display; import android.view.DragEvent; +import android.view.InputApplicationHandle; import android.view.InputChannel; import android.view.InputDevice; +import android.view.InputWindowHandle; import android.view.PointerIcon; import android.view.SurfaceControl; import android.view.View; @@ -59,8 +58,6 @@ import android.view.animation.Interpolator; import com.android.internal.view.IDragAndDropPermissions; import com.android.server.LocalServices; -import android.view.InputApplicationHandle; -import android.view.InputWindowHandle; import java.util.ArrayList; @@ -125,6 +122,12 @@ class DragState { private final Rect mTmpClipRect = new Rect(); + /** + * Whether we are finishing this drag and drop. This starts with {@code false}, and is set to + * {@code true} when {@link #closeLocked()} is called. + */ + private boolean mIsClosing; + DragState(WindowManagerService service, DragDropController controller, IBinder token, SurfaceControl surface, int flags, IBinder localWin) { mService = service; @@ -137,6 +140,10 @@ class DragState { } + boolean isClosing() { + return mIsClosing; + } + void hideInputSurface(SurfaceControl.Transaction t, int displayId) { if (displayId != mDisplayContent.getDisplayId()) { return; @@ -177,6 +184,7 @@ class DragState { * DragDropController#mDragState becomes null. */ void closeLocked() { + mIsClosing = true; // Unregister the input interceptor. if (mInputInterceptor != null) { if (DEBUG_DRAG) diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index e96f0b1c4416..282838f7d58b 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -18,11 +18,18 @@ package com.android.server.wm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Point; import android.graphics.Rect; +import android.util.proto.ProtoOutputStream; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; import android.view.InsetsSource; +import android.view.InsetsSourceControl; import com.android.internal.util.function.TriConsumer; -import com.android.server.policy.WindowManagerPolicy; +import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; + +import java.io.PrintWriter; /** * Controller for a specific inset source on the server. It's called provider as it provides the @@ -32,11 +39,19 @@ class InsetsSourceProvider { private final Rect mTmpRect = new Rect(); private final @NonNull InsetsSource mSource; + private final DisplayContent mDisplayContent; + private final InsetsStateController mStateController; + private @Nullable InsetsSourceControl mControl; + private @Nullable WindowState mControllingWin; + private @Nullable ControlAdapter mAdapter; private WindowState mWin; private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider; - InsetsSourceProvider(InsetsSource source) { + InsetsSourceProvider(InsetsSource source, InsetsStateController stateController, + DisplayContent displayContent) { mSource = source; + mDisplayContent = displayContent; + mStateController = stateController; } InsetsSource getSource() { @@ -84,4 +99,81 @@ class InsetsSourceProvider { mSource.setVisible(mWin.isVisible() && !mWin.mGivenInsetsPending); } + + void updateControlForTarget(@Nullable WindowState target) { + if (target == mControllingWin) { + return; + } + if (target == null) { + revokeControl(); + return; + } + mAdapter = new ControlAdapter(); + mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter, + false /* TODO hidden */); + mControllingWin = target; + mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash); + } + + InsetsSourceControl getControl() { + return mControl; + } + + void revokeControl() { + if (mControllingWin != null) { + + // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields. + mWin.cancelAnimation(); + } + } + + private class ControlAdapter implements AnimationAdapter { + + private SurfaceControl mCapturedLeash; + + @Override + public boolean getShowWallpaper() { + return false; + } + + @Override + public int getBackgroundColor() { + return 0; + } + + @Override + public void startAnimation(SurfaceControl animationLeash, Transaction t, + OnAnimationFinishedCallback finishCallback) { + mCapturedLeash = animationLeash; + t.setPosition(mCapturedLeash, mSource.getFrame().left, mSource.getFrame().top); + } + + @Override + public void onAnimationCancelled(SurfaceControl animationLeash) { + if (mAdapter == this) { + mStateController.notifyControlRevoked(mControllingWin, InsetsSourceProvider.this); + mControl = null; + mControllingWin = null; + mAdapter = null; + } + } + + @Override + public long getDurationHint() { + return 0; + } + + @Override + public long getStatusBarTransitionsStartTime() { + return 0; + } + + @Override + public void dump(PrintWriter pw, String prefix) { + } + + @Override + public void writeToProto(ProtoOutputStream proto) { + } + }; } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 1189ee660605..592b7fba4bfd 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -20,10 +20,17 @@ import static android.view.InsetsState.TYPE_IME; import static android.view.InsetsState.TYPE_NAVIGATION_BAR; import static android.view.InsetsState.TYPE_TOP_BAR; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.SparseArray; +import android.view.InsetsSourceControl; import android.view.InsetsState; +import android.view.ViewRootImpl; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.function.Consumer; /** @@ -34,7 +41,11 @@ class InsetsStateController { private final InsetsState mLastState = new InsetsState(); private final InsetsState mState = new InsetsState(); private final DisplayContent mDisplayContent; - private ArrayMap<Integer, InsetsSourceProvider> mControllers = new ArrayMap<>(); + + private final ArrayMap<Integer, InsetsSourceProvider> mControllers = new ArrayMap<>(); + private final ArrayMap<WindowState, ArrayList<Integer>> mWinControlTypeMap = new ArrayMap<>(); + private final SparseArray<WindowState> mTypeWinControlMap = new SparseArray<>(); + private final ArraySet<WindowState> mPendingControlChanged = new ArraySet<>(); private final Consumer<WindowState> mDispatchInsetsChanged = w -> { if (w.isVisible()) { @@ -72,12 +83,25 @@ class InsetsStateController { return state; } + @Nullable InsetsSourceControl[] getControlsForDispatch(WindowState target) { + ArrayList<Integer> controlled = mWinControlTypeMap.get(target); + if (controlled == null) { + return null; + } + final int size = controlled.size(); + final InsetsSourceControl[] result = new InsetsSourceControl[size]; + for (int i = 0; i < size; i++) { + result[i] = mControllers.get(controlled.get(i)).getControl(); + } + return result; + } + /** * @return The provider of a specific type. */ InsetsSourceProvider getSourceProvider(int type) { return mControllers.computeIfAbsent(type, - key -> new InsetsSourceProvider(mState.getSource(key))); + key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent)); } /** @@ -93,6 +117,84 @@ class InsetsStateController { } } + void onImeTargetChanged(@Nullable WindowState imeTarget) { + onControlChanged(TYPE_IME, imeTarget); + notifyPendingInsetsControlChanged(); + } + + /** + * Called when the top opaque fullscreen window that is able to control the system bars changes. + * + * @param controllingWindow The window that is now able to control the system bars appearance + * and visibility. + */ + void onBarControllingWindowChanged(@Nullable WindowState controllingWindow) { + // TODO: Apply policy that determines whether controllingWindow is able to control system + // bars + + // TODO: Depending on the form factor, mapping is different + onControlChanged(TYPE_TOP_BAR, controllingWindow); + onControlChanged(TYPE_NAVIGATION_BAR, controllingWindow); + notifyPendingInsetsControlChanged(); + } + + void notifyControlRevoked(@NonNull WindowState previousControllingWin, + InsetsSourceProvider provider) { + removeFromControlMaps(previousControllingWin, provider.getSource().getType()); + } + + private void onControlChanged(int type, @Nullable WindowState win) { + if (!ViewRootImpl.USE_NEW_INSETS) { + return; + } + final WindowState previous = mTypeWinControlMap.get(type); + if (win == previous) { + return; + } + final InsetsSourceProvider controller = mControllers.get(type); + if (controller == null) { + return; + } + controller.updateControlForTarget(win); + if (previous != null) { + removeFromControlMaps(previous, type); + mPendingControlChanged.add(previous); + } + if (win != null) { + addToControlMaps(win, type); + mPendingControlChanged.add(win); + } + } + + private void removeFromControlMaps(@NonNull WindowState win, int type) { + final ArrayList<Integer> array = mWinControlTypeMap.get(win); + if (array == null) { + return; + } + array.remove((Integer) type); + if (array.isEmpty()) { + mWinControlTypeMap.remove(win); + } + mTypeWinControlMap.remove(type); + } + + private void addToControlMaps(@NonNull WindowState win, int type) { + final ArrayList<Integer> array = mWinControlTypeMap.computeIfAbsent(win, + key -> new ArrayList<>()); + array.add(type); + mTypeWinControlMap.put(type, win); + } + + private void notifyPendingInsetsControlChanged() { + mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { + for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) { + final WindowState controllingWin = mPendingControlChanged.valueAt(i); + controllingWin.notifyInsetsControlChanged(); + } + mPendingControlChanged.clear(); + }); + } + private void notifyInsetsChanged() { mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */); } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index b6609e467e85..83ba384c9069 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -504,10 +504,12 @@ public class RecentsAnimationController implements DeathRecipient { public void binderDied() { cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); - // Clear associated input consumers on runner death - final InputMonitor inputMonitor = - mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); - inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION); + synchronized (mService.getWindowManagerLock()) { + // Clear associated input consumers on runner death + final InputMonitor inputMonitor = + mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); + inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION); + } } void checkAnimationReady(WallpaperController wallpaperController) { @@ -603,8 +605,8 @@ public class RecentsAnimationController implements DeathRecipient { mTask = task; mIsRecentTaskInvisible = isRecentTaskInvisible; final WindowContainer container = mTask.getParent(); - container.getRelativePosition(mPosition); - container.getBounds(mBounds); + container.getRelativeDisplayedPosition(mPosition); + mBounds.set(container.getDisplayedBounds()); } RemoteAnimationTarget createRemoteAnimationApp() { diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index 35264a22bce5..8f18aa56b001 100644 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ b/services/core/java/com/android/server/wm/StackWindowController.java @@ -252,7 +252,7 @@ public class StackWindowController * before mContainer has been updated, any relevant properties (like {@param windowingMode}) * need to be passed in. */ - public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds, + public void adjustConfigurationForBounds(Rect bounds, Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth, boolean overrideHeight, float density, Configuration config, Configuration parentConfig, int windowingMode) { @@ -303,11 +303,9 @@ public class StackWindowController // Additionally task dimensions should not be bigger than its parents dimensions. // The non decor inset are areas that could never be removed in Honeycomb. See // {@link WindowManagerPolicy#getNonDecorInsetsLw}. - intersectDisplayBoundsExcludeInsets(nonDecorBounds, - insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets, + intersectDisplayBoundsExcludeInsets(nonDecorBounds, bounds, mTmpNonDecorInsets, mTmpDisplayBounds, overrideWidth, overrideHeight); - intersectDisplayBoundsExcludeInsets(stableBounds, - insetBounds != null ? insetBounds : bounds, mTmpStableInsets, + intersectDisplayBoundsExcludeInsets(stableBounds, bounds, mTmpStableInsets, mTmpDisplayBounds, overrideWidth, overrideHeight); width = Math.min((int) (stableBounds.width() / density), parentConfig.screenWidthDp); @@ -323,7 +321,7 @@ public class StackWindowController config.screenWidthDp = width; config.screenHeightDp = height; config.smallestScreenWidthDp = getSmallestWidthForTaskBounds( - insetBounds != null ? insetBounds : bounds, density, windowingMode); + bounds, density, windowingMode); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index d3db5dfa5e0f..c70f0751ef96 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -27,11 +27,11 @@ import static com.android.server.EventLogTags.WM_TASK_REMOVED; import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS; import static com.android.server.wm.TaskProto.BOUNDS; import static com.android.server.wm.TaskProto.DEFER_REMOVAL; +import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS; import static com.android.server.wm.TaskProto.FILLS_PARENT; import static com.android.server.wm.TaskProto.ID; import static com.android.server.wm.TaskProto.SURFACE_HEIGHT; import static com.android.server.wm.TaskProto.SURFACE_WIDTH; -import static com.android.server.wm.TaskProto.TEMP_INSET_BOUNDS; import static com.android.server.wm.TaskProto.WINDOW_CONTAINER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -66,8 +66,8 @@ class Task extends WindowContainer<AppWindowToken> { final Rect mPreparedFrozenBounds = new Rect(); final Configuration mPreparedFrozenMergedConfig = new Configuration(); - // Bounds used to calculate the insets. - private final Rect mTempInsetBounds = new Rect(); + // If non-empty, bounds used to display the task during animations/interactions. + private final Rect mOverrideDisplayedBounds = new Rect(); /** ID of the display which rotation {@link #mRotation} has. */ private int mLastRotationDisplayId = Display.INVALID_DISPLAY; @@ -307,23 +307,23 @@ class Task extends WindowContainer<AppWindowToken> { } /** - * Sets the bounds used to calculate the insets. See - * {@link android.app.IActivityTaskManager#resizeDockedStack} why this is needed. + * Sets bounds that override where the task is displayed. Used during transient operations + * like animation / interaction. */ - void setTempInsetBounds(Rect tempInsetBounds) { - if (tempInsetBounds != null) { - mTempInsetBounds.set(tempInsetBounds); + void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) { + if (overrideDisplayedBounds != null) { + mOverrideDisplayedBounds.set(overrideDisplayedBounds); } else { - mTempInsetBounds.setEmpty(); + mOverrideDisplayedBounds.setEmpty(); } } /** - * Gets the bounds used to calculate the insets. See + * Gets the bounds that override where the task is displayed. See * {@link android.app.IActivityTaskManager#resizeDockedStack} why this is needed. */ - void getTempInsetBounds(Rect out) { - out.set(mTempInsetBounds); + Rect getOverrideDisplayedBounds() { + return mOverrideDisplayedBounds; } void setResizeable(int resizeMode) { @@ -380,8 +380,13 @@ class Task extends WindowContainer<AppWindowToken> { } else { mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top); } - setTempInsetBounds(tempInsetBounds); - setBounds(mTmpRect2, false /* forced */); + if (tempInsetBounds == null || tempInsetBounds.isEmpty()) { + setOverrideDisplayedBounds(null); + setBounds(mTmpRect2); + } else { + setOverrideDisplayedBounds(mTmpRect2); + setBounds(tempInsetBounds); + } } /** Return true if the current bound can get outputted to the rest of the system as-is. */ @@ -407,6 +412,15 @@ class Task extends WindowContainer<AppWindowToken> { mStack.getDisplayContent().getBounds(out); } + @Override + public Rect getDisplayedBounds() { + if (mOverrideDisplayedBounds.isEmpty()) { + return super.getDisplayedBounds(); + } else { + return mOverrideDisplayedBounds; + } + } + /** * Calculate the maximum visible area of this task. If the task has only one app, * the result will be visible frame of that app. If the task has more than one apps, @@ -723,7 +737,7 @@ class Task extends WindowContainer<AppWindowToken> { } proto.write(FILLS_PARENT, matchParentBounds()); getBounds().writeToProto(proto, BOUNDS); - mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS); + mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS); proto.write(DEFER_REMOVAL, mDeferRemoval); proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth()); proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight()); @@ -739,7 +753,7 @@ class Task extends WindowContainer<AppWindowToken> { pw.println(doublePrefix + "mBounds=" + getBounds().toShortString()); pw.println(doublePrefix + "mdr=" + mDeferRemoval); pw.println(doublePrefix + "appTokens=" + mChildren); - pw.println(doublePrefix + "mTempInsetBounds=" + mTempInsetBounds.toShortString()); + pw.println(doublePrefix + "mDisplayedBounds=" + mOverrideDisplayedBounds.toShortString()); final String triplePrefix = doublePrefix + " "; final String quadruplePrefix = triplePrefix + " "; diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java index 5a70325fbd87..e15bf5b9a6f0 100644 --- a/services/core/java/com/android/server/wm/TaskPositioningController.java +++ b/services/core/java/com/android/server/wm/TaskPositioningController.java @@ -28,12 +28,12 @@ import android.os.Looper; import android.os.RemoteException; import android.util.Slog; import android.view.Display; -import android.view.SurfaceControl; import android.view.IWindow; +import android.view.InputWindowHandle; +import android.view.SurfaceControl; import com.android.internal.annotations.GuardedBy; import com.android.server.input.InputManagerService; -import android.view.InputWindowHandle; /** * Controller for task positioning by drag. @@ -184,9 +184,7 @@ class TaskPositioningController { if (!mInputManager.transferTouchFocus( transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) { Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus"); - mTaskPositioner.unregister(); - mTaskPositioner = null; - displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); + cleanUpTaskPositioner(); return false; } @@ -199,12 +197,21 @@ class TaskPositioningController { if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning"); synchronized (mService.mGlobalLock) { - if (mTaskPositioner != null) { - mTaskPositioner.unregister(); - mTaskPositioner = null; - } + cleanUpTaskPositioner(); mPositioningDisplay = null; } }); } + + private void cleanUpTaskPositioner() { + final TaskPositioner positioner = mTaskPositioner; + if (positioner == null) { + return; + } + + // We need to assign task positioner to null first to indicate that we're finishing task + // positioning. + mTaskPositioner = null; + positioner.unregister(); + } } diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index 30751bcebe07..3cf0bd793c64 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -310,6 +310,11 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont // This number will be assigned when we evaluate OOM scores for all visible tasks. int mLayerRank = -1; + // When non-empty, this represents the bounds this task will be drawn at. This gets set during + // transient operations such as split-divider dragging and animations. + // TODO(b/119687367): This member is temporary. + final Rect mDisplayedBounds = new Rect(); + /** Helper object used for updating override configuration. */ private Configuration mTmpConfig = new Configuration(); @@ -447,6 +452,9 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont } mWindowContainerController = controller; + if (!mDisplayedBounds.isEmpty() && controller.mContainer != null) { + controller.mContainer.setOverrideDisplayedBounds(mDisplayedBounds); + } } void removeWindowContainer() { @@ -1732,9 +1740,15 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont final Configuration newOverrideConfig = new Configuration(); if (bounds != null) { newOverrideConfig.setTo(getOverrideConfiguration()); - mTmpRect.set(bounds); + if (insetBounds != null && !insetBounds.isEmpty()) { + mTmpRect.set(insetBounds); + setDisplayedBounds(bounds); + } else { + mTmpRect.set(bounds); + setDisplayedBounds(null); + } adjustForMinimalTaskDimensions(mTmpRect); - computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds, + computeOverrideConfiguration(newOverrideConfig, mTmpRect, mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom); } @@ -1782,16 +1796,23 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont setLastNonFullscreenBounds(currentBounds); } setBounds(null); + setDisplayedBounds(null); newConfig.unset(); } else { - mTmpRect.set(bounds); + if (insetBounds != null && !insetBounds.isEmpty()) { + mTmpRect.set(insetBounds); + setDisplayedBounds(bounds); + } else { + mTmpRect.set(bounds); + setDisplayedBounds(null); + } adjustForMinimalTaskDimensions(mTmpRect); setBounds(mTmpRect); if (mStack == null || persistBounds) { setLastNonFullscreenBounds(getOverrideBounds()); } - computeOverrideConfiguration(newConfig, mTmpRect, insetBounds, + computeOverrideConfiguration(newConfig, mTmpRect, mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom); } onOverrideConfigurationChanged(newConfig); @@ -1847,11 +1868,44 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont mService.mStackSupervisor.mLaunchParamsPersister.saveTask(this); } + /** + * Displayed bounds are used to set where the task is drawn at any given time. This is + * separate from its actual bounds so that the app doesn't see any meaningful configuration + * changes during transitionary periods. + */ + void setDisplayedBounds(Rect bounds) { + if (bounds == null) { + mDisplayedBounds.setEmpty(); + } else { + mDisplayedBounds.set(bounds); + } + final TaskWindowContainerController controller = getWindowContainerController(); + if (controller != null && controller.mContainer != null) { + controller.mContainer.setOverrideDisplayedBounds( + mDisplayedBounds.isEmpty() ? null : mDisplayedBounds); + } + } + + /** + * Gets the current overridden displayed bounds. These will be empty if the task is not + * currently overriding where it is displayed. + */ + Rect getDisplayedBounds() { + return mDisplayedBounds; + } + + /** + * @return {@code true} if this has overridden displayed bounds. + */ + boolean hasDisplayedBounds() { + return !mDisplayedBounds.isEmpty(); + } + /** Clears passed config and fills it with new override values. */ // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't // depend on task or stacks, but uses those object to get the display to base the calculation // on. Probably best to centralize calculations like this in ConfigurationContainer. - void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds, + void computeOverrideConfiguration(Configuration config, Rect bounds, boolean overrideWidth, boolean overrideHeight) { mTmpNonDecorBounds.set(bounds); mTmpStableBounds.set(bounds); @@ -1863,7 +1917,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont if (mStack != null) { final StackWindowController stackController = mStack.getWindowContainerController(); - stackController.adjustConfigurationForBounds(bounds, insetBounds, + stackController.adjustConfigurationForBounds(bounds, mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density, config, parentConfig, getWindowingMode()); } else { diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index b1f95f894490..b16e184c81af 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -184,9 +184,15 @@ public class TaskStack extends WindowContainer<Task> implements // Update bounds of containing tasks. for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) { final Task task = mChildren.get(taskNdx); - task.setBounds(taskBounds.get(task.mTaskId), false /* forced */); - task.setTempInsetBounds(taskTempInsetBounds != null ? - taskTempInsetBounds.get(task.mTaskId) : null); + final Rect insetBounds = + taskTempInsetBounds != null ? taskTempInsetBounds.get(task.mTaskId) : null; + if (insetBounds != null) { + task.setBounds(insetBounds); + task.setOverrideDisplayedBounds(taskBounds.get(task.mTaskId)); + } else { + task.setBounds(taskBounds.get(task.mTaskId)); + task.setOverrideDisplayedBounds(null); + } } return true; } @@ -739,7 +745,7 @@ public class TaskStack extends WindowContainer<Task> implements return; } - final Rect stackBounds = getBounds(); + final Rect stackBounds = getDisplayedBounds(); int width = stackBounds.width(); int height = stackBounds.height(); @@ -1754,14 +1760,6 @@ public class TaskStack extends WindowContainer<Task> implements scheduleAnimation(); } - @Override - void getRelativePosition(Point outPos) { - super.getRelativePosition(outPos); - final int outset = getStackOutset(); - outPos.x -= outset; - outPos.y -= outset; - } - AnimatingAppWindowTokenRegistry getAnimatingAppWindowTokenRegistry() { return mAnimatingAppWindowTokenRegistry; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 1275ca057e65..c30cc1736674 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1266,7 +1266,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return; } - getRelativePosition(mTmpPos); + getRelativeDisplayedPosition(mTmpPos); if (mTmpPos.equals(mLastSurfacePosition)) { return; } @@ -1275,12 +1275,22 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y); } - void getRelativePosition(Point outPos) { - final Rect bounds = getBounds(); - outPos.set(bounds.left, bounds.top); + /** + * Displayed bounds specify where to display this container at. It differs from bounds during + * certain operations (like animation or interactive dragging). + * + * @return the bounds to display this container at. + */ + Rect getDisplayedBounds() { + return getBounds(); + } + + void getRelativeDisplayedPosition(Point outPos) { + final Rect dispBounds = getDisplayedBounds(); + outPos.set(dispBounds.left, dispBounds.top); final WindowContainer parent = getParent(); if (parent != null) { - final Rect parentBounds = parent.getBounds(); + final Rect parentBounds = parent.getDisplayedBounds(); outPos.offset(-parentBounds.left, -parentBounds.top); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index cdf911881395..5cc36235ce75 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -790,6 +790,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } @Override + public Rect getDisplayedBounds() { + final Task task = getTask(); + if (task != null) { + Rect bounds = task.getOverrideDisplayedBounds(); + if (!bounds.isEmpty()) { + return bounds; + } + } + return super.getDisplayedBounds(); + } + + @Override public void computeFrameLw() { if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) { // This window is being replaced and either already got information that it's being @@ -805,16 +817,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean windowsAreFloating = task != null && task.isFloating(); final DisplayContent dc = getDisplayContent(); - // If the task has temp inset bounds set, we have to make sure all its windows uses - // the temp inset frame. Otherwise different display frames get applied to the main - // window and the child window, making them misaligned. - // Otherwise we need to clear the inset frame, to avoid using a stale frame after leaving - // multi window mode. - if (task != null && isInMultiWindowMode()) { - task.getTempInsetBounds(mInsetFrame); - } else { - mInsetFrame.setEmpty(); - } + mInsetFrame.set(getBounds()); // Denotes the actual frame used to calculate the insets and to perform the layout. When // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the @@ -834,7 +837,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP layoutXDiff = 0; layoutYDiff = 0; } else { - getBounds(mWindowFrames.mContainingFrame); + mWindowFrames.mContainingFrame.set(getDisplayedBounds()); if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { // If the bounds are frozen, we still want to translate the window freely and only @@ -884,14 +887,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP layoutDisplayFrame = new Rect(mWindowFrames.mDisplayFrame); mWindowFrames.mDisplayFrame.set(mWindowFrames.mContainingFrame); - layoutXDiff = - !mInsetFrame.isEmpty() ? mInsetFrame.left - mWindowFrames.mContainingFrame.left - : 0; - layoutYDiff = - !mInsetFrame.isEmpty() ? mInsetFrame.top - mWindowFrames.mContainingFrame.top - : 0; - layoutContainingFrame = - !mInsetFrame.isEmpty() ? mInsetFrame : mWindowFrames.mContainingFrame; + layoutXDiff = mInsetFrame.left - mWindowFrames.mContainingFrame.left; + layoutYDiff = mInsetFrame.top - mWindowFrames.mContainingFrame.top; + layoutContainingFrame = mInsetFrame; mTmpRect.set(0, 0, dc.getDisplayInfo().logicalWidth, dc.getDisplayInfo().logicalHeight); subtractInsets(mWindowFrames.mDisplayFrame, layoutContainingFrame, layoutDisplayFrame, mTmpRect); @@ -2176,9 +2174,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP getTouchableRegion(region); } - // The area containing the shadows is not touchable. - region.translate(mAttrs.surfaceInsets.left, mAttrs.surfaceInsets.top); - return flags; } @@ -2972,6 +2967,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } + void notifyInsetsControlChanged() { + final InsetsStateController stateController = + getDisplayContent().getInsetsStateController(); + try { + mClient.insetsControlChanged(stateController.getInsetsForDispatch(this), + stateController.getControlsForDispatch(this)); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to deliver inset state change", e); + } + } + Rect getBackdropFrame(Rect frame) { // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing // start even if we haven't received the relayout window, so that the client requests @@ -4603,7 +4609,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP outPoint.offset(-parent.mWindowFrames.mFrame.left + parent.mAttrs.surfaceInsets.left, -parent.mWindowFrames.mFrame.top + parent.mAttrs.surfaceInsets.top); } else if (parentWindowContainer != null) { - final Rect parentBounds = parentWindowContainer.getBounds(); + final Rect parentBounds = parentWindowContainer.getDisplayedBounds(); outPoint.offset(-parentBounds.left, -parentBounds.top); } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 8bc6db7fb9a7..fb5c556e1643 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1020,7 +1020,7 @@ class WindowStateAnimator { mTmpPos.x = 0; mTmpPos.y = 0; if (stack != null) { - stack.getRelativePosition(mTmpPos); + stack.getRelativeDisplayedPosition(mTmpPos); } xOffset = -mTmpPos.x; diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 8b873e3f9ad7..b85489a92464 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -2,8 +2,6 @@ cc_library_static { name: "libservices.core", defaults: ["libservices.core-libs"], - cpp_std: "c++17", - cflags: [ "-Wall", "-Werror", diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index b9dabb9ee7ec..65d32450b27f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -120,4 +120,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { int userHandle) { return false; } + + @Override + public List<String> getCrossProfileCalendarPackagesForUser(int userHandle) { + return Collections.emptyList(); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6fbb850e4e40..f68f4d7424f4 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -13426,10 +13426,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { enforceCrossUsersPermission(userHandle); synchronized (getLockObject()) { final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle); - if (admin != null && admin.mCrossProfileCalendarPackages != null) { + if (admin != null) { return admin.mCrossProfileCalendarPackages.contains(packageName); } } return false; } + + @Override + public List<String> getCrossProfileCalendarPackagesForUser(int userHandle) { + if (!mHasFeature) { + return Collections.emptyList(); + } + enforceCrossUsersPermission(userHandle); + synchronized (getLockObject()) { + final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle); + if (admin != null) { + return new ArrayList<String>(admin.mCrossProfileCalendarPackages); + } + } + return Collections.emptyList(); + } } diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java index 08fbf5549a87..14912c474995 100644 --- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java +++ b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java @@ -19,9 +19,9 @@ import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.os.IBinder; -import android.service.intelligence.IntelligenceService; import android.service.intelligence.InteractionContext; import android.service.intelligence.InteractionSessionId; +import android.service.intelligence.SmartSuggestionsService; import android.service.intelligence.SnapshotData; import android.util.Slog; import android.view.autofill.AutofillId; @@ -59,7 +59,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks mService = service; mId = Preconditions.checkNotNull(sessionId); mRemoteService = new RemoteIntelligenceService(context, - IntelligenceService.SERVICE_INTERFACE, serviceComponentName, userId, this, + SmartSuggestionsService.SERVICE_INTERFACE, serviceComponentName, userId, this, bindInstantServiceAllowed, verbose); mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags); } @@ -72,7 +72,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } /** - * Notifies the {@link IntelligenceService} that the service started. + * Notifies the {@link SmartSuggestionsService} that the service started. */ @GuardedBy("mLock") public void notifySessionStartedLocked() { @@ -80,14 +80,14 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } /** - * Notifies the {@link IntelligenceService} of a batch of events. + * Notifies the {@link SmartSuggestionsService} of a batch of events. */ public void sendEventsLocked(@NonNull List<ContentCaptureEvent> events) { mRemoteService.onContentCaptureEventsRequest(mId, events); } /** - * Notifies the {@link IntelligenceService} of a snapshot of an activity. + * Notifies the {@link SmartSuggestionsService} of a snapshot of an activity. */ @GuardedBy("mLock") public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) { @@ -110,7 +110,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks * Cleans up the session and removes it from the service. * * @param notifyRemoteService whether it should trigger a {@link - * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)} + * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)} * request. */ @GuardedBy("mLock") @@ -126,7 +126,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks * Cleans up the session, but not removes it from the service. * * @param notifyRemoteService whether it should trigger a {@link - * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)} + * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)} * request. */ @GuardedBy("mLock") @@ -146,7 +146,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } @Override // from RemoteScreenObservationServiceCallbacks - public void onServiceDied(AbstractRemoteService service) { + public void onServiceDied(AbstractRemoteService<?> service) { // TODO(b/111276913): implement (remove session from PerUserSession?) if (mService.isDebug()) { Slog.d(TAG, "onServiceDied() for " + mId); @@ -176,6 +176,10 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks pw.println(mAutofillCallback != null); } + String toShortString() { + return mId.getValue() + ":" + mActivityToken; + } + @Override public String toString() { return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]"; diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java index 9fd797d1e549..b8f2ad01d502 100644 --- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java +++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java @@ -16,7 +16,8 @@ package com.android.server.intelligence; -import static android.content.Context.INTELLIGENCE_MANAGER_SERVICE; +import static android.Manifest.permission.MANAGE_SMART_SUGGESTIONS; +import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -26,8 +27,13 @@ import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.IBinder; +import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.os.UserHandle; import android.os.UserManager; import android.service.intelligence.InteractionSessionId; +import android.util.Slog; import android.view.autofill.AutofillId; import android.view.autofill.IAutoFillManagerClient; import android.view.intelligence.ContentCaptureEvent; @@ -42,6 +48,7 @@ import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.List; /** @@ -50,11 +57,16 @@ import java.util.List; * <p>The data collected by this service can be analyzed and combined with other sources to provide * contextual data in other areas of the system such as Autofill. */ +//TODO(b/111276913): rename once the final name is defined public final class IntelligenceManagerService extends AbstractMasterSystemService<IntelligenceManagerService, IntelligencePerUserService> { private static final String TAG = "IntelligenceManagerService"; + static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; + + private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes + @GuardedBy("mLock") private ActivityManagerInternal mAm; @@ -65,12 +77,6 @@ public final class IntelligenceManagerService extends } @Override // from AbstractMasterSystemService - protected String getServiceSettingsProperty() { - // TODO(b/111276913): STOPSHIP temporary settings, until it's set by resourcs + cmd - return "intel_service"; - } - - @Override // from AbstractMasterSystemService protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled) { return new IntelligencePerUserService(this, mLock, resolvedUserId); @@ -78,7 +84,7 @@ public final class IntelligenceManagerService extends @Override // from SystemService public void onStart() { - publishBinderService(INTELLIGENCE_MANAGER_SERVICE, + publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE, new IntelligenceManagerServiceStub()); publishLocalService(IntelligenceManagerInternal.class, mLocalService); } @@ -89,6 +95,66 @@ public final class IntelligenceManagerService extends service.destroyLocked(); } + @Override // from AbstractMasterSystemService + protected void enforceCallingPermissionForManagement() { + getContext().enforceCallingPermission(MANAGE_SMART_SUGGESTIONS, TAG); + } + + @Override // from AbstractMasterSystemService + protected int getMaximumTemporaryServiceDurationMs() { + return MAX_TEMP_SERVICE_DURATION_MS; + } + + // Called by Shell command. + void destroySessions(@UserIdInt int userId, @NonNull IResultReceiver receiver) { + Slog.i(TAG, "destroySessions() for userId " + userId); + enforceCallingPermissionForManagement(); + + synchronized (mLock) { + if (userId != UserHandle.USER_ALL) { + final IntelligencePerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.destroySessionsLocked(); + } + } else { + visitServicesLocked((s) -> s.destroySessionsLocked()); + } + } + + try { + receiver.send(0, new Bundle()); + } catch (RemoteException e) { + // Just ignore it... + } + } + + // Called by Shell command. + void listSessions(int userId, IResultReceiver receiver) { + Slog.i(TAG, "listSessions() for userId " + userId); + enforceCallingPermissionForManagement(); + + final Bundle resultData = new Bundle(); + final ArrayList<String> sessions = new ArrayList<>(); + + synchronized (mLock) { + if (userId != UserHandle.USER_ALL) { + final IntelligencePerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.listSessionsLocked(sessions); + } + } else { + visitServicesLocked((s) -> s.listSessionsLocked(sessions)); + } + } + + resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); + try { + receiver.send(0, resultData); + } catch (RemoteException e) { + // Just ignore it... + } + } + private ActivityManagerInternal getAmInternal() { synchronized (mLock) { if (mAm == null) { @@ -118,7 +184,7 @@ public final class IntelligenceManagerService extends synchronized (mLock) { final IntelligencePerUserService service = getServiceForUserLocked(userId); service.startSessionLocked(activityToken, componentName, taskId, displayId, - sessionId, flags, result); + sessionId, flags, mAllowInstantService, result); } } @@ -153,6 +219,14 @@ public final class IntelligenceManagerService extends dumpLocked("", pw); } } + + @Override + public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, + String[] args, ShellCallback callback, ResultReceiver resultReceiver) + throws RemoteException { + new IntelligenceServiceShellCommand(IntelligenceManagerService.this).exec( + this, in, out, err, args, callback, resultReceiver); + } } private final class LocalService extends IntelligenceManagerInternal { diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java index 9ab7e58feb9b..6f047c51633a 100644 --- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java +++ b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java @@ -36,12 +36,13 @@ import android.os.IBinder; import android.os.RemoteException; import android.service.intelligence.InteractionSessionId; import android.service.intelligence.SnapshotData; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; import android.view.autofill.AutofillId; import android.view.autofill.IAutoFillManagerClient; import android.view.intelligence.ContentCaptureEvent; -import android.view.intelligence.IntelligenceManager; +import android.view.intelligence.ContentCaptureManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.IResultReceiver; @@ -49,11 +50,13 @@ import com.android.server.AbstractPerUserSystemService; import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.List; /** * Per-user instance of {@link IntelligenceManagerService}. */ +//TODO(b/111276913): rename once the final name is defined final class IntelligencePerUserService extends AbstractPerUserSystemService<IntelligencePerUserService, IntelligenceManagerService> { @@ -75,35 +78,56 @@ final class IntelligencePerUserService protected ServiceInfo newServiceInfo(@NonNull ComponentName serviceComponent) throws NameNotFoundException { + int flags = PackageManager.GET_META_DATA; + final boolean isTemp = isTemporaryServiceSetLocked(); + if (!isTemp) { + flags |= PackageManager.MATCH_SYSTEM_ONLY; + } + ServiceInfo si; try { - // TODO(b/111276913): must check that either the service is from a system component, - // or it matches a service set by shell cmd (so it can be used on CTS tests and when - // OEMs are implementing the real service - si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, - PackageManager.GET_META_DATA, mUserId); + si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags, mUserId); } catch (RemoteException e) { Slog.w(TAG, "Could not get service for " + serviceComponent + ": " + e); return null; } - if (!Manifest.permission.BIND_INTELLIGENCE_SERVICE.equals(si.permission)) { - Slog.w(TAG, "IntelligenceService from '" + si.packageName + if (si == null) { + Slog.w(TAG, "Could not get serviceInfo for " + (isTemp ? " (temp)" : "(default system)") + + " " + serviceComponent.flattenToShortString()); + return null; + } + if (!Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE.equals(si.permission)) { + Slog.w(TAG, "SmartSuggestionsService from '" + si.packageName + "' does not require permission " - + Manifest.permission.BIND_INTELLIGENCE_SERVICE); + + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE); throw new SecurityException("Service does not require permission " - + Manifest.permission.BIND_INTELLIGENCE_SERVICE); + + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE); } return si; } + @Override // from PerUserSystemService + @GuardedBy("mLock") + protected boolean updateLocked(boolean disabled) { + destroyLocked(); + return super.updateLocked(disabled); + } + + @Override // from PerUserSystemService + protected String getDefaultComponentName() { + final String name = getContext() + .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService); + return TextUtils.isEmpty(name) ? null : name; + } + // TODO(b/111276913): log metrics @GuardedBy("mLock") public void startSessionLocked(@NonNull IBinder activityToken, @NonNull ComponentName componentName, int taskId, int displayId, - @NonNull InteractionSessionId sessionId, int flags, + @NonNull InteractionSessionId sessionId, int flags, boolean bindInstantServiceAllowed, @NonNull IResultReceiver resultReceiver) { if (!isEnabledLocked()) { - sendToClient(resultReceiver, IntelligenceManager.STATE_DISABLED); + sendToClient(resultReceiver, ContentCaptureManager.STATE_DISABLED); return; } final ComponentName serviceComponentName = getServiceComponentName(); @@ -126,13 +150,10 @@ final class IntelligencePerUserService // TODO(b/111276913): check if local ids match and decide what to do if they don't // TODO(b/111276913): should we call session.notifySessionStartedLocked() again?? // if not, move notifySessionStartedLocked() into session constructor - sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE); + sendToClient(resultReceiver, ContentCaptureManager.STATE_ACTIVE); return; } - // TODO(b/117779333): get from mMaster once it's moved to superclass - final boolean bindInstantServiceAllowed = false; - session = new ContentCaptureSession(getContext(), mUserId, mLock, activityToken, this, serviceComponentName, componentName, taskId, displayId, sessionId, flags, bindInstantServiceAllowed, mMaster.verbose); @@ -142,7 +163,7 @@ final class IntelligencePerUserService } mSessions.put(sessionId, session); session.notifySessionStartedLocked(); - sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE); + sendToClient(resultReceiver, ContentCaptureManager.STATE_ACTIVE); } // TODO(b/111276913): log metrics @@ -192,7 +213,7 @@ final class IntelligencePerUserService return; } if (mMaster.verbose) { - Slog.v(TAG, "sendEvents(): id=" + sessionId + "; events =" + events.size()); + Slog.v(TAG, "sendEvents(): id=" + sessionId + ", events=" + events.size()); } session.sendEventsLocked(events); } @@ -245,6 +266,11 @@ final class IntelligencePerUserService @GuardedBy("mLock") public void destroyLocked() { if (mMaster.debug) Slog.d(TAG, "destroyLocked()"); + destroySessionsLocked(); + } + + @GuardedBy("mLock") + void destroySessionsLocked() { final int numSessions = mSessions.size(); for (int i = 0; i < numSessions; i++) { final ContentCaptureSession session = mSessions.valueAt(i); @@ -253,6 +279,15 @@ final class IntelligencePerUserService mSessions.clear(); } + @GuardedBy("mLock") + void listSessionsLocked(ArrayList<String> output) { + final int numSessions = mSessions.size(); + for (int i = 0; i < numSessions; i++) { + final ContentCaptureSession session = mSessions.valueAt(i); + output.add(session.toShortString()); + } + } + public AugmentedAutofillCallback requestAutofill(@NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken, int autofillSessionId, @NonNull AutofillId focusedId) { synchronized (mLock) { diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java new file mode 100644 index 000000000000..0d92a972aa96 --- /dev/null +++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.intelligence; + +import static com.android.server.intelligence.IntelligenceManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS; + +import android.annotation.NonNull; +import android.os.Bundle; +import android.os.ShellCommand; +import android.os.UserHandle; + +import com.android.internal.os.IResultReceiver; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Shell Command implementation for {@link IntelligenceManagerService}. + */ +//TODO(b/111276913): rename once the final name is defined +public final class IntelligenceServiceShellCommand extends ShellCommand { + + private final IntelligenceManagerService mService; + + public IntelligenceServiceShellCommand(@NonNull IntelligenceManagerService service) { + mService = service; + } + + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + final PrintWriter pw = getOutPrintWriter(); + switch (cmd) { + case "list": + return requestList(pw); + case "destroy": + return requestDestroy(pw); + case "get": + return requestGet(pw); + case "set": + return requestSet(pw); + default: + return handleDefaultCommands(cmd); + } + } + + @Override + public void onHelp() { + try (PrintWriter pw = getOutPrintWriter();) { + // TODO(b/111276913): rename "intelligence" once SELinux rule changed + pw.println("Intelligence Service (intelligence) commands:"); + pw.println(" help"); + pw.println(" Prints this help text."); + pw.println(""); + pw.println(" get bind-instant-service-allowed"); + pw.println(" Gets whether binding to services provided by instant apps is allowed"); + pw.println(""); + pw.println(" set bind-instant-service-allowed [true | false]"); + pw.println(" Sets whether binding to services provided by instant apps is allowed"); + pw.println(""); + pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]"); + pw.println(" Temporarily (for DURATION ms) changes the service implemtation."); + pw.println(" To reset, call with just the USER_ID argument."); + pw.println(""); + pw.println(" list sessions [--user USER_ID]"); + pw.println(" Lists all pending sessions."); + pw.println(""); + pw.println(" destroy sessions [--user USER_ID]"); + pw.println(" Destroys all pending sessions."); + pw.println(""); + } + } + + private int requestGet(PrintWriter pw) { + final String what = getNextArgRequired(); + switch(what) { + case "bind-instant-service-allowed": + return getBindInstantService(pw); + default: + pw.println("Invalid set: " + what); + return -1; + } + } + + private int requestSet(PrintWriter pw) { + final String what = getNextArgRequired(); + + switch(what) { + case "bind-instant-service-allowed": + return setBindInstantService(pw); + case "temporary-service": + return setTemporaryService(); + default: + pw.println("Invalid set: " + what); + return -1; + } + } + + private int getBindInstantService(PrintWriter pw) { + if (mService.getAllowInstantService()) { + pw.println("true"); + } else { + pw.println("false"); + } + return 0; + } + + private int setBindInstantService(PrintWriter pw) { + final String mode = getNextArgRequired(); + switch (mode.toLowerCase()) { + case "true": + mService.setAllowInstantService(true); + return 0; + case "false": + mService.setAllowInstantService(false); + return 0; + default: + pw.println("Invalid mode: " + mode); + return -1; + } + } + + private int setTemporaryService() { + final int userId = getNextIntArgRequired(); + final String serviceName = getNextArg(); + if (serviceName == null) { + mService.resetTemporaryService(userId); + return 0; + } + final int duration = getNextIntArgRequired(); + mService.setTemporaryService(userId, serviceName, duration); + return 0; + } + + private int requestDestroy(PrintWriter pw) { + if (!isNextArgSessions(pw)) { + return -1; + } + + final int userId = getUserIdFromArgsOrAllUsers(); + final CountDownLatch latch = new CountDownLatch(1); + final IResultReceiver receiver = new IResultReceiver.Stub() { + @Override + public void send(int resultCode, Bundle resultData) { + latch.countDown(); + } + }; + return requestSessionCommon(pw, latch, () -> mService.destroySessions(userId, receiver)); + } + + private int requestList(PrintWriter pw) { + if (!isNextArgSessions(pw)) { + return -1; + } + + final int userId = getUserIdFromArgsOrAllUsers(); + final CountDownLatch latch = new CountDownLatch(1); + final IResultReceiver receiver = new IResultReceiver.Stub() { + @Override + public void send(int resultCode, Bundle resultData) { + final ArrayList<String> sessions = resultData + .getStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS); + for (String session : sessions) { + pw.println(session); + } + latch.countDown(); + } + }; + return requestSessionCommon(pw, latch, () -> mService.listSessions(userId, receiver)); + } + + private boolean isNextArgSessions(PrintWriter pw) { + final String type = getNextArgRequired(); + if (!type.equals("sessions")) { + pw.println("Error: invalid list type"); + return false; + } + return true; + } + + private int requestSessionCommon(PrintWriter pw, CountDownLatch latch, + Runnable command) { + command.run(); + return waitForLatch(pw, latch); + } + + private int waitForLatch(PrintWriter pw, CountDownLatch latch) { + try { + final boolean received = latch.await(5, TimeUnit.SECONDS); + if (!received) { + pw.println("Timed out after 5 seconds"); + return -1; + } + } catch (InterruptedException e) { + pw.println("System call interrupted"); + Thread.currentThread().interrupt(); + return -1; + } + return 0; + } + + private int getUserIdFromArgsOrAllUsers() { + if ("--user".equals(getNextArg())) { + return UserHandle.parseUserArg(getNextArgRequired()); + } + return UserHandle.USER_ALL; + } + + private int getNextIntArgRequired() { + return Integer.parseInt(getNextArgRequired()); + } +} diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java index 00c5b6a1d67b..d9f4f20dc971 100644 --- a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java +++ b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.IInterface; import android.os.RemoteException; +import android.service.intelligence.ContentCaptureEventsRequest; import android.service.intelligence.IIntelligenceService; import android.service.intelligence.InteractionContext; import android.service.intelligence.InteractionSessionId; @@ -35,11 +36,13 @@ import android.view.autofill.IAutoFillManagerClient; import android.view.intelligence.ContentCaptureEvent; import com.android.internal.os.IResultReceiver; -import com.android.server.AbstractRemoteService; +import com.android.server.AbstractMultiplePendingRequestsRemoteService; import java.util.List; -final class RemoteIntelligenceService extends AbstractRemoteService { +//TODO(b/111276913): rename once the final name is defined +final class RemoteIntelligenceService + extends AbstractMultiplePendingRequestsRemoteService<RemoteIntelligenceService> { private static final String TAG = "RemoteIntelligenceService"; @@ -54,7 +57,7 @@ final class RemoteIntelligenceService extends AbstractRemoteService { RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed, boolean verbose) { super(context, serviceInterface, componentName, userId, callbacks, - bindInstantServiceAllowed, verbose); + bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2); mCallbacks = callbacks; } @@ -194,7 +197,8 @@ final class RemoteIntelligenceService extends AbstractRemoteService { @Override // from MyPendingRequest public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException { - remoteService.mService.onContentCaptureEvents(mSessionId, mEvents); + remoteService.mService.onContentCaptureEventsRequest(mSessionId, + new ContentCaptureEventsRequest(mEvents)); } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 56f7cff565af..05ff6601a477 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -22,6 +22,7 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.view.Display.DEFAULT_DISPLAY; +import android.annotation.NonNull; import android.app.ActivityThread; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; @@ -55,6 +56,9 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.storage.IStorageManager; +import android.provider.Settings; +import android.sysprop.VoldProperties; +import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; @@ -120,6 +124,7 @@ import com.android.server.restrictions.RestrictionsManagerService; import com.android.server.role.RoleManagerService; import com.android.server.security.KeyAttestationApplicationIdProviderService; import com.android.server.security.KeyChainSystemService; +import com.android.server.signedconfig.SignedConfigService; import com.android.server.soundtrigger.SoundTriggerService; import com.android.server.stats.StatsCompanionService; import com.android.server.statusbar.StatusBarManagerService; @@ -654,7 +659,7 @@ public final class SystemServer { traceEnd(); // Only run "core" apps if we're encrypting the device. - String cryptState = SystemProperties.get("vold.decrypt"); + String cryptState = VoldProperties.decrypt().orElse(""); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; @@ -796,10 +801,6 @@ public final class SystemServer { boolean disableSystemTextClassifier = SystemProperties.getBoolean( "config.disable_systemtextclassifier", false); - //TODO(b/111276913): temporarily disabled until the manager is properly implemented to - // ignore events when disabled and buffer when enabled - boolean disableIntelligence = SystemProperties.getBoolean( - "config.disable_intelligence", true); boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false); boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice", @@ -994,6 +995,11 @@ public final class SystemServer { traceBeginAndSlog("PinnerService"); mSystemServiceManager.startService(PinnerService.class); traceEnd(); + + traceBeginAndSlog("SignedConfigService"); + SignedConfigService.registerUpdateReceiver(mSystemContext); + traceEnd(); + } catch (RuntimeException e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service", e); @@ -1130,13 +1136,7 @@ public final class SystemServer { traceEnd(); } - if (!disableIntelligence) { - traceBeginAndSlog("StartIntelligenceService"); - mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS); - traceEnd(); - } else { - Slog.d(TAG, "IntelligenceService disabled"); - } + startIntelligenceService(context); // NOTE: ClipboardService indirectly depends on IntelligenceService traceBeginAndSlog("StartClipboardService"); @@ -1503,6 +1503,14 @@ public final class SystemServer { } traceEnd(); + traceBeginAndSlog("RuntimeService"); + try { + ServiceManager.addService("runtime", new RuntimeService(context)); + } catch (Throwable e) { + reportWtf("starting RuntimeService", e); + } + traceEnd(); + // timezone.RulesManagerService will prevent a device starting up if the chain of trust // required for safe time zone updates might be broken. RuleManagerService cannot do // this check when mOnlyCore == true, so we don't enable the service in this case. @@ -2092,6 +2100,37 @@ public final class SystemServer { }, BOOT_TIMINGS_TRACE_LOG); } + private void startIntelligenceService(@NonNull Context context) { + + // First check if it was explicitly enabled by Settings + boolean explicitlySupported = false; + final String settings = Settings.Global.getString(context.getContentResolver(), + Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED); + if (settings != null) { + explicitlySupported = Boolean.parseBoolean(settings); + if (explicitlySupported) { + Slog.d(TAG, "IntelligenceService explicitly enabled by Settings"); + } else { + Slog.d(TAG, "IntelligenceService explicitly disabled by Settings"); + return; + } + } + + // Then check if OEM overlaid the resource that defines the service. + if (!explicitlySupported) { + final String serviceName = context + .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService); + if (TextUtils.isEmpty(serviceName)) { + Slog.d(TAG, "IntelligenceService disabled because config resource is not overlaid"); + return; + } + } + + traceBeginAndSlog("StartIntelligenceService"); + mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS); + traceEnd(); + } + static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 746c4530a5e1..cf4d3a8070f9 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -66,6 +66,7 @@ <uses-permission android:name="android.permission.SUSPEND_APPS"/> <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/> <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/> + <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> <!-- Uses API introduced in O (26) --> <uses-sdk android:minSdkVersion="1" diff --git a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java index 81107cf2ef4f..2a78b6f6ca24 100644 --- a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java @@ -17,9 +17,10 @@ package com.android.server; -import static org.mockito.Mockito.when; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + import android.content.Context; import android.content.Intent; import android.os.BatteryManager; @@ -134,4 +135,44 @@ public class CachedDeviceStateServiceTest { mContext.sendBroadcast(intentUnplugged); assertThat(deviceState.isCharging()).isFalse(); } + + @Test + public void correctlyTracksTimeOnBattery() throws Exception { + CachedDeviceStateService service = new CachedDeviceStateService(mContext); + when(mBatteryManager.getPlugType()).thenReturn(OsProtoEnums.BATTERY_PLUGGED_NONE); + + service.onStart(); + CachedDeviceState.Readonly deviceState = + LocalServices.getService(CachedDeviceState.Readonly.class); + + CachedDeviceState.TimeInStateStopwatch stopwatch = + deviceState.createTimeOnBatteryStopwatch(); + + // State can be initialized correctly only after PHASE_SYSTEM_SERVICES_READY. + assertThat(stopwatch.isRunning()).isFalse(); + service.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); + + assertThat(stopwatch.isRunning()).isTrue(); + stopwatch.reset(); + + Thread.sleep(100); + assertThat(stopwatch.isRunning()).isTrue(); + assertThat(stopwatch.getMillis()).isAtLeast(100L); + + long timeOnBatteryBeforePluggedIn = stopwatch.getMillis(); + Intent intentPluggedIn = new Intent(Intent.ACTION_BATTERY_CHANGED); + intentPluggedIn.putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC); + mContext.sendBroadcast(intentPluggedIn); + + assertThat(stopwatch.getMillis()).isAtLeast(timeOnBatteryBeforePluggedIn); + assertThat(stopwatch.isRunning()).isFalse(); + + long timeOnBatteryAfterPluggedIn = stopwatch.getMillis(); + Thread.sleep(20); + assertThat(stopwatch.getMillis()).isEqualTo(timeOnBatteryAfterPluggedIn); + + stopwatch.reset(); + assertThat(stopwatch.getMillis()).isEqualTo(0L); + assertThat(stopwatch.isRunning()).isFalse(); + } } diff --git a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java index 53711a623704..e0ecd3ee24f0 100644 --- a/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java @@ -35,6 +35,7 @@ import android.test.mock.MockContentResolver; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.R; import com.android.internal.app.ColorDisplayController; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; @@ -911,7 +912,11 @@ public class ColorDisplayServiceTest { startService(); assertAccessibilityTransformActivated(true /* activated */ ); assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL); - assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + if (isColorModeValid(ColorDisplayController.COLOR_MODE_SATURATED)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + } else if (isColorModeValid(ColorDisplayController.COLOR_MODE_AUTOMATIC)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_AUTOMATIC); + } } @Test @@ -926,7 +931,11 @@ public class ColorDisplayServiceTest { startService(); assertAccessibilityTransformActivated(true /* activated */ ); assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL); - assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + if (isColorModeValid(ColorDisplayController.COLOR_MODE_SATURATED)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + } else if (isColorModeValid(ColorDisplayController.COLOR_MODE_AUTOMATIC)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_AUTOMATIC); + } } @Test @@ -942,7 +951,11 @@ public class ColorDisplayServiceTest { startService(); assertAccessibilityTransformActivated(true /* activated */ ); assertUserColorMode(ColorDisplayController.COLOR_MODE_NATURAL); - assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + if (isColorModeValid(ColorDisplayController.COLOR_MODE_SATURATED)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_SATURATED); + } else if (isColorModeValid(ColorDisplayController.COLOR_MODE_AUTOMATIC)) { + assertActiveColorMode(ColorDisplayController.COLOR_MODE_AUTOMATIC); + } } @Test @@ -1030,6 +1043,24 @@ public class ColorDisplayServiceTest { } /** + * Returns whether the color mode is valid on the device the tests are running on. + * + * @param mode the mode to check + */ + private boolean isColorModeValid(int mode) { + final int[] availableColorModes = mContext.getResources().getIntArray( + R.array.config_availableColorModes); + if (availableColorModes != null) { + for (int availableMode : availableColorModes) { + if (mode == availableMode) { + return true; + } + } + } + return false; + } + + /** * Convenience method to start {@link #mColorDisplayService}. */ private void startService() { @@ -1038,7 +1069,6 @@ public class ColorDisplayServiceTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { - mColorDisplayService.onStart(); mColorDisplayService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); mColorDisplayService.onStartUser(mUserId); } diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java index 7cf7df1343af..c1963da3b3af 100644 --- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java @@ -268,10 +268,10 @@ public class ThermalManagerServiceTest { @Test public void testGetCurrentStatus() throws RemoteException { - int status = Temperature.THROTTLING_WARNING; + int status = Temperature.THROTTLING_EMERGENCY; Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status); mFakeHal.mCallback.onValues(newSkin); - assertEquals(status, mService.mService.getCurrentStatus()); + assertEquals(status, mService.mService.getCurrentThermalStatus()); } @Test @@ -294,6 +294,6 @@ public class ThermalManagerServiceTest { assertEquals(0, mService.mService.getCurrentTemperatures().size()); assertEquals(0, mService.mService.getCurrentTemperaturesWithType(Temperature.TYPE_SKIN).size()); - assertEquals(Temperature.THROTTLING_NONE, mService.mService.getCurrentStatus()); + assertEquals(Temperature.THROTTLING_NONE, mService.mService.getCurrentThermalStatus()); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 9da204fe3c02..41d5a1c2fac4 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -456,6 +456,31 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { } @Test + public void testNoBeepForImportanceDefaultInAutomotive() throws Exception { + mService.setIsAutomotive(true); + + NotificationRecord r = getBeepyNotification(); + r.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT); + + mService.buzzBeepBlinkLocked(r); + + verifyNeverBeep(); + assertFalse(r.isInterruptive()); + } + + @Test + public void testBeepForImportanceHighInAutomotive() throws Exception { + mService.setIsAutomotive(true); + + NotificationRecord r = getBeepyNotification(); + + mService.buzzBeepBlinkLocked(r); + + verifyBeepLooped(); + assertTrue(r.isInterruptive()); + } + + @Test public void testNoInterruptionForMin() throws Exception { NotificationRecord r = getBeepyNotification(); r.setSystemImportance(NotificationManager.IMPORTANCE_MIN); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index b94f472965ab..845a09f44b82 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -95,308 +95,340 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } @Test - public void layoutWindowLw_appDrawsBars() { + public void addingWindow_doesNotTamperWithSysuiFlags() { mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + assertEquals(0, mWindow.mAttrs.systemUiVisibility); + assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility); } @Test - public void layoutWindowLw_appWontDrawBars() { - mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT); + public void layoutWindowLw_appDrawsBars() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + } } @Test - public void layoutWindowLw_appWontDrawBars_forceStatus() throws Exception { - mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; - mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT); + public void layoutWindowLw_appWontDrawBars() { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT); + } } @Test - public void addingWindow_doesNotTamperWithSysuiFlags() { - mWindow.mAttrs.flags |= FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; - addWindow(mWindow); - - assertEquals(0, mWindow.mAttrs.systemUiVisibility); - assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility); + public void layoutWindowLw_appWontDrawBars_forceStatus() throws Exception { + synchronized (mWm.mGlobalLock) { + mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT); + } } @Test public void layoutWindowLw_withDisplayCutout() { - addDisplayCutout(); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); - addWindow(mWindow); + addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_never() { - addDisplayCutout(); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); - mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; - addWindow(mWindow); + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; + addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); + assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_layoutFullscreen() { - addDisplayCutout(); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); - mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - addWindow(mWindow); + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_fullscreen() { - addDisplayCutout(); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); - mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; - addWindow(mWindow); + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; + addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); + assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_fullscreenInCutout() { - addDisplayCutout(); - - mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; - mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); + + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN; + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_landscape() { - addDisplayCutout(); - setRotation(ROTATION_90); - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrameLw(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); + setRotation(ROTATION_90); + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getContentFrameLw(), + DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_seascape() { - addDisplayCutout(); - setRotation(ROTATION_270); - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetBy(mWindow.getParentFrame(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); - assertInsetBy(mWindow.getStableFrameLw(), NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); - assertInsetBy(mWindow.getContentFrameLw(), - NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); + setRotation(ROTATION_270); + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); + assertInsetBy(mWindow.getStableFrameLw(), NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); + assertInsetBy(mWindow.getContentFrameLw(), + NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_fullscreen_landscape() { - addDisplayCutout(); - setRotation(ROTATION_90); - - mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrameLw(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); + setRotation(ROTATION_90); + + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getContentFrameLw(), + DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + } } @Test public void layoutWindowLw_withDisplayCutout_floatingInScreen() { - addDisplayCutout(); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); - mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN; - mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY; - mWindow.mAttrs.width = DISPLAY_WIDTH; - mWindow.mAttrs.height = DISPLAY_HEIGHT; - addWindow(mWindow); + mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN; + mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY; + mWindow.mAttrs.width = DISPLAY_WIDTH; + mWindow.mAttrs.height = DISPLAY_HEIGHT; + addWindow(mWindow); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); + assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); + } } @Test public void layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape() { - addDisplayCutout(); - setRotation(ROTATION_90); - - mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; - addWindow(mWindow); - - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - - assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrameLw(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + synchronized (mWm.mGlobalLock) { + addDisplayCutout(); + setRotation(ROTATION_90); + + mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getContentFrameLw(), + DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + } } @Test public void layoutHint_appWindow() { - // Initialize DisplayFrames - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - - final Rect outFrame = new Rect(); - final Rect outContentInsets = new Rect(); - final Rect outStableInsets = new Rect(); - final Rect outOutsets = new Rect(); - final DisplayCutout.ParcelableWrapper outDisplayCutout = - new DisplayCutout.ParcelableWrapper(); - - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, null, mFrames, - false /* floatingStack */, outFrame, outContentInsets, outStableInsets, outOutsets, - outDisplayCutout); - - assertThat(outFrame, is(mFrames.mUnrestricted)); - assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); - assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); - assertThat(outOutsets, is(new Rect())); - assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + synchronized (mWm.mGlobalLock) { + // Initialize DisplayFrames + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + + final Rect outFrame = new Rect(); + final Rect outContentInsets = new Rect(); + final Rect outStableInsets = new Rect(); + final Rect outOutsets = new Rect(); + final DisplayCutout.ParcelableWrapper outDisplayCutout = + new DisplayCutout.ParcelableWrapper(); + + mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, null, mFrames, + false /* floatingStack */, outFrame, outContentInsets, outStableInsets, + outOutsets, outDisplayCutout); + + assertThat(outFrame, is(mFrames.mUnrestricted)); + assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); + assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); + assertThat(outOutsets, is(new Rect())); + assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + } } @Test public void layoutHint_appWindowInTask() { - // Initialize DisplayFrames - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - - final Rect taskBounds = new Rect(100, 100, 200, 200); - - final Rect outFrame = new Rect(); - final Rect outContentInsets = new Rect(); - final Rect outStableInsets = new Rect(); - final Rect outOutsets = new Rect(); - final DisplayCutout.ParcelableWrapper outDisplayCutout = - new DisplayCutout.ParcelableWrapper(); - - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, - false /* floatingStack */, outFrame, outContentInsets, outStableInsets, outOutsets, - outDisplayCutout); - - assertThat(outFrame, is(taskBounds)); - assertThat(outContentInsets, is(new Rect())); - assertThat(outStableInsets, is(new Rect())); - assertThat(outOutsets, is(new Rect())); - assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + synchronized (mWm.mGlobalLock) { + // Initialize DisplayFrames + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + + final Rect taskBounds = new Rect(100, 100, 200, 200); + + final Rect outFrame = new Rect(); + final Rect outContentInsets = new Rect(); + final Rect outStableInsets = new Rect(); + final Rect outOutsets = new Rect(); + final DisplayCutout.ParcelableWrapper outDisplayCutout = + new DisplayCutout.ParcelableWrapper(); + + mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, + false /* floatingStack */, outFrame, outContentInsets, outStableInsets, + outOutsets, outDisplayCutout); + + assertThat(outFrame, is(taskBounds)); + assertThat(outContentInsets, is(new Rect())); + assertThat(outStableInsets, is(new Rect())); + assertThat(outOutsets, is(new Rect())); + assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + } } @Test public void layoutHint_appWindowInTask_outsideContentFrame() { - // Initialize DisplayFrames - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - - // Task is in the nav bar area (usually does not happen, but this is similar enough to the - // possible overlap with the IME) - final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1, - 200, mFrames.mContent.bottom + 10); - - final Rect outFrame = new Rect(); - final Rect outContentInsets = new Rect(); - final Rect outStableInsets = new Rect(); - final Rect outOutsets = new Rect(); - final DisplayCutout.ParcelableWrapper outDisplayCutout = - new DisplayCutout.ParcelableWrapper(); - - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, - true /* floatingStack */, outFrame, outContentInsets, outStableInsets, outOutsets, - outDisplayCutout); - - assertThat(outFrame, is(taskBounds)); - assertThat(outContentInsets, is(new Rect())); - assertThat(outStableInsets, is(new Rect())); - assertThat(outOutsets, is(new Rect())); - assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + synchronized (mWm.mGlobalLock) { + // Initialize DisplayFrames + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + + // Task is in the nav bar area (usually does not happen, but this is similar enough to + // the possible overlap with the IME) + final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1, + 200, mFrames.mContent.bottom + 10); + + final Rect outFrame = new Rect(); + final Rect outContentInsets = new Rect(); + final Rect outStableInsets = new Rect(); + final Rect outOutsets = new Rect(); + final DisplayCutout.ParcelableWrapper outDisplayCutout = + new DisplayCutout.ParcelableWrapper(); + + mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, + true /* floatingStack */, outFrame, outContentInsets, outStableInsets, + outOutsets, outDisplayCutout); + + assertThat(outFrame, is(taskBounds)); + assertThat(outContentInsets, is(new Rect())); + assertThat(outStableInsets, is(new Rect())); + assertThat(outOutsets, is(new Rect())); + assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper())); + } } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java index c11e606386e6..8821544903c1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java @@ -29,6 +29,7 @@ import android.view.InsetsSource; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; +import org.junit.Before; import org.junit.Test; @SmallTest @@ -36,8 +37,15 @@ import org.junit.Test; @Presubmit public class InsetsSourceProviderTest extends WindowTestsBase { - private InsetsSourceProvider mProvider = new InsetsSourceProvider( - new InsetsSource(TYPE_TOP_BAR)); + private InsetsSource mSource = new InsetsSource(TYPE_TOP_BAR); + private InsetsSourceProvider mProvider; + + @Before + public void setUp() throws Exception { + mSource.setVisible(true); + mProvider = new InsetsSourceProvider(mSource, + mDisplayContent.getInsetsStateController(), mDisplayContent); + } @Test public void testPostLayout() { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 331622ce22a5..11526a85aafb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -23,8 +23,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import android.platform.test.annotations.Presubmit; +import android.view.InsetsSourceControl; import android.view.InsetsState; import androidx.test.filters.FlakyTest; @@ -41,12 +43,9 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testStripForDispatch_notOwn() { final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow"); - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR) - .setWindow(topBar, null); - topBar.setInsetProvider( - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)); - assertNotNull(mDisplayContent.getInsetsStateController().getInsetsForDispatch(app) - .getSource(TYPE_TOP_BAR)); + getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null); + topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR)); + assertNotNull(getController().getInsetsForDispatch(app).getSource(TYPE_TOP_BAR)); } @Test @@ -54,10 +53,8 @@ public class InsetsStateControllerTest extends WindowTestsBase { final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR) .setWindow(topBar, null); - topBar.setInsetProvider( - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)); - assertEquals(new InsetsState(), - mDisplayContent.getInsetsStateController().getInsetsForDispatch(topBar)); + topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR)); + assertEquals(new InsetsState(), getController().getInsetsForDispatch(topBar)); } @Test @@ -65,13 +62,47 @@ public class InsetsStateControllerTest extends WindowTestsBase { final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); final WindowState ime = createWindow(null, TYPE_APPLICATION, "parentWindow"); - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR) - .setWindow(topBar, null); - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_NAVIGATION_BAR) - .setWindow(navBar, null); - mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_IME) - .setWindow(ime, null); - assertEquals(new InsetsState(), - mDisplayContent.getInsetsStateController().getInsetsForDispatch(navBar)); + getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null); + getController().getSourceProvider(TYPE_NAVIGATION_BAR).setWindow(navBar, null); + getController().getSourceProvider(TYPE_IME).setWindow(ime, null); + assertEquals(new InsetsState(), getController().getInsetsForDispatch(navBar)); + } + + @Test + public void testBarControllingWinChanged() { + final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); + final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); + final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow"); + getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null); + getController().getSourceProvider(TYPE_NAVIGATION_BAR).setWindow(navBar, null); + getController().onBarControllingWindowChanged(app); + InsetsSourceControl[] controls = getController().getControlsForDispatch(app); + assertEquals(2, controls.length); + } + + @Test + public void testControlRevoked() { + final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); + final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow"); + getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null); + getController().onBarControllingWindowChanged(app); + assertNotNull(getController().getControlsForDispatch(app)); + getController().onBarControllingWindowChanged(null); + assertNull(getController().getControlsForDispatch(app)); + } + + @Test + public void testControlRevoked_animation() { + final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow"); + final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow"); + getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null); + getController().onBarControllingWindowChanged(app); + assertNotNull(getController().getControlsForDispatch(app)); + topBar.cancelAnimation(); + assertNull(getController().getControlsForDispatch(app)); + } + + private InsetsStateController getController() { + return mDisplayContent.getInsetsStateController(); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index 432af0d7a469..29738ff2a63d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -24,6 +24,7 @@ import android.util.MergedConfiguration; import android.view.DisplayCutout; import android.view.DragEvent; import android.view.IWindow; +import android.view.InsetsSourceControl; import android.view.InsetsState; import com.android.internal.os.IResultReceiver; @@ -40,11 +41,17 @@ public class TestIWindow extends IWindow.Stub { Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId, DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException { } + @Override public void insetsChanged(InsetsState insetsState) throws RemoteException { } @Override + public void insetsControlChanged(InsetsState insetsState, InsetsSourceControl[] activeControls) + throws RemoteException { + } + + @Override public void moved(int newX, int newY) throws RemoteException { } 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 3643457f061f..885a7e02199b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java @@ -231,7 +231,7 @@ public class WindowConfigurationTests extends WindowTestsBase { final Configuration config = new Configuration(); final WindowConfiguration winConfig = config.windowConfiguration; - stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/, + stackController.adjustConfigurationForBounds(bounds, new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/, false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig, windowingMode); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java index b3e90debc84b..60a8aeb5fcc6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java @@ -76,7 +76,7 @@ public class WindowFrameTests extends WindowTestsBase { private static class TaskWithBounds extends Task { final Rect mBounds; - final Rect mInsetBounds = new Rect(); + final Rect mOverrideDisplayedBounds = new Rect(); boolean mFullscreenForTest = true; TaskWithBounds(TaskStack stack, WindowManagerService wm, Rect bounds) { @@ -100,8 +100,8 @@ public class WindowFrameTests extends WindowTestsBase { outBounds.set(mBounds); } @Override - void getTempInsetBounds(Rect outBounds) { - outBounds.set(mInsetBounds); + Rect getOverrideDisplayedBounds() { + return mOverrideDisplayedBounds; } @Override boolean isFullscreen() { @@ -343,14 +343,14 @@ public class WindowFrameTests extends WindowTestsBase { taskBottom - contentInsetBottom)); pf.set(0, 0, logicalWidth, logicalHeight); - // However if we set temp inset bounds, the insets will be computed - // as if our window was laid out there, but it will be laid out according to - // the task bounds. + // If we set displayed bounds, the insets will be computed with the main task bounds + // but the frame will be positioned according to the displayed bounds. final int insetLeft = logicalWidth / 5; final int insetTop = logicalHeight / 5; final int insetRight = insetLeft + (taskRight - taskLeft); final int insetBottom = insetTop + (taskBottom - taskTop); - task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom); + task.mOverrideDisplayedBounds.set(taskBounds); + task.mBounds.set(insetLeft, insetTop, insetRight, insetBottom); windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect); w.computeFrameLw(); assertFrame(w, taskLeft, taskTop, taskRight, taskBottom); @@ -430,7 +430,6 @@ public class WindowFrameTests extends WindowTestsBase { final int taskBottom = logicalHeight / 4 * 3; final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom); final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, taskBounds); - task.mInsetBounds.set(taskLeft, taskTop, taskRight, taskBottom); task.mFullscreenForTest = false; WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT); w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; @@ -486,12 +485,12 @@ public class WindowFrameTests extends WindowTestsBase { } @Test - public void testDisplayCutout_tempInsetBounds() { + public void testDisplayCutout_tempDisplayedBounds() { // Regular fullscreen task and window final TaskWithBounds task = new TaskWithBounds(mStubStack, mWm, - new Rect(0, -500, 1000, 1500)); + new Rect(0, 0, 1000, 2000)); task.mFullscreenForTest = false; - task.mInsetBounds.set(0, 0, 1000, 2000); + task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500)); WindowState w = createWindow(task, MATCH_PARENT, MATCH_PARENT); w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java index 4a99172160f5..266d88493b9e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java @@ -173,21 +173,21 @@ public class WindowManagerServiceRule implements TestRule { }; } - public WindowManagerService getWindowManagerService() { + WindowManagerService getWindowManagerService() { return mService; } - public TestWindowManagerPolicy getWindowManagerPolicy() { - return mPolicy; - } - - public void waitUntilWindowManagerHandlersIdle() { + void waitUntilWindowManagerHandlersIdle() { final WindowManagerService wm = getWindowManagerService(); - if (wm != null) { - wm.mH.runWithScissors(() -> { }, 0); - wm.mAnimationHandler.runWithScissors(() -> { }, 0); - SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0); + if (wm == null) { + return; } + wm.mH.removeCallbacksAndMessages(null); + wm.mAnimationHandler.removeCallbacksAndMessages(null); + SurfaceAnimationThread.getHandler().removeCallbacksAndMessages(null); + wm.mH.runWithScissors(() -> { }, 0); + wm.mAnimationHandler.runWithScissors(() -> { }, 0); + SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0); } private void destroyAllSurfaceTransactions() { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java index a1b0411afcde..aa0ecf8447f3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java @@ -28,6 +28,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.WindowContainer.POSITION_TOP; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; @@ -117,11 +120,11 @@ public class WindowTestUtils { // many components rely on the {@link StackWindowController#adjustConfigurationForBounds} // to properly set bounds values in the configuration. We must mimick those actions here. doAnswer((InvocationOnMock invocationOnMock) -> { - final Configuration config = invocationOnMock.<Configuration>getArgument(7); + final Configuration config = invocationOnMock.<Configuration>getArgument(6); final Rect bounds = invocationOnMock.<Rect>getArgument(0); config.windowConfiguration.setBounds(bounds); return null; - }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(), + }).when(controller).adjustConfigurationForBounds(any(), any(), any(), anyBoolean(), anyBoolean(), anyFloat(), any(), any(), anyInt()); return controller; diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp index 0c40a6b5fa84..de40e0df48e7 100644 --- a/startop/view_compiler/Android.bp +++ b/startop/view_compiler/Android.bp @@ -24,7 +24,6 @@ cc_defaults { "libdexfile", "slicer", ], - cppflags: ["-std=c++17"], } cc_library_host_static { diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index cef998651cfe..d617de0af6a1 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -29,7 +29,6 @@ import android.os.ParcelFileDescriptor; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.lang.String; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.charset.StandardCharsets; @@ -908,10 +907,16 @@ public final class Call { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[pa: "); + sb.append("[id: "); + sb.append(mTelecomCallId); + sb.append(", pa: "); sb.append(mAccountHandle); sb.append(", hdl: "); - sb.append(Log.pii(mHandle)); + sb.append(Log.piiHandle(mHandle)); + sb.append(", hdlPres: "); + sb.append(mHandlePresentation); + sb.append(", videoState: "); + sb.append(VideoProfile.videoStateToString(mVideoState)); sb.append(", caps: "); sb.append(capabilitiesToString(mCallCapabilities)); sb.append(", props: "); diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java index 7db69407ad3d..662874316a7f 100644 --- a/telecomm/java/android/telecom/CallScreeningService.java +++ b/telecomm/java/android/telecom/CallScreeningService.java @@ -27,8 +27,8 @@ import android.os.Message; import android.os.RemoteException; import com.android.internal.os.SomeArgs; -import com.android.internal.telecom.ICallScreeningService; import com.android.internal.telecom.ICallScreeningAdapter; +import com.android.internal.telecom.ICallScreeningService; /** * This service can be implemented by the default dialer (see @@ -147,7 +147,7 @@ public abstract class CallScreeningService extends Service { private boolean mShouldSkipCallLog; private boolean mShouldSkipNotification; - /* + /** * Sets whether the incoming call should be blocked. */ public Builder setDisallowCall(boolean shouldDisallowCall) { @@ -155,7 +155,7 @@ public abstract class CallScreeningService extends Service { return this; } - /* + /** * Sets whether the incoming call should be disconnected as if the user had manually * rejected it. This property should only be set to true if the call is disallowed. */ @@ -164,16 +164,20 @@ public abstract class CallScreeningService extends Service { return this; } - /* + /** * Sets whether the incoming call should not be displayed in the call log. This property * should only be set to true if the call is disallowed. + * <p> + * Note: Calls will still be logged with type + * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}, regardless of how this property + * is set. */ public Builder setSkipCallLog(boolean shouldSkipCallLog) { mShouldSkipCallLog = shouldSkipCallLog; return this; } - /* + /** * Sets whether a missed call notification should not be shown for the incoming call. * This property should only be set to true if the call is disallowed. */ @@ -211,6 +215,17 @@ public abstract class CallScreeningService extends Service { * Called when a new incoming call is added. * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)} * should be called to allow or disallow the call. + * <p> + * Note: The {@link Call.Details} instance provided to a call screening service will only have + * the following properties set. The rest of the {@link Call.Details} properties will be set to + * their default value or {@code null}. + * <ul> + * <li>{@link Call.Details#getState()}</li> + * <li>{@link Call.Details#getConnectTimeMillis()}</li> + * <li>{@link Call.Details#getCreationTimeMillis()}</li> + * <li>{@link Call.Details#getHandle()}</li> + * <li>{@link Call.Details#getHandlePresentation()}</li> + * </ul> * * @param callDetails Information about a new incoming call, see {@link Call.Details}. */ diff --git a/telephony/OWNERS b/telephony/OWNERS index 054288b85ba6..2236cba498aa 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -13,3 +13,4 @@ satk@google.com shuoq@google.com refuhoo@google.com paulye@google.com +nazaninb@google.com
\ No newline at end of file diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.aidl b/telephony/java/android/telephony/AvailableNetworkInfo.aidl new file mode 100644 index 000000000000..1d4378c502a3 --- /dev/null +++ b/telephony/java/android/telephony/AvailableNetworkInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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.telephony; + +parcelable AvailableNetworkInfo; diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java new file mode 100644 index 000000000000..fe07370394ad --- /dev/null +++ b/telephony/java/android/telephony/AvailableNetworkInfo.java @@ -0,0 +1,168 @@ +/* + * 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.telephony; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * Defines available network information which includes corresponding subscription id, + * network plmns and corresponding priority to be used for network selection by Alternative Network + * Service. + */ +public final class AvailableNetworkInfo implements Parcelable { + + /* + * Defines number of priority level high. + */ + public static final int PRIORITY_HIGH = 1; + + /* + * Defines number of priority level medium. + */ + public static final int PRIORITY_MED = 2; + + /* + * Defines number of priority level low. + */ + public static final int PRIORITY_LOW = 3; + + /** + * subscription Id of the available network. This value must be one of the entry retrieved from + * {@link SubscriptionManager#getOpportunisticSubscriptions} + */ + private int mSubId; + + /** + * Priority for the subscription id. + * Priorities are in the range of 1 to 3 where 1 + * has the highest priority. + */ + private int mPriority; + + /** + * Describes the List of PLMN ids (MCC-MNC) associated with mSubId. + * If this entry is left empty, then the platform software will not scan the network + * to revalidate the input. + */ + private ArrayList<String> mMccMncs; + + /** + * Return subscription Id of the available network. + * This value must be one of the entry retrieved from + * {@link SubscriptionManager#getOpportunisticSubscriptions} + * @return subscription id + */ + public int getSubId() { + return mSubId; + } + + /** + * Return priority for the subscription id. Valid value will be within + * [{@link AvailableNetworkInfo#PRIORITY_HIGH}, {@link AvailableNetworkInfo#PRIORITY_LOW}] + * @return priority level + */ + public int getPriority() { + return mPriority; + } + + /** + * Return List of PLMN ids (MCC-MNC) associated with the sub ID. + * If this entry is left empty, then the platform software will not scan the network + * to revalidate the input. + * @return list of PLMN ids + */ + public List<String> getMccMncs() { + return (List<String>) mMccMncs.clone(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSubId); + dest.writeInt(mPriority); + dest.writeStringList(mMccMncs); + } + + private AvailableNetworkInfo(Parcel in) { + mSubId = in.readInt(); + mPriority = in.readInt(); + in.readStringList(mMccMncs); + } + + public AvailableNetworkInfo(int subId, int priority, ArrayList<String> mccMncs) { + mSubId = subId; + mPriority = priority; + mMccMncs = new ArrayList<String>(mccMncs); + } + + @Override + public boolean equals(Object o) { + AvailableNetworkInfo ani; + + try { + ani = (AvailableNetworkInfo) o; + } catch (ClassCastException ex) { + return false; + } + + if (o == null) { + return false; + } + + return (mSubId == ani.mSubId + && mPriority == ani.mPriority + && (((mMccMncs != null) + && mMccMncs.equals(ani.mMccMncs)))); + } + + @Override + public int hashCode() { + return Objects.hash(mSubId, mPriority, mMccMncs); + } + + public static final Parcelable.Creator<AvailableNetworkInfo> CREATOR = + new Creator<AvailableNetworkInfo>() { + @Override + public AvailableNetworkInfo createFromParcel(Parcel in) { + return new AvailableNetworkInfo(in); + } + + @Override + public AvailableNetworkInfo[] newArray(int size) { + return new AvailableNetworkInfo[size]; + } + }; + + @Override + public String toString() { + return ("AvailableNetworkInfo:" + + " mSubId: " + mSubId + + " mPriority: " + mPriority + + " mMccMncs: " + Arrays.toString(mMccMncs.toArray())); + } +} + diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 185c886e4c49..62cead17ac54 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1154,20 +1154,33 @@ public class CarrierConfigManager { */ public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string"; - /** - * The Component Name of a carrier-provided CallScreeningService implementation. Telecom will - * bind to {@link android.telecom.CallScreeningService} for ALL incoming calls and provide - * the carrier - * CallScreeningService with the opportunity to allow or block calls. - * <p> - * The String includes the package name/the class name. - * Example: - * <item>com.android.carrier/com.android.carrier.callscreeningserviceimpl</item> - * <p> - * Using {@link ComponentName#flattenToString()} to convert a ComponentName object to String. - * Using {@link ComponentName#unflattenFromString(String)} to convert a String object to a - * ComponentName. - */ + /** + * String to override sim country iso. + * Sim country iso is based on sim MCC which is coarse and doesn't work with dual IMSI SIM where + * a SIM can have multiple MCC from different countries. + * Instead, each sim carrier should have a single country code, apply per carrier based iso + * code as an override. The overridden value can be read from + * {@link TelephonyManager#getSimCountryIso()} and {@link SubscriptionInfo#getCountryIso()} + * + * @hide + */ + public static final String KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING = + "sim_country_iso_override_string"; + + /** + * The Component Name of a carrier-provided CallScreeningService implementation. Telecom will + * bind to {@link android.telecom.CallScreeningService} for ALL incoming calls and provide + * the carrier + * CallScreeningService with the opportunity to allow or block calls. + * <p> + * The String includes the package name/the class name. + * Example: + * <item>com.android.carrier/com.android.carrier.callscreeningserviceimpl</item> + * <p> + * Using {@link ComponentName#flattenToString()} to convert a ComponentName object to String. + * Using {@link ComponentName#unflattenFromString(String)} to convert a String object to a + * ComponentName. + */ public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app"; /** @@ -2533,6 +2546,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false); sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false); sDefaults.putString(KEY_CARRIER_NAME_STRING, ""); + sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, ""); sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false); sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, ""); diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java index b6e6cbae8c26..5d809d0b7c36 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java @@ -33,17 +33,31 @@ public class DataSpecificRegistrationStates implements Parcelable{ */ public final boolean isNrAvailable; + /** + * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving + * cell. + * + * True the primary serving cell is LTE cell and the plmn-InfoList-r15 is present in SIB2 and + * at least one bit in this list is true, otherwise this value should be false. + * + * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks. + */ + public final boolean isEnDcAvailable; + DataSpecificRegistrationStates( - int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) { + int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, + boolean isEnDcAvailable) { this.maxDataCalls = maxDataCalls; this.isDcNrRestricted = isDcNrRestricted; this.isNrAvailable = isNrAvailable; + this.isEnDcAvailable = isEnDcAvailable; } private DataSpecificRegistrationStates(Parcel source) { maxDataCalls = source.readInt(); isDcNrRestricted = source.readBoolean(); isNrAvailable = source.readBoolean(); + isEnDcAvailable = source.readBoolean(); } @Override @@ -51,6 +65,7 @@ public class DataSpecificRegistrationStates implements Parcelable{ dest.writeInt(maxDataCalls); dest.writeBoolean(isDcNrRestricted); dest.writeBoolean(isNrAvailable); + dest.writeBoolean(isEnDcAvailable); } @Override @@ -65,13 +80,14 @@ public class DataSpecificRegistrationStates implements Parcelable{ .append(" maxDataCalls = " + maxDataCalls) .append(" isDcNrRestricted = " + isDcNrRestricted) .append(" isNrAvailable = " + isNrAvailable) + .append(" isEnDcAvailable = " + isEnDcAvailable) .append(" }") .toString(); } @Override public int hashCode() { - return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable); + return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable); } @Override @@ -83,7 +99,8 @@ public class DataSpecificRegistrationStates implements Parcelable{ DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o; return this.maxDataCalls == other.maxDataCalls && this.isDcNrRestricted == other.isDcNrRestricted - && this.isNrAvailable == other.isNrAvailable; + && this.isNrAvailable == other.isNrAvailable + && this.isEnDcAvailable == other.isEnDcAvailable; } public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR = diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java index aee744fac20c..b00665e26ff2 100644 --- a/telephony/java/android/telephony/NetworkRegistrationState.java +++ b/telephony/java/android/telephony/NetworkRegistrationState.java @@ -219,12 +219,13 @@ public class NetworkRegistrationState implements Parcelable { public NetworkRegistrationState(int domain, int transportType, int regState, int accessNetworkTechnology, int rejectCause, boolean emergencyOnly, int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls, - boolean isDcNrRestricted, boolean isNrAvailable) { + boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable) { this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly, availableServices, cellIdentity); mDataSpecificStates = new DataSpecificRegistrationStates( - maxDataCalls, isDcNrRestricted, isNrAvailable); + maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable); + updateNrStatus(mDataSpecificStates); } protected NetworkRegistrationState(Parcel source) { @@ -448,6 +449,34 @@ public class NetworkRegistrationState implements Parcelable { dest.writeInt(mNrStatus); } + /** + * Use the 5G NR Non-Standalone indicators from the network registration state to update the + * NR status. There are 3 indicators in the network registration state: + * + * 1. if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving cell. + * 2. if NR is supported by the selected PLMN. + * 3. if the use of dual connectivity with NR is restricted. + * + * The network has 5G NR capability if E-UTRA-NR Dual Connectivity is supported by the primary + * serving cell. + * + * The use of NR 5G is not restricted If the network has 5G NR capability and both the use of + * DCNR is not restricted and NR is supported by the selected PLMN. Otherwise the use of 5G + * NR is restricted. + * + * @param state data specific registration state contains the 5G NR indicators. + */ + private void updateNrStatus(DataSpecificRegistrationStates state) { + mNrStatus = NR_STATUS_NONE; + if (state.isEnDcAvailable) { + if (!state.isDcNrRestricted && state.isNrAvailable) { + mNrStatus = NR_STATUS_NOT_RESTRICTED; + } else { + mNrStatus = NR_STATUS_RESTRICTED; + } + } + } + public static final Parcelable.Creator<NetworkRegistrationState> CREATOR = new Parcelable.Creator<NetworkRegistrationState>() { @Override diff --git a/telephony/java/android/telephony/NumberVerificationCallback.java b/telephony/java/android/telephony/NumberVerificationCallback.java new file mode 100644 index 000000000000..b00c57351589 --- /dev/null +++ b/telephony/java/android/telephony/NumberVerificationCallback.java @@ -0,0 +1,88 @@ +/* + * 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.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; + +/** + * A callback for number verification. After a request for number verification is received, + * the system will call {@link #onCallReceived(String)} if a phone call was received from a number + * matching the provided {@link PhoneNumberRange} or it will call {@link #onVerificationFailed(int)} + * if an error occurs. + * @hide + */ +@SystemApi +public interface NumberVerificationCallback { + /** @hide */ + @IntDef(value = {REASON_UNSPECIFIED, REASON_TIMED_OUT, REASON_NETWORK_NOT_AVAILABLE, + REASON_TOO_MANY_CALLS, REASON_CONCURRENT_REQUESTS, REASON_IN_ECBM, + REASON_IN_EMERGENCY_CALL}, + prefix = {"REASON_"}) + @interface NumberVerificationFailureReason {} + + /** + * Verification failed for an unspecified reason. + */ + int REASON_UNSPECIFIED = 0; + + /** + * Verification failed because no phone call was received from a matching number within the + * provided timeout. + */ + int REASON_TIMED_OUT = 1; + + /** + * Verification failed because no cellular voice network is available. + */ + int REASON_NETWORK_NOT_AVAILABLE = 2; + + /** + * Verification failed because there are currently too many ongoing phone calls for a new + * incoming phone call to be received. + */ + int REASON_TOO_MANY_CALLS = 3; + + /** + * Verification failed because a previous request for verification has not yet completed. + */ + int REASON_CONCURRENT_REQUESTS = 4; + + /** + * Verification failed because the phone is in emergency callback mode. + */ + int REASON_IN_ECBM = 5; + + /** + * Verification failed because the phone is currently in an emergency call. + */ + int REASON_IN_EMERGENCY_CALL = 6; + + /** + * Called when the device receives a phone call from the provided {@link PhoneNumberRange}. + * @param phoneNumber The phone number within the range that called. May or may not contain the + * country code, but will be entirely numeric. + */ + default void onCallReceived(@NonNull String phoneNumber) { } + + /** + * Called when verification fails for some reason. + * @param reason The reason for failure. + */ + default void onVerificationFailed(@NumberVerificationFailureReason int reason) { } +} diff --git a/telephony/java/android/telephony/PhoneNumberRange.aidl b/telephony/java/android/telephony/PhoneNumberRange.aidl new file mode 100644 index 000000000000..b0727be50e0b --- /dev/null +++ b/telephony/java/android/telephony/PhoneNumberRange.aidl @@ -0,0 +1,19 @@ +/* + * 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 android.telephony; + +parcelable PhoneNumberRange; diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java new file mode 100644 index 000000000000..d65156fd3ca2 --- /dev/null +++ b/telephony/java/android/telephony/PhoneNumberRange.java @@ -0,0 +1,176 @@ +/* + * 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.telephony; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.util.Objects; +import java.util.regex.Pattern; + +/** + * This class is used to represent a range of phone numbers. Each range corresponds to a contiguous + * block of phone numbers. + * + * Example: + * {@code + * { + * mCountryCode = "1" + * mPrefix = "650555" + * mLowerBound = "0055" + * mUpperBound = "0899" + * } + * } + * would match 16505550089 and 6505550472, but not 63827593759 or 16505550900 + * @hide + */ +@SystemApi +public final class PhoneNumberRange implements Parcelable { + public static final Creator<PhoneNumberRange> CREATOR = new Creator<PhoneNumberRange>() { + @Override + public PhoneNumberRange createFromParcel(Parcel in) { + return new PhoneNumberRange(in); + } + + @Override + public PhoneNumberRange[] newArray(int size) { + return new PhoneNumberRange[size]; + } + }; + + private final String mCountryCode; + private final String mPrefix; + private final String mLowerBound; + private final String mUpperBound; + + /** + * @param countryCode The country code, omitting the leading "+" + * @param prefix A prefix that all numbers matching the range must have. + * @param lowerBound When concatenated with the prefix, represents the lower bound of phone + * numbers that match this range. + * @param upperBound When concatenated with the prefix, represents the upper bound of phone + * numbers that match this range. + */ + public PhoneNumberRange(@NonNull String countryCode, @NonNull String prefix, + @NonNull String lowerBound, @NonNull String upperBound) { + validateLowerAndUpperBounds(lowerBound, upperBound); + if (!Pattern.matches("[0-9]+", countryCode)) { + throw new IllegalArgumentException("Country code must be all numeric"); + } + if (!Pattern.matches("[0-9]+", prefix)) { + throw new IllegalArgumentException("Prefix must be all numeric"); + } + mCountryCode = countryCode; + mPrefix = prefix; + mLowerBound = lowerBound; + mUpperBound = upperBound; + } + + private PhoneNumberRange(Parcel in) { + mCountryCode = in.readStringNoHelper(); + mPrefix = in.readStringNoHelper(); + mLowerBound = in.readStringNoHelper(); + mUpperBound = in.readStringNoHelper(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeStringNoHelper(mCountryCode); + dest.writeStringNoHelper(mPrefix); + dest.writeStringNoHelper(mLowerBound); + dest.writeStringNoHelper(mUpperBound); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PhoneNumberRange that = (PhoneNumberRange) o; + return Objects.equals(mCountryCode, that.mCountryCode) + && Objects.equals(mPrefix, that.mPrefix) + && Objects.equals(mLowerBound, that.mLowerBound) + && Objects.equals(mUpperBound, that.mUpperBound); + } + + @Override + public int hashCode() { + return Objects.hash(mCountryCode, mPrefix, mLowerBound, mUpperBound); + } + + @Override + public String toString() { + return "PhoneNumberRange{" + + "mCountryCode='" + mCountryCode + '\'' + + ", mPrefix='" + mPrefix + '\'' + + ", mLowerBound='" + mLowerBound + '\'' + + ", mUpperBound='" + mUpperBound + '\'' + + '}'; + } + + private void validateLowerAndUpperBounds(String lowerBound, String upperBound) { + if (lowerBound.length() != upperBound.length()) { + throw new IllegalArgumentException("Lower and upper bounds must have the same length"); + } + if (!Pattern.matches("[0-9]+", lowerBound)) { + throw new IllegalArgumentException("Lower bound must be all numeric"); + } + if (!Pattern.matches("[0-9]+", upperBound)) { + throw new IllegalArgumentException("Upper bound must be all numeric"); + } + if (Integer.parseInt(lowerBound) > Integer.parseInt(upperBound)) { + throw new IllegalArgumentException("Lower bound must be lower than upper bound"); + } + } + + /** + * Checks to see if the provided phone number matches this range. + * @param number A phone number, with or without separators or a country code. + * @return {@code true} if the number matches, {@code false} otherwise. + */ + public boolean matches(String number) { + // Check the prefix, make sure it matches either with or without the country code. + String normalizedNumber = number.replaceAll("[^0-9]", ""); + String prefixWithCountryCode = mCountryCode + mPrefix; + String numberPostfix; + if (normalizedNumber.startsWith(prefixWithCountryCode)) { + numberPostfix = normalizedNumber.substring(prefixWithCountryCode.length()); + } else if (normalizedNumber.startsWith(mPrefix)) { + numberPostfix = normalizedNumber.substring(mPrefix.length()); + } else { + return false; + } + + // Next check the postfix to make sure it lies within the bounds. + try { + int lower = Integer.parseInt(mLowerBound); + int upper = Integer.parseInt(mUpperBound); + int numberToCheck = Integer.parseInt(numberPostfix); + return numberToCheck <= upper && numberToCheck >= lower; + } catch (NumberFormatException e) { + Log.e(PhoneNumberRange.class.getSimpleName(), "Invalid bounds or number.", e); + return false; + } + } +} diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 13fbeaaa02b7..ca0c854a1a75 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -118,6 +118,13 @@ public class ServiceState implements Parcelable { */ public static final int FREQUENCY_RANGE_MMWAVE = 4; + private static final List<Integer> FREQUENCY_RANGE_ORDER = Arrays.asList( + FREQUENCY_RANGE_UNKNOWN, + FREQUENCY_RANGE_LOW, + FREQUENCY_RANGE_MID, + FREQUENCY_RANGE_HIGH, + FREQUENCY_RANGE_MMWAVE); + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "DUPLEX_MODE_", @@ -1835,4 +1842,13 @@ public class ServiceState implements Parcelable { mNetworkRegistrationStates.add(regState); } } + + /** + * @hide + */ + public static final int getBetterNRFrequencyRange(int range1, int range2) { + return FREQUENCY_RANGE_ORDER.indexOf(range1) > FREQUENCY_RANGE_ORDER.indexOf(range2) + ? range1 + : range2; + } } diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index b41e14e09554..bacfe61a1a10 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -150,6 +150,11 @@ public class SubscriptionInfo implements Parcelable { private String mGroupUUID; /** + * A property in opportunistic subscription to indicate whether it is metered or not. + */ + private boolean mIsMetered; + + /** * @hide */ public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, @@ -158,7 +163,7 @@ public class SubscriptionInfo implements Parcelable { @Nullable UiccAccessRule[] accessRules, String cardId) { this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId, - false, null); + false, null, true); } /** @@ -168,7 +173,7 @@ public class SubscriptionInfo implements Parcelable { CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic, - @Nullable String groupUUID) { + @Nullable String groupUUID, boolean isMetered) { this.mId = id; this.mIccId = iccId; this.mSimSlotIndex = simSlotIndex; @@ -187,8 +192,10 @@ public class SubscriptionInfo implements Parcelable { this.mCardId = cardId; this.mIsOpportunistic = isOpportunistic; this.mGroupUUID = groupUUID; + this.mIsMetered = isMetered; } + /** * @return the subscription ID. */ @@ -403,6 +410,18 @@ public class SubscriptionInfo implements Parcelable { } /** + * Used in opportunistic subscription ({@link #isOpportunistic()}) to indicate whether it's + * metered or not.This is one of the factors when deciding to switch to the subscription. + * (a non-metered subscription, for example, would likely be preferred over a metered one). + * + * @return whether subscription is metered. + * @hide + */ + public boolean isMetered() { + return mIsMetered; + } + + /** * Checks whether the app with the given context is authorized to manage this subscription * according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} * returns true). @@ -496,10 +515,11 @@ public class SubscriptionInfo implements Parcelable { String cardId = source.readString(); boolean isOpportunistic = source.readBoolean(); String groupUUID = source.readString(); + boolean isMetered = source.readBoolean(); return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, - isEmbedded, accessRules, cardId, isOpportunistic, groupUUID); + isEmbedded, accessRules, cardId, isOpportunistic, groupUUID, isMetered); } @Override @@ -528,6 +548,7 @@ public class SubscriptionInfo implements Parcelable { dest.writeString(mCardId); dest.writeBoolean(mIsOpportunistic); dest.writeString(mGroupUUID); + dest.writeBoolean(mIsMetered); } @Override @@ -561,14 +582,14 @@ public class SubscriptionInfo implements Parcelable { + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded + " accessRules " + Arrays.toString(mAccessRules) + " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic - + " mGroupUUID=" + mGroupUUID + "}"; + + " mGroupUUID=" + mGroupUUID + " isMetered=" + mIsMetered + "}"; } @Override public int hashCode() { return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded, - mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, - mCardId, mDisplayName, mCarrierName, mAccessRules); + mIsOpportunistic, mGroupUUID, mIsMetered, mIccId, mNumber, mMcc, mMnc, + mCountryIso, mCardId, mDisplayName, mCarrierName, mAccessRules); } @Override @@ -591,6 +612,7 @@ public class SubscriptionInfo implements Parcelable { && mIsEmbedded == toCompare.mIsEmbedded && mIsOpportunistic == toCompare.mIsOpportunistic && Objects.equals(mGroupUUID, toCompare.mGroupUUID) + && mIsMetered == toCompare.mIsMetered && Objects.equals(mIccId, toCompare.mIccId) && Objects.equals(mNumber, toCompare.mNumber) && Objects.equals(mMcc, toCompare.mMcc) diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 45cfe1e303ec..2a01ac4b8df2 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -407,6 +407,13 @@ public class SubscriptionManager { public static final String MNC = "mnc"; /** + * TelephonyProvider column name for the iso country code associated with a SIM. + * <P>Type: TEXT (String)</P> + * @hide + */ + public static final String ISO_COUNTRY_CODE = "iso_country_code"; + + /** * TelephonyProvider column name for the sim provisioning status associated with a SIM. * <P>Type: INTEGER (int)</P> * @hide @@ -576,7 +583,12 @@ public class SubscriptionManager { * @hide */ public static final String GROUP_UUID = "group_uuid"; - + /** + * TelephonyProvider column name for whether a subscription is metered or not, that is, whether + * the network it connects to charges for subscription or not. For example, paid CBRS or unpaid. + * @hide + */ + public static final String IS_METERED = "is_metered"; /** * Broadcast Action: The user has changed one of the default subs related to * data, phone calls, or sms</p> @@ -2403,6 +2415,21 @@ public class SubscriptionManager { return groupUUID; } + /** + * Set metered by simInfo index + * + * @param isMetered whether it’s a metered subscription. + * @param subId the unique SubscriptionInfo index in database + * @return the number of records updated + * @hide + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public int setMetered(boolean isMetered, int subId) { + if (VDBG) logd("[setIsMetered]+ isMetered:" + isMetered + " subId:" + subId); + return setSubscriptionPropertyHelper(subId, "setIsMetered", + (iSub)-> iSub.setMetered(isMetered, subId)); + } + private interface CallISubMethodHelper { int callMethod(ISub iSub) throws RemoteException; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index d54da0905e18..45d914e0dfdd 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -77,6 +77,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.ITelecomService; import com.android.internal.telephony.CellNetworkScanResult; import com.android.internal.telephony.IAns; +import com.android.internal.telephony.INumberVerificationCallback; import com.android.internal.telephony.IPhoneSubInfo; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.ITelephonyRegistry; @@ -1341,6 +1342,13 @@ public class TelephonyManager { */ public static final String EXTRA_RECOVERY_ACTION = "recoveryAction"; + /** + * The max value for the timeout passed in {@link #requestNumberVerification}. + * @hide + */ + @SystemApi + public static final long MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS = 60000; + // // // Device Info @@ -5372,7 +5380,7 @@ public class TelephonyManager { /** * Rollback modem configurations to factory default except some config which are in whitelist. - * Used for device configuration by some CDMA operators. + * Used for device configuration by some carriers. * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling @@ -5399,7 +5407,7 @@ public class TelephonyManager { } /** - * Generate a radio modem reset. Used for device configuration by some CDMA operators. + * Generate a radio modem reset. Used for device configuration by some carriers. * * <p>Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling @@ -5503,6 +5511,52 @@ public class TelephonyManager { } /** + * Request that the next incoming call from a number matching {@code range} be intercepted. + * + * This API is intended for OEMs to provide a service for apps to verify the device's phone + * number. When called, the Telephony stack will store the provided {@link PhoneNumberRange} and + * intercept the next incoming call from a number that lies within the range, within a timeout + * specified by {@code timeoutMillis}. + * + * If such a phone call is received, the caller will be notified via + * {@link NumberVerificationCallback#onCallReceived(String)} on the provided {@link Executor}. + * If verification fails for any reason, the caller will be notified via + * {@link NumberVerificationCallback#onVerificationFailed(int)} + * on the provided {@link Executor}. + * + * In addition to the {@link Manifest.permission#MODIFY_PHONE_STATE} permission, callers of this + * API must also be listed in the device configuration as an authorized app in + * {@code packages/services/Telephony/res/values/config.xml} under the + * {@code config_number_verification_package_name} key. + * + * @hide + * @param range The range of phone numbers the caller expects a phone call from. + * @param timeoutMillis The amount of time to wait for such a call, or + * {@link #MAX_NUMBER_VERIFICATION_TIMEOUT_MILLIS}, whichever is lesser. + * @param executor The {@link Executor} that callbacks should be executed on. + * @param callback The callback to use for delivering results. + */ + @SystemApi + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void requestNumberVerification(@NonNull PhoneNumberRange range, long timeoutMillis, + @NonNull @CallbackExecutor Executor executor, + @NonNull NumberVerificationCallback callback) { + INumberVerificationCallback internalCallback = new INumberVerificationCallback.Stub() { + @Override + public void onCallReceived(String phoneNumber) throws RemoteException { + Binder.withCleanCallingIdentity(() -> callback.onCallReceived(phoneNumber)); + } + + @Override + public void onVerificationFailed(int reason) throws RemoteException { + Binder.withCleanCallingIdentity(() -> callback.onVerificationFailed(reason)); + } + }; + + // TODO -- call the aidl method + } + + /** * Sets a per-phone telephony property with the value specified. * * @hide @@ -9533,4 +9587,34 @@ public class TelephonyManager { } return subId; } + + /** + * Update availability of a list of networks in the current location. + * + * This api should be called to inform AlternativeNetwork Service about the availability + * of a network at the current location. This information will be used by AlternativeNetwork + * service to decide to attach to the network opportunistically. If an empty list is passed, + * it is assumed that no network is available. + * Requires that the calling app has carrier privileges on both primary and + * secondary subscriptions (see {@link #hasCarrierPrivileges}), or has permission + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * @param availableNetworks is a list of available network information. + * @return true if request is accepted + * + */ + @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + public boolean updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks) { + String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; + boolean ret = false; + try { + IAns iAlternativeNetworkService = getIAns(); + if (iAlternativeNetworkService != null) { + ret = iAlternativeNetworkService.updateAvailableNetworks(availableNetworks, + pkgForDebug); + } + } catch (RemoteException ex) { + Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex); + } + return ret; + } } diff --git a/telephony/java/com/android/internal/telephony/IAns.aidl b/telephony/java/com/android/internal/telephony/IAns.aidl index e9a46491522e..98bcd415a1ca 100755 --- a/telephony/java/com/android/internal/telephony/IAns.aidl +++ b/telephony/java/com/android/internal/telephony/IAns.aidl @@ -16,6 +16,7 @@ package com.android.internal.telephony; +import android.telephony.AvailableNetworkInfo; interface IAns { @@ -78,4 +79,23 @@ interface IAns { * */ int getPreferredData(String callingPackage); + + /** + * Update availability of a list of networks in the current location. + * + * This api should be called if the caller is aware of the availability of a network + * at the current location. This information will be used by AlternativeNetwork service + * to decide to attach to the network. If an empty list is passed, + * it is assumed that no network is available. + * Requires that the calling app has carrier privileges on both primary and + * secondary subscriptions (see + * {@link #hasCarrierPrivileges}), or has permission + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * @param availableNetworks is a list of available network information. + * @param callingPackage caller's package name + * @return true if request is accepted + * + */ + boolean updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks, + String callingPackage); } diff --git a/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl b/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl new file mode 100644 index 000000000000..76918afb564a --- /dev/null +++ b/telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +oneway interface INumberVerificationCallback { + void onCallReceived(String phoneNumber); + void onVerificationFailed(int reason); +} diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index bc4451977d92..f9db4b0afd12 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -184,6 +184,15 @@ interface ISub { String setSubscriptionGroup(in int[] subIdList, String callingPackage); /** + * Set whether a subscription is metered + * + * @param isMetered whether it’s a metered subscription. + * @param subId the unique SubscriptionInfo index in database + * @return the number of records updated + */ + int setMetered(boolean isMetered, int subId); + + /** * Set which subscription is preferred for cellular data. It's * designed to overwrite default data subscription temporarily. * diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 923ab066ef0f..76e7509c1094 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -25,6 +25,7 @@ import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; import android.telephony.ServiceState; import android.telephony.SignalStrength; +import android.telephony.emergency.EmergencyNumber; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener; @@ -80,4 +81,5 @@ interface ITelephonyRegistry { void notifyPhoneCapabilityChanged(in PhoneCapability capability); void notifyPreferredDataSubIdChanged(int preferredSubId); void notifyRadioPowerStateChanged(in int state); + void notifyEmergencyNumberList(in List<EmergencyNumber> emergencyNumberList); } diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 4dc0341c8e2b..d8f961850906 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -542,7 +542,7 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecApplyTransportModeTransform( - eq(pfd.getFileDescriptor()), + eq(pfd), eq(mUid), eq(IpSecManager.DIRECTION_OUT), anyString(), @@ -555,7 +555,7 @@ public class IpSecServiceParameterizedTest { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); mIpSecService.removeTransportModeTransforms(pfd); - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); + verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); } private IpSecTunnelInterfaceResponse createAndValidateTunnel( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 2c94a601fbf6..724446e11c83 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -425,7 +425,7 @@ public class IpSecServiceTest { ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); mIpSecService.removeTransportModeTransforms(pfd); - verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor()); + verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); } @Test @@ -620,10 +620,10 @@ public class IpSecServiceTest { mIpSecService.openUdpEncapsulationSocket(0, new Binder()); FileDescriptor sockFd = udpEncapResp.fileDescriptor.getFileDescriptor(); - ArgumentMatcher<FileDescriptor> fdMatcher = (arg) -> { + ArgumentMatcher<ParcelFileDescriptor> fdMatcher = (arg) -> { try { StructStat sockStat = Os.fstat(sockFd); - StructStat argStat = Os.fstat(arg); + StructStat argStat = Os.fstat(arg.getFileDescriptor()); return sockStat.st_ino == argStat.st_ino && sockStat.st_dev == argStat.st_dev; diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index ed70fb3c57d6..df0daebe8453 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -240,6 +240,12 @@ bool BinaryResourceParser::ParsePackage(const ResChunk_header* chunk) { } break; + case android::RES_TABLE_OVERLAYABLE_TYPE: + if (!ParseOverlayable(parser.chunk())) { + return false; + } + break; + default: diag_->Warn(DiagMessage(source_) << "unexpected chunk type " @@ -383,24 +389,12 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package, return false; } - const uint32_t type_spec_flags = entry_type_spec_flags_[res_id]; - if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0 || - (type_spec_flags & ResTable_typeSpec::SPEC_OVERLAYABLE) != 0) { - if (entry->flags & ResTable_entry::FLAG_PUBLIC) { - Visibility visibility; - visibility.level = Visibility::Level::kPublic; - visibility.source = source_.WithLine(0); - if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) { - return false; - } - } - - if (type_spec_flags & ResTable_typeSpec::SPEC_OVERLAYABLE) { - Overlayable overlayable; - overlayable.source = source_.WithLine(0); - if (!table_->AddOverlayableMangled(name, overlayable, diag_)) { - return false; - } + if (entry->flags & ResTable_entry::FLAG_PUBLIC) { + Visibility visibility; + visibility.level = Visibility::Level::kPublic; + visibility.source = source_.WithLine(0); + if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) { + return false; } // Erase the ID from the map once processed, so that we don't mark the same symbol more than @@ -433,6 +427,72 @@ bool BinaryResourceParser::ParseLibrary(const ResChunk_header* chunk) { return true; } +bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { + const ResTable_overlayable_header* header = ConvertTo<ResTable_overlayable_header>(chunk); + if (!header) { + diag_->Error(DiagMessage(source_) << "corrupt ResTable_category_header chunk"); + return false; + } + + ResChunkPullParser parser(GetChunkData(chunk), + GetChunkDataLen(chunk)); + while (ResChunkPullParser::IsGoodEvent(parser.Next())) { + if (util::DeviceToHost16(parser.chunk()->type) == android::RES_TABLE_OVERLAYABLE_POLICY_TYPE) { + const ResTable_overlayable_policy_header* policy_header = + ConvertTo<ResTable_overlayable_policy_header>(parser.chunk()); + + std::vector<Overlayable::Policy> policies; + if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PUBLIC) { + policies.push_back(Overlayable::Policy::kPublic); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION) { + policies.push_back(Overlayable::Policy::kSystem); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION) { + policies.push_back(Overlayable::Policy::kVendor); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { + policies.push_back(Overlayable::Policy::kProduct); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) { + policies.push_back(Overlayable::Policy::kProductServices); + } + + const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>( + ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); + const ResTable_ref* const ref_end = ref_begin + + util::DeviceToHost32(policy_header->entry_count); + for (auto ref_iter = ref_begin; ref_iter != ref_end; ++ref_iter) { + ResourceId res_id(util::DeviceToHost32(ref_iter->ident)); + const auto iter = id_index_.find(res_id); + + // If the overlayable chunk comes before the type chunks, the resource ids and resource name + // pairing will not exist at this point. + if (iter == id_index_.cend()) { + diag_->Error(DiagMessage(source_) << "failed to find resource name for overlayable" + << " resource " << res_id); + return false; + } + + for (Overlayable::Policy policy : policies) { + Overlayable overlayable; + overlayable.source = source_.WithLine(0); + overlayable.policy = policy; + if (!table_->AddOverlayable(iter->second, overlayable, diag_)) { + return false; + } + } + } + } + } + + return true; +} + std::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& name, const ConfigDescription& config, const android::Res_value& value) { diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h index 2bdc051f4e29..a2eee5006964 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.h +++ b/tools/aapt2/format/binary/BinaryResourceParser.h @@ -54,6 +54,7 @@ class BinaryResourceParser { bool ParseTypeSpec(const ResourceTablePackage* package, const android::ResChunk_header* chunk); bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk); bool ParseLibrary(const android::ResChunk_header* chunk); + bool ParseOverlayable(const android::ResChunk_header* chunk); std::unique_ptr<Item> ParseValue(const ResourceNameRef& name, const android::ConfigDescription& config, diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index 6c1a9ba2cbad..976c3288bfca 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -24,6 +24,7 @@ #include "android-base/logging.h" #include "android-base/macros.h" #include "android-base/stringprintf.h" +#include "androidfw/ResourceUtils.h" #include "ResourceTable.h" #include "ResourceValues.h" @@ -216,6 +217,11 @@ class MapFlattenVisitor : public ValueVisitor { size_t entry_count_ = 0; }; +struct PolicyChunk { + uint32_t policy_flags; + std::set<ResourceId> ids; +}; + class PackageFlattener { public: PackageFlattener(IAaptContext* context, ResourceTablePackage* package, @@ -267,6 +273,8 @@ class PackageFlattener { FlattenLibrarySpec(buffer); } + FlattenOverlayable(buffer); + pkg_writer.Finish(); return true; } @@ -413,6 +421,97 @@ class PackageFlattener { return sorted_entries; } + void FlattenOverlayable(BigBuffer* buffer) { + std::vector<PolicyChunk> policies; + + CHECK(bool(package_->id)) << "package must have an ID set when flattening <overlayable>"; + for (auto& type : package_->types) { + CHECK(bool(type->id)) << "type must have an ID set when flattening <overlayable>"; + for (auto& entry : type->entries) { + CHECK(bool(type->id)) << "entry must have an ID set when flattening <overlayable>"; + + // TODO(b/120298168): Convert the policies vector to a policy set or bitmask + if (!entry->overlayable_declarations.empty()) { + uint16_t policy_flags = 0; + for (Overlayable overlayable : entry->overlayable_declarations) { + if (overlayable.policy) { + switch (overlayable.policy.value()) { + case Overlayable::Policy::kPublic: + policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; + break; + case Overlayable::Policy::kSystem: + policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION; + break; + case Overlayable::Policy::kVendor: + policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION; + break; + case Overlayable::Policy::kProduct: + policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; + break; + case Overlayable::Policy::kProductServices: + policy_flags |= + ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION; + break; + } + } else { + // Encode overlayable entries defined without a policy as publicly overlayable + policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; + } + } + + // Find the overlayable policy chunk with the same policies as the entry + PolicyChunk* policy_chunk = nullptr; + for (PolicyChunk& policy : policies) { + if (policy.policy_flags == policy_flags) { + policy_chunk = &policy; + break; + } + } + + // Create a new policy chunk if an existing one with the same policy cannot be found + if (policy_chunk == nullptr) { + PolicyChunk p; + p.policy_flags = policy_flags; + policies.push_back(p); + policy_chunk = &policies.back(); + } + + policy_chunk->ids.insert(android::make_resid(package_->id.value(), type->id.value(), + entry->id.value())); + } + } + } + + if (policies.empty()) { + // Only write the overlayable chunk if the APK has overlayable entries + return; + } + + ChunkWriter writer(buffer); + writer.StartChunk<ResTable_overlayable_header>(RES_TABLE_OVERLAYABLE_TYPE); + + // Write each policy block for the overlayable + for (PolicyChunk& policy : policies) { + ChunkWriter policy_writer(buffer); + ResTable_overlayable_policy_header* policy_type = + policy_writer.StartChunk<ResTable_overlayable_policy_header>( + RES_TABLE_OVERLAYABLE_POLICY_TYPE); + policy_type->policy_flags = util::HostToDevice32(policy.policy_flags); + policy_type->entry_count = util::HostToDevice32(static_cast<uint32_t>(policy.ids.size())); + + // Write the ids after the policy header + ResTable_ref* id_block = policy_writer.NextBlock<ResTable_ref>(policy.ids.size()); + for (const ResourceId& id : policy.ids) { + id_block->ident = util::HostToDevice32(id.id); + id_block++; + } + + policy_writer.Finish(); + } + + writer.Finish(); + } + bool FlattenTypeSpec(ResourceTableType* type, std::vector<ResourceEntry*>* sorted_entries, BigBuffer* buffer) { ChunkWriter type_spec_writer(buffer); @@ -446,11 +545,6 @@ class PackageFlattener { config_masks[entry->id.value()] |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC); } - if (!entry->overlayable_declarations.empty()) { - config_masks[entry->id.value()] |= - util::HostToDevice32(ResTable_typeSpec::SPEC_OVERLAYABLE); - } - const size_t config_count = entry->values.size(); for (size_t i = 0; i < config_count; i++) { const ConfigDescription& config = entry->values[i]->config; diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index cd1414c7e628..410efbe83b1b 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -628,24 +628,108 @@ TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithWhitelistSucceeds) { } TEST_F(TableFlattenerTest, FlattenOverlayable) { + std::string name = "com.app.test:integer/overlayable"; std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.test", 0x7f) - .AddSimple("com.app.test:integer/overlayable", ResourceId(0x7f020000)) + .AddSimple(name, ResourceId(0x7f020000)) + .AddOverlayable(name, Overlayable::Policy::kProduct) + .AddOverlayable(name, Overlayable::Policy::kSystem) + .AddOverlayable(name, Overlayable::Policy::kVendor) .Build(); - ASSERT_TRUE(table->AddOverlayable(test::ParseNameOrDie("com.app.test:integer/overlayable"), - Overlayable{}, test::GetDiagnostics())); + ResourceTable output_table; + ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &output_table)); - ResTable res_table; - ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table)); + auto search_result = output_table.FindResource(test::ParseNameOrDie(name)); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + EXPECT_EQ(search_result.value().entry->overlayable_declarations.size(), 3); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[0].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[0].policy, + Overlayable::Policy::kSystem); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[1].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[1].policy, + Overlayable::Policy::kVendor); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[2].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[2].policy, + Overlayable::Policy::kProduct); +} + +TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { + std::string name_zero = "com.app.test:integer/overlayable_zero"; + std::string name_one = "com.app.test:integer/overlayable_one"; + std::string name_two = "com.app.test:integer/overlayable_two"; + std::string name_three = "com.app.test:integer/overlayable_three"; + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .SetPackageId("com.app.test", 0x7f) + .AddSimple(name_zero, ResourceId(0x7f020000)) + .AddOverlayable(name_zero, Overlayable::Policy::kProduct) + .AddOverlayable(name_zero, Overlayable::Policy::kSystem) + .AddOverlayable(name_zero, Overlayable::Policy::kProductServices) + .AddSimple(name_one, ResourceId(0x7f020001)) + .AddOverlayable(name_one, Overlayable::Policy::kPublic) + .AddOverlayable(name_one, Overlayable::Policy::kSystem) + .AddSimple(name_two, ResourceId(0x7f020002)) + .AddOverlayable(name_two, Overlayable::Policy::kProduct) + .AddOverlayable(name_two, Overlayable::Policy::kSystem) + .AddOverlayable(name_two, Overlayable::Policy::kProductServices) + .AddSimple(name_three, ResourceId(0x7f020003)) + .AddOverlayable(name_three, {}) + .Build(); + + ResourceTable output_table; + ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &output_table)); + + auto search_result = output_table.FindResource(test::ParseNameOrDie(name_zero)); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + EXPECT_EQ(search_result.value().entry->overlayable_declarations.size(), 3); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[0].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[0].policy, + Overlayable::Policy::kSystem); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[1].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[1].policy, + Overlayable::Policy::kProduct); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[2].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[2].policy, + Overlayable::Policy::kProductServices); + + search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + EXPECT_EQ(search_result.value().entry->overlayable_declarations.size(), 2); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[0].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[0].policy, + Overlayable::Policy::kPublic); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[1].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[1].policy, + Overlayable::Policy::kSystem); + + search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + EXPECT_EQ(search_result.value().entry->overlayable_declarations.size(), 3); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[0].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[0].policy, + Overlayable::Policy::kSystem); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[1].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[1].policy, + Overlayable::Policy::kProduct); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[2].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[2].policy, + Overlayable::Policy::kProductServices); + + search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + EXPECT_EQ(search_result.value().entry->overlayable_declarations.size(), 1); + EXPECT_TRUE(search_result.value().entry->overlayable_declarations[0].policy); + EXPECT_EQ(search_result.value().entry->overlayable_declarations[0].policy, + Overlayable::Policy::kPublic); - const StringPiece16 overlayable_name(u"com.app.test:integer/overlayable"); - uint32_t spec_flags = 0u; - ASSERT_THAT(res_table.identifierForName(overlayable_name.data(), overlayable_name.size(), nullptr, - 0u, nullptr, 0u, &spec_flags), - Gt(0u)); - EXPECT_TRUE(spec_flags & android::ResTable_typeSpec::SPEC_OVERLAYABLE); } + } // namespace aapt diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index d1a70a75a44e..31d205e1b9c9 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -298,19 +298,20 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res "<colgroup align=\"left\" />\n" "<tr><th>Attribute</th><th>Description</th></tr>\n"; - // Build the table of attributes with their links and names. - for (const StyleableAttr& entry : sorted_attributes) { - if (SkipSymbol(entry.symbol)) { - continue; - } - + // Removed and hidden attributes are public but hidden from the documentation, so don't emit + // them as part of the class documentation. + std::vector<StyleableAttr> documentation_attrs = sorted_attributes; + auto documentation_remove_iter = std::remove_if(documentation_attrs.begin(), + documentation_attrs.end(), + [&](StyleableAttr entry) -> bool { StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment(); - if (attr_comment_line.contains("@removed")) { - // Removed attributes are public but hidden from the documentation, so - // don't emit them as part of the class documentation. - continue; - } + return SkipSymbol(entry.symbol) || attr_comment_line.contains("@removed") + || attr_comment_line.contains("@hide"); + }); + documentation_attrs.erase(documentation_remove_iter, documentation_attrs.end()); + // Build the table of attributes with their links and names. + for (const StyleableAttr& entry : documentation_attrs) { const ResourceName& attr_name = entry.attr_ref->name.value(); styleable_comment << "<tr><td><code>{@link #" << entry.field_name << " " << (!attr_name.package.empty() ? attr_name.package @@ -320,16 +321,14 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res // Only use the comment up until the first '.'. This is to stay compatible with // the way old AAPT did it (presumably to keep it short and to avoid including // annotations like @hide which would affect this Styleable). + StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment(); styleable_comment << "<td>" << AnnotationProcessor::ExtractFirstSentence(attr_comment_line) << "</td></tr>\n"; } styleable_comment << "</table>\n"; // Generate the @see lines for each attribute. - for (const StyleableAttr& entry : sorted_attributes) { - if (SkipSymbol(entry.symbol)) { - continue; - } + for (const StyleableAttr& entry : documentation_attrs) { styleable_comment << "@see #" << entry.field_name << "\n"; } diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp index fa208be120ed..4f51fc48c80e 100644 --- a/tools/aapt2/java/JavaClassGenerator_test.cpp +++ b/tools/aapt2/java/JavaClassGenerator_test.cpp @@ -366,6 +366,46 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) ASSERT_TRUE(generator.Generate("android", &out)); out.Flush(); + EXPECT_THAT(output, HasSubstr("#Container_one android:one")); + EXPECT_THAT(output, HasSubstr("@see #Container_one")); + EXPECT_THAT(output, HasSubstr("attr name android:one")); + EXPECT_THAT(output, HasSubstr("attr description")); + EXPECT_THAT(output, HasSubstr(attr.GetComment())); + EXPECT_THAT(output, HasSubstr(styleable.GetComment())); +} + +TEST(JavaClassGeneratorTest, CommentsForStyleableHiddenAttributesAreNotPresent) { + Attribute attr; + attr.SetComment(StringPiece("This is an attribute @hide")); + + Styleable styleable; + styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one"))); + styleable.SetComment(StringPiece("This is a styleable")); + + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .SetPackageId("android", 0x01) + .AddValue("android:attr/one", util::make_unique<Attribute>(attr)) + .AddValue("android:styleable/Container", + std::unique_ptr<Styleable>(styleable.Clone(nullptr))) + .Build(); + + std::unique_ptr<IAaptContext> context = + test::ContextBuilder() + .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) + .SetNameManglerPolicy(NameManglerPolicy{"android"}) + .Build(); + JavaClassGeneratorOptions options; + options.use_final = false; + JavaClassGenerator generator(context.get(), table.get(), options); + + std::string output; + StringOutputStream out(&output); + ASSERT_TRUE(generator.Generate("android", &out)); + out.Flush(); + + EXPECT_THAT(output, Not(HasSubstr("#Container_one android:one"))); + EXPECT_THAT(output, Not(HasSubstr("@see #Container_one"))); EXPECT_THAT(output, HasSubstr("attr name android:one")); EXPECT_THAT(output, HasSubstr("attr description")); EXPECT_THAT(output, HasSubstr(attr.GetComment())); diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 3a5d5858254d..1b6626a8dfe9 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -368,7 +368,16 @@ bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) { // Symbol state information may be lost if there is no value for the resource. if (entry->visibility.level != Visibility::Level::kUndefined && entry->values.empty()) { context->GetDiagnostics()->Error(DiagMessage(entry->visibility.source) - << "no definition for declared symbol '" << name << "'"); + << "no definition for declared symbol '" << name + << "'"); + error = true; + } + + // Ensure that definitions for values declared as overlayable exist + if (!entry->overlayable_declarations.empty() && entry->values.empty()) { + context->GetDiagnostics()->Error(DiagMessage(entry->overlayable_declarations[0].source) + << "no definition for overlayable symbol '" + << name << "'"); error = true; } diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh index e50c70d0656a..f25fcdcb7479 100755 --- a/tools/aosp/aosp_sha.sh +++ b/tools/aosp/aosp_sha.sh @@ -19,6 +19,6 @@ else echo "If your change contains no confidential details (such as security fixes), please" echo "upload and merge this change at https://android-review.googlesource.com/." echo - exit 77 + exit 1 fi fi diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py index 2f1e53ca5065..01728fa1a0db 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -26,6 +26,7 @@ FLAG_WHITELIST = "whitelist" FLAG_GREYLIST = "greylist" FLAG_BLACKLIST = "blacklist" FLAG_GREYLIST_MAX_O = "greylist-max-o" +FLAG_GREYLIST_MAX_P = "greylist-max-p" # List of all known flags. FLAGS = [ @@ -33,6 +34,7 @@ FLAGS = [ FLAG_GREYLIST, FLAG_BLACKLIST, FLAG_GREYLIST_MAX_O, + FLAG_GREYLIST_MAX_P, ] FLAGS_SET = set(FLAGS) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 47d6712bbc74..89b670390171 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -953,8 +953,12 @@ public class WifiManager { * establish a connection to a remembered access point that is * within range, and will do periodic scans if there are remembered * access points but none are in range. + * + * @deprecated This API is non-functional and will have no impact. */ + @Deprecated public static final int WIFI_MODE_FULL = 1; + /** * In this Wi-Fi lock mode, Wi-Fi will be kept active, * but the only operation that will be supported is initiation of @@ -963,28 +967,62 @@ public class WifiManager { * nor will periodic scans be automatically performed looking for * remembered access points. Scans must be explicitly requested by * an application in this mode. + * + * @deprecated This API is non-functional and will have no impact. */ + @Deprecated public static final int WIFI_MODE_SCAN_ONLY = 2; + /** - * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode - * {@link #WIFI_MODE_FULL} but it operates at high performance - * with minimum packet loss and low packet latency even when - * the device screen is off. This mode will consume more power - * and hence should be used only when there is a need for such - * an active connection. + * In this Wi-Fi lock mode, Wi-Fi will not go to power save. + * This results in operating with low packet latency. + * The lock is active even when the device screen is off or + * the acquiring application is running in the background. + * This mode will consume more power and hence should be used only + * when there is a need for this tradeoff. * <p> * An example use case is when a voice connection needs to be - * kept active even after the device screen goes off. Holding the - * regular {@link #WIFI_MODE_FULL} lock will keep the wifi - * connection active, but the connection can be lossy. + * kept active even after the device screen goes off. * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the - * duration of the voice call will improve the call quality. + * duration of the voice call may improve the call quality. * <p> - * When there is no support from the hardware, this lock mode - * will have the same behavior as {@link #WIFI_MODE_FULL} + * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF} + * lock will have no impact. */ public static final int WIFI_MODE_FULL_HIGH_PERF = 3; + /** + * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency. + * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations: + * <ol> + * <li>The lock is only active when the screen is on.</li> + * <li>The lock is only active when the acquiring app is running in the foreground.</li> + * </ol> + * Low latency mode optimizes for reduced packet latency, + * and as a result other performance measures may suffer when there are trade-offs to make: + * <ol> + * <li>Battery life may be reduced.</li> + * <li>Throughput may be reduced.</li> + * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li> + * <ul> + * <li>The device may not roam or switch to the AP with highest signal quality.</li> + * <li>Location accuracy may be reduced.</li> + * </ul> + * </ol> + * <p> + * Example use cases are real time gaming or virtual reality applications where + * low latency is a key factor for user experience. + * <p> + * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_LOW_LATENCY} + * lock will cause the device not to go power save. + * <p> + * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and + * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY} + * lock will be effective when app is running in foreground and screen is on, + * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise. + */ + public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; + /** Anything worse than or equal to this will show 0 bars. */ @UnsupportedAppUsage private static final int MIN_RSSI = -100; @@ -1176,7 +1214,6 @@ public class WifiManager { * @throws UnsupportedOperationException if Passpoint is not enabled on the device. * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public List<OsuProvider> getMatchingOsuProviders(List<ScanResult> scanResults) { try { @@ -1945,6 +1982,8 @@ public class WifiManager { public static final int WIFI_FEATURE_WPA3_SUITE_B = 0x10000000; // WPA3-Enterprise Suite-B /** @hide */ public static final int WIFI_FEATURE_OWE = 0x20000000; // Enhanced Open + /** @hide */ + public static final int WIFI_FEATURE_LOW_LATENCY = 0x40000000; // Low Latency modes private int getSupportedFeatures() { try { @@ -3831,9 +3870,8 @@ public class WifiManager { /** * Creates a new WifiLock. * - * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, - * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for - * descriptions of the types of Wi-Fi locks. + * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF} + * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks. * @param tag a tag for the WifiLock to identify it in debugging messages. This string is * never shown to the user under normal conditions, but should be descriptive * enough to identify your application and the specific WifiLock within it, if it @@ -3858,12 +3896,14 @@ public class WifiManager { * @return a new, unacquired WifiLock with the given tag. * * @see WifiLock + * + * @deprecated This API is non-functional. */ + @Deprecated public WifiLock createWifiLock(String tag) { return new WifiLock(WIFI_MODE_FULL, tag); } - /** * Create a new MulticastLock * diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java index 87706b936f03..f73b9e5e2a00 100644 --- a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java +++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java @@ -42,8 +42,10 @@ import java.util.List; public class WifiNetworkConfigBuilder { private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*"; private static final String MATCH_EMPTY_SSID_PATTERN_PATH = ""; - private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN = + private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN1 = new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS); + private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN2 = + new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.BROADCAST_ADDRESS); private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN = new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS); private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK = @@ -189,7 +191,13 @@ public class WifiNetworkConfigBuilder { * Set the BSSID to use for filtering networks from scan results. Will only match network whose * BSSID is identical to the specified value. * <p> - * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li> + * <li>For network requests ({@link NetworkSpecifier}), built using + * {@link #buildNetworkSpecifier}, sets the BSSID to use for filtering networks from scan + * results. Will only match networks whose BSSID is identical to specified value.</li> + * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using + * {@link #buildNetworkSuggestion()}, sets a specific BSSID for the network suggestion. + * If set, only the specified BSSID with the specified SSID will be considered for connection. + * If not set, all BSSIDs with the specified SSID will be considered for connection.</li> * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or * {@link #setBssidPattern(MacAddress, MacAddress)}.</li> * @@ -432,6 +440,9 @@ public class WifiNetworkConfigBuilder { if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) { wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\""; } + if (mBssidPatternMatcher.second == MATCH_EXACT_BSSID_PATTERN_MASK) { + wifiConfiguration.BSSID = mBssidPatternMatcher.first.toString(); + } setSecurityParamsInWifiConfiguration(wifiConfiguration); wifiConfiguration.hiddenSSID = mIsHiddenSSID; wifiConfiguration.priority = mPriority; @@ -460,7 +471,10 @@ public class WifiNetworkConfigBuilder { && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) { return true; } - if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN)) { + if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN1)) { + return true; + } + if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN2)) { return true; } return false; @@ -474,6 +488,16 @@ public class WifiNetworkConfigBuilder { return false; } + private boolean hasSetMatchExactPattern() { + // exact ssid match with either match-all bssid or match-exact bssid. + if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL + && (mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN) + || mBssidPatternMatcher.second.equals(MATCH_EXACT_BSSID_PATTERN_MASK))) { + return true; + } + return false; + } + private void validateSecurityParams() { int numSecurityTypes = 0; numSecurityTypes += mIsEnhancedOpen ? 1 : 0; @@ -566,9 +590,42 @@ public class WifiNetworkConfigBuilder { } /** - * Create a network suggestion object use in - * {@link WifiManager#addNetworkSuggestions(List)}. + * Create a network suggestion object use in {@link WifiManager#addNetworkSuggestions(List)}. * See {@link WifiNetworkSuggestion}. + *<p> + * Note: Apps can set a combination of SSID using {@link #setSsid(String)} and BSSID + * using {@link #setBssid(MacAddress)} to provide more fine grained network suggestions to the + * platform. + * </p> + * + * For example: + * To provide credentials for one open, one WPA2 and one WPA3 network with their + * corresponding SSID's: + * {@code + * final WifiNetworkSuggestion suggestion1 = + * new WifiNetworkConfigBuilder() + * .setSsid("test111111") + * .buildNetworkSuggestion() + * final WifiNetworkSuggestion suggestion2 = + * new WifiNetworkConfigBuilder() + * .setSsid("test222222") + * .setWpa2Passphrase("test123456") + * .buildNetworkSuggestion() + * final WifiNetworkSuggestion suggestion3 = + * new WifiNetworkConfigBuilder() + * .setSsid("test333333") + * .setWpa3Passphrase("test6789") + * .buildNetworkSuggestion() + * final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion> {{ + * add(suggestion1); + * add(suggestion2); + * add(suggestion3); + * }}; + * final WifiManager wifiManager = + * context.getSystemService(Context.WIFI_SERVICE); + * wifiManager.addNetworkSuggestions(suggestionsList); + * ... + * } * * @return Instance of {@link WifiNetworkSuggestion}. * @throws IllegalStateException on invalid params set. @@ -577,11 +634,14 @@ public class WifiNetworkConfigBuilder { if (mSsidPatternMatcher == null) { throw new IllegalStateException("setSsid should be invoked for suggestion"); } - if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL - || mBssidPatternMatcher != null) { - throw new IllegalStateException("none of setSsidPattern/setBssidPattern/setBssid are" + setMatchAnyPatternIfUnset(); + if (!hasSetMatchExactPattern()) { + throw new IllegalStateException("none of setSsidPattern/setBssidPattern are" + " allowed for suggestion"); } + if (hasSetMatchNonePattern()) { + throw new IllegalStateException("cannot set match-none for suggestion"); + } validateSecurityParams(); return new WifiNetworkSuggestion( diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index 25121e2dc8c7..760f1e6bc5e2 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -104,8 +104,8 @@ public final class WifiNetworkSuggestion implements Parcelable { @Override public int hashCode() { - return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.allowedKeyManagement, - suggestorUid); + return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID, + wifiConfiguration.allowedKeyManagement, suggestorUid); } /** @@ -121,6 +121,7 @@ public final class WifiNetworkSuggestion implements Parcelable { } WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj; return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID) + && Objects.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID) && Objects.equals(this.wifiConfiguration.allowedKeyManagement, lhs.wifiConfiguration.allowedKeyManagement) && suggestorUid == lhs.suggestorUid; diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java index c455c6f0836d..2505499c85d7 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java @@ -244,7 +244,7 @@ public class WifiNetworkConfigBuilderTest { * when match-none SSID pattern is set. */ @Test(expected = IllegalStateException.class) - public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern() { + public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern1() { new WifiNetworkConfigBuilder() .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_LITERAL)) .buildNetworkSpecifier(); @@ -252,10 +252,21 @@ public class WifiNetworkConfigBuilderTest { /** * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception + * when match-none SSID pattern is set. + */ + @Test(expected = IllegalStateException.class) + public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern2() { + new WifiNetworkConfigBuilder() + .setSsid("") + .buildNetworkSpecifier(); + } + + /** + * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception * when match-none BSSID pattern is set. */ @Test(expected = IllegalStateException.class) - public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern() { + public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern1() { new WifiNetworkConfigBuilder() .setBssidPattern(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS) .buildNetworkSpecifier(); @@ -263,6 +274,28 @@ public class WifiNetworkConfigBuilderTest { /** * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception + * when match-none BSSID pattern is set. + */ + @Test(expected = IllegalStateException.class) + public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern2() { + new WifiNetworkConfigBuilder() + .setBssid(MacAddress.BROADCAST_ADDRESS) + .buildNetworkSpecifier(); + } + + /** + * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception + * when match-none BSSID pattern is set. + */ + @Test(expected = IllegalStateException.class) + public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern3() { + new WifiNetworkConfigBuilder() + .setBssid(MacAddress.ALL_ZEROS_ADDRESS) + .buildNetworkSpecifier(); + } + + /** + * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception * when SSID pattern is set for hidden network. */ @Test(expected = IllegalStateException.class) @@ -429,13 +462,15 @@ public class WifiNetworkConfigBuilderTest { * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for OWE network. */ @Test - public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetwork() { + public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetworkWithBssid() { WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder() .setSsid(TEST_SSID) + .setBssid(MacAddress.fromString(TEST_BSSID)) .setIsEnhancedOpen() .buildNetworkSuggestion(); assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID); + assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID); assertTrue(suggestion.wifiConfiguration.allowedKeyManagement .get(WifiConfiguration.KeyMgmt.OWE)); assertNull(suggestion.wifiConfiguration.preSharedKey); @@ -505,7 +540,7 @@ public class WifiNetworkConfigBuilderTest { /** * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception - * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is set. + * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set. */ @Test(expected = IllegalStateException.class) public void testWifiNetworkSuggestionBuilderWithBssidPattern() { @@ -518,23 +553,46 @@ public class WifiNetworkConfigBuilderTest { /** * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception - * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set. + * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set. + */ + @Test(expected = IllegalStateException.class) + public void testWifiNetworkSuggestionBuilderWithNoSsid() { + new WifiNetworkConfigBuilder() + .buildNetworkSuggestion(); + } + + /** + * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception + * when {@link WifiNetworkConfigBuilder#setSsid(String)} is invoked with an invalid value. */ @Test(expected = IllegalStateException.class) - public void testWifiNetworkSuggestionBuilderWithBssid() { + public void testWifiNetworkSuggestionBuilderWithInvalidSsid() { + new WifiNetworkConfigBuilder() + .setSsid("") + .buildNetworkSuggestion(); + } + + /** + * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception + * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value. + */ + @Test(expected = IllegalStateException.class) + public void testWifiNetworkSuggestionBuilderWithInvalidBroadcastBssid() { new WifiNetworkConfigBuilder() .setSsid(TEST_SSID) - .setBssid(MacAddress.fromString(TEST_BSSID)) + .setBssid(MacAddress.BROADCAST_ADDRESS) .buildNetworkSuggestion(); } /** * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception - * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set. + * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value. */ @Test(expected = IllegalStateException.class) - public void testWifiNetworkSuggestionBuilderWithNoSsid() { + public void testWifiNetworkSuggestionBuilderWithInvalidAllZeroBssid() { new WifiNetworkConfigBuilder() + .setSsid(TEST_SSID) + .setBssid(MacAddress.ALL_ZEROS_ADDRESS) .buildNetworkSuggestion(); } diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java index 6bab60dd480b..5cc821717462 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java @@ -29,6 +29,7 @@ import org.junit.Test; @SmallTest public class WifiNetworkSuggestionTest { private static final String TEST_SSID = "\"Test123\""; + private static final String TEST_BSSID = "12:12:12:12:12:12"; private static final String TEST_SSID_1 = "\"Test1234\""; /** @@ -38,6 +39,7 @@ public class WifiNetworkSuggestionTest { public void testWifiNetworkSuggestionParcel() { WifiConfiguration configuration = new WifiConfiguration(); configuration.SSID = TEST_SSID; + configuration.BSSID = TEST_BSSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(configuration, false, true, 0); @@ -65,18 +67,20 @@ public class WifiNetworkSuggestionTest { /** * Check NetworkSuggestion equals returns {@code true} for 2 network suggestions with the same - * SSID, key mgmt and UID. + * SSID, BSSID, key mgmt and UID. */ @Test public void testWifiNetworkSuggestionEqualsSame() { WifiConfiguration configuration = new WifiConfiguration(); configuration.SSID = TEST_SSID; + configuration.BSSID = TEST_BSSID; configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(configuration, true, false, 0); WifiConfiguration configuration1 = new WifiConfiguration(); configuration1.SSID = TEST_SSID; + configuration1.BSSID = TEST_BSSID; configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion(configuration1, false, true, 0); @@ -86,7 +90,7 @@ public class WifiNetworkSuggestionTest { /** * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same - * key mgmt and UID, but different SSID. + * BSSID, key mgmt and UID, but different SSID. */ @Test public void testWifiNetworkSuggestionEqualsFailsWhenSsidIsDifferent() { @@ -107,7 +111,29 @@ public class WifiNetworkSuggestionTest { /** * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same - * SSID and UID, but different key mgmt. + * SSID, key mgmt and UID, but different BSSID. + */ + @Test + public void testWifiNetworkSuggestionEqualsFailsWhenBssidIsDifferent() { + WifiConfiguration configuration = new WifiConfiguration(); + configuration.SSID = TEST_SSID; + configuration.BSSID = TEST_BSSID; + configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + WifiNetworkSuggestion suggestion = + new WifiNetworkSuggestion(configuration, false, false, 0); + + WifiConfiguration configuration1 = new WifiConfiguration(); + configuration1.SSID = TEST_SSID; + configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + WifiNetworkSuggestion suggestion1 = + new WifiNetworkSuggestion(configuration1, false, false, 0); + + assertNotEquals(suggestion, suggestion1); + } + + /** + * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same + * SSID, BSSID and UID, but different key mgmt. */ @Test public void testWifiNetworkSuggestionEqualsFailsWhenKeyMgmtIsDifferent() { @@ -128,7 +154,7 @@ public class WifiNetworkSuggestionTest { /** * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same - * SSID and key mgmt, but different UID. + * SSID, BSSID and key mgmt, but different UID. */ @Test public void testWifiNetworkSuggestionEqualsFailsWhenUidIsDifferent() { |