diff options
239 files changed, 3915 insertions, 3318 deletions
diff --git a/Android.mk b/Android.mk index 991d18513be8..9072e3b9d077 100644 --- a/Android.mk +++ b/Android.mk @@ -908,7 +908,6 @@ framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \ ext \ icu4j \ framework \ - telephony-common \ voip-common framework_docs_LOCAL_JAVA_LIBRARIES := \ diff --git a/api/current.txt b/api/current.txt index bcc82042ea36..7a01e1a874fc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3635,7 +3635,6 @@ package android.app { method public boolean isInMultiWindowMode(); method public boolean isInPictureInPictureMode(); method public boolean isLocalVoiceInteractionSupported(); - method public boolean isOverlayWithDecorCaptionEnabled(); method public boolean isTaskRoot(); method public boolean isVoiceInteraction(); method public boolean isVoiceInteractionRoot(); @@ -3760,7 +3759,6 @@ package android.app { method public void setImmersive(boolean); method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); - method public void setOverlayWithDecorCaptionEnabled(boolean); method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); @@ -5125,6 +5123,7 @@ package android.app { method public int getBadgeIconType(); method public java.lang.String getChannel(); method public java.lang.String getGroup(); + method public int getGroupAlertBehavior(); method public android.graphics.drawable.Icon getLargeIcon(); method public java.lang.CharSequence getSettingsText(); method public java.lang.String getShortcutId(); @@ -5200,6 +5199,9 @@ package android.app { field public static final int FLAG_ONGOING_EVENT = 2; // 0x2 field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8 field public static final deprecated int FLAG_SHOW_LIGHTS = 1; // 0x1 + field public static final int GROUP_ALERT_ALL = 0; // 0x0 + field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2 + field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1 field public static final java.lang.String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES"; field public static final deprecated int PRIORITY_DEFAULT = 0; // 0x0 field public static final deprecated int PRIORITY_HIGH = 1; // 0x1 @@ -5346,6 +5348,7 @@ package android.app { method public android.app.Notification.Builder setExtras(android.os.Bundle); method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method public android.app.Notification.Builder setGroup(java.lang.String); + method public android.app.Notification.Builder setGroupAlertBehavior(int); method public android.app.Notification.Builder setGroupSummary(boolean); method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap); method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); @@ -6660,8 +6663,8 @@ package android.app.assist { method public int getTextStyle(); method public int getTop(); method public android.graphics.Matrix getTransformation(); - method public java.lang.String getUrl(); method public int getVisibility(); + method public java.lang.String getWebDomain(); method public int getWidth(); method public boolean isAccessibilityFocused(); method public boolean isActivated(); @@ -13779,7 +13782,6 @@ package android.graphics { } public class Typeface { - method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback); method public static android.graphics.Typeface create(java.lang.String, int); method public static android.graphics.Typeface create(android.graphics.Typeface, int); method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String); @@ -13814,17 +13816,6 @@ package android.graphics { method public android.graphics.Typeface.Builder setWeight(int); } - public static abstract deprecated interface Typeface.FontRequestCallback { - method public abstract void onTypefaceRequestFailed(int); - method public abstract void onTypefaceRetrieved(android.graphics.Typeface); - field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd - field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1 - field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2 - field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3 - field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff - field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe - } - public class Xfermode { ctor public Xfermode(); } @@ -23646,7 +23637,7 @@ package android.media { public static final class VolumeShaper.Configuration implements android.os.Parcelable { method public int describeContents(); - method public double getDurationMillis(); + method public long getDuration(); method public int getInterpolatorType(); method public static int getMaximumCurvePoints(); method public float[] getTimes(); @@ -23672,7 +23663,7 @@ package android.media { method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float); method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float); method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]); - method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double); + method public android.media.VolumeShaper.Configuration.Builder setDuration(long); method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int); } @@ -26740,10 +26731,10 @@ package android.net.wifi.aware { field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR; } - public class DiscoverySession { + public class DiscoverySession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String); - method public void destroy(); method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]); } @@ -26795,8 +26786,6 @@ package android.net.wifi.aware { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR; - field public static final int MATCH_STYLE_ALL = 1; // 0x1 - field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0 field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1 field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0 } @@ -26805,7 +26794,6 @@ package android.net.wifi.aware { ctor public SubscribeConfig.Builder(); method public android.net.wifi.aware.SubscribeConfig build(); method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>); - method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]); method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int); @@ -26827,10 +26815,10 @@ package android.net.wifi.aware { field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1 } - public class WifiAwareSession { + public class WifiAwareSession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String); - method public void destroy(); method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); } @@ -34945,6 +34933,7 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + field public static final java.lang.String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -37036,15 +37025,12 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); - method public final deprecated void disableSelf(); method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); - method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public abstract void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -37118,7 +37104,6 @@ package android.service.autofill { method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); - method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -40240,10 +40225,12 @@ package android.telephony { method public void sendDialerSpecialCode(java.lang.String); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); + method public void sendVisualVoicemailSms(java.lang.String, int, java.lang.String, android.app.PendingIntent); method public void setDataEnabled(boolean); method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String); method public boolean setOperatorBrandOverride(java.lang.String); method public boolean setPreferredNetworkTypeToGlobal(); + method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri); method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean); @@ -40317,7 +40304,6 @@ package android.telephony { field public static final int SIM_STATE_UNKNOWN = 0; // 0x0 field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff - field public static final int USSD_RETURN_SUCCESS = 100; // 0x64 field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm"; field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } @@ -40335,8 +40321,6 @@ package android.telephony { method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle); method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms); method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask); - method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent); - method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService"; } @@ -42735,7 +42719,7 @@ package android.text.util { method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter); field public static final int ALL = 15; // 0xf field public static final int EMAIL_ADDRESSES = 2; // 0x2 - field public static final deprecated int MAP_ADDRESSES = 8; // 0x8 + field public static final int MAP_ADDRESSES = 8; // 0x8 field public static final int PHONE_NUMBERS = 4; // 0x4 field public static final int WEB_URLS = 1; // 0x1 field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter; @@ -46593,8 +46577,9 @@ package android.view { method public abstract void setTextLines(int[], int[]); method public abstract void setTextStyle(float, int, int, int); method public abstract void setTransformation(android.graphics.Matrix); - method public abstract void setUrl(java.lang.String); + method public abstract deprecated void setUrl(java.lang.String); method public abstract void setVisibility(int); + method public abstract void setWebDomain(java.lang.String); } public static abstract class ViewStructure.HtmlInfo { @@ -47157,7 +47142,9 @@ package android.view.accessibility { public final class AccessibilityManager { method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); + method public void addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler); method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); + method public void addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler); method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList(); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); @@ -47838,6 +47825,8 @@ package android.view.autofill { method public void cancel(); method public void commit(); method public void disableOwnedAutofillServices(); + method public boolean hasEnabledAutofillServices(); + method public boolean isAutofillSupported(); method public boolean isEnabled(); method public void notifyValueChanged(android.view.View); method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue); @@ -47852,7 +47841,6 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -48286,12 +48274,7 @@ package android.view.inputmethod { package android.view.textclassifier { - public abstract interface LinksInfo { - method public abstract boolean apply(java.lang.CharSequence); - } - public final class TextClassificationManager { - method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); method public android.view.textclassifier.TextClassifier getTextClassifier(); method public void setTextClassifier(android.view.textclassifier.TextClassifier); } @@ -48319,7 +48302,6 @@ package android.view.textclassifier { } public abstract interface TextClassifier { - method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList); field public static final android.view.textclassifier.TextClassifier NO_OP; @@ -48330,20 +48312,6 @@ package android.view.textclassifier { field public static final java.lang.String TYPE_URL = "url"; } - public final class TextLanguage { - method public float getConfidenceScore(java.util.Locale); - method public int getEndIndex(); - method public java.util.Locale getLanguage(int); - method public int getLanguageCount(); - method public int getStartIndex(); - } - - public static final class TextLanguage.Builder { - ctor public TextLanguage.Builder(int, int); - method public android.view.textclassifier.TextLanguage build(); - method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); - } - public final class TextSelection { method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); @@ -48995,7 +48963,7 @@ package android.webkit { method public void documentHasImages(android.os.Message); method public static void enableSlowWholeDocumentDraw(); method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>); - method public static deprecated java.lang.String findAddress(java.lang.String); + method public static java.lang.String findAddress(java.lang.String); method public deprecated int findAll(java.lang.String); method public void findAllAsync(java.lang.String); method public void findNext(boolean); diff --git a/api/removed.txt b/api/removed.txt index dc9c54e8b1cd..73dd09650750 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -1,7 +1,6 @@ package android.app { public class Notification implements android.os.Parcelable { - method public deprecated int getBadgeIcon(); method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } diff --git a/api/system-current.txt b/api/system-current.txt index 9953baa06c7d..450df40795e3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -174,6 +174,7 @@ package android { field public static final java.lang.String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION"; field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY"; field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"; + field public static final java.lang.String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT"; field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR"; field public static final java.lang.String READ_CALL_LOG = "android.permission.READ_CALL_LOG"; @@ -3766,7 +3767,6 @@ package android.app { method public boolean isInMultiWindowMode(); method public boolean isInPictureInPictureMode(); method public boolean isLocalVoiceInteractionSupported(); - method public boolean isOverlayWithDecorCaptionEnabled(); method public boolean isTaskRoot(); method public boolean isVoiceInteraction(); method public boolean isVoiceInteractionRoot(); @@ -3893,7 +3893,6 @@ package android.app { method public void setImmersive(boolean); method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); - method public void setOverlayWithDecorCaptionEnabled(boolean); method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); @@ -5304,6 +5303,7 @@ package android.app { method public int getBadgeIconType(); method public java.lang.String getChannel(); method public java.lang.String getGroup(); + method public int getGroupAlertBehavior(); method public android.graphics.drawable.Icon getLargeIcon(); method public static java.lang.Class<? extends android.app.Notification.Style> getNotificationStyleClass(java.lang.String); method public java.lang.CharSequence getSettingsText(); @@ -5383,6 +5383,9 @@ package android.app { field public static final int FLAG_ONGOING_EVENT = 2; // 0x2 field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8 field public static final deprecated int FLAG_SHOW_LIGHTS = 1; // 0x1 + field public static final int GROUP_ALERT_ALL = 0; // 0x0 + field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2 + field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1 field public static final java.lang.String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES"; field public static final deprecated int PRIORITY_DEFAULT = 0; // 0x0 field public static final deprecated int PRIORITY_HIGH = 1; // 0x1 @@ -5529,6 +5532,7 @@ package android.app { method public android.app.Notification.Builder setExtras(android.os.Bundle); method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method public android.app.Notification.Builder setGroup(java.lang.String); + method public android.app.Notification.Builder setGroupAlertBehavior(int); method public android.app.Notification.Builder setGroupSummary(boolean); method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap); method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); @@ -6905,8 +6909,8 @@ package android.app.assist { method public int getTextStyle(); method public int getTop(); method public android.graphics.Matrix getTransformation(); - method public java.lang.String getUrl(); method public int getVisibility(); + method public java.lang.String getWebDomain(); method public int getWidth(); method public boolean isAccessibilityFocused(); method public boolean isActivated(); @@ -14553,7 +14557,6 @@ package android.graphics { } public class Typeface { - method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback); method public static android.graphics.Typeface create(java.lang.String, int); method public static android.graphics.Typeface create(android.graphics.Typeface, int); method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String); @@ -14588,17 +14591,6 @@ package android.graphics { method public android.graphics.Typeface.Builder setWeight(int); } - public static abstract deprecated interface Typeface.FontRequestCallback { - method public abstract void onTypefaceRequestFailed(int); - method public abstract void onTypefaceRetrieved(android.graphics.Typeface); - field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd - field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1 - field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2 - field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3 - field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff - field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe - } - public class Xfermode { ctor public Xfermode(); } @@ -25493,7 +25485,7 @@ package android.media { public static final class VolumeShaper.Configuration implements android.os.Parcelable { method public int describeContents(); - method public double getDurationMillis(); + method public long getDuration(); method public int getInterpolatorType(); method public static int getMaximumCurvePoints(); method public float[] getTimes(); @@ -25519,7 +25511,7 @@ package android.media { method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float); method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float); method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]); - method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double); + method public android.media.VolumeShaper.Configuration.Builder setDuration(long); method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int); } @@ -27967,13 +27959,13 @@ package android.net { ctor public deprecated NetworkRecommendationProvider(android.os.Handler); ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor); method public final android.os.IBinder getBinder(); - method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback); + method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback); method public abstract void onRequestScores(android.net.NetworkKey[]); - field public static final java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT"; - field public static final java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE"; + field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT"; + field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE"; } - public static class NetworkRecommendationProvider.ResultCallback { + public static deprecated class NetworkRecommendationProvider.ResultCallback { method public void onResult(android.net.RecommendationResult); } @@ -28040,7 +28032,7 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR; } - public final class RecommendationRequest implements android.os.Parcelable { + public final deprecated class RecommendationRequest implements android.os.Parcelable { ctor protected RecommendationRequest(android.os.Parcel); method public int describeContents(); method public android.net.wifi.WifiConfiguration[] getConnectableConfigs(); @@ -28055,7 +28047,7 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR; } - public static final class RecommendationRequest.Builder { + public static final deprecated class RecommendationRequest.Builder { ctor public RecommendationRequest.Builder(); method public android.net.RecommendationRequest build(); method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]); @@ -28065,7 +28057,7 @@ package android.net { method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]); } - public final class RecommendationResult implements android.os.Parcelable { + public final deprecated class RecommendationResult implements android.os.Parcelable { method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration); method public static android.net.RecommendationResult createDoNotConnectRecommendation(); method public int describeContents(); @@ -29483,11 +29475,11 @@ package android.net.wifi.aware { field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR; } - public class DiscoverySession { + public class DiscoverySession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String); method public android.net.NetworkSpecifier createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]); - method public void destroy(); method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]); } @@ -29539,8 +29531,6 @@ package android.net.wifi.aware { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR; - field public static final int MATCH_STYLE_ALL = 1; // 0x1 - field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0 field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1 field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0 } @@ -29549,7 +29539,6 @@ package android.net.wifi.aware { ctor public SubscribeConfig.Builder(); method public android.net.wifi.aware.SubscribeConfig build(); method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>); - method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]); method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int); @@ -29571,11 +29560,11 @@ package android.net.wifi.aware { field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1 } - public class WifiAwareSession { + public class WifiAwareSession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String); method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, byte[], byte[]); - method public void destroy(); method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); } @@ -38037,6 +38026,7 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + field public static final java.lang.String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -38097,7 +38087,6 @@ package android.provider { field public static final java.lang.String BOOT_COUNT = "boot_count"; field public static final java.lang.String CONTACT_METADATA_SYNC_ENABLED = "contact_metadata_sync_enabled"; field public static final android.net.Uri CONTENT_URI; - field public static final java.lang.String CURATE_SAVED_OPEN_NETWORKS = "curate_saved_open_networks"; field public static final java.lang.String DATA_ROAMING = "data_roaming"; field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; @@ -40151,15 +40140,12 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); - method public final deprecated void disableSelf(); method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); - method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public abstract void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -40233,7 +40219,6 @@ package android.service.autofill { method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); - method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -40769,6 +40754,7 @@ package android.service.resolver { method public void onPredictSharingProbabilities(java.util.List<android.service.resolver.ResolverTarget>); method public void onTrainRankingModel(java.util.List<android.service.resolver.ResolverTarget>, int); field public static final java.lang.String BIND_PERMISSION = "android.permission.BIND_RESOLVER_RANKER_SERVICE"; + field public static final java.lang.String HOLD_PERMISSION = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; field public static final java.lang.String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService"; } @@ -43768,6 +43754,7 @@ package android.telephony { method public void sendDialerSpecialCode(java.lang.String); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); + method public void sendVisualVoicemailSms(java.lang.String, int, java.lang.String, android.app.PendingIntent); method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method public void setDataEnabled(boolean); method public void setDataEnabled(int, boolean); @@ -43777,6 +43764,7 @@ package android.telephony { method public boolean setRadio(boolean); method public boolean setRadioPower(boolean); method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); + method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri); method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean); @@ -43861,7 +43849,6 @@ package android.telephony { field public static final int SIM_STATE_UNKNOWN = 0; // 0x0 field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff - field public static final int USSD_RETURN_SUCCESS = 100; // 0x64 field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm"; field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } @@ -46312,7 +46299,7 @@ package android.text.util { method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter); field public static final int ALL = 15; // 0xf field public static final int EMAIL_ADDRESSES = 2; // 0x2 - field public static final deprecated int MAP_ADDRESSES = 8; // 0x8 + field public static final int MAP_ADDRESSES = 8; // 0x8 field public static final int PHONE_NUMBERS = 4; // 0x4 field public static final int WEB_URLS = 1; // 0x1 field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter; @@ -50171,8 +50158,9 @@ package android.view { method public abstract void setTextLines(int[], int[]); method public abstract void setTextStyle(float, int, int, int); method public abstract void setTransformation(android.graphics.Matrix); - method public abstract void setUrl(java.lang.String); + method public abstract deprecated void setUrl(java.lang.String); method public abstract void setVisibility(int); + method public abstract void setWebDomain(java.lang.String); } public static abstract class ViewStructure.HtmlInfo { @@ -50738,7 +50726,9 @@ package android.view.accessibility { public final class AccessibilityManager { method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); + method public void addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler); method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); + method public void addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler); method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList(); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); @@ -51419,6 +51409,8 @@ package android.view.autofill { method public void cancel(); method public void commit(); method public void disableOwnedAutofillServices(); + method public boolean hasEnabledAutofillServices(); + method public boolean isAutofillSupported(); method public boolean isEnabled(); method public void notifyValueChanged(android.view.View); method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue); @@ -51433,7 +51425,6 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -51867,12 +51858,7 @@ package android.view.inputmethod { package android.view.textclassifier { - public abstract interface LinksInfo { - method public abstract boolean apply(java.lang.CharSequence); - } - public final class TextClassificationManager { - method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); method public android.view.textclassifier.TextClassifier getTextClassifier(); method public void setTextClassifier(android.view.textclassifier.TextClassifier); } @@ -51900,7 +51886,6 @@ package android.view.textclassifier { } public abstract interface TextClassifier { - method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList); field public static final android.view.textclassifier.TextClassifier NO_OP; @@ -51911,20 +51896,6 @@ package android.view.textclassifier { field public static final java.lang.String TYPE_URL = "url"; } - public final class TextLanguage { - method public float getConfidenceScore(java.util.Locale); - method public int getEndIndex(); - method public java.util.Locale getLanguage(int); - method public int getLanguageCount(); - method public int getStartIndex(); - } - - public static final class TextLanguage.Builder { - ctor public TextLanguage.Builder(int, int); - method public android.view.textclassifier.TextLanguage build(); - method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); - } - public final class TextSelection { method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); @@ -52669,7 +52640,7 @@ package android.webkit { method public void documentHasImages(android.os.Message); method public static void enableSlowWholeDocumentDraw(); method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>); - method public static deprecated java.lang.String findAddress(java.lang.String); + method public static java.lang.String findAddress(java.lang.String); method public deprecated int findAll(java.lang.String); method public void findAllAsync(java.lang.String); method public void findNext(boolean); diff --git a/api/system-removed.txt b/api/system-removed.txt index 4862bb76f0c2..ed813631e394 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -1,7 +1,6 @@ package android.app { public class Notification implements android.os.Parcelable { - method public deprecated int getBadgeIcon(); method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } diff --git a/api/test-current.txt b/api/test-current.txt index 962aaeec51fa..c00795db237b 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -3637,7 +3637,6 @@ package android.app { method public boolean isInMultiWindowMode(); method public boolean isInPictureInPictureMode(); method public boolean isLocalVoiceInteractionSupported(); - method public boolean isOverlayWithDecorCaptionEnabled(); method public boolean isTaskRoot(); method public boolean isVoiceInteraction(); method public boolean isVoiceInteractionRoot(); @@ -3762,7 +3761,6 @@ package android.app { method public void setImmersive(boolean); method public void setIntent(android.content.Intent); method public final void setMediaController(android.media.session.MediaController); - method public void setOverlayWithDecorCaptionEnabled(boolean); method public void setPictureInPictureArgs(android.app.PictureInPictureArgs); method public final deprecated void setProgress(int); method public final deprecated void setProgressBarIndeterminate(boolean); @@ -5138,6 +5136,7 @@ package android.app { method public int getBadgeIconType(); method public java.lang.String getChannel(); method public java.lang.String getGroup(); + method public int getGroupAlertBehavior(); method public android.graphics.drawable.Icon getLargeIcon(); method public java.lang.CharSequence getSettingsText(); method public java.lang.String getShortcutId(); @@ -5213,6 +5212,9 @@ package android.app { field public static final int FLAG_ONGOING_EVENT = 2; // 0x2 field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8 field public static final deprecated int FLAG_SHOW_LIGHTS = 1; // 0x1 + field public static final int GROUP_ALERT_ALL = 0; // 0x0 + field public static final int GROUP_ALERT_CHILDREN = 2; // 0x2 + field public static final int GROUP_ALERT_SUMMARY = 1; // 0x1 field public static final java.lang.String INTENT_CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES"; field public static final deprecated int PRIORITY_DEFAULT = 0; // 0x0 field public static final deprecated int PRIORITY_HIGH = 1; // 0x1 @@ -5359,6 +5361,7 @@ package android.app { method public android.app.Notification.Builder setExtras(android.os.Bundle); method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method public android.app.Notification.Builder setGroup(java.lang.String); + method public android.app.Notification.Builder setGroupAlertBehavior(int); method public android.app.Notification.Builder setGroupSummary(boolean); method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap); method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); @@ -6690,8 +6693,8 @@ package android.app.assist { method public int getTextStyle(); method public int getTop(); method public android.graphics.Matrix getTransformation(); - method public java.lang.String getUrl(); method public int getVisibility(); + method public java.lang.String getWebDomain(); method public int getWidth(); method public boolean isAccessibilityFocused(); method public boolean isActivated(); @@ -13821,7 +13824,6 @@ package android.graphics { } public class Typeface { - method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback); method public static android.graphics.Typeface create(java.lang.String, int); method public static android.graphics.Typeface create(android.graphics.Typeface, int); method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String); @@ -13856,17 +13858,6 @@ package android.graphics { method public android.graphics.Typeface.Builder setWeight(int); } - public static abstract deprecated interface Typeface.FontRequestCallback { - method public abstract void onTypefaceRequestFailed(int); - method public abstract void onTypefaceRetrieved(android.graphics.Typeface); - field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd - field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1 - field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2 - field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3 - field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff - field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe - } - public class Xfermode { ctor public Xfermode(); } @@ -23754,7 +23745,7 @@ package android.media { public static final class VolumeShaper.Configuration implements android.os.Parcelable { method public int describeContents(); - method public double getDurationMillis(); + method public long getDuration(); method public int getInterpolatorType(); method public static int getMaximumCurvePoints(); method public float[] getTimes(); @@ -23780,7 +23771,7 @@ package android.media { method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float); method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float); method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]); - method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double); + method public android.media.VolumeShaper.Configuration.Builder setDuration(long); method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int); } @@ -26848,10 +26839,10 @@ package android.net.wifi.aware { field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR; } - public class DiscoverySession { + public class DiscoverySession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String); - method public void destroy(); method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]); } @@ -26903,8 +26894,6 @@ package android.net.wifi.aware { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR; - field public static final int MATCH_STYLE_ALL = 1; // 0x1 - field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0 field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1 field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0 } @@ -26913,7 +26902,6 @@ package android.net.wifi.aware { ctor public SubscribeConfig.Builder(); method public android.net.wifi.aware.SubscribeConfig build(); method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>); - method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String); method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]); method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int); @@ -26935,10 +26923,10 @@ package android.net.wifi.aware { field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1 } - public class WifiAwareSession { + public class WifiAwareSession implements java.lang.AutoCloseable { + method public void close(); method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]); method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String); - method public void destroy(); method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler); } @@ -35082,6 +35070,7 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + field public static final java.lang.String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -37190,15 +37179,12 @@ package android.service.autofill { public abstract class AutofillService extends android.app.Service { ctor public AutofillService(); - method public final deprecated void disableSelf(); method public final android.service.autofill.FillEventHistory getFillEventHistory(); method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); - method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public abstract void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -37272,7 +37258,6 @@ package android.service.autofill { method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); - method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -40435,10 +40420,12 @@ package android.telephony { method public void sendDialerSpecialCode(java.lang.String); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); + method public void sendVisualVoicemailSms(java.lang.String, int, java.lang.String, android.app.PendingIntent); method public void setDataEnabled(boolean); method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String); method public boolean setOperatorBrandOverride(java.lang.String); method public boolean setPreferredNetworkTypeToGlobal(); + method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri); method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean); @@ -40512,7 +40499,6 @@ package android.telephony { field public static final int SIM_STATE_UNKNOWN = 0; // 0x0 field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff - field public static final int USSD_RETURN_SUCCESS = 100; // 0x64 field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm"; field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } @@ -40530,8 +40516,6 @@ package android.telephony { method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle); method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms); method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask); - method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent); - method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService"; } @@ -42934,7 +42918,7 @@ package android.text.util { method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter); field public static final int ALL = 15; // 0xf field public static final int EMAIL_ADDRESSES = 2; // 0x2 - field public static final deprecated int MAP_ADDRESSES = 8; // 0x8 + field public static final int MAP_ADDRESSES = 8; // 0x8 field public static final int PHONE_NUMBERS = 4; // 0x4 field public static final int WEB_URLS = 1; // 0x1 field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter; @@ -46968,8 +46952,9 @@ package android.view { method public abstract void setTextLines(int[], int[]); method public abstract void setTextStyle(float, int, int, int); method public abstract void setTransformation(android.graphics.Matrix); - method public abstract void setUrl(java.lang.String); + method public abstract deprecated void setUrl(java.lang.String); method public abstract void setVisibility(int); + method public abstract void setWebDomain(java.lang.String); } public static abstract class ViewStructure.HtmlInfo { @@ -47534,7 +47519,9 @@ package android.view.accessibility { public final class AccessibilityManager { method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); + method public void addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler); method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); + method public void addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler); method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList(); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); @@ -48217,6 +48204,8 @@ package android.view.autofill { method public void cancel(); method public void commit(); method public void disableOwnedAutofillServices(); + method public boolean hasEnabledAutofillServices(); + method public boolean isAutofillSupported(); method public boolean isEnabled(); method public void notifyValueChanged(android.view.View); method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue); @@ -48231,7 +48220,6 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -48665,12 +48653,7 @@ package android.view.inputmethod { package android.view.textclassifier { - public abstract interface LinksInfo { - method public abstract boolean apply(java.lang.CharSequence); - } - public final class TextClassificationManager { - method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence); method public android.view.textclassifier.TextClassifier getTextClassifier(); method public void setTextClassifier(android.view.textclassifier.TextClassifier); } @@ -48698,7 +48681,6 @@ package android.view.textclassifier { } public abstract interface TextClassifier { - method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList); method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList); field public static final android.view.textclassifier.TextClassifier NO_OP; @@ -48709,20 +48691,6 @@ package android.view.textclassifier { field public static final java.lang.String TYPE_URL = "url"; } - public final class TextLanguage { - method public float getConfidenceScore(java.util.Locale); - method public int getEndIndex(); - method public java.util.Locale getLanguage(int); - method public int getLanguageCount(); - method public int getStartIndex(); - } - - public static final class TextLanguage.Builder { - ctor public TextLanguage.Builder(int, int); - method public android.view.textclassifier.TextLanguage build(); - method public android.view.textclassifier.TextLanguage.Builder setLanguage(java.util.Locale, float); - } - public final class TextSelection { method public float getConfidenceScore(java.lang.String); method public java.lang.String getEntity(int); @@ -49374,7 +49342,7 @@ package android.webkit { method public void documentHasImages(android.os.Message); method public static void enableSlowWholeDocumentDraw(); method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>); - method public static deprecated java.lang.String findAddress(java.lang.String); + method public static java.lang.String findAddress(java.lang.String); method public deprecated int findAll(java.lang.String); method public void findAllAsync(java.lang.String); method public void findNext(boolean); diff --git a/api/test-removed.txt b/api/test-removed.txt index dc9c54e8b1cd..73dd09650750 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -1,7 +1,6 @@ package android.app { public class Notification implements android.os.Parcelable { - method public deprecated int getBadgeIcon(); method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } diff --git a/cmds/vr/src/com/android/commands/vr/Vr.java b/cmds/vr/src/com/android/commands/vr/Vr.java index 3fb40fbc2ca9..bf97bbaa019b 100644 --- a/cmds/vr/src/com/android/commands/vr/Vr.java +++ b/cmds/vr/src/com/android/commands/vr/Vr.java @@ -16,6 +16,7 @@ package com.android.commands.vr; +import android.app.CompatibilityDisplayProperties; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; @@ -36,7 +37,10 @@ public final class Vr extends BaseCommand { (new Vr()).run(args); } - private static final String COMMAND_SET_PERSISTENT_VR_MODE_ENABLED = "set-persistent-vr-mode-enabled"; + private static final String COMMAND_SET_PERSISTENT_VR_MODE_ENABLED = + "set-persistent-vr-mode-enabled"; + private static final String COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES = + "set-display-props"; private IVrManager mVrService; @@ -44,7 +48,8 @@ public final class Vr extends BaseCommand { public void onShowUsage(PrintStream out) { out.println( "usage: vr [subcommand]\n" + - "usage: vr set-persistent-vr-mode-enabled [true|false]\n" + "usage: vr set-persistent-vr-mode-enabled [true|false]\n" + + "usage: vr set-display-props [width] [height] [dpi]\n" ); } @@ -58,6 +63,9 @@ public final class Vr extends BaseCommand { String command = nextArgRequired(); switch (command) { + case COMMAND_SET_COMPATIBILITY_DISPLAY_PROPERTIES: + runSetCompatibilityDisplayProperties(); + break; case COMMAND_SET_PERSISTENT_VR_MODE_ENABLED: runSetPersistentVrModeEnabled(); break; @@ -66,6 +74,26 @@ public final class Vr extends BaseCommand { } } + private void runSetCompatibilityDisplayProperties() throws RemoteException { + String widthStr = nextArgRequired(); + int width = Integer.parseInt(widthStr); + + String heightStr = nextArgRequired(); + int height = Integer.parseInt(heightStr); + + String dpiStr = nextArgRequired(); + int dpi = Integer.parseInt(dpiStr); + + CompatibilityDisplayProperties compatDisplayProperties = + new CompatibilityDisplayProperties(width, height, dpi); + + try { + mVrService.setCompatibilityDisplayProperties(compatDisplayProperties); + } catch (RemoteException re) { + System.err.println("Error: Can't set persistent mode " + re); + } + } + private void runSetPersistentVrModeEnabled() throws RemoteException { String enableStr = nextArg(); boolean enabled = Boolean.parseBoolean(enableStr); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index b320d5d83cc7..06b09c041f1f 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -345,7 +345,13 @@ public class AccountManager { "android.accounts.LOGIN_ACCOUNTS_CHANGED"; /** - * Action sent as a broadcast Intent by the AccountsService when any account is removed. + * Action sent as a broadcast Intent by the AccountsService when any account is removed + * or renamed. Only applications which were able to see the account will receive the intent. + * Intent extra will include the following fields: + * <ul> + * <li> {@link #KEY_ACCOUNT_NAME} - the name of the removed account + * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account + * </ul> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(includeBackground = true) diff --git a/core/java/android/annotation/AnyThread.java b/core/java/android/annotation/AnyThread.java index c101548c0c16..e173bd144832 100644 --- a/core/java/android/annotation/AnyThread.java +++ b/core/java/android/annotation/AnyThread.java @@ -15,30 +15,34 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** - * Denotes that the annotated method can be called from any thread (e.g. it is "thread safe".) - * If the annotated element is a class, then all methods in the class can be called - * from any thread. + * Denotes that the annotated method can be called from any thread (e.g. it is + * "thread safe".) If the annotated element is a class, then all methods in the + * class can be called from any thread. * <p> - * The main purpose of this method is to indicate that you believe a method can be called - * from any thread; static tools can then check that nothing you call from within this method - * or class have more strict threading requirements. + * The main purpose of this method is to indicate that you believe a method can + * be called from any thread; static tools can then check that nothing you call + * from within this method or class have more strict threading requirements. * <p> * Example: - * <pre><code> + * + * <pre> + * <code> * @AnyThread * public void deliverResult(D data) { ... } - * </code></pre> + * </code> + * </pre> * - * {@hide} + * @memberDoc This method is safe to call from any thread. + * @hide */ @Retention(SOURCE) @Target({METHOD,CONSTRUCTOR,TYPE}) diff --git a/core/java/android/annotation/BroadcastBehavior.java b/core/java/android/annotation/BroadcastBehavior.java index 9b2ca3120290..70d82cb5151b 100644 --- a/core/java/android/annotation/BroadcastBehavior.java +++ b/core/java/android/annotation/BroadcastBehavior.java @@ -53,4 +53,9 @@ public @interface BroadcastBehavior { * @see Intent#FLAG_RECEIVER_INCLUDE_BACKGROUND */ boolean includeBackground() default false; + + /** + * This broadcast is protected and can only be sent by the OS. + */ + boolean protectedBroadcast() default false; } diff --git a/core/java/android/annotation/CallSuper.java b/core/java/android/annotation/CallSuper.java index b10a28acf7a4..c16b51161cac 100644 --- a/core/java/android/annotation/CallSuper.java +++ b/core/java/android/annotation/CallSuper.java @@ -15,24 +15,29 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Denotes that any overriding methods should invoke this method as well. * <p> * Example: - * <pre><code> + * + * <pre> + * <code> * @CallSuper * public abstract void onFocusLost(); - * </code></pre> + * </code> + * </pre> * + * @memberDoc If you override this method you <em>must</em> call through to the + * superclass implementation. * @hide */ @Retention(SOURCE) @Target({METHOD}) public @interface CallSuper { -}
\ No newline at end of file +} diff --git a/core/java/android/annotation/MainThread.java b/core/java/android/annotation/MainThread.java index c6ac30c5c5da..d15cfcd94ba7 100644 --- a/core/java/android/annotation/MainThread.java +++ b/core/java/android/annotation/MainThread.java @@ -15,9 +15,6 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; @@ -25,6 +22,9 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.os.Looper; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Denotes that the annotated method should only be called on the main thread. * If the annotated element is a class, then all methods in the class should be diff --git a/core/java/android/annotation/SuppressAutoDoc.java b/core/java/android/annotation/SuppressAutoDoc.java index 0f8fa6cba0a9..e34e03bcee29 100644 --- a/core/java/android/annotation/SuppressAutoDoc.java +++ b/core/java/android/annotation/SuppressAutoDoc.java @@ -16,14 +16,17 @@ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - +import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.LOCAL_VARIABLE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** * Denotes that any automatically generated documentation should be suppressed * for the annotated method, parameter, or field. @@ -31,6 +34,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; * @hide */ @Retention(SOURCE) -@Target({METHOD, PARAMETER, FIELD}) +@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) public @interface SuppressAutoDoc { } diff --git a/core/java/android/annotation/UiThread.java b/core/java/android/annotation/UiThread.java index 53121e7d532f..b2778966dacb 100644 --- a/core/java/android/annotation/UiThread.java +++ b/core/java/android/annotation/UiThread.java @@ -15,28 +15,36 @@ */ package android.annotation; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.os.Looper; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + /** - * Denotes that the annotated method or constructor should only be called on the UI thread. - * If the annotated element is a class, then all methods in the class should be called - * on the UI thread. + * Denotes that the annotated method or constructor should only be called on the + * UI thread. If the annotated element is a class, then all methods in the class + * should be called on the UI thread. * <p> * Example: - * <pre><code> + * + * <pre> + * <code> * @UiThread * public abstract void setText(@NonNull String text) { ... } - * </code></pre> + * </code> + * </pre> * - * {@hide} + * @memberDoc This method must be called on the thread that originally created + * this UI element. This is typically the + * {@linkplain Looper#getMainLooper() main thread} of your app. + * @hide */ @Retention(SOURCE) @Target({METHOD,CONSTRUCTOR,TYPE}) public @interface UiThread { -}
\ No newline at end of file +} diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 1b972f79e48c..cdfb52b132f1 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -696,9 +696,6 @@ public class Activity extends ContextThemeWrapper private static final String TAG = "Activity"; private static final boolean DEBUG_LIFECYCLE = false; - // TODO(b/33197203): set to false once stable - private static final boolean DEBUG_AUTO_FILL = true; - /** Standard activity result: operation canceled. */ public static final int RESULT_CANCELED = 0; /** Standard activity result: operation succeeded. */ @@ -5844,7 +5841,7 @@ public class Activity extends ContextThemeWrapper * @return Returns the single SharedPreferences instance that can be used * to retrieve and modify the preference values. */ - public SharedPreferences getPreferences(int mode) { + public SharedPreferences getPreferences(@Context.PreferencesMode int mode) { return getSharedPreferences(getLocalClassName(), mode); } @@ -7323,6 +7320,7 @@ public class Activity extends ContextThemeWrapper * @return True if caption is displayed on content, false if it pushes the content down. * * @see #setOverlayWithDecorCaptionEnabled(boolean) + * @hide */ public boolean isOverlayWithDecorCaptionEnabled() { return mWindow.isOverlayWithDecorCaptionEnabled(); @@ -7334,6 +7332,7 @@ public class Activity extends ContextThemeWrapper * This affects only freeform windows since they display the caption and only the main * window of the activity. The caption is used to drag the window around and also shows * maximize and close action buttons. + * @hide */ public void setOverlayWithDecorCaptionEnabled(boolean enabled) { mWindow.setOverlayWithDecorCaptionEnabled(enabled); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 44c275f42161..1ab45b56e5ca 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2350,6 +2350,14 @@ public class ActivityManager { } } + /** @hide */ + @IntDef(flag = true, prefix = { "MOVE_TASK_" }, value = { + MOVE_TASK_WITH_HOME, + MOVE_TASK_NO_USER_ACTION, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MoveTaskFlags {} + /** * Flag for {@link #moveTaskToFront(int, int)}: also move the "home" * activity along with the task, so it is positioned immediately behind @@ -2370,28 +2378,26 @@ public class ActivityManager { * * @param taskId The identifier of the task to be moved, as found in * {@link RunningTaskInfo} or {@link RecentTaskInfo}. - * @param flags Additional operational flags, 0 or more of - * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}. + * @param flags Additional operational flags. */ - public void moveTaskToFront(int taskId, int flags) { + @RequiresPermission(android.Manifest.permission.REORDER_TASKS) + public void moveTaskToFront(int taskId, @MoveTaskFlags int flags) { moveTaskToFront(taskId, flags, null); } /** * Ask that the task associated with a given task ID be moved to the - * front of the stack, so it is now visible to the user. Requires that - * the caller hold permission {@link android.Manifest.permission#REORDER_TASKS} - * or a SecurityException will be thrown. + * front of the stack, so it is now visible to the user. * * @param taskId The identifier of the task to be moved, as found in * {@link RunningTaskInfo} or {@link RecentTaskInfo}. - * @param flags Additional operational flags, 0 or more of - * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}. + * @param flags Additional operational flags. * @param options Additional options for the operation, either null or * as per {@link Context#startActivity(Intent, android.os.Bundle) * Context.startActivity(Intent, Bundle)}. */ - public void moveTaskToFront(int taskId, int flags, Bundle options) { + @RequiresPermission(android.Manifest.permission.REORDER_TASKS) + public void moveTaskToFront(int taskId, @MoveTaskFlags int flags, Bundle options) { try { getService().moveTaskToFront(taskId, flags, options); } catch (RemoteException e) { @@ -3081,6 +3087,21 @@ public class ActivityManager { */ public int lastTrimLevel; + /** @hide */ + @IntDef(prefix = { "IMPORTANCE_" }, value = { + IMPORTANCE_FOREGROUND, + IMPORTANCE_FOREGROUND_SERVICE, + IMPORTANCE_TOP_SLEEPING, + IMPORTANCE_VISIBLE, + IMPORTANCE_PERCEPTIBLE, + IMPORTANCE_CANT_SAVE_STATE, + IMPORTANCE_SERVICE, + IMPORTANCE_CACHED, + IMPORTANCE_GONE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Importance {} + /** * Constant for {@link #importance}: This process is running the * foreground UI; that is, it is the thing currently at the top of the screen @@ -3190,7 +3211,7 @@ public class ActivityManager { * will be passed to a client, use {@link #procStateToImportanceForClient}. * @hide */ - public static int procStateToImportance(int procState) { + public static @Importance int procStateToImportance(int procState) { if (procState == PROCESS_STATE_NONEXISTENT) { return IMPORTANCE_GONE; } else if (procState >= PROCESS_STATE_HOME) { @@ -3219,7 +3240,8 @@ public class ActivityManager { * client's target SDK < {@link VERSION_CODES#O}. * @hide */ - public static int procStateToImportanceForClient(int procState, Context clientContext) { + public static @Importance int procStateToImportanceForClient(int procState, + Context clientContext) { final int importance = procStateToImportance(procState); // For pre O apps, convert to the old, wrong values. @@ -3235,7 +3257,7 @@ public class ActivityManager { } /** @hide */ - public static int importanceToProcState(int importance) { + public static int importanceToProcState(@Importance int importance) { if (importance == IMPORTANCE_GONE) { return PROCESS_STATE_NONEXISTENT; } else if (importance >= IMPORTANCE_CACHED) { @@ -3258,14 +3280,11 @@ public class ActivityManager { } /** - * The relative importance level that the system places on this - * process. May be one of {@link #IMPORTANCE_FOREGROUND}, - * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE}, or - * {@link #IMPORTANCE_CACHED}. These - * constants are numbered so that "more important" values are always - * smaller than "less important" values. + * The relative importance level that the system places on this process. + * These constants are numbered so that "more important" values are + * always smaller than "less important" values. */ - public int importance; + public @Importance int importance; /** * An additional ordering within a particular {@link #importance} @@ -3459,7 +3478,7 @@ public class ActivityManager { */ @SystemApi @TestApi @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) - public int getPackageImportance(String packageName) { + public @RunningAppProcessInfo.Importance int getPackageImportance(String packageName) { try { int procState = getService().getPackageProcessState(packageName, mContext.getOpPackageName()); @@ -3479,7 +3498,7 @@ public class ActivityManager { */ @SystemApi @TestApi @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS) - public int getUidImportance(int uid) { + public @RunningAppProcessInfo.Importance int getUidImportance(int uid) { try { int procState = getService().getUidProcessState(uid, mContext.getOpPackageName()); @@ -3505,7 +3524,7 @@ public class ActivityManager { * @param uid The uid whose importance has changed. * @param importance The new importance value as per {@link RunningAppProcessInfo}. */ - void onUidImportance(int uid, int importance); + void onUidImportance(int uid, @RunningAppProcessInfo.Importance int importance); } /** @@ -3527,7 +3546,7 @@ public class ActivityManager { */ @SystemApi @TestApi public void addOnUidImportanceListener(OnUidImportanceListener listener, - int importanceCutpoint) { + @RunningAppProcessInfo.Importance int importanceCutpoint) { synchronized (this) { if (mImportanceListeners.containsKey(listener)) { throw new IllegalArgumentException("Listener already registered: " + listener); @@ -3624,13 +3643,10 @@ public class ActivityManager { * processes to reclaim memory; the system will take care of restarting * these processes in the future as needed. * - * <p>You must hold the permission - * {@link android.Manifest.permission#KILL_BACKGROUND_PROCESSES} to be able to - * call this method. - * * @param packageName The name of the package whose processes are to * be killed. */ + @RequiresPermission(Manifest.permission.KILL_BACKGROUND_PROCESSES) public void killBackgroundProcesses(String packageName) { try { getService().killBackgroundProcesses(packageName, @@ -4002,13 +4018,13 @@ public class ActivityManager { * Perform a system dump of various state associated with the given application * package name. This call blocks while the dump is being performed, so should * not be done on a UI thread. The data will be written to the given file - * descriptor as text. An application must hold the - * {@link android.Manifest.permission#DUMP} permission to make this call. + * descriptor as text. * @param fd The file descriptor that the dump should be written to. The file * descriptor is <em>not</em> closed by this function; the caller continues to * own it. * @param packageName The name of the package that is to be dumped. */ + @RequiresPermission(Manifest.permission.DUMP) public void dumpPackageState(FileDescriptor fd, String packageName) { dumpPackageStateStatic(fd, packageName); } @@ -4263,8 +4279,7 @@ public class ActivityManager { /** * Enable more aggressive scheduling for latency-sensitive low-runtime VR threads that persist - * beyond a single process. It requires holding the - * {@link android.Manifest.permission#RESTRICTED_VR_ACCESS} permission. Only one thread can be a + * beyond a single process. Only one thread can be a * persistent VR thread at a time, and that thread may be subject to restrictions on the amount * of time it can run. Calling this method will disable aggressive scheduling for non-persistent * VR threads set via {@link #setVrThread}. If persistent VR mode is disabled then the diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5022d7d9622b..46ce94f36341 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3004,7 +3004,7 @@ public final class ActivityThread { // - it needs an IAutoFillCallback boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL; - // TODO(b/33197203): decide if lastSessionId logic applies to autofill sessions + // TODO: decide if lastSessionId logic applies to autofill sessions if (mLastSessionId != cmd.sessionId) { // Clear the existing structures mLastSessionId = cmd.sessionId; @@ -3032,8 +3032,6 @@ public final class ActivityThread { if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) { structure = new AssistStructure(r.activity, forAutofill); Intent activityIntent = r.activity.getIntent(); - // TODO(b/33197203): re-evaluate conditions below for autofill. In particular, - // FLAG_SECURE might be allowed on AUTO_FILL but not on AUTO_FILL_SAVE) boolean notSecure = r.window == null || (r.window.getAttributes().flags & WindowManager.LayoutParams.FLAG_SECURE) == 0; @@ -3059,7 +3057,7 @@ public final class ActivityThread { structure = new AssistStructure(); } - // TODO(b/33197203): decide if lastSessionId logic applies to autofill sessions + // TODO: decide if lastSessionId logic applies to autofill sessions structure.setAcquisitionStartTime(startTime); structure.setAcquisitionEndTime(SystemClock.uptimeMillis()); diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java index c561a1908b21..3221c5d89543 100644 --- a/core/java/android/app/AlarmManager.java +++ b/core/java/android/app/AlarmManager.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.IntDef; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.content.Context; @@ -34,6 +35,8 @@ import android.util.Log; import libcore.util.ZoneInfoDB; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * This class provides access to the system alarm services. These allow you @@ -78,6 +81,16 @@ import java.io.IOException; public class AlarmManager { private static final String TAG = "AlarmManager"; + /** @hide */ + @IntDef(prefix = { "RTC", "ELAPSED" }, value = { + RTC_WAKEUP, + RTC, + ELAPSED_REALTIME_WAKEUP, + ELAPSED_REALTIME, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AlarmType {} + /** * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} * (wall clock time in UTC), which will wake up the device when @@ -311,8 +324,7 @@ public class AlarmManager { * will be treated as exact. * </div> * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param operation Action to perform when the alarm goes off; @@ -332,7 +344,7 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void set(int type, long triggerAtMillis, PendingIntent operation) { + public void set(@AlarmType int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null, null, null, null); } @@ -346,8 +358,7 @@ public class AlarmManager { * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param tag string describing the alarm, used for logging and battery-use @@ -360,7 +371,7 @@ public class AlarmManager { * @param targetHandler {@link Handler} on which to execute the listener's onAlarm() * callback, or {@code null} to run that callback on the main looper. */ - public void set(int type, long triggerAtMillis, String tag, OnAlarmListener listener, + public void set(@AlarmType int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, null, listener, tag, targetHandler, null, null); @@ -399,8 +410,7 @@ public class AlarmManager { * whose {@code targetSdkVersion} is earlier than API 19 will continue to have all * of their alarms, including repeating alarms, treated as exact. * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should first * go off, using the appropriate clock (depending on the alarm type). * @param intervalMillis interval in milliseconds between subsequent repeats @@ -422,7 +432,7 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void setRepeating(int type, long triggerAtMillis, + public void setRepeating(@AlarmType int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null, null, null, null, null); @@ -448,8 +458,7 @@ public class AlarmManager { * at precisely-specified times with no acceptable variation, applications can use * {@link #setExact(int, long, PendingIntent)}. * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param windowStartMillis The earliest time, in milliseconds, that the alarm should * be delivered, expressed in the appropriate clock's units (depending on the alarm * type). @@ -473,7 +482,7 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void setWindow(int type, long windowStartMillis, long windowLengthMillis, + public void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null, null, null, null); @@ -488,7 +497,7 @@ public class AlarmManager { * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ - public void setWindow(int type, long windowStartMillis, long windowLengthMillis, + public void setWindow(@AlarmType int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) { setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, null, listener, tag, targetHandler, null, null); @@ -508,8 +517,7 @@ public class AlarmManager { * scheduled as exact. Applications are strongly discouraged from using exact * alarms unnecessarily as they reduce the OS's ability to minimize battery use. * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param operation Action to perform when the alarm goes off; @@ -528,7 +536,7 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void setExact(int type, long triggerAtMillis, PendingIntent operation) { + public void setExact(@AlarmType int type, long triggerAtMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null, null, null, null); } @@ -542,8 +550,8 @@ public class AlarmManager { * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. */ - public void setExact(int type, long triggerAtMillis, String tag, OnAlarmListener listener, - Handler targetHandler) { + public void setExact(@AlarmType int type, long triggerAtMillis, String tag, + OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, null, listener, tag, targetHandler, null, null); } @@ -553,8 +561,8 @@ public class AlarmManager { * the given time. * @hide */ - public void setIdleUntil(int type, long triggerAtMillis, String tag, OnAlarmListener listener, - Handler targetHandler) { + public void setIdleUntil(@AlarmType int type, long triggerAtMillis, String tag, + OnAlarmListener listener, Handler targetHandler) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, null, listener, tag, targetHandler, null, null); } @@ -590,8 +598,8 @@ public class AlarmManager { /** @hide */ @SystemApi - public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, - PendingIntent operation, WorkSource workSource) { + public void set(@AlarmType int type, long triggerAtMillis, long windowMillis, + long intervalMillis, PendingIntent operation, WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null, null, workSource, null); } @@ -606,8 +614,9 @@ public class AlarmManager { * * @hide */ - public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, - String tag, OnAlarmListener listener, Handler targetHandler, WorkSource workSource) { + public void set(@AlarmType int type, long triggerAtMillis, long windowMillis, + long intervalMillis, String tag, OnAlarmListener listener, Handler targetHandler, + WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener, tag, targetHandler, workSource, null); } @@ -623,15 +632,17 @@ public class AlarmManager { * @hide */ @SystemApi - public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, - OnAlarmListener listener, Handler targetHandler, WorkSource workSource) { + public void set(@AlarmType int type, long triggerAtMillis, long windowMillis, + long intervalMillis, OnAlarmListener listener, Handler targetHandler, + WorkSource workSource) { setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener, null, targetHandler, workSource, null); } - private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, - int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag, - Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) { + private void setImpl(@AlarmType int type, long triggerAtMillis, long windowMillis, + long intervalMillis, int flags, PendingIntent operation, final OnAlarmListener listener, + String listenerTag, Handler targetHandler, WorkSource workSource, + AlarmClockInfo alarmClock) { if (triggerAtMillis < 0) { /* NOTYET if (mAlwaysExact) { @@ -728,8 +739,7 @@ public class AlarmManager { * assured that it will get similar behavior on both current and older versions * of Android. * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should first * go off, using the appropriate clock (depending on the alarm type). This * is inexact: the alarm will not fire before this time, but there may be a @@ -763,7 +773,7 @@ public class AlarmManager { * @see #INTERVAL_HALF_DAY * @see #INTERVAL_DAY */ - public void setInexactRepeating(int type, long triggerAtMillis, + public void setInexactRepeating(@AlarmType int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null, null, null, null); @@ -795,8 +805,7 @@ public class AlarmManager { * <p>Regardless of the app's target SDK version, this call always allows batching of the * alarm.</p> * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param operation Action to perform when the alarm goes off; @@ -814,7 +823,8 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { + public void setAndAllowWhileIdle(@AlarmType int type, long triggerAtMillis, + PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null, null, null, null); } @@ -848,8 +858,7 @@ public class AlarmManager { * device is idle it may take even more liberties with scheduling in order to optimize * for battery life.</p> * - * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, - * {@link #RTC}, or {@link #RTC_WAKEUP}. + * @param type type of alarm. * @param triggerAtMillis time in milliseconds that the alarm should go * off, using the appropriate clock (depending on the alarm type). * @param operation Action to perform when the alarm goes off; @@ -868,7 +877,8 @@ public class AlarmManager { * @see #RTC * @see #RTC_WAKEUP */ - public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) { + public void setExactAndAllowWhileIdle(@AlarmType int type, long triggerAtMillis, + PendingIntent operation) { setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_ALLOW_WHILE_IDLE, operation, null, null, null, null, null); } diff --git a/core/java/android/net/RecommendationRequest.aidl b/core/java/android/app/CompatibilityDisplayProperties.aidl index 76497b8a2270..626a63e05819 100644 --- a/core/java/android/net/RecommendationRequest.aidl +++ b/core/java/android/app/CompatibilityDisplayProperties.aidl @@ -1,11 +1,11 @@ -/** - * Copyright (c) 2016, The Android Open Source Project +/* + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ * limitations under the License. */ -package android.net; +package android.app; -parcelable RecommendationRequest; +/** @hide */ +parcelable CompatibilityDisplayProperties; diff --git a/core/java/android/app/CompatibilityDisplayProperties.java b/core/java/android/app/CompatibilityDisplayProperties.java new file mode 100644 index 000000000000..9a9bc2c40d94 --- /dev/null +++ b/core/java/android/app/CompatibilityDisplayProperties.java @@ -0,0 +1,123 @@ +/* + * 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 android.app; + +import android.content.ComponentName; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.PrintWriter; + +/** + * Display properties to be used by VR mode when creating a virtual display. + * + * @hide + */ +public class CompatibilityDisplayProperties implements Parcelable { + + /** + * The actual width, height and dpi. + */ + private final int mWidth; + private final int mHeight; + private final int mDpi; + + public CompatibilityDisplayProperties(int width, int height, int dpi) { + mWidth = width; + mHeight = height; + mDpi = dpi; + } + + @Override + public int hashCode() { + int result = getWidth(); + result = 31 * result + getHeight(); + result = 31 * result + getDpi(); + return result; + } + + @Override + public String toString() { + return "CompatibilityDisplayProperties{" + + "mWidth=" + mWidth + + ", mHeight=" + mHeight + + ", mDpi=" + mDpi + + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CompatibilityDisplayProperties that = (CompatibilityDisplayProperties) o; + + if (getWidth() != that.getWidth()) return false; + if (getHeight() != that.getHeight()) return false; + return getDpi() == that.getDpi(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mWidth); + dest.writeInt(mHeight); + dest.writeInt(mDpi); + } + + public static final Parcelable.Creator<CompatibilityDisplayProperties> CREATOR + = new Parcelable.Creator<CompatibilityDisplayProperties>() { + @Override + public CompatibilityDisplayProperties createFromParcel(Parcel source) { + return new CompatibilityDisplayProperties(source); + } + + @Override + public CompatibilityDisplayProperties[] newArray(int size) { + return new CompatibilityDisplayProperties[size]; + } + }; + + private CompatibilityDisplayProperties(Parcel source) { + mWidth = source.readInt(); + mHeight = source.readInt(); + mDpi = source.readInt(); + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "CompatibilityDisplayProperties:"); + pw.println(prefix + " width=" + mWidth); + pw.println(prefix + " height=" + mHeight); + pw.println(prefix + " dpi=" + mDpi); + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } + + public int getDpi() { + return mDpi; + } +} diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java index 88399e5d6695..c5dc86c79ef9 100644 --- a/core/java/android/app/InstantAppResolverService.java +++ b/core/java/android/app/InstantAppResolverService.java @@ -91,6 +91,9 @@ public abstract class InstantAppResolverService extends Service { @Override public void getInstantAppResolveInfoList( int digestPrefix[], String token, int sequence, IRemoteCallback callback) { + if (DEBUG_EPHEMERAL) { + Slog.v(TAG, "[" + token + "] Phase1 called; posting"); + } final SomeArgs args = SomeArgs.obtain(); args.arg1 = callback; args.arg2 = digestPrefix; @@ -103,6 +106,9 @@ public abstract class InstantAppResolverService extends Service { @Override public void getInstantAppIntentFilterList( int digestPrefix[], String token, String hostName, IRemoteCallback callback) { + if (DEBUG_EPHEMERAL) { + Slog.v(TAG, "[" + token + "] Phase2 called; posting"); + } final SomeArgs args = SomeArgs.obtain(); args.arg1 = callback; args.arg2 = digestPrefix; @@ -140,7 +146,7 @@ public abstract class InstantAppResolverService extends Service { void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, InstantAppResolutionCallback callback) { if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Instant resolver; getInstantAppResolveInfo;" + Slog.d(TAG, "[" + token + "] Phase1 request;" + " prefix: " + Arrays.toString(digestPrefix)); } onGetInstantAppResolveInfo(digestPrefix, token, callback); @@ -149,7 +155,7 @@ public abstract class InstantAppResolverService extends Service { void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName, InstantAppResolutionCallback callback) { if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Instant resolver; getInstantAppIntentFilter;" + Slog.d(TAG, "[" + token + "] Phase2 request;" + " prefix: " + Arrays.toString(digestPrefix)); } onGetInstantAppIntentFilter(digestPrefix, token, callback); diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index c0bf0c46988a..b8a5f572ccfc 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -169,9 +169,6 @@ public class KeyguardManager { * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} * is enabled that requires a password. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#DISABLE_KEYGUARD}. - * * @see #reenableKeyguard() */ @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) @@ -191,9 +188,6 @@ public class KeyguardManager { * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} * is enabled that requires a password. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#DISABLE_KEYGUARD}. - * * @see #disableKeyguard() */ @RequiresPermission(Manifest.permission.DISABLE_KEYGUARD) @@ -431,9 +425,6 @@ public class KeyguardManager { * This will, if the keyguard is secure, bring up the unlock screen of * the keyguard. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#DISABLE_KEYGUARD}. - * * @param callback Let's you know whether the operation was succesful and * it is safe to launch anything that would normally be considered safe * once the user has gotten past the keyguard. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 602cccb1070d..e53e3da4d216 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -676,7 +676,16 @@ public class Notification implements Parcelable * Finally, a notification can be made {@link #VISIBILITY_SECRET}, which will suppress its icon * and ticker until the user has bypassed the lockscreen. */ - public int visibility; + public @Visibility int visibility; + + /** @hide */ + @IntDef(prefix = { "VISIBILITY_" }, value = { + VISIBILITY_PUBLIC, + VISIBILITY_PRIVATE, + VISIBILITY_SECRET, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Visibility {} /** * Notification visibility: Show this notification in its entirety on all lockscreens. @@ -1097,6 +1106,45 @@ public class Notification implements Parcelable private String mShortcutId; private CharSequence mSettingsText; + /** @hide */ + @IntDef(prefix = { "GROUP_ALERT_" }, value = { + GROUP_ALERT_ALL, GROUP_ALERT_CHILDREN, GROUP_ALERT_SUMMARY + }) + @Retention(RetentionPolicy.SOURCE) + public @interface GroupAlertBehavior {} + + /** + * Constant for {@link Builder#setGroupAlertBehavior(int)}, meaning that all notifications in a + * group with sound or vibration ought to make sound or vibrate (respectively), so this + * notification will not be muted when it is in a group. + */ + public static final int GROUP_ALERT_ALL = 0; + + /** + * Constant for {@link Builder#setGroupAlertBehavior(int)}, meaning that all children + * notification in a group should be silenced (no sound or vibration) even if they are posted + * to a {@link NotificationChannel} that has sound and/or vibration. Use this constant to + * mute this notification if this notification is a group child. + * + * <p> For example, you might want to use this constant if you post a number of children + * notifications at once (say, after a periodic sync), and only need to notify the user + * audibly once. + */ + public static final int GROUP_ALERT_SUMMARY = 1; + + /** + * Constant for {@link Builder#setGroupAlertBehavior(int)}, meaning that the summary + * notification in a group should be silenced (no sound or vibration) even if they are + * posted to a {@link NotificationChannel} that has sound and/or vibration. Use this constant + * to mute this notification if this notification is a group summary. + * + * <p>For example, you might want to use this constant if only the children notifications + * in your group have content and the summary is only used to visually group notifications. + */ + public static final int GROUP_ALERT_CHILDREN = 2; + + private int mGroupAlertBehavior = GROUP_ALERT_ALL; + /** * If this notification is being shown as a badge, always show as a number. */ @@ -1869,6 +1917,8 @@ public class Notification implements Parcelable if (parcel.readInt() != 0) { mSettingsText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); } + + mGroupAlertBehavior = parcel.readInt(); } @Override @@ -1981,6 +2031,7 @@ public class Notification implements Parcelable that.mShortcutId = this.mShortcutId; that.mBadgeIcon = this.mBadgeIcon; that.mSettingsText = this.mSettingsText; + that.mGroupAlertBehavior = this.mGroupAlertBehavior; if (!heavy) { that.lightenPayload(); // will clean out extras @@ -2257,6 +2308,8 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } + + parcel.writeInt(mGroupAlertBehavior); } /** @@ -2462,17 +2515,6 @@ public class Notification implements Parcelable } /** - * @removed - * Returns what icon should be shown for this notification if it is being displayed in a - * Launcher that supports badging. Will be one of {@link #BADGE_ICON_NONE}, - * {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}. - */ - @Deprecated - public int getBadgeIcon() { - return mBadgeIcon; - } - - /** * Returns what icon should be shown for this notification if it is being displayed in a * Launcher that supports badging. Will be one of {@link #BADGE_ICON_NONE}, * {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}. @@ -2497,6 +2539,15 @@ public class Notification implements Parcelable } /** + * Returns which type of notifications in a group are responsible for audibly alerting the + * user. See {@link #GROUP_ALERT_ALL}, {@link #GROUP_ALERT_CHILDREN}, + * {@link #GROUP_ALERT_SUMMARY}. + */ + public @GroupAlertBehavior int getGroupAlertBehavior() { + return mGroupAlertBehavior; + } + + /** * The small icon representing this notification in the status bar and content view. * * @return the small icon representing this notification. @@ -2744,6 +2795,19 @@ public class Notification implements Parcelable } /** + * Sets the group alert behavior for this notification. Use this method to mute this + * notification if alerts for this notification's group should be handled by a different + * notification. This is only applicable for notifications that belong to a + * {@link #setGroup(String) group}. + * + * <p> The default value is {@link #GROUP_ALERT_ALL}.</p> + */ + public Builder setGroupAlertBehavior(@GroupAlertBehavior int groupAlertBehavior) { + mN.mGroupAlertBehavior = groupAlertBehavior; + return this; + } + + /** * Specifies the channel the notification should be delivered on. */ public Builder setChannel(String channelId) { @@ -3545,12 +3609,9 @@ public class Notification implements Parcelable /** * Specify the value of {@link #visibility}. * - * @param visibility One of {@link #VISIBILITY_PRIVATE} (the default), - * {@link #VISIBILITY_SECRET}, or {@link #VISIBILITY_PUBLIC}. - * * @return The same Builder. */ - public Builder setVisibility(int visibility) { + public Builder setVisibility(@Visibility int visibility) { mN.visibility = visibility; return this; } diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 9059daa62dc7..2dd33013ab8e 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -162,10 +162,9 @@ public final class NotificationChannel implements Parcelable { * broadcast. The recommended maximum length is 40 characters; the value may be * truncated if it is too long. * @param importance The importance of the channel. This controls how interruptive notifications - * posted to this channel are. See e.g. - * {@link NotificationManager#IMPORTANCE_DEFAULT}. + * posted to this channel are. */ - public NotificationChannel(String id, CharSequence name, int importance) { + public NotificationChannel(String id, CharSequence name, @Importance int importance) { this.mId = getTrimmedString(id); this.mName = name != null ? getTrimmedString(name.toString()) : null; this.mImportance = importance; diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index 4dd578e7deab..878c8c38516d 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -45,6 +45,26 @@ public class VrManager { } /** + * Sets the resolution and DPI of the compatibility virtual display used to display 2D + * applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param {@link android.app.CompatibilityDisplayProperties} properties to be set to the + * virtual display for 2D applications in VR mode. + * + * {@hide} + */ + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + try { + mService.setCompatibilityDisplayProperties(compatDisplayProp); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** * Initiate connection for system controller data. * * @param fd Controller data file descriptor. diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 82ad8252c5a9..a939eb046e11 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2972,9 +2972,9 @@ public class DevicePolicyManager { * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param timeoutMs The new timeout, after which the user will have to unlock with strong - * authentication method. A value of 0 means the admin is not participating in - * controlling the timeout. + * @param timeoutMs The new timeout in milliseconds, after which the user will have to unlock + * with strong authentication method. A value of 0 means the admin is not participating + * in controlling the timeout. * The minimum and maximum timeouts are platform-defined and are typically 1 hour and * 72 hours, respectively. Though discouraged, the admin may choose to require strong * auth at all times using {@link #KEYGUARD_DISABLE_FINGERPRINT} and/or @@ -3004,7 +3004,7 @@ public class DevicePolicyManager { * * @param admin The name of the admin component to check, or {@code null} to aggregate * accross all participating admins. - * @return The timeout or 0 if not configured for the provided admin. + * @return The timeout in milliseconds or 0 if not configured for the provided admin. */ public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin) { return getRequiredStrongAuthTimeout(admin, myUserId()); @@ -7681,6 +7681,8 @@ public class DevicePolicyManager { * * <p> Backup service is off by default when device owner is present. * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param enabled {@code true} to enable the backup service, {@code false} to disable it. * @throws SecurityException if {@code admin} is not a device owner. */ public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) { diff --git a/core/java/android/app/admin/SystemUpdateInfo.java b/core/java/android/app/admin/SystemUpdateInfo.java index 6bb9f2d0ea22..fa31273eff7b 100644 --- a/core/java/android/app/admin/SystemUpdateInfo.java +++ b/core/java/android/app/admin/SystemUpdateInfo.java @@ -89,8 +89,9 @@ public final class SystemUpdateInfo implements Parcelable { } /** - * Gets time when the update was first available. - * @return Time as given by {@link System#currentTimeMillis()} + * Gets time when the update was first available in milliseconds since midnight, January 1, + * 1970 UTC. + * @return Time in milliseconds as given by {@link System#currentTimeMillis()} */ public long getReceivedTime() { return mReceivedTime; diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 9e5c9e7741ce..d757f3edd892 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -6,6 +6,7 @@ import android.app.Activity; import android.content.ComponentName; import android.graphics.Matrix; import android.graphics.Rect; +import android.net.Uri; import android.os.BadParcelableException; import android.os.Binder; import android.os.Bundle; @@ -34,8 +35,18 @@ import java.util.ArrayList; import java.util.Arrays; /** - * Assist data automatically created by the platform's implementation - * of {@link android.app.Activity#onProvideAssistData}. + * Assist data automatically created by the platform's implementation of Assist and Autofill. + * + * <p>The structure is used for Assist purposes when created by + * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)}, + * or {@link View#onProvideVirtualStructure(ViewStructure)}. + * + * <p>The structure is used for Autofill purposes when created by + * {@link View#onProvideAutofillStructure(ViewStructure, int)}, + * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}. + * + * <p>For performance reasons, some properties of the Assist data might be available just for Assist + * or Autofill purposes; in those case, the property availability will be document in its javadoc. */ public class AssistStructure implements Parcelable { static final String TAG = "AssistStructure"; @@ -589,10 +600,10 @@ public class AssistStructure implements Parcelable { String mIdType; String mIdEntry; - // TODO(b/33197203): once we have more flags, it might be better to store the individual + // TODO: once we have more flags, it might be better to store the individual // fields (viewId and childId) of the field. AutofillId mAutofillId; - @View.AutofillType int mAutofillType; + @View.AutofillType int mAutofillType = View.AUTOFILL_TYPE_NONE; @Nullable String[] mAutofillHints; AutofillValue mAutofillValue; CharSequence[] mAutofillOptions; @@ -628,7 +639,7 @@ public class AssistStructure implements Parcelable { static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000; static final int FLAGS_OPAQUE = 0x00008000; - // TODO(b/33197203): autofill data is made of many fields and ideally we should verify + // TODO: autofill data is made of many fields and ideally we should verify // one-by-one to optimize what's sent over, but there isn't enough flag bits for that, we'd // need to create a 'flags2' or 'autoFillFlags' field and add these flags there. // So, to keep thinkg simpler for now, let's just use on flag for all of them... @@ -656,7 +667,7 @@ public class AssistStructure implements Parcelable { ViewNodeText mText; int mInputType; - String mUrl; + String mWebDomain; Bundle mExtras; LocaleList mLocaleList; @@ -733,7 +744,7 @@ public class AssistStructure implements Parcelable { mInputType = in.readInt(); } if ((flags&FLAGS_HAS_URL) != 0) { - mUrl = in.readString(); + mWebDomain = in.readString(); } if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) { mLocaleList = in.readParcelable(null); @@ -795,7 +806,7 @@ public class AssistStructure implements Parcelable { if (mInputType != 0) { flags |= FLAGS_HAS_INPUT_TYPE; } - if (mUrl != null) { + if (mWebDomain != null) { flags |= FLAGS_HAS_URL; } if (mLocaleList != null) { @@ -890,7 +901,7 @@ public class AssistStructure implements Parcelable { out.writeInt(mInputType); } if ((flags&FLAGS_HAS_URL) != 0) { - out.writeString(mUrl); + out.writeString(mWebDomain); } if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) { out.writeParcelable(mLocaleList, 0); @@ -938,18 +949,22 @@ public class AssistStructure implements Parcelable { /** * Gets the id that can be used to autofill the view contents. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist. + * <p>It's relevant set when the {@link AssistStructure} is used for Autofill purposes. + * + * @return id that can be used to autofill the view contents, or {@code null} if the + * structure was created for Assist purposes. */ - public AutofillId getAutofillId() { + @Nullable public AutofillId getAutofillId() { return mAutofillId; } /** * Gets the the type of value that can be used to autofill the view contents. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist. + * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes. + * + * @return autofill type as defined by {@link View#getAutofillType()}, + * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for Assist purposes. */ public @View.AutofillType int getAutofillType() { return mAutofillType; @@ -959,32 +974,26 @@ public class AssistStructure implements Parcelable { * Describes the content of a view so that a autofill service can fill in the appropriate * data. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist.</p> + * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes, + * not for Assist - see {@link View#getAutofillHints()} for more info. * - * @return The hints for this view + * @return The autofill hints for this view, or {@code null} if the structure was created + * for Assist purposes. */ @Nullable public String[] getAutofillHints() { return mAutofillHints; } /** - * @hide - * @deprecated use getAutofillHints() instead. - */ - // TODO(b/33197203): remove once clients don't use it anymore... - @Deprecated - @Nullable public String[] getAutoFillHints() { - return mAutofillHints; - } - - /** * Gets the the value of this view. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist. + * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes, + * not for Assist purposes. + * + * @return the autofill value of this view, or {@code null} if the structure was created + * for Assist purposes. */ - public AutofillValue getAutofillValue() { + @Nullable public AutofillValue getAutofillValue() { return mAutofillValue; } @@ -994,15 +1003,18 @@ public class AssistStructure implements Parcelable { } /** - * Gets the options that can be used to autofill this structure. + * Gets the options that can be used to autofill this view. * * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate * the meaning of each possible value in the list. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist. + * <p>It's relevant when the {@link AssistStructure} is used for Autofill purposes, not + * for Assist purposes. + * + * @return the options that can be used to autofill this view, or {@code null} if the + * structure was created for Assist purposes. */ - public CharSequence[] getAutofillOptions() { + @Nullable public CharSequence[] getAutofillOptions() { return mAutofillOptions; } @@ -1031,8 +1043,6 @@ public class AssistStructure implements Parcelable { */ public void updateAutofillValue(AutofillValue value) { mAutofillValue = value; - // TODO(b/33197203, b/33802548): decide whether to set text as well (so it would work - // with "legacy" views) or just the autofill value if (value.isText()) { mText.mText = value.getTextValue(); } @@ -1226,33 +1236,39 @@ public class AssistStructure implements Parcelable { } /** - * Returns the URL represented by this node. + * Returns the domain of the HTML document represented by this view. * - * <p>Typically used when the view associated with the node is a container for an HTML + * <p>Typically used when the view associated with the view is a container for an HTML * document. * * <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only - * use this URL for autofill purposes when it trusts the app generating it (i.e., the app + * use this domain for Autofill purposes when it trusts the app generating it (i.e., the app * defined by {@link AssistStructure#getActivityComponent()}). + * + * @return domain-only part of the document. For example, if the full URL is + * {@code http://my.site/login?user=my_user}, it returns {@code my.site}. */ - public String getUrl() { - return mUrl; + @Nullable public String getWebDomain() { + return mWebDomain; } /** - * Returns the HTML properties associated with this node. + * Returns the HTML properties associated with this view. * - * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not - * for assist. + * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes, + * not for Assist purposes. + * + * @return the HTML properties associated with this view, or {@code null} if the + * structure was created for Assist purposes. */ - public HtmlInfo getHtmlInfo() { + @Nullable public HtmlInfo getHtmlInfo() { return mHtmlInfo; } /** - * Returns the the list of locales associated with this node. + * Returns the the list of locales associated with this view. */ - public LocaleList getLocaleList() { + @Nullable public LocaleList getLocaleList() { return mLocaleList; } @@ -1710,7 +1726,18 @@ public class AssistStructure implements Parcelable { @Override public void setUrl(String url) { - mNode.mUrl = url; + if (url == null) return; + + setWebDomain(url); + } + + @Override + public void setWebDomain(@Nullable String domain) { + if (domain == null) { + mNode.mWebDomain = null; + return; + } + mNode.mWebDomain = Uri.parse(domain).getHost(); } @Override @@ -1932,9 +1959,9 @@ public class AssistStructure implements Parcelable { Log.i(TAG, prefix + " Text color fg: #" + Integer.toHexString(node.getTextColor()) + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor())); } - CharSequence url = node.getUrl(); - if (url != null) { - Log.i(TAG, prefix + " URL: " + url); + String webDomain = node.getWebDomain(); + if (webDomain != null) { + Log.i(TAG, prefix + " Web domain: " + webDomain); } HtmlInfo htmlInfo = node.getHtmlInfo(); if (htmlInfo != null) { @@ -1965,7 +1992,7 @@ public class AssistStructure implements Parcelable { + ", type=" + node.getAutofillType() + ", options=" + Arrays.toString(node.getAutofillOptions()) + ", inputType=" + node.getInputType() - + ", hints=" + Arrays.toString(node.getAutoFillHints()) + + ", hints=" + Arrays.toString(node.getAutofillHints()) + ", value=" + node.getAutofillValue() + ", sanitized=" + node.isSanitized()); } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 3538256761aa..007ea88d676c 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -18,8 +18,10 @@ package android.app.job; import static android.util.TimeUtils.formatDuration; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.content.ClipData; import android.content.ComponentName; import android.net.Uri; @@ -30,6 +32,8 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; @@ -43,6 +47,18 @@ import java.util.Objects; */ public class JobInfo implements Parcelable { private static String TAG = "JobInfo"; + + /** @hide */ + @IntDef(prefix = { "NETWORK_TYPE_" }, value = { + NETWORK_TYPE_NONE, + NETWORK_TYPE_ANY, + NETWORK_TYPE_UNMETERED, + NETWORK_TYPE_NOT_ROAMING, + NETWORK_TYPE_METERED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NetworkType {} + /** Default. */ public static final int NETWORK_TYPE_NONE = 0; /** This job requires network connectivity. */ @@ -64,6 +80,14 @@ public class JobInfo implements Parcelable { */ public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours. + /** @hide */ + @IntDef(prefix = { "BACKOFF_POLICY_" }, value = { + BACKOFF_POLICY_LINEAR, + BACKOFF_POLICY_EXPONENTIAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface BackoffPolicy {} + /** * Linearly back-off a failed job. See * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} @@ -349,14 +373,8 @@ public class JobInfo implements Parcelable { /** * The kind of connectivity requirements that the job has. - * - * @return One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY}, - * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, - * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}, - * {@link android.app.job.JobInfo#NETWORK_TYPE_METERED}, or - * {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING}, */ - public int getNetworkType() { + public @NetworkType int getNetworkType() { return networkType; } @@ -421,11 +439,9 @@ public class JobInfo implements Parcelable { } /** - * One of either {@link android.app.job.JobInfo#BACKOFF_POLICY_EXPONENTIAL}, or - * {@link android.app.job.JobInfo#BACKOFF_POLICY_LINEAR}, depending on which criteria you set - * when creating this job. + * Return the backoff policy of this job. */ - public int getBackoffPolicy() { + public @BackoffPolicy int getBackoffPolicy() { return backoffPolicy; } @@ -692,6 +708,13 @@ public class JobInfo implements Parcelable { private final Uri mUri; private final int mFlags; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = { "FLAG_" }, value = { + FLAG_NOTIFY_FOR_DESCENDANTS, + }) + public @interface Flags { } + /** * Flag for trigger: also trigger if any descendants of the given URI change. * Corresponds to the <var>notifyForDescendants</var> of @@ -702,10 +725,9 @@ public class JobInfo implements Parcelable { /** * Create a new trigger description. * @param uri The URI to observe. Must be non-null. - * @param flags Optional flags for the observer, either 0 or - * {@link #FLAG_NOTIFY_FOR_DESCENDANTS}. + * @param flags Flags for the observer. */ - public TriggerContentUri(@NonNull Uri uri, int flags) { + public TriggerContentUri(@NonNull Uri uri, @Flags int flags) { mUri = uri; mFlags = flags; } @@ -720,7 +742,7 @@ public class JobInfo implements Parcelable { /** * Return the flags supplied for the trigger. */ - public int getFlags() { + public @Flags int getFlags() { return mFlags; } @@ -886,7 +908,7 @@ public class JobInfo implements Parcelable { * job. If the network requested is not available your job will never run. See * {@link #setOverrideDeadline(long)} to change this behaviour. */ - public Builder setRequiredNetworkType(int networkType) { + public Builder setRequiredNetworkType(@NetworkType int networkType) { mNetworkType = networkType; return this; } @@ -1067,10 +1089,9 @@ public class JobInfo implements Parcelable { * mode. * @param initialBackoffMillis Millisecond time interval to wait initially when job has * failed. - * @param backoffPolicy is one of {@link #BACKOFF_POLICY_LINEAR} or - * {@link #BACKOFF_POLICY_EXPONENTIAL} */ - public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) { + public Builder setBackoffCriteria(long initialBackoffMillis, + @BackoffPolicy int backoffPolicy) { mBackoffPolicySet = true; mInitialBackoffMillis = initialBackoffMillis; mBackoffPolicy = backoffPolicy; @@ -1078,13 +1099,12 @@ public class JobInfo implements Parcelable { } /** - * Set whether or not to persist this job across device reboots. This will only have an - * effect if your application holds the permission - * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}. Otherwise an exception will - * be thrown. - * @param isPersisted True to indicate that the job will be written to disk and loaded at - * boot. + * Set whether or not to persist this job across device reboots. + * + * @param isPersisted True to indicate that the job will be written to + * disk and loaded at boot. */ + @RequiresPermission(android.Manifest.permission.RECEIVE_BOOT_COMPLETED) public Builder setPersisted(boolean isPersisted) { mIsPersisted = isPersisted; return this; diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java index 23f9eea65abe..1768828eb76c 100644 --- a/core/java/android/app/job/JobScheduler.java +++ b/core/java/android/app/job/JobScheduler.java @@ -16,6 +16,7 @@ package android.app.job; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -24,6 +25,8 @@ import android.content.Intent; import android.os.Bundle; import android.os.PersistableBundle; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -51,6 +54,14 @@ import java.util.List; * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}. */ public abstract class JobScheduler { + /** @hide */ + @IntDef(prefix = { "RESULT_" }, value = { + RESULT_FAILURE, + RESULT_SUCCESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Result {} + /** * Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur * if the run-time for your job is too short, or perhaps the system can't resolve the @@ -70,9 +81,9 @@ public abstract class JobScheduler { * @param job The job you wish scheduled. See * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs * you can schedule. - * @return An int representing ({@link #RESULT_SUCCESS} or {@link #RESULT_FAILURE}). + * @return the result of the schedule request. */ - public abstract int schedule(@NonNull JobInfo job); + public abstract @Result int schedule(@NonNull JobInfo job); /** * Similar to {@link #schedule}, but allows you to enqueue work for a new <em>or existing</em> @@ -107,9 +118,9 @@ public abstract class JobScheduler { * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs * you can schedule. * @param work New work to enqueue. This will be available later when the job starts running. - * @return An int representing ({@link #RESULT_SUCCESS} or {@link #RESULT_FAILURE}). + * @return the result of the enqueue request. */ - public abstract int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work); + public abstract @Result int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work); /** * @@ -118,11 +129,10 @@ public abstract class JobScheduler { * used to track battery usage and appIdleState. * @param userId User on behalf of whom this job is to be scheduled. * @param tag Debugging tag for dumps associated with this job (instead of the service class) - * @return {@link #RESULT_SUCCESS} or {@link #RESULT_FAILURE} * @hide */ @SystemApi - public abstract int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName, + public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName, int userId, String tag); /** diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index a64a023fec6b..06b0aacd8654 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -51,8 +51,6 @@ public class TrustManager { * Changes the lock status for the given user. This is only applicable to Managed Profiles, * other users should be handled by Keyguard. * - * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. - * * @param userId The id for the user to be locked/unlocked. * @param locked The value for that user's locked state. */ diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 9f35e85b0665..6327f34ebd5e 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -712,12 +712,13 @@ public class AppWidgetManager { * * @param profile The profile for which to get providers. Passing null is equivalent * to querying for only the calling user. - * @return The installed providers. + * @return The installed providers, or an empty list if none are found for the given user. * * @see android.os.Process#myUserHandle() * @see android.os.UserManager#getUserProfiles() */ - public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(@Nullable UserHandle profile) { + public @NonNull List<AppWidgetProviderInfo> getInstalledProvidersForProfile( + @Nullable UserHandle profile) { if (mService == null) { return Collections.emptyList(); } @@ -735,13 +736,20 @@ public class AppWidgetManager { * equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}. * @param profile The profile for which to get providers. Passing null is equivalent * to querying for only the calling user. - * @return The installed providers. + * @return The installed providers, or an empty list if none are found for the given + * package and user. + * @throws NullPointerException if the provided package name is null * * @see android.os.Process#myUserHandle() * @see android.os.UserManager#getUserProfiles() */ - public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName, - @Nullable UserHandle profile) { + public @NonNull List<AppWidgetProviderInfo> getInstalledProvidersForPackage( + @NonNull String packageName, @Nullable UserHandle profile) { + if (packageName == null) { + throw new NullPointerException("A non-null package must be passed to this method. " + + "If you want all widgets regardless of package, see " + + "getInstalledProvidersForProfile(UserHandle)"); + } if (mService == null) { return Collections.emptyList(); } diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 1ca2be5b2a1f..d1ad8de0b113 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -422,8 +422,6 @@ public final class BluetoothA2dp implements BluetoothProfile { * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param device Bluetooth device * @return priority of the device * @hide diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 735d84e72b67..d60d4db1cab1 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -697,7 +697,6 @@ public final class BluetoothAdapter { * Return true if Bluetooth is currently enabled and ready for use. * <p>Equivalent to: * <code>getBluetoothState() == STATE_ON</code> - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return true if the local adapter is turned on */ @@ -835,7 +834,6 @@ public final class BluetoothAdapter { * {@link #STATE_TURNING_ON}, * {@link #STATE_ON}, * {@link #STATE_TURNING_OFF}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return current state of Bluetooth adapter */ @@ -878,7 +876,6 @@ public final class BluetoothAdapter { * {@link #STATE_ON}, * {@link #STATE_TURNING_OFF}, * {@link #STATE_BLE_TURNING_OFF}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return current state of Bluetooth adapter * @hide @@ -934,8 +931,6 @@ public final class BluetoothAdapter { * #STATE_ON}. If this call returns false then there was an * immediate problem that will prevent the adapter from being turned on - * such as Airplane mode, or the adapter is already turned on. - * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission * * @return true to indicate adapter startup has begun, or false on * immediate error @@ -970,8 +965,6 @@ public final class BluetoothAdapter { * #STATE_ON}. If this call returns false then there was an * immediate problem that will prevent the adapter from being turned off - * such as the adapter already being turned off. - * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission * * @return true to indicate adapter shutdown has begun, or false on * immediate error @@ -1005,7 +998,6 @@ public final class BluetoothAdapter { /** * Returns the hardware address of the local Bluetooth adapter. * <p>For example, "00:11:22:AA:BB:CC". - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return Bluetooth hardware address as string */ @@ -1109,7 +1101,6 @@ public final class BluetoothAdapter { * will return false. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * * @param name a valid Bluetooth name * @return true if the name was set, false otherwise @@ -1140,7 +1131,6 @@ public final class BluetoothAdapter { * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return scan mode */ @@ -1279,7 +1269,6 @@ public final class BluetoothAdapter { * will return false. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * * @return true on success, false on error */ @@ -1299,7 +1288,6 @@ public final class BluetoothAdapter { /** * Cancel the current device discovery process. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * <p>Because discovery is a heavyweight procedure for the Bluetooth * adapter, this method should always be called before attempting to connect * to a remote device with {@link @@ -1343,7 +1331,6 @@ public final class BluetoothAdapter { * will return false. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return true if discovering */ @@ -1610,7 +1597,6 @@ public final class BluetoothAdapter { * will return an empty set. After turning on Bluetooth, * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} * to get the updated value. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return unmodifiable set of {@link BluetoothDevice}, or null on error */ @@ -1695,8 +1681,6 @@ public final class BluetoothAdapter { * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, * {@link BluetoothProfile#A2DP}. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. - * * <p> Return value can be one of * {@link BluetoothProfile#STATE_DISCONNECTED}, * {@link BluetoothProfile#STATE_CONNECTING}, @@ -1786,7 +1770,6 @@ public final class BluetoothAdapter { * closed, or if this application closes unexpectedly. * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to * connect to this socket from another device using the same {@link UUID}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * @param name service name for SDP record * @param uuid uuid for SDP record * @return a listening RFCOMM BluetoothServerSocket @@ -1818,7 +1801,6 @@ public final class BluetoothAdapter { * closed, or if this application closes unexpectedly. * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to * connect to this socket from another device using the same {@link UUID}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * @param name service name for SDP record * @param uuid uuid for SDP record * @return a listening RFCOMM BluetoothServerSocket @@ -2410,8 +2392,6 @@ public final class BluetoothAdapter { * <p>Results of the scan are reported using the * {@link LeScanCallback#onLeScan} callback. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} @@ -2430,8 +2410,6 @@ public final class BluetoothAdapter { * <p>Devices which advertise all specified services are reported using the * {@link LeScanCallback#onLeScan} callback. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * * @param serviceUuids Array of services to look for * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully @@ -2519,8 +2497,6 @@ public final class BluetoothAdapter { /** * Stops an ongoing Bluetooth LE device scan. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * * @param callback used to identify which scan to stop * must be the same handle used to start the scan * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e6cebc0819f5..639e05622334 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -762,7 +762,6 @@ public final class BluetoothDevice implements Parcelable { * <p>The local adapter will automatically retrieve remote names when * performing a device scan, and will cache them. This method just returns * the name for this device from the cache. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return the Bluetooth name, or null if there was a problem. */ @@ -781,8 +780,6 @@ public final class BluetoothDevice implements Parcelable { /** * Get the Bluetooth device type of the remote device. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} - * * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} * {@link #DEVICE_TYPE_DUAL}. * {@link #DEVICE_TYPE_UNKNOWN} if it's not available @@ -862,7 +859,6 @@ public final class BluetoothDevice implements Parcelable { * the bonding process completes, and its result. * <p>Android system services will handle the necessary user interactions * to confirm and complete the bonding process. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * * @return false on immediate error, true if bonding will begin */ @@ -1022,7 +1018,6 @@ public final class BluetoothDevice implements Parcelable { * {@link #BOND_NONE}, * {@link #BOND_BONDING}, * {@link #BOND_BONDED}. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return the bond state */ @@ -1089,7 +1084,6 @@ public final class BluetoothDevice implements Parcelable { /** * Get the Bluetooth class of the remote device. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return Bluetooth class object, or null on error */ @@ -1114,7 +1108,6 @@ public final class BluetoothDevice implements Parcelable { * from the remote device. Instead, the local cached copy of the service * UUIDs are returned. * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return the supported features (UUIDs) of the remote device, * or null on error @@ -1140,7 +1133,6 @@ public final class BluetoothDevice implements Parcelable { * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently * present in the cache. Clients should use the {@link #getUuids} to get UUIDs * if service discovery is not to be performed. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return False if the sanity check fails, True if the process * of initiating an ACL connection to the remote device @@ -1221,7 +1213,6 @@ public final class BluetoothDevice implements Parcelable { /** * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. * * @return true confirmation has been sent out * false for error @@ -1502,7 +1493,6 @@ public final class BluetoothDevice implements Parcelable { * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. * However if you are connecting to an Android peer then please generate * your own unique UUID. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @param uuid service record uuid to lookup RFCOMM channel * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection @@ -1541,7 +1531,6 @@ public final class BluetoothDevice implements Parcelable { * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. * However if you are connecting to an Android peer then please generate * your own unique UUID. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @param uuid service record uuid to lookup RFCOMM channel * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java index 29283e793ce9..c7191ba2638b 100644 --- a/core/java/android/bluetooth/BluetoothManager.java +++ b/core/java/android/bluetooth/BluetoothManager.java @@ -85,8 +85,6 @@ public final class BluetoothManager { * This can be used by applications like status bar which would just like * to know the state of Bluetooth. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param device Remote bluetooth device. * @param profile GATT or GATT_SERVER * @return State of the profile connection. One of @@ -118,8 +116,6 @@ public final class BluetoothManager { * This can be used by applications like status bar which would just like * to know the state of Bluetooth. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param profile GATT or GATT_SERVER * @return List of devices. The list will be empty on error. */ @@ -159,8 +155,6 @@ public final class BluetoothManager { * This can be used by applications like status bar which would just like * to know the state of the local adapter. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param profile GATT or GATT_SERVER * @param states Array of states. States can be one of * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING}, diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 2f64c719ec10..c5b58e97e528 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -187,8 +187,6 @@ public interface BluetoothProfile { * * <p> Return the set of devices which are in state {@link #STATE_CONNECTED} * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @return List of devices. The list will be empty on error. */ @RequiresPermission(Manifest.permission.BLUETOOTH) @@ -201,8 +199,6 @@ public interface BluetoothProfile { * <p> If none of the devices match any of the given states, * an empty list will be returned. * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param states Array of states. States can be one of * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, @@ -214,8 +210,6 @@ public interface BluetoothProfile { /** * Get the current connection state of the profile * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. - * * @param device Remote bluetooth device. * @return State of the profile connection. One of * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index b65a7ad0c017..52465137dfd6 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -73,7 +73,7 @@ public final class BluetoothLeScanner { /** * Optional extra indicating the callback type, which will be one of - * ScanSettings.CALLBACK_TYPE_*. + * CALLBACK_TYPE_* constants in {@link ScanSettings}. * @see ScanCallback#onScanResult(int, ScanResult) */ public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; @@ -100,7 +100,6 @@ public final class BluetoothLeScanner { * Start Bluetooth LE scan with default parameters and no filters. The scan results will be * delivered through {@code callback}. * <p> - * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * An app must hold * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission @@ -117,7 +116,6 @@ public final class BluetoothLeScanner { /** * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}. * <p> - * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * An app must hold * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission @@ -243,8 +241,6 @@ public final class BluetoothLeScanner { /** * Stops an ongoing Bluetooth LE scan. - * <p> - * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param callback */ @@ -263,8 +259,6 @@ public final class BluetoothLeScanner { /** * Stops an ongoing Bluetooth LE scan started using a PendingIntent. - * <p> - * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param callbackIntent The PendingIntent that was used to start the scan. * @see #startScan(List, ScanSettings, PendingIntent) diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index e50b2a97c2d2..fac9e13db322 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -118,6 +118,9 @@ public final class CompanionDeviceManager { * association is no longer relevant to avoid unnecessary battery and/or data drain resulting * from special privileges that the association provides</p> * + * <p>Calling this API requires a uses-feature + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> + * * @param request specific details about this request * @param callback will be called once there's at least one device found for user to choose from * @param handler A handler to control which thread the callback will be delivered on, or null, @@ -160,6 +163,9 @@ public final class CompanionDeviceManager { } /** + * <p>Calling this API requires a uses-feature + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> + * * @return a list of MAC addresses of devices that have been previously associated with the * current app. You can use these with {@link #disassociate} */ @@ -184,6 +190,9 @@ public final class CompanionDeviceManager { * association is no longer relevant to avoid unnecessary battery and/or data drain resulting * from special privileges that the association provides</p> * + * <p>Calling this API requires a uses-feature + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> + * * @param deviceMacAddress the MAC address of device to disassociate from this app */ public void disassociate(@NonNull String deviceMacAddress) { @@ -206,6 +215,9 @@ public final class CompanionDeviceManager { * are allowed. * * Your app must have an association with a device before calling this API + * + * <p>Calling this API requires a uses-feature + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> */ public void requestNotificationAccess(ComponentName component) { if (!checkFeaturePresent()) { @@ -226,6 +238,9 @@ public final class CompanionDeviceManager { * * Your app must have an association with a device before calling this API * + * <p>Calling this API requires a uses-feature + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p> + * * @param component the name of the component * @return whether the given component has the notification listener permission */ diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java index d8ff2229a0e4..8e30fd6eb60f 100644 --- a/core/java/android/content/ClipDescription.java +++ b/core/java/android/content/ClipDescription.java @@ -148,7 +148,7 @@ public class ClipDescription implements Parcelable { * Used for setting the timestamp at which the associated {@link ClipData} is copied to * global clipboard. * - * @param timeStamp at which the associated {@link ClipData} is copeid to clipboard in + * @param timeStamp at which the associated {@link ClipData} is copied to clipboard in * {@link System#currentTimeMillis()} time base. * @hide */ diff --git a/core/java/android/content/ComponentCallbacks2.java b/core/java/android/content/ComponentCallbacks2.java index b78548b873b1..6576c0f9b388 100644 --- a/core/java/android/content/ComponentCallbacks2.java +++ b/core/java/android/content/ComponentCallbacks2.java @@ -16,6 +16,11 @@ package android.content; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Extended {@link ComponentCallbacks} interface with a new callback for * finer-grained memory management. This interface is available in all application components @@ -83,6 +88,19 @@ package android.content; */ public interface ComponentCallbacks2 extends ComponentCallbacks { + /** @hide */ + @IntDef(prefix = { "TRIM_MEMORY_" }, value = { + TRIM_MEMORY_COMPLETE, + TRIM_MEMORY_MODERATE, + TRIM_MEMORY_BACKGROUND, + TRIM_MEMORY_UI_HIDDEN, + TRIM_MEMORY_RUNNING_CRITICAL, + TRIM_MEMORY_RUNNING_LOW, + TRIM_MEMORY_RUNNING_MODERATE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TrimMemoryLevel {} + /** * Level for {@link #onTrimMemory(int)}: the process is nearing the end * of the background LRU list, and if more memory isn't found soon it will @@ -132,7 +150,6 @@ public interface ComponentCallbacks2 extends ComponentCallbacks { */ static final int TRIM_MEMORY_RUNNING_LOW = 10; - /** * Level for {@link #onTrimMemory(int)}: the process is not an expendable * background process, but the device is running moderately low on memory. @@ -155,11 +172,7 @@ public interface ComponentCallbacks2 extends ComponentCallbacks { * ActivityManager.getMyMemoryState(RunningAppProcessInfo)}. * * @param level The context of the trim, giving a hint of the amount of - * trimming the application may like to perform. May be - * {@link #TRIM_MEMORY_COMPLETE}, {@link #TRIM_MEMORY_MODERATE}, - * {@link #TRIM_MEMORY_BACKGROUND}, {@link #TRIM_MEMORY_UI_HIDDEN}, - * {@link #TRIM_MEMORY_RUNNING_CRITICAL}, {@link #TRIM_MEMORY_RUNNING_LOW}, - * or {@link #TRIM_MEMORY_RUNNING_MODERATE}. + * trimming the application may like to perform. */ - void onTrimMemory(int level); + void onTrimMemory(@TrimMemoryLevel int level); } diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java index 8aeb22dddd1e..ea6b7690b431 100644 --- a/core/java/android/content/ComponentName.java +++ b/core/java/android/content/ComponentName.java @@ -16,6 +16,8 @@ package android.content; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -52,7 +54,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * the component * @return the new ComponentName */ - public static ComponentName createRelative(String pkg, String cls) { + public static @NonNull ComponentName createRelative(@NonNull String pkg, @NonNull String cls) { if (TextUtils.isEmpty(cls)) { throw new IllegalArgumentException("class name cannot be empty"); } @@ -83,7 +85,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * the component * @return the new ComponentName */ - public static ComponentName createRelative(Context pkg, String cls) { + public static @NonNull ComponentName createRelative(@NonNull Context pkg, @NonNull String cls) { return createRelative(pkg.getPackageName(), cls); } @@ -95,7 +97,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * @param cls The name of the class inside of <var>pkg</var> that * implements the component. Can not be null. */ - public ComponentName(String pkg, String cls) { + public ComponentName(@NonNull String pkg, @NonNull String cls) { if (pkg == null) throw new NullPointerException("package name is null"); if (cls == null) throw new NullPointerException("class name is null"); mPackage = pkg; @@ -110,7 +112,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * @param cls The name of the class inside of <var>pkg</var> that * implements the component. */ - public ComponentName(Context pkg, String cls) { + public ComponentName(@NonNull Context pkg, @NonNull String cls) { if (cls == null) throw new NullPointerException("class name is null"); mPackage = pkg.getPackageName(); mClass = cls; @@ -124,7 +126,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * @param cls The Class object of the desired component, from which the * actual class name will be retrieved. */ - public ComponentName(Context pkg, Class<?> cls) { + public ComponentName(@NonNull Context pkg, @NonNull Class<?> cls) { mPackage = pkg.getPackageName(); mClass = cls.getName(); } @@ -136,14 +138,14 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co /** * Return the package name of this component. */ - public String getPackageName() { + public @NonNull String getPackageName() { return mPackage; } /** * Return the class name of this component. */ - public String getClassName() { + public @NonNull String getClassName() { return mClass; } @@ -200,7 +202,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * * @see #unflattenFromString(String) */ - public String flattenToString() { + public @NonNull String flattenToString() { return mPackage + "/" + mClass; } @@ -215,7 +217,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * * @see #unflattenFromString(String) */ - public String flattenToShortString() { + public @NonNull String flattenToShortString() { StringBuilder sb = new StringBuilder(mPackage.length() + mClass.length()); appendShortString(sb, mPackage, mClass); return sb.toString(); @@ -255,7 +257,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * * @see #flattenToString() */ - public static ComponentName unflattenFromString(String str) { + public static @Nullable ComponentName unflattenFromString(@NonNull String str) { int sep = str.indexOf('/'); if (sep < 0 || (sep+1) >= str.length()) { return null; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 1585d2164cd1..42ef871ef3ba 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -85,6 +85,37 @@ import java.lang.annotation.RetentionPolicy; * broadcasting and receiving intents, etc. */ public abstract class Context { + /** @hide */ + @IntDef(flag = true, prefix = { "MODE_" }, value = { + MODE_PRIVATE, + MODE_WORLD_READABLE, + MODE_WORLD_WRITEABLE, + MODE_APPEND, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FileMode {} + + /** @hide */ + @IntDef(flag = true, prefix = { "MODE_" }, value = { + MODE_PRIVATE, + MODE_WORLD_READABLE, + MODE_WORLD_WRITEABLE, + MODE_MULTI_PROCESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PreferencesMode {} + + /** @hide */ + @IntDef(flag = true, prefix = { "MODE_" }, value = { + MODE_PRIVATE, + MODE_WORLD_READABLE, + MODE_WORLD_WRITEABLE, + MODE_ENABLE_WRITE_AHEAD_LOGGING, + MODE_NO_LOCALIZED_COLLATORS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DatabaseMode {} + /** * File creation mode: the default mode, where the created file can only * be accessed by the calling application (or all applications sharing the @@ -720,15 +751,14 @@ public abstract class Context { * @param name Desired preferences file. If a preferences file by this name * does not exist, it will be created when you retrieve an * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. + * @param mode Operating mode. * * @return The single {@link SharedPreferences} instance that can be used * to retrieve and modify the preference values. * * @see #MODE_PRIVATE */ - public abstract SharedPreferences getSharedPreferences(String name, int mode); + public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode); /** * Retrieve and hold the contents of the preferences file, returning @@ -740,8 +770,7 @@ public abstract class Context { * @param file Desired preferences file. If a preferences file by this name * does not exist, it will be created when you retrieve an * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. + * @param mode Operating mode. * * @return The single {@link SharedPreferences} instance that can be used * to retrieve and modify the preference values. @@ -750,7 +779,7 @@ public abstract class Context { * @see #MODE_PRIVATE * @removed */ - public abstract SharedPreferences getSharedPreferences(File file, int mode); + public abstract SharedPreferences getSharedPreferences(File file, @PreferencesMode int mode); /** * Move an existing shared preferences file from the given source storage @@ -805,9 +834,7 @@ public abstract class Context { * * @param name The name of the file to open; can not contain path * separators. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. Use {@link #MODE_APPEND} to append to an - * existing file. + * @param mode Operating mode. * @return The resulting {@link FileOutputStream}. * @see #MODE_APPEND * @see #MODE_PRIVATE @@ -816,7 +843,7 @@ public abstract class Context { * @see #deleteFile * @see java.io.FileOutputStream#FileOutputStream(String) */ - public abstract FileOutputStream openFileOutput(String name, int mode) + public abstract FileOutputStream openFileOutput(String name, @FileMode int mode) throws FileNotFoundException; /** @@ -1413,26 +1440,21 @@ public abstract class Context { * * @param name Name of the directory to retrieve. This is a directory * that is created as part of your application data. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. + * @param mode Operating mode. * * @return A {@link File} object for the requested directory. The directory * will have been created if it does not already exist. * * @see #openFileOutput(String, int) */ - public abstract File getDir(String name, int mode); + public abstract File getDir(String name, @FileMode int mode); /** * Open a new private SQLiteDatabase associated with this Context's * application package. Create the database file if it doesn't exist. * * @param name The name (unique in the application package) of the database. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. Use - * {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead - * logging by default. Use {@link #MODE_NO_LOCALIZED_COLLATORS} - * to disable localized collators. + * @param mode Operating mode. * @param factory An optional factory class that is called to instantiate a * cursor when query is called. * @return The contents of a newly created database with the given name. @@ -1444,7 +1466,7 @@ public abstract class Context { * @see #deleteDatabase */ public abstract SQLiteDatabase openOrCreateDatabase(String name, - int mode, CursorFactory factory); + @DatabaseMode int mode, CursorFactory factory); /** * Open a new private SQLiteDatabase associated with this Context's @@ -1455,11 +1477,7 @@ public abstract class Context { * </p> * * @param name The name (unique in the application package) of the database. - * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the - * default operation. Use - * {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead - * logging by default. Use {@link #MODE_NO_LOCALIZED_COLLATORS} - * to disable localized collators. + * @param mode Operating mode. * @param factory An optional factory class that is called to instantiate a * cursor when query is called. * @param errorHandler the {@link DatabaseErrorHandler} to be used when @@ -1475,7 +1493,7 @@ public abstract class Context { * @see #deleteDatabase */ public abstract SQLiteDatabase openOrCreateDatabase(String name, - int mode, CursorFactory factory, + @DatabaseMode int mode, CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler); /** @@ -1777,9 +1795,9 @@ public abstract class Context { * @see #startActivity(Intent) * @see #startIntentSender(IntentSender, Intent, int, int, int, Bundle) */ - public abstract void startIntentSender(IntentSender intent, - Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) - throws IntentSender.SendIntentException; + public abstract void startIntentSender(IntentSender intent, @Nullable Intent fillInIntent, + @Intent.MutableFlags int flagsMask, @Intent.MutableFlags int flagsValues, + int extraFlags) throws IntentSender.SendIntentException; /** * Like {@link #startActivity(Intent, Bundle)}, but taking a IntentSender @@ -1806,9 +1824,9 @@ public abstract class Context { * @see #startActivity(Intent, Bundle) * @see #startIntentSender(IntentSender, Intent, int, int, int) */ - public abstract void startIntentSender(IntentSender intent, - @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, - Bundle options) throws IntentSender.SendIntentException; + public abstract void startIntentSender(IntentSender intent, @Nullable Intent fillInIntent, + @Intent.MutableFlags int flagsMask, @Intent.MutableFlags int flagsValues, + int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException; /** * Broadcast the given intent to all interested BroadcastReceivers. This @@ -2192,10 +2210,6 @@ public abstract class Context { * all other ways, this behaves the same as * {@link #sendBroadcast(Intent)}. * - * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY} - * permission in order to use this API. If you do not hold that - * permission, {@link SecurityException} will be thrown. - * * @deprecated Sticky broadcasts should not be used. They provide no security (anyone * can access them), no protection (anyone can modify them), and many other problems. * The recommended pattern is to use a non-sticky broadcast to report that <em>something</em> @@ -2210,6 +2224,7 @@ public abstract class Context { * @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle) */ @Deprecated + @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission Intent intent); /** @@ -2259,6 +2274,7 @@ public abstract class Context { * @see android.app.Activity#RESULT_OK */ @Deprecated + @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyOrderedBroadcast(@RequiresPermission Intent intent, BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode, @Nullable String initialData, @@ -2268,10 +2284,6 @@ public abstract class Context { * <p>Remove the data previously sent with {@link #sendStickyBroadcast}, * so that it is as if the sticky broadcast had never happened. * - * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY} - * permission in order to use this API. If you do not hold that - * permission, {@link SecurityException} will be thrown. - * * @deprecated Sticky broadcasts should not be used. They provide no security (anyone * can access them), no protection (anyone can modify them), and many other problems. * The recommended pattern is to use a non-sticky broadcast to report that <em>something</em> @@ -2283,6 +2295,7 @@ public abstract class Context { * @see #sendStickyBroadcast */ @Deprecated + @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void removeStickyBroadcast(@RequiresPermission Intent intent); /** @@ -3048,7 +3061,7 @@ public abstract class Context { * @see android.os.HardwarePropertiesManager * @see #HARDWARE_PROPERTIES_SERVICE */ - public abstract Object getSystemService(@ServiceName @NonNull String name); + public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name); /** * Return the handle to a system-level service by class. @@ -3078,7 +3091,7 @@ public abstract class Context { * @return The service or null if the class is not a supported system service. */ @SuppressWarnings("unchecked") - public final <T> T getSystemService(Class<T> serviceClass) { + public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { // Because subclasses may override getSystemService(String) we cannot // perform a lookup by class alone. We must first map the class to its // service name then invoke the string-based method. @@ -3092,7 +3105,7 @@ public abstract class Context { * @param serviceClass The class of the desired service. * @return The service name or null if the class is not a supported system service. */ - public abstract String getSystemServiceName(Class<?> serviceClass); + public abstract @Nullable String getSystemServiceName(@NonNull Class<?> serviceClass); /** * Use with {@link #getSystemService} to retrieve a @@ -4181,10 +4194,12 @@ public abstract class Context { * @see #checkCallingUriPermission */ @CheckResult(suggest="#enforceUriPermission(Uri,int,int,String)") + @PackageManager.PermissionResult public abstract int checkUriPermission(Uri uri, int pid, int uid, @Intent.AccessUriMode int modeFlags); /** @hide */ + @PackageManager.PermissionResult public abstract int checkUriPermission(Uri uri, int pid, int uid, @Intent.AccessUriMode int modeFlags, IBinder callerToken); @@ -4208,6 +4223,7 @@ public abstract class Context { * @see #checkUriPermission(Uri, int, int, int) */ @CheckResult(suggest="#enforceCallingUriPermission(Uri,int,String)") + @PackageManager.PermissionResult public abstract int checkCallingUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags); /** @@ -4226,6 +4242,7 @@ public abstract class Context { * @see #checkCallingUriPermission */ @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") + @PackageManager.PermissionResult public abstract int checkCallingOrSelfUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags); @@ -4250,6 +4267,7 @@ public abstract class Context { * {@link PackageManager#PERMISSION_DENIED} if it is not. */ @CheckResult(suggest="#enforceUriPermission(Uri,String,String,int,int,int,String)") + @PackageManager.PermissionResult public abstract int checkUriPermission(@Nullable Uri uri, @Nullable String readPermission, @Nullable String writePermission, int pid, int uid, @Intent.AccessUriMode int modeFlags); @@ -4336,8 +4354,14 @@ public abstract class Context { @Nullable String message); /** @hide */ - @IntDef(flag = true, - value = {CONTEXT_INCLUDE_CODE, CONTEXT_IGNORE_SECURITY, CONTEXT_RESTRICTED}) + @IntDef(flag = true, prefix = { "CONTEXT_" }, value = { + CONTEXT_INCLUDE_CODE, + CONTEXT_IGNORE_SECURITY, + CONTEXT_RESTRICTED, + CONTEXT_DEVICE_PROTECTED_STORAGE, + CONTEXT_CREDENTIAL_PROTECTED_STORAGE, + CONTEXT_REGISTER_PACKAGE, + }) @Retention(RetentionPolicy.SOURCE) public @interface CreatePackageOptions {} @@ -4409,8 +4433,7 @@ public abstract class Context { * {@link #CONTEXT_INCLUDE_CODE} for more information}. * * @param packageName Name of the application's package. - * @param flags Option flags, one of {@link #CONTEXT_INCLUDE_CODE} - * or {@link #CONTEXT_IGNORE_SECURITY}. + * @param flags Option flags. * * @return A {@link Context} for the application. * @@ -4429,7 +4452,7 @@ public abstract class Context { * @hide */ public abstract Context createPackageContextAsUser( - String packageName, int flags, UserHandle user) + String packageName, @CreatePackageOptions int flags, UserHandle user) throws PackageManager.NameNotFoundException; /** @@ -4438,7 +4461,7 @@ public abstract class Context { * @hide */ public abstract Context createApplicationContext(ApplicationInfo application, - int flags) throws PackageManager.NameNotFoundException; + @CreatePackageOptions int flags) throws PackageManager.NameNotFoundException; /** * Return a new Context object for the given split name. The new Context has a ClassLoader and diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b6f9ac97e727..9c87ff27caaf 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -19,6 +19,8 @@ package android.content; import android.annotation.AnyRes; import android.annotation.BroadcastBehavior; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; @@ -4903,6 +4905,96 @@ public class Intent implements Parcelable, Cloneable { | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) != 0; } + /** @hide */ + @IntDef(flag = true, prefix = { "FLAG_" }, value = { + FLAG_GRANT_READ_URI_PERMISSION, + FLAG_GRANT_WRITE_URI_PERMISSION, + FLAG_FROM_BACKGROUND, + FLAG_DEBUG_LOG_RESOLUTION, + FLAG_EXCLUDE_STOPPED_PACKAGES, + FLAG_INCLUDE_STOPPED_PACKAGES, + FLAG_GRANT_PERSISTABLE_URI_PERMISSION, + FLAG_GRANT_PREFIX_URI_PERMISSION, + FLAG_DEBUG_TRIAGED_MISSING, + FLAG_IGNORE_EPHEMERAL, + FLAG_ACTIVITY_NO_HISTORY, + FLAG_ACTIVITY_SINGLE_TOP, + FLAG_ACTIVITY_NEW_TASK, + FLAG_ACTIVITY_MULTIPLE_TASK, + FLAG_ACTIVITY_CLEAR_TOP, + FLAG_ACTIVITY_FORWARD_RESULT, + FLAG_ACTIVITY_PREVIOUS_IS_TOP, + FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, + FLAG_ACTIVITY_BROUGHT_TO_FRONT, + FLAG_ACTIVITY_RESET_TASK_IF_NEEDED, + FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY, + FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, + FLAG_ACTIVITY_NEW_DOCUMENT, + FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, + FLAG_ACTIVITY_NO_USER_ACTION, + FLAG_ACTIVITY_REORDER_TO_FRONT, + FLAG_ACTIVITY_NO_ANIMATION, + FLAG_ACTIVITY_CLEAR_TASK, + FLAG_ACTIVITY_TASK_ON_HOME, + FLAG_ACTIVITY_RETAIN_IN_RECENTS, + FLAG_ACTIVITY_LAUNCH_ADJACENT, + FLAG_RECEIVER_REGISTERED_ONLY, + FLAG_RECEIVER_REPLACE_PENDING, + FLAG_RECEIVER_FOREGROUND, + FLAG_RECEIVER_NO_ABORT, + FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, + FLAG_RECEIVER_BOOT_UPGRADE, + FLAG_RECEIVER_INCLUDE_BACKGROUND, + FLAG_RECEIVER_EXCLUDE_BACKGROUND, + FLAG_RECEIVER_FROM_SHELL, + FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Flags {} + + /** @hide */ + @IntDef(flag = true, prefix = { "FLAG_" }, value = { + FLAG_FROM_BACKGROUND, + FLAG_DEBUG_LOG_RESOLUTION, + FLAG_EXCLUDE_STOPPED_PACKAGES, + FLAG_INCLUDE_STOPPED_PACKAGES, + FLAG_DEBUG_TRIAGED_MISSING, + FLAG_IGNORE_EPHEMERAL, + FLAG_ACTIVITY_NO_HISTORY, + FLAG_ACTIVITY_SINGLE_TOP, + FLAG_ACTIVITY_NEW_TASK, + FLAG_ACTIVITY_MULTIPLE_TASK, + FLAG_ACTIVITY_CLEAR_TOP, + FLAG_ACTIVITY_FORWARD_RESULT, + FLAG_ACTIVITY_PREVIOUS_IS_TOP, + FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, + FLAG_ACTIVITY_BROUGHT_TO_FRONT, + FLAG_ACTIVITY_RESET_TASK_IF_NEEDED, + FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY, + FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, + FLAG_ACTIVITY_NEW_DOCUMENT, + FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, + FLAG_ACTIVITY_NO_USER_ACTION, + FLAG_ACTIVITY_REORDER_TO_FRONT, + FLAG_ACTIVITY_NO_ANIMATION, + FLAG_ACTIVITY_CLEAR_TASK, + FLAG_ACTIVITY_TASK_ON_HOME, + FLAG_ACTIVITY_RETAIN_IN_RECENTS, + FLAG_ACTIVITY_LAUNCH_ADJACENT, + FLAG_RECEIVER_REGISTERED_ONLY, + FLAG_RECEIVER_REPLACE_PENDING, + FLAG_RECEIVER_FOREGROUND, + FLAG_RECEIVER_NO_ABORT, + FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, + FLAG_RECEIVER_BOOT_UPGRADE, + FLAG_RECEIVER_INCLUDE_BACKGROUND, + FLAG_RECEIVER_EXCLUDE_BACKGROUND, + FLAG_RECEIVER_FROM_SHELL, + FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MutableFlags {} + /** * If set, the recipient of this Intent will be granted permission to * perform read operations on the URI in the Intent's data and any URIs @@ -5369,6 +5461,15 @@ public class Intent implements Parcelable, Cloneable { // --------------------------------------------------------------------- // toUri() and parseUri() options. + /** @hide */ + @IntDef(flag = true, prefix = { "URI_" }, value = { + URI_ALLOW_UNSAFE, + URI_ANDROID_APP_SCHEME, + URI_INTENT_SCHEME, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface UriFlags {} + /** * Flag for use with {@link #toUri} and {@link #parseUri}: the URI string * always has the "intent:" scheme. This syntax can be used when you want @@ -5538,7 +5639,7 @@ public class Intent implements Parcelable, Cloneable { * Make a clone of only the parts of the Intent that are relevant for * filter matching: the action, data, type, component, and categories. */ - public Intent cloneFilter() { + public @NonNull Intent cloneFilter() { return new Intent(this, false); } @@ -5727,8 +5828,7 @@ public class Intent implements Parcelable, Cloneable { * the scheme and full path. * * @param uri The URI to turn into an Intent. - * @param flags Additional processing flags. Either 0, - * {@link #URI_INTENT_SCHEME}, or {@link #URI_ANDROID_APP_SCHEME}. + * @param flags Additional processing flags. * * @return Intent The newly created Intent object. * @@ -5738,7 +5838,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #toUri */ - public static Intent parseUri(String uri, int flags) throws URISyntaxException { + public static Intent parseUri(String uri, @UriFlags int flags) throws URISyntaxException { int i = 0; try { final boolean androidApp = uri.startsWith("android-app:"); @@ -6568,7 +6668,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #setAction */ - public String getAction() { + public @Nullable String getAction() { return mAction; } @@ -6583,7 +6683,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getScheme * @see #setData */ - public Uri getData() { + public @Nullable Uri getData() { return mData; } @@ -6591,7 +6691,7 @@ public class Intent implements Parcelable, Cloneable { * The same as {@link #getData()}, but returns the URI as an encoded * String. */ - public String getDataString() { + public @Nullable String getDataString() { return mData != null ? mData.toString() : null; } @@ -6607,7 +6707,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #getData */ - public String getScheme() { + public @Nullable String getScheme() { return mData != null ? mData.getScheme() : null; } @@ -6621,7 +6721,7 @@ public class Intent implements Parcelable, Cloneable { * @see #resolveType(ContentResolver) * @see #setType */ - public String getType() { + public @Nullable String getType() { return mType; } @@ -6636,7 +6736,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getType * @see #resolveType(ContentResolver) */ - public String resolveType(Context context) { + public @Nullable String resolveType(@NonNull Context context) { return resolveType(context.getContentResolver()); } @@ -6654,7 +6754,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getType * @see #resolveType(Context) */ - public String resolveType(ContentResolver resolver) { + public @Nullable String resolveType(@NonNull ContentResolver resolver) { if (mType != null) { return mType; } @@ -6678,7 +6778,7 @@ public class Intent implements Parcelable, Cloneable { * @return The MIME type of this intent, or null if it is unknown or not * needed. */ - public String resolveTypeIfNeeded(ContentResolver resolver) { + public @Nullable String resolveTypeIfNeeded(@NonNull ContentResolver resolver) { if (mComponent != null) { return mType; } @@ -6718,7 +6818,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #setSelector */ - public Intent getSelector() { + public @Nullable Intent getSelector() { return mSelector; } @@ -6728,7 +6828,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #setClipData */ - public ClipData getClipData() { + public @Nullable ClipData getClipData() { return mClipData; } @@ -6754,7 +6854,7 @@ public class Intent implements Parcelable, Cloneable { * @param loader a ClassLoader, or null to use the default loader * at the time of unmarshalling. */ - public void setExtrasClassLoader(ClassLoader loader) { + public void setExtrasClassLoader(@Nullable ClassLoader loader) { if (mExtras != null) { mExtras.setClassLoader(loader); } @@ -7275,7 +7375,7 @@ public class Intent implements Parcelable, Cloneable { * @return the map of all extras previously added with putExtra(), * or null if none have been added. */ - public Bundle getExtras() { + public @Nullable Bundle getExtras() { return (mExtras != null) ? new Bundle(mExtras) : null; @@ -7296,11 +7396,12 @@ public class Intent implements Parcelable, Cloneable { * normally just set them with {@link #setFlags} and let the system * take the appropriate action with them. * - * @return int The currently set flags. - * + * @return The currently set flags. * @see #setFlags + * @see #addFlags + * @see #removeFlags */ - public int getFlags() { + public @Flags int getFlags() { return mFlags; } @@ -7320,7 +7421,7 @@ public class Intent implements Parcelable, Cloneable { * @see #resolveActivity * @see #setPackage */ - public String getPackage() { + public @Nullable String getPackage() { return mPackage; } @@ -7335,7 +7436,7 @@ public class Intent implements Parcelable, Cloneable { * @see #resolveActivity * @see #setComponent */ - public ComponentName getComponent() { + public @Nullable ComponentName getComponent() { return mComponent; } @@ -7344,7 +7445,7 @@ public class Intent implements Parcelable, Cloneable { * used as a hint to the receiver for animations and the like. Null means that there * is no source bounds. */ - public Rect getSourceBounds() { + public @Nullable Rect getSourceBounds() { return mSourceBounds; } @@ -7395,7 +7496,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getComponent * @see #resolveActivityInfo */ - public ComponentName resolveActivity(PackageManager pm) { + public ComponentName resolveActivity(@NonNull PackageManager pm) { if (mComponent != null) { return mComponent; } @@ -7427,7 +7528,8 @@ public class Intent implements Parcelable, Cloneable { * * @see #resolveActivity */ - public ActivityInfo resolveActivityInfo(PackageManager pm, int flags) { + public ActivityInfo resolveActivityInfo(@NonNull PackageManager pm, + @PackageManager.ComponentInfoFlags int flags) { ActivityInfo ai = null; if (mComponent != null) { try { @@ -7453,7 +7555,8 @@ public class Intent implements Parcelable, Cloneable { * there are no matches. * @hide */ - public ComponentName resolveSystemService(PackageManager pm, int flags) { + public @Nullable ComponentName resolveSystemService(@NonNull PackageManager pm, + @PackageManager.ComponentInfoFlags int flags) { if (mComponent != null) { return mComponent; } @@ -7490,7 +7593,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #getAction */ - public Intent setAction(String action) { + public @NonNull Intent setAction(@Nullable String action) { mAction = action != null ? action.intern() : null; return this; } @@ -7516,7 +7619,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setDataAndNormalize * @see android.net.Uri#normalizeScheme() */ - public Intent setData(Uri data) { + public @NonNull Intent setData(@Nullable Uri data) { mData = data; mType = null; return this; @@ -7544,7 +7647,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setType * @see android.net.Uri#normalizeScheme */ - public Intent setDataAndNormalize(Uri data) { + public @NonNull Intent setDataAndNormalize(@NonNull Uri data) { return setData(data.normalizeScheme()); } @@ -7573,7 +7676,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setDataAndType * @see #normalizeMimeType */ - public Intent setType(String type) { + public @NonNull Intent setType(@Nullable String type) { mData = null; mType = type; return this; @@ -7604,7 +7707,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setData * @see #normalizeMimeType */ - public Intent setTypeAndNormalize(String type) { + public @NonNull Intent setTypeAndNormalize(@Nullable String type) { return setType(normalizeMimeType(type)); } @@ -7633,7 +7736,7 @@ public class Intent implements Parcelable, Cloneable { * @see android.net.Uri#normalizeScheme * @see #setDataAndTypeAndNormalize */ - public Intent setDataAndType(Uri data, String type) { + public @NonNull Intent setDataAndType(@Nullable Uri data, @Nullable String type) { mData = data; mType = type; return this; @@ -7664,7 +7767,7 @@ public class Intent implements Parcelable, Cloneable { * @see #normalizeMimeType * @see android.net.Uri#normalizeScheme */ - public Intent setDataAndTypeAndNormalize(Uri data, String type) { + public @NonNull Intent setDataAndTypeAndNormalize(@NonNull Uri data, @Nullable String type) { return setDataAndType(data.normalizeScheme(), normalizeMimeType(type)); } @@ -7684,7 +7787,7 @@ public class Intent implements Parcelable, Cloneable { * @see #hasCategory * @see #removeCategory */ - public Intent addCategory(String category) { + public @NonNull Intent addCategory(String category) { if (mCategories == null) { mCategories = new ArraySet<String>(); } @@ -7739,7 +7842,7 @@ public class Intent implements Parcelable, Cloneable { * @param selector The desired selector Intent; set to null to not use * a special selector. */ - public void setSelector(Intent selector) { + public void setSelector(@Nullable Intent selector) { if (selector == this) { throw new IllegalArgumentException( "Intent being set as a selector of itself"); @@ -7778,7 +7881,7 @@ public class Intent implements Parcelable, Cloneable { * * @param clip The new clip to set. May be null to clear the current clip. */ - public void setClipData(ClipData clip) { + public void setClipData(@Nullable ClipData clip) { mClipData = clip; } @@ -7811,7 +7914,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getBooleanExtra(String, boolean) */ - public Intent putExtra(String name, boolean value) { + public @NonNull Intent putExtra(String name, boolean value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7834,7 +7937,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getByteExtra(String, byte) */ - public Intent putExtra(String name, byte value) { + public @NonNull Intent putExtra(String name, byte value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7857,7 +7960,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getCharExtra(String, char) */ - public Intent putExtra(String name, char value) { + public @NonNull Intent putExtra(String name, char value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7880,7 +7983,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getShortExtra(String, short) */ - public Intent putExtra(String name, short value) { + public @NonNull Intent putExtra(String name, short value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7903,7 +8006,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getIntExtra(String, int) */ - public Intent putExtra(String name, int value) { + public @NonNull Intent putExtra(String name, int value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7926,7 +8029,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getLongExtra(String, long) */ - public Intent putExtra(String name, long value) { + public @NonNull Intent putExtra(String name, long value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7949,7 +8052,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getFloatExtra(String, float) */ - public Intent putExtra(String name, float value) { + public @NonNull Intent putExtra(String name, float value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7972,7 +8075,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getDoubleExtra(String, double) */ - public Intent putExtra(String name, double value) { + public @NonNull Intent putExtra(String name, double value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -7995,7 +8098,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getStringExtra(String) */ - public Intent putExtra(String name, String value) { + public @NonNull Intent putExtra(String name, String value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8018,7 +8121,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getCharSequenceExtra(String) */ - public Intent putExtra(String name, CharSequence value) { + public @NonNull Intent putExtra(String name, CharSequence value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8041,7 +8144,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getParcelableExtra(String) */ - public Intent putExtra(String name, Parcelable value) { + public @NonNull Intent putExtra(String name, Parcelable value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8064,7 +8167,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getParcelableArrayExtra(String) */ - public Intent putExtra(String name, Parcelable[] value) { + public @NonNull Intent putExtra(String name, Parcelable[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8087,7 +8190,8 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getParcelableArrayListExtra(String) */ - public Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) { + public @NonNull Intent putParcelableArrayListExtra(String name, + ArrayList<? extends Parcelable> value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8110,7 +8214,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getIntegerArrayListExtra(String) */ - public Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) { + public @NonNull Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8133,7 +8237,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getStringArrayListExtra(String) */ - public Intent putStringArrayListExtra(String name, ArrayList<String> value) { + public @NonNull Intent putStringArrayListExtra(String name, ArrayList<String> value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8156,7 +8260,8 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getCharSequenceArrayListExtra(String) */ - public Intent putCharSequenceArrayListExtra(String name, ArrayList<CharSequence> value) { + public @NonNull Intent putCharSequenceArrayListExtra(String name, + ArrayList<CharSequence> value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8179,7 +8284,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getSerializableExtra(String) */ - public Intent putExtra(String name, Serializable value) { + public @NonNull Intent putExtra(String name, Serializable value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8202,7 +8307,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getBooleanArrayExtra(String) */ - public Intent putExtra(String name, boolean[] value) { + public @NonNull Intent putExtra(String name, boolean[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8225,7 +8330,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getByteArrayExtra(String) */ - public Intent putExtra(String name, byte[] value) { + public @NonNull Intent putExtra(String name, byte[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8248,7 +8353,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getShortArrayExtra(String) */ - public Intent putExtra(String name, short[] value) { + public @NonNull Intent putExtra(String name, short[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8271,7 +8376,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getCharArrayExtra(String) */ - public Intent putExtra(String name, char[] value) { + public @NonNull Intent putExtra(String name, char[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8294,7 +8399,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getIntArrayExtra(String) */ - public Intent putExtra(String name, int[] value) { + public @NonNull Intent putExtra(String name, int[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8317,7 +8422,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getLongArrayExtra(String) */ - public Intent putExtra(String name, long[] value) { + public @NonNull Intent putExtra(String name, long[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8340,7 +8445,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getFloatArrayExtra(String) */ - public Intent putExtra(String name, float[] value) { + public @NonNull Intent putExtra(String name, float[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8363,7 +8468,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getDoubleArrayExtra(String) */ - public Intent putExtra(String name, double[] value) { + public @NonNull Intent putExtra(String name, double[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8386,7 +8491,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getStringArrayExtra(String) */ - public Intent putExtra(String name, String[] value) { + public @NonNull Intent putExtra(String name, String[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8409,7 +8514,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getCharSequenceArrayExtra(String) */ - public Intent putExtra(String name, CharSequence[] value) { + public @NonNull Intent putExtra(String name, CharSequence[] value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8432,7 +8537,7 @@ public class Intent implements Parcelable, Cloneable { * @see #removeExtra * @see #getBundleExtra(String) */ - public Intent putExtra(String name, Bundle value) { + public @NonNull Intent putExtra(String name, Bundle value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8459,7 +8564,7 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @Deprecated - public Intent putExtra(String name, IBinder value) { + public @NonNull Intent putExtra(String name, IBinder value) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8474,7 +8579,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #putExtra */ - public Intent putExtras(Intent src) { + public @NonNull Intent putExtras(@NonNull Intent src) { if (src.mExtras != null) { if (mExtras == null) { mExtras = new Bundle(src.mExtras); @@ -8495,7 +8600,7 @@ public class Intent implements Parcelable, Cloneable { * @see #putExtra * @see #removeExtra */ - public Intent putExtras(Bundle extras) { + public @NonNull Intent putExtras(@NonNull Bundle extras) { if (mExtras == null) { mExtras = new Bundle(); } @@ -8510,7 +8615,7 @@ public class Intent implements Parcelable, Cloneable { * @param src The exact extras contained in this Intent are copied * into the target intent, replacing any that were previously there. */ - public Intent replaceExtras(Intent src) { + public @NonNull Intent replaceExtras(@NonNull Intent src) { mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null; return this; } @@ -8522,7 +8627,7 @@ public class Intent implements Parcelable, Cloneable { * @param extras The new set of extras in the Intent, or null to erase * all extras. */ - public Intent replaceExtras(Bundle extras) { + public @NonNull Intent replaceExtras(@NonNull Bundle extras) { mExtras = extras != null ? new Bundle(extras) : null; return this; } @@ -8555,41 +8660,13 @@ public class Intent implements Parcelable, Cloneable { * the behavior of your application. * * @param flags The desired flags. - * * @return Returns the same Intent object, for chaining multiple calls * into a single statement. - * * @see #getFlags * @see #addFlags * @see #removeFlags - * - * @see #FLAG_GRANT_READ_URI_PERMISSION - * @see #FLAG_GRANT_WRITE_URI_PERMISSION - * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION - * @see #FLAG_GRANT_PREFIX_URI_PERMISSION - * @see #FLAG_DEBUG_LOG_RESOLUTION - * @see #FLAG_FROM_BACKGROUND - * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT - * @see #FLAG_ACTIVITY_CLEAR_TASK - * @see #FLAG_ACTIVITY_CLEAR_TOP - * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET - * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - * @see #FLAG_ACTIVITY_FORWARD_RESULT - * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - * @see #FLAG_ACTIVITY_MULTIPLE_TASK - * @see #FLAG_ACTIVITY_NEW_DOCUMENT - * @see #FLAG_ACTIVITY_NEW_TASK - * @see #FLAG_ACTIVITY_NO_ANIMATION - * @see #FLAG_ACTIVITY_NO_HISTORY - * @see #FLAG_ACTIVITY_NO_USER_ACTION - * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP - * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - * @see #FLAG_ACTIVITY_REORDER_TO_FRONT - * @see #FLAG_ACTIVITY_SINGLE_TOP - * @see #FLAG_ACTIVITY_TASK_ON_HOME - * @see #FLAG_RECEIVER_REGISTERED_ONLY - */ - public Intent setFlags(int flags) { + */ + public @NonNull Intent setFlags(@Flags int flags) { mFlags = flags; return this; } @@ -8600,36 +8677,11 @@ public class Intent implements Parcelable, Cloneable { * @param flags The new flags to set. * @return Returns the same Intent object, for chaining multiple calls into * a single statement. - * @see #setFlags(int) - * @see #removeFlags(int) - * - * @see #FLAG_GRANT_READ_URI_PERMISSION - * @see #FLAG_GRANT_WRITE_URI_PERMISSION - * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION - * @see #FLAG_GRANT_PREFIX_URI_PERMISSION - * @see #FLAG_DEBUG_LOG_RESOLUTION - * @see #FLAG_FROM_BACKGROUND - * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT - * @see #FLAG_ACTIVITY_CLEAR_TASK - * @see #FLAG_ACTIVITY_CLEAR_TOP - * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET - * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - * @see #FLAG_ACTIVITY_FORWARD_RESULT - * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - * @see #FLAG_ACTIVITY_MULTIPLE_TASK - * @see #FLAG_ACTIVITY_NEW_DOCUMENT - * @see #FLAG_ACTIVITY_NEW_TASK - * @see #FLAG_ACTIVITY_NO_ANIMATION - * @see #FLAG_ACTIVITY_NO_HISTORY - * @see #FLAG_ACTIVITY_NO_USER_ACTION - * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP - * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - * @see #FLAG_ACTIVITY_REORDER_TO_FRONT - * @see #FLAG_ACTIVITY_SINGLE_TOP - * @see #FLAG_ACTIVITY_TASK_ON_HOME - * @see #FLAG_RECEIVER_REGISTERED_ONLY - */ - public Intent addFlags(int flags) { + * @see #setFlags + * @see #getFlags + * @see #removeFlags + */ + public @NonNull Intent addFlags(@Flags int flags) { mFlags |= flags; return this; } @@ -8638,36 +8690,11 @@ public class Intent implements Parcelable, Cloneable { * Remove these flags from the intent. * * @param flags The flags to remove. - * @see #setFlags(int) - * @see #addFlags(int) - * - * @see #FLAG_GRANT_READ_URI_PERMISSION - * @see #FLAG_GRANT_WRITE_URI_PERMISSION - * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION - * @see #FLAG_GRANT_PREFIX_URI_PERMISSION - * @see #FLAG_DEBUG_LOG_RESOLUTION - * @see #FLAG_FROM_BACKGROUND - * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT - * @see #FLAG_ACTIVITY_CLEAR_TASK - * @see #FLAG_ACTIVITY_CLEAR_TOP - * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET - * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - * @see #FLAG_ACTIVITY_FORWARD_RESULT - * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - * @see #FLAG_ACTIVITY_MULTIPLE_TASK - * @see #FLAG_ACTIVITY_NEW_DOCUMENT - * @see #FLAG_ACTIVITY_NEW_TASK - * @see #FLAG_ACTIVITY_NO_ANIMATION - * @see #FLAG_ACTIVITY_NO_HISTORY - * @see #FLAG_ACTIVITY_NO_USER_ACTION - * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP - * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - * @see #FLAG_ACTIVITY_REORDER_TO_FRONT - * @see #FLAG_ACTIVITY_SINGLE_TOP - * @see #FLAG_ACTIVITY_TASK_ON_HOME - * @see #FLAG_RECEIVER_REGISTERED_ONLY - */ - public void removeFlags(int flags) { + * @see #setFlags + * @see #getFlags + * @see #addFlags + */ + public void removeFlags(@Flags int flags) { mFlags &= ~flags; } @@ -8687,7 +8714,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getPackage * @see #resolveActivity */ - public Intent setPackage(String packageName) { + public @NonNull Intent setPackage(@Nullable String packageName) { if (packageName != null && mSelector != null) { throw new IllegalArgumentException( "Can't set package name when selector is already set"); @@ -8719,7 +8746,7 @@ public class Intent implements Parcelable, Cloneable { * @see #getComponent * @see #resolveActivity */ - public Intent setComponent(ComponentName component) { + public @NonNull Intent setComponent(@Nullable ComponentName component) { mComponent = component; return this; } @@ -8739,7 +8766,8 @@ public class Intent implements Parcelable, Cloneable { * @see #setComponent * @see #setClass */ - public Intent setClassName(Context packageContext, String className) { + public @NonNull Intent setClassName(@NonNull Context packageContext, + @NonNull String className) { mComponent = new ComponentName(packageContext, className); return this; } @@ -8759,7 +8787,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setComponent * @see #setClass */ - public Intent setClassName(String packageName, String className) { + public @NonNull Intent setClassName(@NonNull String packageName, @NonNull String className) { mComponent = new ComponentName(packageName, className); return this; } @@ -8778,7 +8806,7 @@ public class Intent implements Parcelable, Cloneable { * * @see #setComponent */ - public Intent setClass(Context packageContext, Class<?> cls) { + public @NonNull Intent setClass(@NonNull Context packageContext, @NonNull Class<?> cls) { mComponent = new ComponentName(packageContext, cls); return this; } @@ -8788,7 +8816,7 @@ public class Intent implements Parcelable, Cloneable { * used as a hint to the receiver for animations and the like. Null means that there * is no source bounds. */ - public void setSourceBounds(Rect r) { + public void setSourceBounds(@Nullable Rect r) { if (r != null) { mSourceBounds = new Rect(r); } else { @@ -8909,7 +8937,7 @@ public class Intent implements Parcelable, Cloneable { * changed. */ @FillInFlags - public int fillIn(Intent other, @FillInFlags int flags) { + public int fillIn(@NonNull Intent other, @FillInFlags int flags) { int changes = 0; boolean mayHaveCopiedUris = false; if (other.mAction != null @@ -9257,13 +9285,12 @@ public class Intent implements Parcelable, Cloneable { * <p>You can convert the returned string back to an Intent with * {@link #getIntent}. * - * @param flags Additional operating flags. Either 0, - * {@link #URI_INTENT_SCHEME}, or {@link #URI_ANDROID_APP_SCHEME}. + * @param flags Additional operating flags. * * @return Returns a URI encoding URI string describing the entire contents * of the Intent. */ - public String toUri(int flags) { + public String toUri(@UriFlags int flags) { StringBuilder uri = new StringBuilder(128); if ((flags&URI_ANDROID_APP_SCHEME) != 0) { if (mPackage == null) { @@ -9530,7 +9557,8 @@ public class Intent implements Parcelable, Cloneable { * @throws XmlPullParserException If there was an XML parsing error. * @throws IOException If there was an I/O error. */ - public static Intent parseIntent(Resources resources, XmlPullParser parser, AttributeSet attrs) + public static @NonNull Intent parseIntent(@NonNull Resources resources, + @NonNull XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException { Intent intent = new Intent(); @@ -9677,7 +9705,7 @@ public class Intent implements Parcelable, Cloneable { * @see #setType * @see #setTypeAndNormalize */ - public static String normalizeMimeType(String type) { + public static @Nullable String normalizeMimeType(@Nullable String type) { if (type == null) { return null; } diff --git a/core/java/android/content/pm/ChangedPackages.java b/core/java/android/content/pm/ChangedPackages.java index 78c057d9e0f4..b78c71d73095 100644 --- a/core/java/android/content/pm/ChangedPackages.java +++ b/core/java/android/content/pm/ChangedPackages.java @@ -35,7 +35,6 @@ public final class ChangedPackages implements Parcelable { /** The names of the packages that have changed */ private final List<String> mPackageNames; - @TestApi public ChangedPackages(int sequenceNumber, @NonNull List<String> packageNames) { this.mSequenceNumber = sequenceNumber; this.mPackageNames = packageNames; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index bc7a61200e8b..c7dd1fad4edc 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -474,15 +474,6 @@ interface IPackageManager { void notifyDexLoad(String loadingPackageName, in List<String> dexPaths, String loaderIsa); /** - * Ask the package manager to perform dex-opt (if needed) on the given - * package if it already hasn't done so. - * - * In most cases, apps are dexopted in advance and this function will - * be a no-op. - */ - boolean performDexOptIfNeeded(String packageName); - - /** * Ask the package manager to perform a dex-opt for the given reason. The package * manager will map the reason to a compiler filter according to the current system * configuration. diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 9e4a86db8684..aaaff0c059db 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1084,8 +1084,6 @@ public class PackageInstaller { /** * Sets which runtime permissions to be granted to the package at installation. - * Using this API requires holding {@link android.Manifest.permission - * #INSTALL_GRANT_RUNTIME_PERMISSIONS} * * @param permissions The permissions to grant or null to grant all runtime * permissions. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 09affa15ba67..ecaf7ebe07d2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -522,6 +522,18 @@ public abstract class PackageManager { */ public static final int PERMISSION_DENIED = -1; + /** @hide */ + @IntDef(prefix = { "SIGNATURE_" }, value = { + SIGNATURE_MATCH, + SIGNATURE_NEITHER_SIGNED, + SIGNATURE_FIRST_NOT_SIGNED, + SIGNATURE_SECOND_NOT_SIGNED, + SIGNATURE_NO_MATCH, + SIGNATURE_UNKNOWN_PACKAGE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SignatureResult {} + /** * Signature check result: this is returned by {@link #checkSignatures} * if all signatures on the two packages match. @@ -558,11 +570,25 @@ public abstract class PackageManager { */ public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; + /** @hide */ + @IntDef(prefix = { "COMPONENT_ENABLED_STATE_" }, value = { + COMPONENT_ENABLED_STATE_DEFAULT, + COMPONENT_ENABLED_STATE_ENABLED, + COMPONENT_ENABLED_STATE_DISABLED, + COMPONENT_ENABLED_STATE_DISABLED_USER, + COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EnabledState {} + /** - * Flag for {@link #setApplicationEnabledSetting(String, int, int)} - * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This - * component or application is in its default enabled state (as specified - * in its manifest). + * Flag for {@link #setApplicationEnabledSetting(String, int, int)} and + * {@link #setComponentEnabledSetting(ComponentName, int, int)}: This + * component or application is in its default enabled state (as specified in + * its manifest). + * <p> + * Explicitly setting the component state to this value restores it's + * enabled state to whatever is set in the manifest. */ public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; @@ -764,6 +790,13 @@ public abstract class PackageManager { */ public static final int INSTALL_ALLOCATE_AGGRESSIVE = 0x00008000; + /** @hide */ + @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = { + DONT_KILL_APP + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EnabledFlags {} + /** * Flag parameter for * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate @@ -2871,7 +2904,7 @@ public abstract class PackageManager { * does not contain such an activity, or if <em>packageName</em> is not * recognized. */ - public abstract Intent getLaunchIntentForPackage(String packageName); + public abstract @Nullable Intent getLaunchIntentForPackage(@NonNull String packageName); /** * Return a "good" intent to launch a front-door Leanback activity in a @@ -2885,7 +2918,7 @@ public abstract class PackageManager { * the main Leanback activity in the package, or null if the package * does not contain such an activity. */ - public abstract Intent getLeanbackLaunchIntentForPackage(String packageName); + public abstract @Nullable Intent getLeanbackLaunchIntentForPackage(@NonNull String packageName); /** * Return an array of all of the POSIX secondary group IDs that have been @@ -2901,7 +2934,7 @@ public abstract class PackageManager { * @throws NameNotFoundException if a package with the given name cannot be * found on the system. */ - public abstract int[] getPackageGids(String packageName) + public abstract int[] getPackageGids(@NonNull String packageName) throws NameNotFoundException; /** @@ -3189,7 +3222,7 @@ public abstract class PackageManager { * @see #PERMISSION_DENIED */ @CheckResult - public abstract int checkPermission(String permName, String pkgName); + public abstract @PermissionResult int checkPermission(String permName, String pkgName); /** * Checks whether a particular permissions has been revoked for a @@ -3419,12 +3452,9 @@ public abstract class PackageManager { * #SIGNATURE_NO_MATCH} or {@link #SIGNATURE_UNKNOWN_PACKAGE}). * * @see #checkSignatures(int, int) - * @see #SIGNATURE_MATCH - * @see #SIGNATURE_NO_MATCH - * @see #SIGNATURE_UNKNOWN_PACKAGE */ @CheckResult - public abstract int checkSignatures(String pkg1, String pkg2); + public abstract @SignatureResult int checkSignatures(String pkg1, String pkg2); /** * Like {@link #checkSignatures(String, String)}, but takes UIDs of @@ -3442,12 +3472,9 @@ public abstract class PackageManager { * #SIGNATURE_NO_MATCH} or {@link #SIGNATURE_UNKNOWN_PACKAGE}). * * @see #checkSignatures(String, String) - * @see #SIGNATURE_MATCH - * @see #SIGNATURE_NO_MATCH - * @see #SIGNATURE_UNKNOWN_PACKAGE */ @CheckResult - public abstract int checkSignatures(int uid1, int uid2); + public abstract @SignatureResult int checkSignatures(int uid1, int uid2); /** * Retrieve the names of all packages that are associated with a particular @@ -3535,8 +3562,7 @@ public abstract class PackageManager { @ApplicationInfoFlags int flags, @UserIdInt int userId); /** - * Gets the instant applications the user recently used. Requires - * holding "android.permission.ACCESS_INSTANT_APPS". + * Gets the instant applications the user recently used. * * @return The instant app list. * @@ -3882,8 +3908,8 @@ public abstract class PackageManager { * included by one of the <var>specifics</var> intents. If there are * no matching activities, an empty list is returned. */ - public abstract List<ResolveInfo> queryIntentActivityOptions( - ComponentName caller, Intent[] specifics, Intent intent, @ResolveInfoFlags int flags); + public abstract List<ResolveInfo> queryIntentActivityOptions(@Nullable ComponentName caller, + @Nullable Intent[] specifics, Intent intent, @ResolveInfoFlags int flags); /** * Retrieve all receivers that can handle a broadcast of the given intent. @@ -5137,18 +5163,11 @@ public abstract class PackageManager { * manifest. * * @param componentName The component to enable - * @param newState The new enabled state for the component. The legal values for this state - * are: - * {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED} - * and - * {@link #COMPONENT_ENABLED_STATE_DEFAULT} - * The last one removes the setting, thereby restoring the component's state to - * whatever was set in it's manifest (or enabled, by default). - * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. + * @param newState The new enabled state for the component. + * @param flags Optional behavior flags. */ public abstract void setComponentEnabledSetting(ComponentName componentName, - int newState, int flags); + @EnabledState int newState, @EnabledFlags int flags); /** * Return the enabled setting for a package component (activity, @@ -5158,14 +5177,10 @@ public abstract class PackageManager { * the value originally specified in the manifest has not been modified. * * @param componentName The component to retrieve. - * @return Returns the current enabled state for the component. May - * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or - * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the - * component's enabled state is based on the original information in - * the manifest as found in {@link ComponentInfo}. + * @return Returns the current enabled state for the component. */ - public abstract int getComponentEnabledSetting(ComponentName componentName); + public abstract @EnabledState int getComponentEnabledSetting( + ComponentName componentName); /** * Set the enabled setting for an application @@ -5175,18 +5190,11 @@ public abstract class PackageManager { * {@link #setComponentEnabledSetting} for any of the application's components. * * @param packageName The package name of the application to enable - * @param newState The new enabled state for the component. The legal values for this state - * are: - * {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED} - * and - * {@link #COMPONENT_ENABLED_STATE_DEFAULT} - * The last one removes the setting, thereby restoring the applications's state to - * whatever was set in its manifest (or enabled, by default). - * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. + * @param newState The new enabled state for the application. + * @param flags Optional behavior flags. */ public abstract void setApplicationEnabledSetting(String packageName, - int newState, int flags); + @EnabledState int newState, @EnabledFlags int flags); /** * Return the enabled setting for an application. This returns @@ -5196,15 +5204,10 @@ public abstract class PackageManager { * the value originally specified in the manifest has not been modified. * * @param packageName The package name of the application to retrieve. - * @return Returns the current enabled state for the application. May - * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, - * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or - * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the - * application's enabled state is based on the original information in - * the manifest as found in {@link ApplicationInfo}. + * @return Returns the current enabled state for the application. * @throws IllegalArgumentException if the named package does not exist. */ - public abstract int getApplicationEnabledSetting(String packageName); + public abstract @EnabledState int getApplicationEnabledSetting(String packageName); /** * Flush the package restrictions for a given user to disk. This forces the package restrictions diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 1f78bff9e1a7..86093512090e 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -145,7 +145,12 @@ public class PackageParser { private static final boolean DEBUG_PARSER = false; private static final boolean DEBUG_BACKUP = false; - private static final boolean MULTI_PACKAGE_APK_ENABLED = false; + private static final String PROPERTY_CHILD_PACKAGES_ENABLED = + "persist.sys.child_packages_enabled"; + + private static final boolean MULTI_PACKAGE_APK_ENABLED = + SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); + private static final int MAX_PACKAGES_PER_APK = 5; public static final int APK_SIGNING_UNKNOWN = 0; diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 10c4cb3df89c..f5ad5cc63a12 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -322,7 +322,10 @@ public class SystemSensorManager extends SensorManager { if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { synchronized(mTriggerListeners) { - for (TriggerEventListener l: mTriggerListeners.keySet()) { + HashMap<TriggerEventListener, TriggerEventQueue> triggerListeners = + new HashMap<TriggerEventListener, TriggerEventQueue>(mTriggerListeners); + + for (TriggerEventListener l: triggerListeners.keySet()) { if (DEBUG_DYNAMIC_SENSOR){ Log.i(TAG, "removed trigger listener" + l.toString() + " due to sensor disconnection"); @@ -332,7 +335,10 @@ public class SystemSensorManager extends SensorManager { } } else { synchronized(mSensorListeners) { - for (SensorEventListener l: mSensorListeners.keySet()) { + HashMap<SensorEventListener, SensorEventQueue> sensorListeners = + new HashMap<SensorEventListener, SensorEventQueue>(mSensorListeners); + + for (SensorEventListener l: sensorListeners.keySet()) { if (DEBUG_DYNAMIC_SENSOR){ Log.i(TAG, "removed event listener" + l.toString() + " due to sensor disconnection"); diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 1cf8f0314980..279d73d215e3 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1662,9 +1662,13 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>The output images for request B may have contents captured before the output images for * request A, and the result metadata for request B may be older than the result metadata for * request A.</p> - * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the - * past for requests with STILL_CAPTURE capture intent.</p> - * <p>The value of enableZsl in capture templates is always <code>false</code> if present.</p> + * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in + * the past for requests with STILL_CAPTURE capture intent.</p> + * <p>For applications targeting SDK versions O and newer, the value of enableZsl in + * TEMPLATE_STILL_CAPTURE template may be <code>true</code>. The value in other templates is always + * <code>false</code> if present.</p> + * <p>For applications targeting SDK versions older than O, the value of enableZsl in all + * capture templates is always <code>false</code> if present.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CaptureRequest#CONTROL_CAPTURE_INTENT diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 419e3e28d36d..aedfc4b702a7 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2167,9 +2167,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <p>The output images for request B may have contents captured before the output images for * request A, and the result metadata for request B may be older than the result metadata for * request A.</p> - * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the - * past for requests with STILL_CAPTURE capture intent.</p> - * <p>The value of enableZsl in capture templates is always <code>false</code> if present.</p> + * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in + * the past for requests with STILL_CAPTURE capture intent.</p> + * <p>For applications targeting SDK versions O and newer, the value of enableZsl in + * TEMPLATE_STILL_CAPTURE template may be <code>true</code>. The value in other templates is always + * <code>false</code> if present.</p> + * <p>For applications targeting SDK versions older than O, the value of enableZsl in all + * capture templates is always <code>false</code> if present.</p> * <p><b>Optional</b> - This value may be {@code null} on some devices.</p> * * @see CaptureRequest#CONTROL_CAPTURE_INTENT diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 768beea94e18..b854cbf2d0f8 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; @@ -742,8 +743,6 @@ public class ConnectivityManager { /** * Retrieves the current preferred network type. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an integer representing the preferred network type * @@ -753,6 +752,7 @@ public class ConnectivityManager { * the networks to describe their precedence. */ @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference() { return TYPE_NONE; } @@ -763,12 +763,11 @@ public class ConnectivityManager { * You should always check {@link NetworkInfo#isConnected()} before initiating * network traffic. This may return {@code null} when there is no default * network. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return a {@link NetworkInfo} object for the current default network * or {@code null} if no default network is currently active */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkInfo getActiveNetworkInfo() { try { return mService.getActiveNetworkInfo(); @@ -783,12 +782,11 @@ public class ConnectivityManager { * network disconnects, the returned {@code Network} object will no longer * be usable. This will return {@code null} when there is no default * network. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return a {@link Network} object for the current default network or * {@code null} if no default network is currently active */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public Network getActiveNetwork() { try { return mService.getActiveNetwork(); @@ -803,14 +801,13 @@ public class ConnectivityManager { * network disconnects, the returned {@code Network} object will no longer * be usable. This will return {@code null} when there is no default * network for the UID. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. * * @return a {@link Network} object for the current default network for the * given UID or {@code null} if no default network is currently active * * @hide */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public Network getActiveNetworkForUid(int uid) { return getActiveNetworkForUid(uid, false); } @@ -871,8 +868,6 @@ public class ConnectivityManager { * Returns details about the currently active default data network * for a given uid. This is for internal use only to avoid spying * other apps. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} * * @return a {@link NetworkInfo} object for the current default network * for the given uid or {@code null} if no default network is @@ -880,6 +875,7 @@ public class ConnectivityManager { * * {@hide} */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public NetworkInfo getActiveNetworkInfoForUid(int uid) { return getActiveNetworkInfoForUid(uid, false); } @@ -896,8 +892,6 @@ public class ConnectivityManager { /** * Returns connection status information about a particular * network type. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param networkType integer specifying which networkType in * which you're interested. @@ -910,6 +904,7 @@ public class ConnectivityManager { * {@link #getNetworkInfo(android.net.Network)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkInfo getNetworkInfo(int networkType) { try { return mService.getNetworkInfo(networkType); @@ -921,8 +916,6 @@ public class ConnectivityManager { /** * Returns connection status information about a particular * Network. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param network {@link Network} specifying which network * in which you're interested. @@ -930,6 +923,7 @@ public class ConnectivityManager { * network or {@code null} if the {@code Network} * is not valid. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkInfo getNetworkInfo(Network network) { return getNetworkInfoForUid(network, Process.myUid(), false); } @@ -946,8 +940,6 @@ public class ConnectivityManager { /** * Returns connection status information about all network * types supported by the device. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of {@link NetworkInfo} objects. Check each * {@link NetworkInfo#getType} for which type each applies. @@ -957,6 +949,7 @@ public class ConnectivityManager { * {@link #getNetworkInfo(android.net.Network)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkInfo[] getAllNetworkInfo() { try { return mService.getAllNetworkInfo(); @@ -969,15 +962,13 @@ public class ConnectivityManager { * Returns the {@link Network} object currently serving a given type, or * null if the given type is not connected. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. - * * @hide * @deprecated This method does not support multiple connected networks * of the same type. Use {@link #getAllNetworks} and * {@link #getNetworkInfo(android.net.Network)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public Network getNetworkForType(int networkType) { try { return mService.getNetworkForType(networkType); @@ -989,11 +980,10 @@ public class ConnectivityManager { /** * Returns an array of all {@link Network} currently tracked by the * framework. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of {@link Network} objects. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public Network[] getAllNetworks() { try { return mService.getAllNetworks(); @@ -1017,8 +1007,6 @@ public class ConnectivityManager { /** * Returns the IP information for the current default network. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return a {@link LinkProperties} object describing the IP info * for the current default network, or {@code null} if there @@ -1026,6 +1014,7 @@ public class ConnectivityManager { * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public LinkProperties getActiveLinkProperties() { try { return mService.getActiveLinkProperties(); @@ -1036,8 +1025,6 @@ public class ConnectivityManager { /** * Returns the IP information for a given network type. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param networkType the network type of interest. * @return a {@link LinkProperties} object describing the IP info @@ -1051,6 +1038,7 @@ public class ConnectivityManager { * {@link #getLinkProperties(android.net.Network)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public LinkProperties getLinkProperties(int networkType) { try { return mService.getLinkPropertiesForType(networkType); @@ -1062,12 +1050,11 @@ public class ConnectivityManager { /** * Get the {@link LinkProperties} for the given {@link Network}. This * will return {@code null} if the network is unknown. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param network The {@link Network} object identifying the network in question. * @return The {@link LinkProperties} for the network, or {@code null}. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public LinkProperties getLinkProperties(Network network) { try { return mService.getLinkProperties(network); @@ -1079,12 +1066,11 @@ public class ConnectivityManager { /** * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param network The {@link Network} object identifying the network in question. * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkCapabilities getNetworkCapabilities(Network network) { try { return mService.getNetworkCapabilities(network); @@ -1727,11 +1713,9 @@ public class ConnectivityManager { * network is active. Quota status can change rapidly, so these values * shouldn't be cached. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. - * * @hide */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public NetworkQuotaInfo getActiveNetworkQuotaInfo() { try { return mService.getActiveNetworkQuotaInfo(); @@ -1929,13 +1913,12 @@ public class ConnectivityManager { /** * Get the set of tetherable, available interfaces. This list is limited by * device configuration and current interface existence. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more Strings of tetherable interface names. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetherableIfaces() { try { return mService.getTetherableIfaces(); @@ -1946,13 +1929,12 @@ public class ConnectivityManager { /** * Get the set of tethered interfaces. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more String of currently tethered interface names. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetheredIfaces() { try { return mService.getTetheredIfaces(); @@ -1968,14 +1950,13 @@ public class ConnectivityManager { * may cause them to reset to the available state. * {@link ConnectivityManager#getLastTetherError} can be used to get more * information on the cause of the errors. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more String indicating the interface names * which failed to tether. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetheringErroredIfaces() { try { return mService.getTetheringErroredIfaces(); @@ -2060,14 +2041,13 @@ public class ConnectivityManager { * Check if the device allows for tethering. It may be disabled via * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or * due to device configuration. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return a boolean - {@code true} indicating Tethering is supported. * * {@hide} */ @SystemApi + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isTetheringSupported() { try { return mService.isTetheringSupported(); @@ -2171,14 +2151,13 @@ public class ConnectivityManager { * Get the list of regular expressions that define any tetherable * USB network interfaces. If USB tethering is not supported by the * device, this list should be empty. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable usb interfaces. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetherableUsbRegexs() { try { return mService.getTetherableUsbRegexs(); @@ -2191,14 +2170,13 @@ public class ConnectivityManager { * Get the list of regular expressions that define any tetherable * Wifi network interfaces. If Wifi tethering is not supported by the * device, this list should be empty. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable wifi interfaces. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetherableWifiRegexs() { try { return mService.getTetherableWifiRegexs(); @@ -2211,14 +2189,13 @@ public class ConnectivityManager { * Get the list of regular expressions that define any tetherable * Bluetooth network interfaces. If Bluetooth tethering is not supported by the * device, this list should be empty. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable bluetooth interfaces. * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public String[] getTetherableBluetoothRegexs() { try { return mService.getTetherableBluetoothRegexs(); @@ -2280,8 +2257,6 @@ public class ConnectivityManager { /** * Get a more detailed error code after a Tethering or Untethering * request asynchronously failed. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param iface The name of the interface of interest * @return error The error code of the last error tethering or untethering the named @@ -2289,6 +2264,7 @@ public class ConnectivityManager { * * {@hide} */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getLastTetherError(String iface) { try { return mService.getLastTetherError(iface); @@ -2362,13 +2338,12 @@ public class ConnectivityManager { * for typical HTTP proxies - they are general network dependent. However if you're * doing something unusual like general internal filtering this may be useful. On * a private network where the proxy is not accessible, you may break HTTP using this. - * <p>This method requires the caller to hold the permission - * android.Manifest.permission#CONNECTIVITY_INTERNAL. * * @param p A {@link ProxyInfo} object defining the new global * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * @hide */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void setGlobalProxy(ProxyInfo p) { try { mService.setGlobalProxy(p); @@ -2434,14 +2409,13 @@ public class ConnectivityManager { * hardware supports it. For example a GSM phone without a SIM * should still return {@code true} for mobile data, but a wifi only * tablet would return {@code false}. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param networkType The network type we'd like to check * @return {@code true} if supported, else {@code false} * * @hide */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isNetworkSupported(int networkType) { try { return mService.isNetworkSupported(networkType); @@ -2457,12 +2431,11 @@ public class ConnectivityManager { * battery/performance issues. You should check this before doing large * data transfers, and warn the user or delay the operation until another * network is available. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @return {@code true} if large transfers should be avoided, otherwise * {@code false}. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered() { try { return mService.isActiveNetworkMetered(); @@ -2541,13 +2514,12 @@ public class ConnectivityManager { /** * Set the value for enabling/disabling airplane mode - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. * * @param enable whether to enable airplane mode or not * * @hide */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void setAirplaneMode(boolean enable) { try { mService.setAirplaneMode(enable); @@ -3225,14 +3197,13 @@ public class ConnectivityManager { * Registers to receive notifications about all networks which satisfy the given * {@link NetworkRequest}. The callbacks will continue to be called until * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param request {@link NetworkRequest} describing this request. * @param networkCallback The {@link NetworkCallback} that the system will call as suitable * networks change state. * The callback is invoked on the default internal Handler. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(NetworkRequest request, NetworkCallback networkCallback) { registerNetworkCallback(request, networkCallback, getDefaultHandler()); } @@ -3241,14 +3212,13 @@ public class ConnectivityManager { * Registers to receive notifications about all networks which satisfy the given * {@link NetworkRequest}. The callbacks will continue to be called until * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param request {@link NetworkRequest} describing this request. * @param networkCallback The {@link NetworkCallback} that the system will call as suitable * networks change state. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback( NetworkRequest request, NetworkCallback networkCallback, Handler handler) { CallbackHandler cbHandler = new CallbackHandler(handler); @@ -3280,13 +3250,12 @@ public class ConnectivityManager { * <p> * The request may be released normally by calling * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @param request {@link NetworkRequest} describing this request. * @param operation Action to perform when the network is available (corresponds * to the {@link NetworkCallback#onAvailable} call. Typically * comes from {@link PendingIntent#getBroadcast}. Cannot be null. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) { checkPendingIntent(operation); try { @@ -3300,13 +3269,12 @@ public class ConnectivityManager { * Registers to receive notifications about changes in the system default network. The callbacks * will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param networkCallback The {@link NetworkCallback} that the system will call as the * system default network changes. * The callback is invoked on the default internal Handler. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(NetworkCallback networkCallback) { registerDefaultNetworkCallback(networkCallback, getDefaultHandler()); } @@ -3315,13 +3283,12 @@ public class ConnectivityManager { * Registers to receive notifications about changes in the system default network. The callbacks * will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param networkCallback The {@link NetworkCallback} that the system will call as the * system default network changes. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(NetworkCallback networkCallback, Handler handler) { // This works because if the NetworkCapabilities are null, // ConnectivityService takes them from the default request. @@ -3398,15 +3365,13 @@ public class ConnectivityManager { * {@code always} is true, then the choice is remembered, so that the next time the user * connects to this network, the system will switch to it. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} - * * @param network The network to accept. * @param accept Whether to accept the network even if unvalidated. * @param always Whether to remember this choice in the future. * * @hide */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { try { mService.setAcceptUnvalidated(network, accept, always); @@ -3421,13 +3386,11 @@ public class ConnectivityManager { * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code * NETWORK_AVOID_BAD_WIFI setting is unset}. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} - * * @param network The network to accept. * * @hide */ + @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void setAvoidUnvalidated(Network network) { try { mService.setAvoidUnvalidated(network); @@ -3488,15 +3451,13 @@ public class ConnectivityManager { * for multipath data transfer on this network when it is not the system default network. * Applications desiring to use multipath network protocols should call this method before * each such operation. - * <p> - * This method requires the caller to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * * @param network The network on which the application desires to use multipath data. * If {@code null}, this method will return the a preference that will generally * apply to metered networks. * @return a bitwise OR of zero or more of the {@code MULTIPATH_PREFERENCE_*} constants. */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public @MultipathPreference int getMultipathPreference(Network network) { try { return mService.getMultipathPreference(network); diff --git a/core/java/android/net/INetworkRecommendationProvider.aidl b/core/java/android/net/INetworkRecommendationProvider.aidl index 052c92c0309f..cde0185d2288 100644 --- a/core/java/android/net/INetworkRecommendationProvider.aidl +++ b/core/java/android/net/INetworkRecommendationProvider.aidl @@ -17,8 +17,6 @@ package android.net; import android.net.NetworkKey; -import android.net.RecommendationRequest; -import android.os.IRemoteCallback; /** * The service responsible for answering network recommendation requests. @@ -27,20 +25,6 @@ import android.os.IRemoteCallback; oneway interface INetworkRecommendationProvider { /** - * Request a recommendation for the best network to connect to - * taking into account the inputs from the {@link RecommendationRequest}. - * - * @param request a {@link RecommendationRequest} instance containing the details of the request - * @param callback a {@link IRemoteCallback} instance to invoke when the recommendation - * is available - * @param sequence an internal number used for tracking the request - * @hide - */ - void requestRecommendation(in RecommendationRequest request, - in IRemoteCallback callback, - int sequence); - - /** * Request scoring for networks. * * Implementations should use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl index 362ea9d6bc54..73e52c89dcc4 100644 --- a/core/java/android/net/INetworkScoreService.aidl +++ b/core/java/android/net/INetworkScoreService.aidl @@ -19,10 +19,7 @@ package android.net; import android.net.INetworkScoreCache; import android.net.NetworkKey; import android.net.NetworkScorerAppData; -import android.net.RecommendationRequest; -import android.net.RecommendationResult; import android.net.ScoredNetwork; -import android.os.RemoteCallback; /** * A service for updating network scores from a network scorer application. @@ -81,16 +78,6 @@ interface INetworkScoreService void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** - * Request a recommendation for the best network to connect to - * taking into account the inputs from the {@link RecommendationRequest}. - * - * @param request a {@link RecommendationRequest} instance containing the details of the request - * @return a {@link RecommendationResult} containing the recommended network to connect to - * @throws SecurityException if the caller is not the system - */ - RecommendationResult requestRecommendation(in RecommendationRequest request); - - /** * Request scoring for networks. * * Implementations should delegate to the registered network recommendation provider or @@ -119,18 +106,6 @@ interface INetworkScoreService * scorer. */ String getActiveScorerPackage(); - - /** - * Request a recommendation for the best network to connect to - * taking into account the inputs from the {@link RecommendationRequest}. - * - * @param request a {@link RecommendationRequest} instance containing the details of the request - * @param remoteCallback a {@link RemoteCallback} instance to invoke when the recommendation - * is available. - * @throws SecurityException if the caller is not the system - */ - oneway void requestRecommendationAsync(in RecommendationRequest request, - in RemoteCallback remoteCallback); /** * Returns metadata about the active scorer or <code>null</code> if there is no active scorer. diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java index af0459d63718..1eaa1f90d64c 100644 --- a/core/java/android/net/NetworkRecommendationProvider.java +++ b/core/java/android/net/NetworkRecommendationProvider.java @@ -39,10 +39,14 @@ import java.util.concurrent.atomic.AtomicBoolean; public abstract class NetworkRecommendationProvider { private static final String TAG = "NetworkRecProvider"; private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE); - /** The key into the callback Bundle where the RecommendationResult will be found. */ + /** The key into the callback Bundle where the RecommendationResult will be found. + * @deprecated to be removed. + */ public static final String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT"; - /** The key into the callback Bundle where the sequence will be found. */ + /** The key into the callback Bundle where the sequence will be found. + * @deprecated to be removed. + */ public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE"; private final IBinder mService; @@ -77,9 +81,9 @@ public abstract class NetworkRecommendationProvider { * @param callback a {@link ResultCallback} instance. When a {@link RecommendationResult} is * available it must be passed into * {@link ResultCallback#onResult(RecommendationResult)}. + * @deprecated to be removed. */ - public abstract void onRequestRecommendation(RecommendationRequest request, - ResultCallback callback); + public void onRequestRecommendation(RecommendationRequest request, ResultCallback callback) {} /** * Invoked when network scores have been requested. @@ -101,6 +105,8 @@ public abstract class NetworkRecommendationProvider { /** * A callback implementing applications should invoke when a {@link RecommendationResult} * is available. + * + * @deprecated to be removed. */ public static class ResultCallback { private final IRemoteCallback mCallback; @@ -176,23 +182,6 @@ public abstract class NetworkRecommendationProvider { } @Override - public void requestRecommendation(final RecommendationRequest request, - final IRemoteCallback callback, final int sequence) throws RemoteException { - enforceCallingPermission(); - if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")"); - execute(new Runnable() { - @Override - public void run() { - if (VERBOSE) { - Log.v(TAG, "requestRecommendation(seq=" + sequence + ") running..."); - } - ResultCallback resultCallback = new ResultCallback(callback, sequence); - onRequestRecommendation(request, resultCallback); - } - }); - } - - @Override public void requestScores(final NetworkKey[] networks) throws RemoteException { enforceCallingPermission(); if (networks != null && networks.length > 0) { diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 29483cd98bd1..eeb426a4bcf9 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -428,14 +428,11 @@ public class NetworkScoreManager { * @throws SecurityException if the caller does not hold the * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. * @hide + * @deprecated to be removed. */ public RecommendationResult requestRecommendation(RecommendationRequest request) throws SecurityException { - try { - return mService.requestRecommendation(request); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return null; } /** @@ -452,43 +449,4 @@ public class NetworkScoreManager { throw e.rethrowFromSystemServer(); } } - - /** - * Request a recommendation for which network to connect to. - * - * <p>The callback will be run on the thread associated with provided {@link Handler}. - * - * @param request a {@link RecommendationRequest} instance containing additional - * request details - * @param handler a {@link Handler} instance representing the thread to complete the future on. - * If null the responding binder thread will be used. - * @return a {@link CompletableFuture} instance that will eventually receive the - * {@link RecommendationResult}. - * @throws SecurityException - * @hide - */ - public CompletableFuture<RecommendationResult> requestRecommendation( - final @NonNull RecommendationRequest request, - final @Nullable Handler handler) { - Preconditions.checkNotNull(request, "RecommendationRequest cannot be null."); - - final CompletableFuture<RecommendationResult> futureResult = - new CompletableFuture<>(); - - RemoteCallback remoteCallback = new RemoteCallback(new RemoteCallback.OnResultListener() { - @Override - public void onResult(Bundle data) { - RecommendationResult result = data.getParcelable(EXTRA_RECOMMENDATION_RESULT); - futureResult.complete(result); - } - }, handler); - - try { - mService.requestRecommendationAsync(request, remoteCallback); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - return futureResult; - } } diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java index 9f97c5a79506..45ee3a5283dd 100644 --- a/core/java/android/net/RecommendationRequest.java +++ b/core/java/android/net/RecommendationRequest.java @@ -30,6 +30,7 @@ import com.android.internal.annotations.VisibleForTesting; * * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}. * @hide + * @deprecated to be removed. */ @SystemApi public final class RecommendationRequest implements Parcelable { @@ -43,6 +44,7 @@ public final class RecommendationRequest implements Parcelable { /** * Builder class for constructing {@link RecommendationRequest} instances. * @hide + * @deprecated to be removed. */ @SystemApi public static final class Builder { diff --git a/core/java/android/net/RecommendationResult.aidl b/core/java/android/net/RecommendationResult.aidl deleted file mode 100644 index f36995b8cc68..000000000000 --- a/core/java/android/net/RecommendationResult.aidl +++ /dev/null @@ -1,19 +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 android.net; - -parcelable RecommendationResult; diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java index 70cf09c7df5b..ce4d83af3f01 100644 --- a/core/java/android/net/RecommendationResult.java +++ b/core/java/android/net/RecommendationResult.java @@ -31,6 +31,7 @@ import com.android.internal.util.Preconditions; * * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}. * @hide + * @deprecated to be removed. */ @SystemApi public final class RecommendationResult implements Parcelable { diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 0610499dbce4..86fcfc8fb961 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -115,8 +115,7 @@ public class Build { public static final String SERIAL = getString("no.such.thing"); /** - * Gets the hardware serial, if available. Requires holding the {@link - * android.Manifest.permission#READ_PHONE_STATE} permission. + * Gets the hardware serial, if available. * @return The serial if specified. */ @RequiresPermission(Manifest.permission.READ_PHONE_STATE) diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index c10abec7a80a..6632ca51e74c 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -16,6 +16,11 @@ package android.os; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Interface for classes whose instances can be written to * and restored from a {@link Parcel}. Classes implementing the Parcelable @@ -53,6 +58,14 @@ package android.os; * }</pre> */ public interface Parcelable { + /** @hide */ + @IntDef(flag = true, prefix = { "PARCELABLE_" }, value = { + PARCELABLE_WRITE_RETURN_VALUE, + PARCELABLE_ELIDE_DUPLICATES, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WriteFlags {} + /** * Flag for use with {@link #writeToParcel}: the object being written * is a return value, that is the result of a function such as @@ -79,6 +92,13 @@ public interface Parcelable { * marshalled. */ + /** @hide */ + @IntDef(flag = true, prefix = { "CONTENTS_" }, value = { + CONTENTS_FILE_DESCRIPTOR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ContentsFlags {} + /** * Descriptor bit used with {@link #describeContents()}: indicates that * the Parcelable object's flattened representation includes a file descriptor. @@ -96,10 +116,8 @@ public interface Parcelable { * * @return a bitmask indicating the set of special object types marshaled * by this Parcelable object instance. - * - * @see #CONTENTS_FILE_DESCRIPTOR */ - public int describeContents(); + public @ContentsFlags int describeContents(); /** * Flatten this object in to a Parcel. @@ -108,7 +126,7 @@ public interface Parcelable { * @param flags Additional flags about how the object should be written. * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. */ - public void writeToParcel(Parcel dest, int flags); + public void writeToParcel(Parcel dest, @WriteFlags int flags); /** * Interface that must be implemented and provided as a public CREATOR diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index c6bbf484e702..1e55c78845d1 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.RequiresPermission; import android.app.ActivityThread; import android.content.Context; import android.media.AudioAttributes; @@ -65,22 +66,19 @@ public abstract class Vibrator { /** * Vibrate constantly for the specified period of time. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#VIBRATE}. * * @param milliseconds The number of milliseconds to vibrate. * * @deprecated Use {@link #vibrate(VibrationEffect)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long milliseconds) { vibrate(milliseconds, null); } /** * Vibrate constantly for the specified period of time. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#VIBRATE}. * * @param milliseconds The number of milliseconds to vibrate. * @param attributes {@link AudioAttributes} corresponding to the vibration. For example, @@ -91,6 +89,7 @@ public abstract class Vibrator { * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long milliseconds, AudioAttributes attributes) { try { // This ignores all exceptions to stay compatible with pre-O implementations. @@ -115,8 +114,6 @@ public abstract class Vibrator { * To cause the pattern to repeat, pass the index into the pattern array at which * to start the repeat, or -1 to disable repeating. * </p> - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#VIBRATE}. * * @param pattern an array of longs of times for which to turn the vibrator on or off. * @param repeat the index into pattern at which to repeat, or -1 if @@ -125,6 +122,7 @@ public abstract class Vibrator { * @deprecated Use {@link #vibrate(VibrationEffect)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[] pattern, int repeat) { vibrate(pattern, repeat, null); } @@ -142,8 +140,6 @@ public abstract class Vibrator { * To cause the pattern to repeat, pass the index into the pattern array at which * to start the repeat, or -1 to disable repeating. * </p> - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#VIBRATE}. * * @param pattern an array of longs of times for which to turn the vibrator on or off. * @param repeat the index into pattern at which to repeat, or -1 if @@ -156,6 +152,7 @@ public abstract class Vibrator { * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead. */ @Deprecated + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) { // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other // exceptions for compatibility purposes @@ -170,10 +167,12 @@ public abstract class Vibrator { } } + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(VibrationEffect vibe) { vibrate(vibe, null); } + @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(VibrationEffect vibe, AudioAttributes attributes) { vibrate(Process.myUid(), mPackageName, vibe, attributes); } @@ -183,13 +182,13 @@ public abstract class Vibrator { * that the vibration is owned by someone else. * @hide */ + @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void vibrate(int uid, String opPkg, VibrationEffect vibe, AudioAttributes attributes); /** * Turn the vibrator off. - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#VIBRATE}. */ + @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel(); } diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index 7496cb28f046..2179bd45e303 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -17,8 +17,6 @@ package android.preference; import android.annotation.CallSuper; -import com.android.internal.util.CharSequences; - import android.annotation.DrawableRes; import android.annotation.LayoutRes; import android.annotation.Nullable; @@ -42,6 +40,8 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; +import com.android.internal.util.CharSequences; + import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -650,7 +650,11 @@ public class Preference implements Comparable<Preference> { final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame); if (imageFrame != null) { - imageFrame.setVisibility(mIcon != null ? View.VISIBLE : View.GONE); + if (mIcon != null) { + imageFrame.setVisibility(View.VISIBLE); + } else { + imageFrame.setVisibility(mIconSpaceReserved ? View.INVISIBLE : View.GONE); + } } if (mShouldDisableView) { diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index 068628a6a783..e68c7bb547a0 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -33,7 +33,6 @@ import android.content.pm.Signature; import android.database.Cursor; import android.graphics.Typeface; import android.graphics.fonts.FontRequest; -import android.graphics.fonts.FontResult; import android.graphics.fonts.FontVariationAxis; import android.net.Uri; import android.os.Bundle; @@ -43,6 +42,7 @@ import android.os.HandlerThread; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.ResultReceiver; +import android.util.ArraySet; import android.util.Log; import android.util.LruCache; @@ -64,6 +64,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * Utility class to deal with Font ContentProviders. @@ -181,6 +182,8 @@ public class FontsContract { private Handler mHandler; @GuardedBy("mLock") private HandlerThread mThread; + @GuardedBy("mLock") + private Set<String> mInQueueSet; private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16); @@ -330,81 +333,54 @@ public class FontsContract { mThread.quitSafely(); mThread = null; mHandler = null; + mInQueueSet = null; } } } }; /** @hide */ - public void getFont(FontRequest request, ResultReceiver receiver) { + public Typeface getFontOrWarmUpCache(FontRequest request) { + final String id = request.getIdentifier(); + Typeface cachedTypeface = sTypefaceCache.get(id); + if (cachedTypeface != null) { + return cachedTypeface; + } + + // Unfortunately the typeface is not available at this time, but requesting from the font + // provider takes too much time. For now, request the font data to ensure it is in the cache + // next time and return. synchronized (mLock) { if (mHandler == null) { mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND); mThread.start(); mHandler = new Handler(mThread.getLooper()); + mInQueueSet = new ArraySet<String>(); } + if (mInQueueSet.contains(id)) { + return null; // Already requested. + } + mInQueueSet.add(id); mHandler.post(() -> { - ProviderInfo providerInfo; - try { - providerInfo = getProvider(mPackageManager, request); - if (providerInfo == null) { - receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); - return; - } - } catch (PackageManager.NameNotFoundException e) { - receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); - return; + synchronized (mLock) { + mInQueueSet.remove(id); } - FontInfo[] fonts; try { - fonts = getFontFromProvider(mContext, request, providerInfo.authority, - null /* cancellation signal */); - } catch (InvalidFormatException e) { - receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); - return; - } - - ArrayList<FontResult> result = new ArrayList<>(); - int resultCode = -1; - for (FontInfo font : fonts) { - try { - resultCode = font.getResultCode(); - if (resultCode != Columns.RESULT_CODE_OK) { - if (resultCode < 0) { - // Negative values are reserved for the internal errors. - resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND; - } - for (int i = 0; i < result.size(); ++i) { - try { - result.get(i).getFileDescriptor().close(); - } catch (IOException e) { - // Ignore, as we are closing fds for cleanup. - } - } - receiver.send(resultCode, null); - return; + FontFamilyResult result = fetchFonts(mContext, null, request); + if (result.getStatusCode() == FontFamilyResult.STATUS_OK) { + Typeface typeface = buildTypeface(mContext, null, result.getFonts()); + if (typeface != null) { + sTypefaceCache.put(id, typeface); } - ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor( - font.getUri(), "r"); - result.add(new FontResult(pfd, font.getTtcIndex(), - FontVariationAxis.toFontVariationSettings(font.getAxes()), - font.getWeight(), font.isItalic())); - } catch (FileNotFoundException e) { - Log.e(TAG, "FileNotFoundException raised when interacting with content " - + "provider " + providerInfo.authority, e); } + } catch (NameNotFoundException e) { + // Ignore. } - if (!result.isEmpty()) { - Bundle bundle = new Bundle(); - bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result); - receiver.send(Columns.RESULT_CODE_OK, bundle); - return; - } - receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null); }); mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable); mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS); } + return null; } /** @@ -452,16 +428,14 @@ public class FontsContract { public FontRequestCallback() {} /** - * Called then a Typeface request done via {@link Typeface#create(FontRequest, - * FontRequestCallback)} is complete. Note that this method will not be called if - * {@link #onTypefaceRequestFailed(int)} is called instead. + * Called then a Typeface request done via {@link #requestFont} is complete. Note that this + * method will not be called if {@link #onTypefaceRequestFailed(int)} is called instead. * @param typeface The Typeface object retrieved. */ public void onTypefaceRetrieved(Typeface typeface) {} /** - * Called when a Typeface request done via {@link Typeface#create(FontRequest, - * FontRequestCallback)} fails. + * Called when a Typeface request done via {@link #requestFont}} fails. * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND}, * {@link #FAIL_REASON_FONT_NOT_FOUND}, * {@link #FAIL_REASON_FONT_LOAD_ERROR}, diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 75f95ae844d7..69371be4f24a 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1398,6 +1398,26 @@ public final class Settings { public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS"; + /** + * Activity Action: Show screen that let user select its Autofill Service. + * <p> + * Input: Intent's data URI set with an application name, using the + * "package" schema (like "package:com.my.app"). + * + * <p> + * Output: {@link android.app.Activity#RESULT_OK} if user selected an Autofill Service belonging + * to the caller package. + * + * <p> + * <b>NOTE: </b> applications should call + * {@link android.view.autofill.AutofillManager#hasEnabledAutofillServices()} and + * {@link android.view.autofill.AutofillManager#isAutofillSupported()} first, and only + * broadcast this intent if they return {@code false} and {@code true} respectively. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = + "android.settings.REQUEST_SET_AUTOFILL_SERVICE"; + // End of Intent actions for Settings /** @@ -8280,16 +8300,6 @@ public final class Settings { "network_recommendations_package"; /** - * Value to specify if the Wi-Fi Framework should defer to - * {@link com.android.server.NetworkScoreService} for evaluating saved open networks. - * - * Type: int (0 for false, 1 for true) - * @hide - */ - @SystemApi - public static final String CURATE_SAVED_OPEN_NETWORKS = "curate_saved_open_networks"; - - /** * The package name of the application that connect and secures high quality open wifi * networks automatically. * @@ -8304,6 +8314,7 @@ public final class Settings { * * Type: long * @hide + * @deprecated to be removed */ public static final String NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS = "network_recommendation_request_timeout_ms"; @@ -9805,7 +9816,6 @@ public final class Settings { CHARGING_SOUNDS_ENABLED, USB_MASS_STORAGE_ENABLED, NETWORK_RECOMMENDATIONS_ENABLED, - CURATE_SAVED_OPEN_NETWORKS, WIFI_WAKEUP_ENABLED, WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, USE_OPEN_WIFI_PACKAGE, diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 813c54f53db9..cb47c104ed9f 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -36,9 +36,6 @@ import com.android.internal.os.SomeArgs; import java.util.List; -//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the -//life-cycle (and how state could be maintained on server-side) is well documented. - /** * Top-level service of the current autofill service for a given user. * @@ -50,19 +47,6 @@ public abstract class AutofillService extends Service { /** * 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_AUTO_FILL} permission so - * that other applications can not abuse it. - * - * @hide - * @deprecated TODO(b/35956626): remove once clients use AutofillService - */ - @Deprecated - @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) - public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService"; - - /** - * 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_AUTOFILL} permission so * that other applications can not abuse it. */ @@ -82,18 +66,12 @@ public abstract class AutofillService extends Service { */ public static final String SERVICE_META_DATA = "android.autofill"; - // Internal extras - /** @hide */ - public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID"; - // Handler messages. private static final int MSG_CONNECT = 1; private static final int MSG_DISCONNECT = 2; private static final int MSG_ON_FILL_REQUEST = 3; private static final int MSG_ON_SAVE_REQUEST = 4; - private static final int UNUSED_ARG = -1; - private final IAutoFillService mInterface = new IAutoFillService.Stub() { @Override public void onConnectedStateChanged(boolean connected) { @@ -136,7 +114,13 @@ public abstract class AutofillService extends Service { final IFillCallback callback = (IFillCallback) args.arg3; final FillCallback fillCallback = new FillCallback(callback, request.getId()); args.recycle(); - onFillRequest(request, cancellation, fillCallback); + // TODO(b/37563972): temporary try-catch hack to support old method + try { + onFillRequest(request, cancellation, fillCallback); + } catch (AbstractMethodError e) { + onFillRequest(request.getStructure(), request.getClientState(), + request.getFlags(), cancellation, fillCallback); + } break; } case MSG_ON_SAVE_REQUEST: { final SomeArgs args = (SomeArgs) msg.obj; @@ -144,7 +128,14 @@ public abstract class AutofillService extends Service { final ISaveCallback callback = (ISaveCallback) args.arg2; final SaveCallback saveCallback = new SaveCallback(callback); args.recycle(); - onSaveRequest(request, saveCallback); + // TODO(b/37563972): temporary try-catch hack to support old method + try { + onSaveRequest(request, saveCallback); + } catch (AbstractMethodError e) { + final List<FillContext> contexts = request.getFillContexts(); + onSaveRequest(contexts.get(contexts.size() - 1).getStructure(), + request.getClientState(), saveCallback); + } break; } case MSG_DISCONNECT: { onDisconnected(); @@ -170,8 +161,7 @@ public abstract class AutofillService extends Service { @Override public final IBinder onBind(Intent intent) { - if (SERVICE_INTERFACE.equals(intent.getAction()) - || OLD_SERVICE_INTERFACE.equals(intent.getAction())) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { return mInterface.asBinder(); } Log.w(TAG, "Tried to bind to wrong intent: " + intent); @@ -202,11 +192,8 @@ public abstract class AutofillService extends Service { * handling this fill request in order to save resources. * @param callback object used to notify the result of the request. */ - public void onFillRequest(@NonNull FillRequest request, - @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) { - onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(), - cancellationSignal, callback); - } + public abstract void onFillRequest(@NonNull FillRequest request, + @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); /** * Called by the Android system do decide if an {@link Activity} can be autofilled by the @@ -229,6 +216,8 @@ public abstract class AutofillService extends Service { * this to notify you that the fill result is no longer needed and you should stop * handling this fill request in order to save resources. * @param callback object used to notify the result of the request. + * + * @hide */ @Deprecated public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, @@ -246,11 +235,8 @@ public abstract class AutofillService extends Service { * See {@link FillResponse} for examples of multiple-sections requests. * @param callback object used to notify the result of the request. */ - public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) { - final List<FillContext> contexts = request.getFillContexts(); - onSaveRequest(contexts.get(contexts.size() - 1).getStructure(), - request.getClientState(), callback); - } + public abstract void onSaveRequest(@NonNull SaveRequest request, + @NonNull SaveCallback callback); /** * Called when user requests service to save the fields of an {@link Activity}. @@ -267,6 +253,8 @@ public abstract class AutofillService extends Service { * conserve resources. * See {@link FillResponse} for examples of multiple-sections requests. * @param callback object used to notify the result of the request. + * + * @hide */ @Deprecated public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data, @@ -280,9 +268,9 @@ public abstract class AutofillService extends Service { public void onDisconnected() { } + /** @hide */ @Deprecated public final void disableSelf() { - // TODO(b/33197203): Remove when GCore has migrated off this API getSystemService(AutofillManager.class).disableOwnedAutofillServices(); } diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index aa6db4d092f2..49f348c79ef2 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -39,8 +39,6 @@ import java.util.concurrent.atomic.AtomicInteger; * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback) */ public final class FillRequest implements Parcelable { - private static AtomicInteger sIdCounter = new AtomicInteger(); - /** * Indicates autofill was explicitly requested by the user. */ @@ -58,12 +56,6 @@ public final class FillRequest implements Parcelable { private final @NonNull AssistStructure mStructure; private final @Nullable Bundle mClientState; - /** @hide */ - public FillRequest(@NonNull AssistStructure structure, - @Nullable Bundle clientState, @RequestFlags int flags) { - this(sIdCounter.incrementAndGet(), structure, clientState, flags); - } - private FillRequest(@NonNull Parcel parcel) { mId = parcel.readInt(); mStructure = parcel.readParcelable(null); @@ -71,7 +63,8 @@ public final class FillRequest implements Parcelable { mFlags = parcel.readInt(); } - private FillRequest(int id, @NonNull AssistStructure structure, + /** @hide */ + public FillRequest(int id, @NonNull AssistStructure structure, @Nullable Bundle clientState, @RequestFlags int flags) { mId = id; mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST); diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 68ce0b52c070..2afb1f4fc9be 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -242,7 +242,7 @@ public final class FillResponse implements Parcelable { public @NonNull Builder setAuthentication(@NonNull AutofillId[] ids, @Nullable IntentSender authentication, @Nullable RemoteViews presentation) { throwIfDestroyed(); - // TODO(b/33197203): assert ids is not null nor empty once old version is removed + // TODO(b/37424539): assert ids is not null nor empty once old version is removed if (authentication == null ^ presentation == null) { throw new IllegalArgumentException("authentication and presentation" + " must be both non-null or null"); @@ -254,7 +254,7 @@ public final class FillResponse implements Parcelable { } /** - * TODO(b/33197203): will be removed once clients use the version that takes ids + * TODO(b/37424539): will be removed once clients use the version that takes ids * @hide * @deprecated */ @@ -311,6 +311,7 @@ public final class FillResponse implements Parcelable { /** * @deprecated Use {@link #setClientState(Bundle)} instead. + * @hide */ @Deprecated public Builder setExtras(@Nullable Bundle extras) { diff --git a/core/java/android/service/resolver/ResolverRankerService.java b/core/java/android/service/resolver/ResolverRankerService.java index 05067479bf45..75233474415a 100644 --- a/core/java/android/service/resolver/ResolverRankerService.java +++ b/core/java/android/service/resolver/ResolverRankerService.java @@ -65,6 +65,12 @@ public abstract class ResolverRankerService extends Service { public static final String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService"; /** + * The permission that a service must hold. If the service does not hold the permission, the + * system will skip that service. + */ + public static final String HOLD_PERMISSION = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"; + + /** * The permission that a service must require to ensure that only Android system can bind to it. * If this permission is not enforced in the AndroidManifest of the service, the system will * skip that service. diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl index 6eea07d33c40..8b2d0c6293e8 100644 --- a/core/java/android/service/vr/IVrManager.aidl +++ b/core/java/android/service/vr/IVrManager.aidl @@ -16,6 +16,7 @@ package android.service.vr; +import android.app.CompatibilityDisplayProperties; import android.service.vr.IVrStateCallbacks; import android.service.vr.IPersistentVrStateCallbacks; @@ -67,6 +68,18 @@ interface IVrManager { void setPersistentVrModeEnabled(in boolean enabled); /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProperties Compatibitlity display properties to be set for + * the VR virtual display + */ + void setCompatibilityDisplayProperties( + in CompatibilityDisplayProperties compatDisplayProperties); + + /** * Return current virtual display id. * * @return {@link android.view.Display.INVALID_DISPLAY} if there is no virtual display diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java index 0f8515988d1e..7e6eb4906c20 100644 --- a/core/java/android/text/util/Linkify.java +++ b/core/java/android/text/util/Linkify.java @@ -88,11 +88,7 @@ public class Linkify { * {@link android.webkit.WebView#findAddress(String) findAddress()} method in * {@link android.webkit.WebView} for finding addresses, which has various * limitations. - * - * @deprecated See {@link android.webkit.WebView#findAddress(String) findAddress()} - * for more explanation. */ - @Deprecated public static final int MAP_ADDRESSES = 0x08; /** diff --git a/core/java/android/transition/ChangeClipBounds.java b/core/java/android/transition/ChangeClipBounds.java index 8d0943c50430..a6398d3faeb7 100644 --- a/core/java/android/transition/ChangeClipBounds.java +++ b/core/java/android/transition/ChangeClipBounds.java @@ -16,6 +16,7 @@ package android.transition; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.RectEvaluator; import android.content.Context; @@ -84,6 +85,7 @@ public class ChangeClipBounds extends Transition { } Rect start = (Rect) startValues.values.get(PROPNAME_CLIP); Rect end = (Rect) endValues.values.get(PROPNAME_CLIP); + boolean endIsNull = end == null; if (start == null && end == null) { return null; // No animation required since there is no clip. } @@ -99,6 +101,17 @@ public class ChangeClipBounds extends Transition { endValues.view.setClipBounds(start); RectEvaluator evaluator = new RectEvaluator(new Rect()); - return ObjectAnimator.ofObject(endValues.view, "clipBounds", evaluator, start, end); + ObjectAnimator animator = + ObjectAnimator.ofObject(endValues.view, "clipBounds", evaluator, start, end); + if (endIsNull) { + final View endView = endValues.view; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + endView.setClipBounds(null); + } + }); + } + return animator; } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bcf0b9060ed7..d42c6db106fd 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -7381,17 +7381,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * optimal implementation providing this data. */ public void onProvideVirtualStructure(ViewStructure structure) { - onProvideVirtualStructureForAssistOrAutofill(structure, false); + AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); + if (provider != null) { + AccessibilityNodeInfo info = createAccessibilityNodeInfo(); + structure.setChildCount(1); + ViewStructure root = structure.newChild(0); + populateVirtualStructure(root, provider, info); + info.recycle(); + } } /** * Called when assist structure is being retrieved from a view as part of an autofill request * to generate additional virtual structure under this view. * - * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to - * generate this from the view's virtual accessibility nodes, if any. You can override this - * for a more optimal implementation providing this data. - * * <p>When implementing this method, subclasses must follow the rules below: * * <ol> @@ -7415,27 +7418,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param flags optional flags (currently {@code 0}). */ public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { - onProvideVirtualStructureForAssistOrAutofill(structure, true); - } - - private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure, - boolean forAutofill) { - if (forAutofill) { - setAutofillId(structure); - } - // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well, - // this method should take a boolean with the type of request. - AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); - if (provider != null) { - AccessibilityNodeInfo info = createAccessibilityNodeInfo(); - structure.setChildCount(1); - ViewStructure root = structure.newChild(0); - if (forAutofill) { - setAutofillId(root); - } - populateVirtualStructure(root, provider, info, forAutofill); - info.recycle(); - } + // TODO(b/36171235): need a way to let apps set the ViewStructure without forcing them + // to call super() (in case they override both this method and dispatchProvide.... + // Perhaps the best solution would simply make setAutofillId(ViewStructure) public. + setAutofillId(structure); } /** @@ -7652,7 +7638,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void populateVirtualStructure(ViewStructure structure, - AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) { + AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), null, null, null); Rect rect = structure.getTempRect(); @@ -7690,10 +7676,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, CharSequence cname = info.getClassName(); structure.setClassName(cname != null ? cname.toString() : null); structure.setContentDescription(info.getContentDescription()); - if (!forAutofill && (info.getText() != null || info.getError() != null)) { - // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to - // just set sanitized values (like text coming from resource files), rather than not - // setting it at all. + if ((info.getText() != null || info.getError() != null)) { structure.setText(info.getText(), info.getTextSelectionStart(), info.getTextSelectionEnd()); } @@ -7704,12 +7687,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); ViewStructure child = structure.newChild(i); - if (forAutofill) { - // TODO(b/33197203): add CTS test to autofill virtual children based on - // Accessibility API. - child.setAutofillId(structure, i); - } - populateVirtualStructure(child, provider, cinfo, forAutofill); + populateVirtualStructure(child, provider, cinfo); cinfo.recycle(); } } @@ -9598,13 +9576,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @return Returns {@code false} if assist data collection for autofill is not blocked, * else {@code true}. - * - * TODO(b/33197203): update / remove javadoc tags below - * @see #setAssistBlocked(boolean) - * @attr ref android.R.styleable#View_assistBlocked */ public boolean isAutofillBlocked() { - return false; // TODO(b/33197203): properly implement it + // TODO(b/36171235): properly implement it using isImportantForAutofill() + return false; } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9ecced61c917..1f13220289c2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -435,8 +435,9 @@ public final class ViewRootImpl implements ViewParent, AccessibilityInteractionController mAccessibilityInteractionController; - AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager; - HighContrastTextManager mHighContrastTextManager; + final AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager = + new AccessibilityInteractionConnectionManager(); + final HighContrastTextManager mHighContrastTextManager; SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent; @@ -496,13 +497,11 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); mAccessibilityManager = AccessibilityManager.getInstance(context); - mAccessibilityInteractionConnectionManager = - new AccessibilityInteractionConnectionManager(); mAccessibilityManager.addAccessibilityStateChangeListener( - mAccessibilityInteractionConnectionManager); + mAccessibilityInteractionConnectionManager, mHandler); mHighContrastTextManager = new HighContrastTextManager(); mAccessibilityManager.addHighTextContrastStateChangeListener( - mHighContrastTextManager); + mHighContrastTextManager, mHandler); mViewConfiguration = ViewConfiguration.get(context); mDensity = context.getResources().getDisplayMetrics().densityDpi; mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi; diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index 435610e648cb..387a9ce41f90 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -362,11 +362,19 @@ public abstract class ViewStructure { public abstract AutofillId getAutofillId(); /** - * Sets the URL represented by this node. + * @deprecated - use {@link #setWebDomain(String)} instead. + */ + @Deprecated + public abstract void setUrl(String url); + + /** + * Sets the Web domain represented by this node. * * <p>Typically used when the view is a container for an HTML document. + * + * @param domain URL representing the domain; only the host part will be used. */ - public abstract void setUrl(String url); + public abstract void setWebDomain(@Nullable String domain); /** * Sets the the list of locales associated with this node. diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 6c884c400dd8..dfb0095cc0fe 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -37,6 +37,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; +import android.util.ArrayMap; import android.util.Log; import android.view.IWindow; import android.view.View; @@ -47,7 +48,6 @@ import com.android.internal.util.IntPair; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; /** * System level service that serves as an event dispatch for {@link AccessibilityEvent}s, @@ -137,17 +137,18 @@ public final class AccessibilityManager { boolean mIsHighTextContrastEnabled; - private final CopyOnWriteArrayList<AccessibilityStateChangeListener> - mAccessibilityStateChangeListeners = new CopyOnWriteArrayList<>(); + private final ArrayMap<AccessibilityStateChangeListener, Handler> + mAccessibilityStateChangeListeners = new ArrayMap<>(); - private final CopyOnWriteArrayList<TouchExplorationStateChangeListener> - mTouchExplorationStateChangeListeners = new CopyOnWriteArrayList<>(); + private final ArrayMap<TouchExplorationStateChangeListener, Handler> + mTouchExplorationStateChangeListeners = new ArrayMap<>(); - private final CopyOnWriteArrayList<HighTextContrastChangeListener> - mHighTextContrastStateChangeListeners = new CopyOnWriteArrayList<>(); + private final ArrayMap<HighTextContrastChangeListener, Handler> + mHighTextContrastStateChangeListeners = new ArrayMap<>(); + + private final ArrayMap<AccessibilityServicesStateChangeListener, Handler> + mServicesStateChangeListeners = new ArrayMap<>(); - private final CopyOnWriteArrayList<AccessibilityServicesStateChangeListener> - mServicesStateChangeListeners = new CopyOnWriteArrayList<>(); /** * Listener for the system accessibility state. To listen for changes to the * accessibility state on the device, implement this interface and register @@ -229,7 +230,21 @@ public final class AccessibilityManager { @Override public void notifyServicesStateChanged() { - mHandler.obtainMessage(MyCallback.MSG_NOTIFY_SERVICES_STATE_CHANGED).sendToTarget(); + final ArrayMap<AccessibilityServicesStateChangeListener, Handler> listeners; + synchronized (mLock) { + if (mServicesStateChangeListeners.isEmpty()) { + return; + } + listeners = new ArrayMap<>(mServicesStateChangeListeners); + } + + int numListeners = listeners.size(); + for (int i = 0; i < numListeners; i++) { + final AccessibilityServicesStateChangeListener listener = + mServicesStateChangeListeners.keyAt(i); + mServicesStateChangeListeners.valueAt(i).post(() -> listener + .onAccessibilityServicesStateChanged(AccessibilityManager.this)); + } } @Override @@ -565,73 +580,118 @@ public final class AccessibilityManager { /** * Registers an {@link AccessibilityStateChangeListener} for changes in - * the global accessibility state of the system. + * the global accessibility state of the system. Equivalent to calling + * {@link #addAccessibilityStateChangeListener(AccessibilityStateChangeListener, Handler)} + * with a null handler. * * @param listener The listener. - * @return True if successfully registered. + * @return Always returns {@code true}. */ public boolean addAccessibilityStateChangeListener( @NonNull AccessibilityStateChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mAccessibilityStateChangeListeners.add(listener); + addAccessibilityStateChangeListener(listener, null); + return true; + } + + /** + * Registers an {@link AccessibilityStateChangeListener} for changes in + * the global accessibility state of the system. If the listener has already been registered, + * the handler used to call it back is updated. + * + * @param listener The listener. + * @param handler The handler on which the listener should be called back, or {@code null} + * for a callback on the process's main handler. + */ + public void addAccessibilityStateChangeListener( + @NonNull AccessibilityStateChangeListener listener, @Nullable Handler handler) { + synchronized (mLock) { + mAccessibilityStateChangeListeners + .put(listener, (handler == null) ? mHandler : handler); + } } /** * Unregisters an {@link AccessibilityStateChangeListener}. * * @param listener The listener. - * @return True if successfully unregistered. + * @return True if the listener was previously registered. */ public boolean removeAccessibilityStateChangeListener( @NonNull AccessibilityStateChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mAccessibilityStateChangeListeners.remove(listener); + synchronized (mLock) { + int index = mAccessibilityStateChangeListeners.indexOfKey(listener); + mAccessibilityStateChangeListeners.remove(listener); + return (index >= 0); + } } /** * Registers a {@link TouchExplorationStateChangeListener} for changes in - * the global touch exploration state of the system. + * the global touch exploration state of the system. Equivalent to calling + * {@link #addTouchExplorationStateChangeListener(TouchExplorationStateChangeListener, Handler)} + * with a null handler. * * @param listener The listener. - * @return True if successfully registered. + * @return Always returns {@code true}. */ public boolean addTouchExplorationStateChangeListener( @NonNull TouchExplorationStateChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mTouchExplorationStateChangeListeners.add(listener); + addTouchExplorationStateChangeListener(listener, null); + return true; + } + + /** + * Registers an {@link TouchExplorationStateChangeListener} for changes in + * the global touch exploration state of the system. If the listener has already been + * registered, the handler used to call it back is updated. + * + * @param listener The listener. + * @param handler The handler on which the listener should be called back, or {@code null} + * for a callback on the process's main handler. + */ + public void addTouchExplorationStateChangeListener( + @NonNull TouchExplorationStateChangeListener listener, @Nullable Handler handler) { + synchronized (mLock) { + mTouchExplorationStateChangeListeners + .put(listener, (handler == null) ? mHandler : handler); + } } /** * Unregisters a {@link TouchExplorationStateChangeListener}. * * @param listener The listener. - * @return True if successfully unregistered. + * @return True if listener was previously registered. */ public boolean removeTouchExplorationStateChangeListener( @NonNull TouchExplorationStateChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mTouchExplorationStateChangeListeners.remove(listener); + synchronized (mLock) { + int index = mTouchExplorationStateChangeListeners.indexOfKey(listener); + mTouchExplorationStateChangeListeners.remove(listener); + return (index >= 0); + } } /** * Registers a {@link AccessibilityServicesStateChangeListener}. * * @param listener The listener. - * @return True if successfully registered. - * + * @param handler The handler on which the listener should be called back, or {@code null} + * for a callback on the process's main handler. * @hide */ public void addAccessibilityServicesStateChangeListener( - @NonNull AccessibilityServicesStateChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - mServicesStateChangeListeners.add(listener); + @NonNull AccessibilityServicesStateChangeListener listener, @Nullable Handler handler) { + synchronized (mLock) { + mServicesStateChangeListeners + .put(listener, (handler == null) ? mHandler : handler); + } } /** * Unregisters a {@link AccessibilityServicesStateChangeListener}. * * @param listener The listener. - * @return True if successfully unregistered. * * @hide */ @@ -646,28 +706,29 @@ public final class AccessibilityManager { * the global high text contrast state of the system. * * @param listener The listener. - * @return True if successfully registered. * * @hide */ - public boolean addHighTextContrastStateChangeListener( - @NonNull HighTextContrastChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mHighTextContrastStateChangeListeners.add(listener); + public void addHighTextContrastStateChangeListener( + @NonNull HighTextContrastChangeListener listener, @Nullable Handler handler) { + synchronized (mLock) { + mHighTextContrastStateChangeListeners + .put(listener, (handler == null) ? mHandler : handler); + } } /** * Unregisters a {@link HighTextContrastChangeListener}. * * @param listener The listener. - * @return True if successfully unregistered. * * @hide */ - public boolean removeHighTextContrastStateChangeListener( + public void removeHighTextContrastStateChangeListener( @NonNull HighTextContrastChangeListener listener) { - // Final CopyOnWriteArrayList - no lock needed. - return mHighTextContrastStateChangeListeners.remove(listener); + synchronized (mLock) { + mHighTextContrastStateChangeListeners.remove(listener); + } } /** @@ -732,15 +793,15 @@ public final class AccessibilityManager { mIsHighTextContrastEnabled = highTextContrastEnabled; if (wasEnabled != enabled) { - mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED); + notifyAccessibilityStateChanged(); } if (wasTouchExplorationEnabled != touchExplorationEnabled) { - mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_EXPLORATION_STATE_CHANGED); + notifyTouchExplorationStateChanged(); } if (wasHighTextContrastEnabled != highTextContrastEnabled) { - mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED); + notifyHighTextContrastStateChanged(); } } @@ -932,81 +993,78 @@ public final class AccessibilityManager { /** * Notifies the registered {@link AccessibilityStateChangeListener}s. */ - private void handleNotifyAccessibilityStateChanged() { + private void notifyAccessibilityStateChanged() { final boolean isEnabled; + final ArrayMap<AccessibilityStateChangeListener, Handler> listeners; synchronized (mLock) { + if (mAccessibilityStateChangeListeners.isEmpty()) { + return; + } isEnabled = mIsEnabled; + listeners = new ArrayMap<>(mAccessibilityStateChangeListeners); } - // Listeners are a final CopyOnWriteArrayList, hence no lock needed. - for (AccessibilityStateChangeListener listener : mAccessibilityStateChangeListeners) { - listener.onAccessibilityStateChanged(isEnabled); + + int numListeners = listeners.size(); + for (int i = 0; i < numListeners; i++) { + final AccessibilityStateChangeListener listener = + mAccessibilityStateChangeListeners.keyAt(i); + mAccessibilityStateChangeListeners.valueAt(i) + .post(() -> listener.onAccessibilityStateChanged(isEnabled)); } } /** * Notifies the registered {@link TouchExplorationStateChangeListener}s. */ - private void handleNotifyTouchExplorationStateChanged() { + private void notifyTouchExplorationStateChanged() { final boolean isTouchExplorationEnabled; + final ArrayMap<TouchExplorationStateChangeListener, Handler> listeners; synchronized (mLock) { + if (mTouchExplorationStateChangeListeners.isEmpty()) { + return; + } isTouchExplorationEnabled = mIsTouchExplorationEnabled; + listeners = new ArrayMap<>(mTouchExplorationStateChangeListeners); } - // Listeners are a final CopyOnWriteArrayList, hence no lock needed. - for (TouchExplorationStateChangeListener listener :mTouchExplorationStateChangeListeners) { - listener.onTouchExplorationStateChanged(isTouchExplorationEnabled); + + int numListeners = listeners.size(); + for (int i = 0; i < numListeners; i++) { + final TouchExplorationStateChangeListener listener = + mTouchExplorationStateChangeListeners.keyAt(i); + mTouchExplorationStateChangeListeners.valueAt(i) + .post(() -> listener.onTouchExplorationStateChanged(isTouchExplorationEnabled)); } } /** * Notifies the registered {@link HighTextContrastChangeListener}s. */ - private void handleNotifyHighTextContrastStateChanged() { + private void notifyHighTextContrastStateChanged() { final boolean isHighTextContrastEnabled; + final ArrayMap<HighTextContrastChangeListener, Handler> listeners; synchronized (mLock) { + if (mHighTextContrastStateChangeListeners.isEmpty()) { + return; + } isHighTextContrastEnabled = mIsHighTextContrastEnabled; + listeners = new ArrayMap<>(mHighTextContrastStateChangeListeners); } - // Listeners are a final CopyOnWriteArrayList, hence no lock needed. - for (HighTextContrastChangeListener listener : mHighTextContrastStateChangeListeners) { - listener.onHighTextContrastStateChanged(isHighTextContrastEnabled); - } - } - /** - * Notifies the registered {@link AccessibilityServicesStateChangeListener}s. - */ - private void handleNotifyServicesStateChanged() { - // Listeners are a final CopyOnWriteArrayList, hence no lock needed. - for (AccessibilityServicesStateChangeListener listener : mServicesStateChangeListeners) { - listener.onAccessibilityServicesStateChanged(this); + int numListeners = listeners.size(); + for (int i = 0; i < numListeners; i++) { + final HighTextContrastChangeListener listener = + mHighTextContrastStateChangeListeners.keyAt(i); + mHighTextContrastStateChangeListeners.valueAt(i) + .post(() -> listener.onHighTextContrastStateChanged(isHighTextContrastEnabled)); } } private final class MyCallback implements Handler.Callback { - public static final int MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED = 1; - public static final int MSG_NOTIFY_EXPLORATION_STATE_CHANGED = 2; - public static final int MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED = 3; - public static final int MSG_SET_STATE = 4; - public static final int MSG_NOTIFY_SERVICES_STATE_CHANGED = 5; + public static final int MSG_SET_STATE = 1; @Override public boolean handleMessage(Message message) { switch (message.what) { - case MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED: { - handleNotifyAccessibilityStateChanged(); - } break; - - case MSG_NOTIFY_EXPLORATION_STATE_CHANGED: { - handleNotifyTouchExplorationStateChanged(); - } break; - - case MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED: { - handleNotifyHighTextContrastStateChanged(); - } break; - - case MSG_NOTIFY_SERVICES_STATE_CHANGED: { - handleNotifyServicesStateChanged(); - } break; - case MSG_SET_STATE: { // See comment at mClient final int state = message.arg1; diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java index d678015b36f9..268f7f3557d1 100644 --- a/core/java/android/view/autofill/AutofillId.java +++ b/core/java/android/view/autofill/AutofillId.java @@ -30,7 +30,6 @@ public final class AutofillId implements Parcelable { private final boolean mVirtual; private final int mVirtualId; - // TODO(b/33197203): use factory and cache values, since they're immutable /** @hide */ public AutofillId(int id) { mVirtual = false; diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 981be21f4f61..caf188d510f8 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -51,12 +51,10 @@ import java.util.List; import java.util.Objects; /** - * App entry point to the AutoFill Framework. + * App entry point to the Autofill Framework. * * <p>It is safe to call into this from any thread. */ -// TODO(b/33197203): improve this javadoc -//TODO(b/33197203): restrict manager calls to activity public final class AutofillManager { private static final String TAG = "AutofillManager"; @@ -101,17 +99,15 @@ public final class AutofillManager { static final String SESSION_ID_TAG = "android:sessionId"; static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; - // Public flags start from the lowest bit /** - * Indicates autofill was explicitly requested by the user. - * * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST} + * @hide */ - // TODO(b/33197203): remove (and change value of private flags) + // TODO(b/37563972): remove (and change value of private flags) @Deprecated public static final int FLAG_MANUAL_REQUEST = 0x1; - // Private flags start from the highest bit + // TODO(b/37563972): start from 0x1 once FLAG_MANUAL_REQUEST is gone /** @hide */ public static final int FLAG_START_SESSION = 0x80000000; /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x40000000; /** @hide */ public static final int FLAG_VIEW_EXITED = 0x20000000; @@ -663,6 +659,39 @@ public final class AutofillManager { } } + /** + * Returns {@code true} if the calling application provides a {@link AutofillService} that is + * enabled for the current user, or {@code false} otherwise. + */ + public boolean hasEnabledAutofillServices() { + if (mService == null) return false; + + try { + return mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns {@code true} if Autofill is supported for this user. + * + * <p>Autofill is typically supported, but it could be unsupported in cases like: + * <ol> + * <li>Low-end devices. + * <li>Device policy rules that forbid its usage. + * </ol> + */ + public boolean isAutofillSupported() { + if (mService == null) return false; + + try { + return mService.isServiceSupported(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private AutofillClient getClientLocked() { if (mContext instanceof AutofillClient) { return (AutofillClient) mContext; @@ -675,7 +704,7 @@ public final class AutofillManager { if (!hasAutofillFeature()) { return; } - // TODO(b/33197203): the result code is being ignored, so this method is not reliably + // TODO: the result code is being ignored, so this method is not reliably // handling the cases where it's not RESULT_OK: it works fine if the service does not // set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the // service set the extra and returned RESULT_CANCELED... @@ -1323,8 +1352,6 @@ public final class AutofillManager { @Override public void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids, List<AutofillValue> values) { - // TODO(b/33197203): must keep the dataset so subsequent calls pass the same - // dataset.extras to service final AutofillManager afm = mAfm.get(); if (afm != null) { afm.mContext.getMainThreadHandler().post( diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java index e2dd7fe9eeaa..b1a9d90cc4ca 100644 --- a/core/java/android/view/autofill/AutofillValue.java +++ b/core/java/android/view/autofill/AutofillValue.java @@ -252,7 +252,6 @@ public final class AutofillValue implements Parcelable { * * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info. */ - // TODO(b/33197203): use cache public static AutofillValue forText(@Nullable CharSequence value) { return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, value); } diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java index aa94de0bf693..2b25ae7aa5e8 100644 --- a/core/java/android/view/autofill/Helper.java +++ b/core/java/android/view/autofill/Helper.java @@ -25,7 +25,8 @@ import java.util.Set; /** @hide */ public final class Helper { - public static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable + // TODO(b/36141126): set to false and remove guard from places that should always be on + public static final boolean DEBUG = true; public static final boolean VERBOSE = false; public static final String REDACTED = "[REDACTED]"; diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index df777c4a6869..9417bd07a267 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -44,4 +44,6 @@ interface IAutoFillManager { void setAuthenticationResult(in Bundle data, int sessionId, int userId); void setHasCallback(int sessionId, int userId, boolean hasIt); void disableOwnedAutofillServices(int userId); + boolean isServiceSupported(int userId); + boolean isServiceEnabled(int userId, String packageName); } diff --git a/core/java/android/view/textclassifier/LinksInfo.java b/core/java/android/view/textclassifier/LinksInfo.java index 3acbdc0261bd..754c9e90ed4b 100644 --- a/core/java/android/view/textclassifier/LinksInfo.java +++ b/core/java/android/view/textclassifier/LinksInfo.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; * Link information that can be applied to text. See: {@link #apply(CharSequence)}. * Typical implementations of this interface will annotate spannable text with e.g * {@link android.text.style.ClickableSpan}s or other annotations. + * @hide */ public interface LinksInfo { diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java index dcdbe5738b03..6b641dbfef8e 100644 --- a/core/java/android/view/textclassifier/TextClassificationManager.java +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -82,6 +82,7 @@ public final class TextClassificationManager { * This is a blocking operation you should avoid calling it on the UI thread. * * @throws IllegalArgumentException if text is null + * @hide */ public List<TextLanguage> detectLanguages(@NonNull CharSequence text) { Preconditions.checkArgument(text != null); diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index 0831e20101b2..46fed43cbe6a 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -132,6 +132,7 @@ public interface TextClassifier { * a default locale, or use the system default. * * @throws IllegalArgumentException if text is null + * @hide */ LinksInfo getLinks( @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales); diff --git a/core/java/android/view/textclassifier/TextLanguage.java b/core/java/android/view/textclassifier/TextLanguage.java index d94d163577e1..209813a2beac 100644 --- a/core/java/android/view/textclassifier/TextLanguage.java +++ b/core/java/android/view/textclassifier/TextLanguage.java @@ -28,6 +28,7 @@ import java.util.Locale; /** * Specifies detected languages for a section of text indicated by a start and end index. + * @hide */ public final class TextLanguage { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9202889ac9f2..6213a63e108a 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1731,14 +1731,7 @@ public class WebView extends AbsoluteLayout * * @param addr the string to search for addresses * @return the address, or if no address is found, null - * - * @deprecated findAddress is deprecated. It only supports a subset of US - * addresses and has a high false positive rate. Calling findAddress also causes - * WebView to be loaded into the app, which significantly increases memory usage - * if the app doesn't already use WebView. Use {@link TextClassifier} instead for - * classifying text and finding addresses. */ - @Deprecated public static String findAddress(String addr) { // TODO: Rewrite this in Java so it is not needed to start up chromium // Could also be deprecated diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 2123debfeb67..b519ec9c42a2 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -40,6 +40,7 @@ public class WebViewZygote { private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32"; private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64"; + private static final String WEBVIEW_ZYGOTE_SOCKET = "webview_zygote"; /** * Lock object that protects all other static members. @@ -202,7 +203,7 @@ public class WebViewZygote { } try { - sZygote = new ZygoteProcess("webview_zygote", null); + sZygote = new ZygoteProcess(WEBVIEW_ZYGOTE_SOCKET, null); // All the work below is usually done by LoadedApk, but the zygote can't talk to // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so @@ -217,6 +218,8 @@ public class WebViewZygote { final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : TextUtils.join(File.pathSeparator, zipPaths); + waitForZygote(); + Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey, Build.SUPPORTED_ABIS[0]); @@ -225,4 +228,25 @@ public class WebViewZygote { sZygote = null; } } + + /** + * Wait until a connection to the Zygote can be established. + */ + private static void waitForZygote() { + while (true) { + try { + final ZygoteProcess.ZygoteState zs = + ZygoteProcess.ZygoteState.connect(WEBVIEW_ZYGOTE_SOCKET); + zs.close(); + break; + } catch (IOException ioe) { + Log.w(LOGTAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage()); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + } + } + } } diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java index f80c9e667935..816c9499e292 100644 --- a/core/java/android/widget/AbsSpinner.java +++ b/core/java/android/widget/AbsSpinner.java @@ -491,8 +491,6 @@ public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> { return AbsSpinner.class.getName(); } - // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable) - @Override public void autofill(AutofillValue value) { if (!isEnabled()) return; diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index c7ba7b5d5a48..0762b15626f7 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -574,8 +574,6 @@ public abstract class CompoundButton extends Button implements Checkable { stream.addProperty("checked", isChecked()); } - // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable) - @Override public void onProvideAutofillStructure(ViewStructure structure, int flags) { super.onProvideAutofillStructure(structure, flags); diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 463ff587466a..0dce07936fe5 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -764,8 +764,6 @@ public class DatePicker extends FrameLayout { void onValidationChanged(boolean valid); } - // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable) - @Override public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) { // This view is self-sufficient for autofill, so it needs to call diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java index 08e657559e17..5c4d4d2a7fa0 100644 --- a/core/java/android/widget/RadioGroup.java +++ b/core/java/android/widget/RadioGroup.java @@ -417,8 +417,6 @@ public class RadioGroup extends LinearLayout { } } - // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable) - @Override public void onProvideAutofillStructure(ViewStructure structure, int flags) { super.onProvideAutofillStructure(structure, flags); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 036b39100286..e534233432d2 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -413,6 +413,30 @@ public class RemoteViews implements Parcelable, Filter { recalculateMemoryUsage(); } + private static class RemoteViewsContextWrapper extends ContextWrapper { + private final Context mContextForResources; + + RemoteViewsContextWrapper(Context context, Context contextForResources) { + super(context); + mContextForResources = contextForResources; + } + + @Override + public Resources getResources() { + return mContextForResources.getResources(); + } + + @Override + public Resources.Theme getTheme() { + return mContextForResources.getTheme(); + } + + @Override + public String getPackageName() { + return mContextForResources.getPackageName(); + } + } + private class SetEmptyView extends Action { int viewId; int emptyViewId; @@ -3240,20 +3264,7 @@ public class RemoteViews implements Parcelable, Filter { // still returns the current users userId so settings like data / time formats // are loaded without requiring cross user persmissions. final Context contextForResources = getContextForResources(context); - Context inflationContext = new ContextWrapper(context) { - @Override - public Resources getResources() { - return contextForResources.getResources(); - } - @Override - public Resources.Theme getTheme() { - return contextForResources.getTheme(); - } - @Override - public String getPackageName() { - return contextForResources.getPackageName(); - } - }; + Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java index 57e2ece0df8e..91901178e81e 100644 --- a/core/java/android/widget/SimpleAdapter.java +++ b/core/java/android/widget/SimpleAdapter.java @@ -320,9 +320,6 @@ public class SimpleAdapter extends BaseAdapter implements Filterable, ThemedSpin return mFilter; } - // TODO(b/33197203): implement getAutofillOptions - - /** * This class can be used by external clients of SimpleAdapter to bind * values to views. diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index f42d6c81f444..399cfac441a9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -10170,8 +10170,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener structure.setInputType(getInputType()); } - // TODO(b/33197203): add unit/CTS tests for autofill methods - boolean canRequestAutofill() { final AutofillManager afm = mContext.getSystemService(AutofillManager.class); if (afm != null) { diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index fb00c4392333..df99fb4dd06b 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -519,8 +519,6 @@ public class TimePicker extends FrameLayout { } } - // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable) - @Override public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) { // This view is self-sufficient for autofill, so it needs to call diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 73b62a5fe60d..54b9cd869f2d 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -438,6 +438,14 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { + " in the manifest."); continue; } + if (PackageManager.PERMISSION_GRANTED != mPm.checkPermission( + ResolverRankerService.HOLD_PERMISSION, + resolveInfo.serviceInfo.packageName)) { + Log.w(TAG, "ResolverRankerService " + componentName + " does not hold" + + " permission " + ResolverRankerService.HOLD_PERMISSION + + " - this service will not be queried for ResolverComparator."); + continue; + } } catch (NameNotFoundException e) { Log.e(TAG, "Could not look up service " + componentName + "; component name not found"); diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 2c8e4e0414b6..73886a700c7f 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -169,6 +169,13 @@ public class ArrayUtils { } /** + * Length of the given array or 0 if it's null. + */ + public static int size(@Nullable Object[] array) { + return array == null ? 0 : array.length; + } + + /** * Checks that value is present as at least one of the elements of the array. * @param array the array to check in * @param value the value to check for diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 96285cd4c17d..ceb3cc8b4ef5 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -234,6 +234,7 @@ LOCAL_STATIC_LIBRARIES := \ libseccomp_policy \ libselinux \ libcrypto \ + libgrallocusage \ LOCAL_SHARED_LIBRARIES := \ libmemtrack \ diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp index ed0ab6054be7..4b31c91c708c 100644 --- a/core/jni/android_hardware_HardwareBuffer.cpp +++ b/core/jni/android_hardware_HardwareBuffer.cpp @@ -34,6 +34,7 @@ #include <private/gui/ComposerService.h> #include <hardware/gralloc1.h> +#include <grallocusage/GrallocUsageConversion.h> #include "core_jni_helpers.h" @@ -85,7 +86,7 @@ static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz, &producerUsage, &consumerUsage, usage, 0); sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers, - producerUsage, consumerUsage, + android_convertGralloc1To0Usage(producerUsage, consumerUsage), std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]"); status_t error = buffer->initCheck(); if (error < 0) { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index b95258bca49c..6000fb56299d 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -685,11 +685,14 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( // Grant CAP_WAKE_ALARM to the Bluetooth process. // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client. + // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for + // audio-related threads. // TODO: consider making such functionality an RPC to netd. if (multiuser_get_app_id(uid) == AID_BLUETOOTH) { capabilities |= (1LL << CAP_WAKE_ALARM); capabilities |= (1LL << CAP_NET_RAW); capabilities |= (1LL << CAP_NET_BIND_SERVICE); + capabilities |= (1LL << CAP_SYS_NICE); } // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1777f2492e28..313130221ff6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3161,6 +3161,14 @@ <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE" android:protectionLevel="signature" /> + <!-- @SystemApi Must be held by services that extend + {@link android.service.resolver.ResolverRankerService}. + <p>Protection level: signature|privileged + @hide + --> + <permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" + android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Must be required by services that extend {@link android.service.resolver.ResolverRankerService}, to ensure that only the system can bind to them. @@ -3702,14 +3710,6 @@ <service android:name="com.android.server.PreloadsFileCacheExpirationJobService" android:permission="android.permission.BIND_JOB_SERVICE" > </service> - - <service android:name="com.android.internal.app.LRResolverRankerService" - android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE" - android:priority="-1" > - <intent-filter> - <action android:name="android.service.resolver.ResolverRankerService" /> - </intent-filter> - </service> </application> </manifest> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 27a4d5c2f5af..0fa1fdb3e844 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2833,4 +2833,34 @@ <!-- Whether the device uses the default focus highlight when focus state isn't specified. --> <bool name="config_useDefaultFocusHighlight">true</bool> + + <!-- Configuration for automotive --> + <bool name="enable_pbap_pce_profile">false</bool> + + <!-- Default data warning level in mb --> + <integer name="default_data_warning_level_mb">2048</integer> + + <!-- Whether to send a custom package name with the PSD.--> + <bool name="config_sendPackageName">false</bool> + + <!-- Name for the set of keys associating package names --> + <string name="config_helpPackageNameKey" translatable="false"></string> + + <!-- Name for the set of values of package names --> + <string name="config_helpPackageNameValue" translatable="false"></string> + + <!-- Intent key for the package name keys --> + <string name="config_helpIntentExtraKey" translatable="false"></string> + + <!-- Intent key for package name values --> + <string name="config_helpIntentNameKey" translatable="false"></string> + + <!-- Intent key for the package name keys --> + <string name="config_feedbackIntentExtraKey" translatable="false"></string> + + <!-- Intent key for package name values --> + <string name="config_feedbackIntentNameKey" translatable="false"></string> + + <!-- The apps that need to be hidden when they are disabled --> + <string-array name="config_hideWhenDisabled_packageNames"></string-array> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 32255aa7333e..35b12ffb5d68 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4595,6 +4595,9 @@ <!-- Accessibility title for the autofill dialog used to select a list of options to autofill an activity. [CHAR LIMIT=NONE] --> <string name="autofill_picker_accessibility_title">Autofill options</string> + <!-- Accessibility title for the autofill dialog used to ask user to save the information on the screen by sending it to an Autofill Service. [CHAR LIMIT=NONE] --> + <string name="autofill_save_accessibility_title">Save for Autofill</string> + <!-- Toast message shown when user manually request autofill but service could not figure out the data that would autofill the screen contents. [CHAR LIMIT=NONE] --> <string name="autofill_error_cannot_autofill">Contents can\u2019t be autofilled</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 70a2beb945a6..63a5cfd7376c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2893,6 +2893,7 @@ <java-symbol type="string" name="autofill_error_cannot_autofill" /> <java-symbol type="string" name="autofill" /> <java-symbol type="string" name="autofill_picker_accessibility_title " /> + <java-symbol type="string" name="autofill_save_accessibility_title " /> <java-symbol type="string" name="autofill_save_title" /> <java-symbol type="string" name="autofill_save_title_with_type" /> <java-symbol type="string" name="autofill_save_title_with_2types" /> @@ -2983,4 +2984,18 @@ <java-symbol type="bool" name="config_quickSettingsSupported" /> <java-symbol type="style" name="Theme.DeviceDefault.QuickSettings" /> + + <java-symbol type="bool" name="enable_pbap_pce_profile" /> + + <java-symbol type="integer" name="default_data_warning_level_mb" /> + + <java-symbol type="bool" name="config_sendPackageName" /> + <java-symbol type="string" name="config_helpPackageNameKey" /> + <java-symbol type="string" name="config_helpPackageNameValue" /> + <java-symbol type="string" name="config_helpIntentExtraKey" /> + <java-symbol type="string" name="config_helpIntentNameKey" /> + <java-symbol type="string" name="config_feedbackIntentExtraKey" /> + <java-symbol type="string" name="config_feedbackIntentNameKey" /> + + <java-symbol type="array" name="config_hideWhenDisabled_packageNames" /> </resources> diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java index 497bc5cd900e..ff9816ad090c 100644 --- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java +++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java @@ -1,26 +1,19 @@ package android.net; -import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; -import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE; - import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; -import static junit.framework.TestCase.assertEquals; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import android.Manifest.permission; import android.content.Context; -import android.os.Bundle; -import android.os.IRemoteCallback; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -35,11 +28,9 @@ import java.util.concurrent.TimeUnit; */ @RunWith(AndroidJUnit4.class) public class NetworkRecommendationProviderTest { - @Mock private IRemoteCallback mMockRemoteCallback; @Mock private Context mContext; private NetworkRecProvider mRecProvider; private INetworkRecommendationProvider mStub; - private CountDownLatch mRecRequestLatch; private CountDownLatch mScoreRequestLatch; private NetworkKey[] mTestNetworkKeys; @@ -48,10 +39,8 @@ public class NetworkRecommendationProviderTest { MockitoAnnotations.initMocks(this); Executor executor = Executors.newSingleThreadExecutor(); - mRecRequestLatch = new CountDownLatch(1); mScoreRequestLatch = new CountDownLatch(1); - mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch, - mScoreRequestLatch); + mRecProvider = new NetworkRecProvider(mContext, executor, mScoreRequestLatch); mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder()); mTestNetworkKeys = new NetworkKey[2]; mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11")); @@ -59,69 +48,6 @@ public class NetworkRecommendationProviderTest { } @Test - public void testRecommendationRequestReceived() throws Exception { - final RecommendationRequest request = new RecommendationRequest.Builder().build(); - final int sequence = 100; - mStub.requestRecommendation(request, mMockRemoteCallback, sequence); - - // wait for onRequestRecommendation() to be called in our impl below. - mRecRequestLatch.await(200, TimeUnit.MILLISECONDS); - NetworkRecommendationProvider.ResultCallback expectedResultCallback = - new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence); - assertEquals(request, mRecProvider.mCapturedRequest); - assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback); - } - - @Test - public void testRecommendationRequest_permissionsEnforced() throws Exception { - final RecommendationRequest request = new RecommendationRequest.Builder().build(); - final int sequence = 100; - Mockito.doThrow(new SecurityException()) - .when(mContext) - .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); - - try { - mStub.requestRecommendation(request, mMockRemoteCallback, sequence); - fail("SecurityException expected."); - } catch (SecurityException e) { - // expected - } - } - - @Test - public void testResultCallbackOnResult() throws Exception { - final int sequence = 100; - final NetworkRecommendationProvider.ResultCallback callback = - new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence); - - final RecommendationResult result = RecommendationResult.createDoNotConnectRecommendation(); - callback.onResult(result); - - final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); - Mockito.verify(mMockRemoteCallback).sendResult(bundleCaptor.capture()); - Bundle capturedBundle = bundleCaptor.getValue(); - assertEquals(sequence, capturedBundle.getInt(EXTRA_SEQUENCE)); - assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT)); - } - - @Test - public void testResultCallbackOnResult_runTwice_throwsException() throws Exception { - final int sequence = 100; - final NetworkRecommendationProvider.ResultCallback callback = - new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence); - - final RecommendationResult result = RecommendationResult.createDoNotConnectRecommendation(); - callback.onResult(result); - - try { - callback.onResult(result); - fail("Callback ran more than once."); - } catch (IllegalStateException e) { - // expected - } - } - - @Test public void testScoreRequestReceived() throws Exception { mStub.requestScores(mTestNetworkKeys); @@ -162,28 +88,15 @@ public class NetworkRecommendationProviderTest { } private static class NetworkRecProvider extends NetworkRecommendationProvider { - private final CountDownLatch mRecRequestLatch; private final CountDownLatch mScoreRequestLatch; - RecommendationRequest mCapturedRequest; - ResultCallback mCapturedCallback; NetworkKey[] mCapturedNetworks; - NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch, - CountDownLatch networkRequestLatch) { + NetworkRecProvider(Context context, Executor executor, CountDownLatch networkRequestLatch) { super(context, executor); - mRecRequestLatch = recRequestLatch; mScoreRequestLatch = networkRequestLatch; } @Override - public void onRequestRecommendation(RecommendationRequest request, - ResultCallback callback) { - mCapturedRequest = request; - mCapturedCallback = callback; - mRecRequestLatch.countDown(); - } - - @Override public void onRequestScores(NetworkKey[] networks) { mCapturedNetworks = networks; mScoreRequestLatch.countDown(); diff --git a/core/tests/coretests/src/android/net/RecommendationRequestTest.java b/core/tests/coretests/src/android/net/RecommendationRequestTest.java deleted file mode 100644 index e2e68834de7b..000000000000 --- a/core/tests/coretests/src/android/net/RecommendationRequestTest.java +++ /dev/null @@ -1,116 +0,0 @@ -package android.net; - -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.os.Parcel; -import android.os.SystemClock; -import android.test.AndroidTestCase; - -public class RecommendationRequestTest extends AndroidTestCase { - private ScanResult[] mScanResults; - private WifiConfiguration mDefaultConfig; - private WifiConfiguration mConnectedConfig; - private WifiConfiguration[] mConnectableConfigs; - private int mLastSelectedNetworkId; - private long mLastSelectedNetworkTimestamp; - - @Override - public void setUp() throws Exception { - mScanResults = new ScanResult[2]; - mScanResults[0] = new ScanResult(); - mScanResults[1] = new ScanResult( - "ssid", - "bssid", - 0L /*hessid*/, - 1 /*anqpDominId*/, - "caps", - 2 /*level*/, - 3 /*frequency*/, - 4L /*tsf*/, - 5 /*distCm*/, - 6 /*distSdCm*/, - 7 /*channelWidth*/, - 8 /*centerFreq0*/, - 9 /*centerFreq1*/, - false /*is80211McRTTResponder*/); - mDefaultConfig = new WifiConfiguration(); - mDefaultConfig.SSID = "default_config"; - mConnectedConfig = new WifiConfiguration(); - mConnectedConfig.SSID = "connected_config"; - mConnectableConfigs = new WifiConfiguration[] {mDefaultConfig, mConnectedConfig}; - mLastSelectedNetworkId = 5; - mLastSelectedNetworkTimestamp = SystemClock.elapsedRealtime(); - } - - public void testParceling() throws Exception { - RecommendationRequest request = new RecommendationRequest.Builder() - .setDefaultWifiConfig(mDefaultConfig) - .setScanResults(mScanResults) - .setConnectedWifiConfig(mConnectedConfig) - .setConnectableConfigs(mConnectableConfigs) - .setLastSelectedNetwork(mLastSelectedNetworkId, mLastSelectedNetworkTimestamp) - .build(); - - RecommendationRequest parceled = passThroughParcel(request); - assertEquals(request.getDefaultWifiConfig().SSID, - parceled.getDefaultWifiConfig().SSID); - assertEquals(request.getConnectedConfig().SSID, - parceled.getConnectedConfig().SSID); - ScanResult[] parceledScanResults = parceled.getScanResults(); - assertNotNull(parceledScanResults); - assertEquals(mScanResults.length, parceledScanResults.length); - for (int i = 0; i < mScanResults.length; i++) { - assertEquals(mScanResults[i].SSID, parceledScanResults[i].SSID); - } - WifiConfiguration[] parceledConfigs = parceled.getConnectableConfigs(); - for (int i = 0; i < parceledConfigs.length; i++) { - assertEquals(mConnectableConfigs[i].SSID, parceledConfigs[i].SSID); - } - assertEquals(mLastSelectedNetworkId, parceled.getLastSelectedNetworkId()); - assertEquals(mLastSelectedNetworkTimestamp, parceled.getLastSelectedNetworkTimestamp()); - } - - public void testParceling_nullScanResults() throws Exception { - RecommendationRequest request = new RecommendationRequest.Builder() - .setDefaultWifiConfig(mDefaultConfig) - .build(); - - RecommendationRequest parceled = passThroughParcel(request); - ScanResult[] parceledScanResults = parceled.getScanResults(); - assertNull(parceledScanResults); - } - - public void testParceling_nullWifiConfigArray() throws Exception { - RecommendationRequest request = new RecommendationRequest.Builder() - .setDefaultWifiConfig(mDefaultConfig) - .build(); - - RecommendationRequest parceled = passThroughParcel(request); - WifiConfiguration[] parceledConfigs = parceled.getConnectableConfigs(); - assertNull(parceledConfigs); - } - - public void testParceling_unsetLastSelectedNetwork() throws Exception { - RecommendationRequest request = new RecommendationRequest.Builder() - .build(); - - RecommendationRequest parceled = passThroughParcel(request); - - assertEquals(-1, parceled.getLastSelectedNetworkId()); - assertEquals(0, parceled.getLastSelectedNetworkTimestamp()); - } - - private RecommendationRequest passThroughParcel(RecommendationRequest request) { - Parcel p = Parcel.obtain(); - RecommendationRequest output = null; - try { - request.writeToParcel(p, 0); - p.setDataPosition(0); - output = RecommendationRequest.CREATOR.createFromParcel(p); - } finally { - p.recycle(); - } - assertNotNull(output); - return output; - } -} diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 86ab3dc227f4..344f3c83ba6c 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -181,9 +181,6 @@ <allow-in-power-save package="com.android.cellbroadcastreceiver" /> <allow-in-power-save package="com.android.shell" /> - <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly --> - <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" /> - <!-- These are the packages that are white-listed to be able to run as system user --> <system-user-whitelisted-app package="com.android.settings" /> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 7f07f03dde61..efed165238cc 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -356,4 +356,8 @@ applications that come with the platform <permission name="android.permission.CONTROL_VPN"/> </privapp-permissions> + <privapp-permissions package="com.google.android.ext.services"> + <permission name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" /> + </privapp-permissions> + </permissions> diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index 8cbf921f6a34..bdd828fd5127 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -24,7 +24,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; - +import android.annotation.SuppressAutoDoc; import android.util.Half; import com.android.internal.util.XmlUtils; @@ -289,6 +289,7 @@ import java.util.function.DoubleUnaryOperator; * and <code>(1.0, 0.0, 0.0, 0.5)</code>.</p> */ @AnyThread +@SuppressAutoDoc public class Color { @ColorInt public static final int BLACK = 0xFF000000; @ColorInt public static final int DKGRAY = 0xFF444444; diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index f2957a30b05e..5814df5b5cc0 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -22,6 +22,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.SuppressAutoDoc; import android.util.Pair; import java.util.ArrayList; @@ -131,6 +132,7 @@ import java.util.function.DoubleUnaryOperator; */ @AnyThread @SuppressWarnings("StaticInitializerReferencesSubClass") +@SuppressAutoDoc public abstract class ColorSpace { /** * Standard CIE 1931 2° illuminant A, encoded in xyY. diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 115c77faf1a8..42fd5d8c6a06 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -31,7 +31,6 @@ import android.content.Context; import android.content.res.AssetManager; import android.graphics.FontListParser; import android.graphics.fonts.FontRequest; -import android.graphics.fonts.FontResult; import android.graphics.fonts.FontVariationAxis; import android.graphics.fonts.FontVariationAxis.InvalidFormatException; import android.net.Uri; @@ -102,8 +101,6 @@ public class Typeface { new LongSparseArray<>(3); @GuardedBy("sLock") private static FontsContract sFontsContract; - @GuardedBy("sLock") - private static Handler sHandler; /** * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16. @@ -205,16 +202,9 @@ public class Typeface { public static Typeface createFromResources( FamilyResourceEntry entry, AssetManager mgr, String path) { if (sFallbackFonts != null) { - Typeface typeface = findFromCache(mgr, path); - if (typeface != null) return typeface; - if (entry instanceof ProviderResourceEntry) { final ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry; // Downloadable font - typeface = findFromCache(providerEntry.getAuthority(), providerEntry.getQuery()); - if (typeface != null) { - return typeface; - } List<List<String>> givenCerts = providerEntry.getCerts(); List<List<byte[]>> certs = new ArrayList<>(); if (givenCerts != null) { @@ -229,11 +219,15 @@ public class Typeface { } // Downloaded font and it wasn't cached, request it again and return a // default font instead (nothing we can do now). - create(new FontRequest(providerEntry.getAuthority(), providerEntry.getPackage(), - providerEntry.getQuery(), certs), NO_OP_REQUEST_CALLBACK); - return DEFAULT; + FontRequest request = new FontRequest(providerEntry.getAuthority(), + providerEntry.getPackage(), providerEntry.getQuery(), certs); + Typeface typeface = sFontsContract.getFontOrWarmUpCache(request); + return typeface == null ? DEFAULT : typeface; } + Typeface typeface = findFromCache(mgr, path); + if (typeface != null) return typeface; + // family is FontFamilyFilesResourceEntry final FontFamilyFilesResourceEntry filesEntry = (FontFamilyFilesResourceEntry) entry; @@ -291,214 +285,10 @@ public class Typeface { synchronized (sLock) { if (sFontsContract == null) { sFontsContract = new FontsContract(context); - sHandler = new Handler(); - } - } - } - - /** - * Create a typeface object given a font request. The font will be asynchronously fetched, - * therefore the result is delivered to the given callback. See {@link FontRequest}. - * Only one of the methods in callback will be invoked, depending on whether the request - * succeeds or fails. These calls will happen on the main thread. - * @param request A {@link FontRequest} object that identifies the provider and query for the - * request. May not be null. - * @param callback A callback that will be triggered when results are obtained. May not be null. - */ - @Deprecated - public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) { - // Check the cache first - // TODO: would the developer want to avoid a cache hit and always ask for the freshest - // result? - Typeface cachedTypeface = findFromCache( - request.getProviderAuthority(), request.getQuery()); - if (cachedTypeface != null) { - sHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface)); - return; - } - synchronized (sLock) { - if (sFontsContract == null) { - throw new RuntimeException("Context not initialized, can't query provider"); - } - final ResultReceiver receiver = new ResultReceiver(null) { - @Override - public void onReceiveResult(int resultCode, Bundle resultData) { - sHandler.post(() -> receiveResult(request, callback, resultCode, resultData)); - } - }; - sFontsContract.getFont(request, receiver); - } - } - - private static Typeface findFromCache(String providerAuthority, String query) { - synchronized (sDynamicTypefaceCache) { - final String key = createProviderUid(providerAuthority, query); - Typeface typeface = sDynamicTypefaceCache.get(key); - if (typeface != null) { - return typeface; } } - return null; } - private static void receiveResult(FontRequest request, FontRequestCallback callback, - int resultCode, Bundle resultData) { - Typeface cachedTypeface = findFromCache( - request.getProviderAuthority(), request.getQuery()); - if (cachedTypeface != null) { - // We already know the result. - // Probably the requester requests the same font again in a short interval. - callback.onTypefaceRetrieved(cachedTypeface); - return; - } - if (resultCode != FontsContract.Columns.RESULT_CODE_OK) { - callback.onTypefaceRequestFailed(resultCode); - return; - } - if (resultData == null) { - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND); - return; - } - List<FontResult> resultList = - resultData.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS); - if (resultList == null || resultList.isEmpty()) { - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND); - return; - } - FontFamily fontFamily = new FontFamily(); - for (int i = 0; i < resultList.size(); ++i) { - FontResult result = resultList.get(i); - ParcelFileDescriptor fd = result.getFileDescriptor(); - if (fd == null) { - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); - return; - } - try (FileInputStream is = new FileInputStream(fd.getFileDescriptor())) { - FileChannel fileChannel = is.getChannel(); - long fontSize = fileChannel.size(); - ByteBuffer fontBuffer = fileChannel.map( - FileChannel.MapMode.READ_ONLY, 0, fontSize); - int weight = result.getWeight(); - int italic = result.getItalic() ? STYLE_ITALIC : STYLE_NORMAL; - FontVariationAxis[] axes = null; - try { - axes = FontVariationAxis.fromFontVariationSettings( - result.getFontVariationSettings()); - } catch (FontVariationAxis.InvalidFormatException e) { - // TODO: Nice to pass FontVariationAxis[] directly instead of string. - } - if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(), - axes, weight, italic)) { - Log.e(TAG, "Error creating font " + request.getQuery()); - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); - return; - } - } catch (IOException e) { - Log.e(TAG, "Error reading font " + request.getQuery(), e); - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); - return; - } finally { - IoUtils.closeQuietly(fd); - } - } - if (!fontFamily.freeze()) { - callback.onTypefaceRequestFailed( - FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); - return; - } - Typeface typeface = Typeface.createFromFamiliesWithDefault( - new FontFamily[] { fontFamily }, - RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE); - synchronized (sDynamicTypefaceCache) { - String key = createProviderUid(request.getProviderAuthority(), request.getQuery()); - sDynamicTypefaceCache.put(key, typeface); - } - callback.onTypefaceRetrieved(typeface); - } - - /** - * Interface used to receive asynchronously fetched typefaces. - */ - @Deprecated - public interface FontRequestCallback { - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given - * provider was not found on the device. - */ - int FAIL_REASON_PROVIDER_NOT_FOUND = FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND; - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given - * provider must be authenticated and the given certificates do not match its signature. - */ - int FAIL_REASON_WRONG_CERTIFICATES = FontsContract.RESULT_CODE_WRONG_CERTIFICATES; - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font - * returned by the provider was not loaded properly. - */ - int FAIL_REASON_FONT_LOAD_ERROR = -3; - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font - * provider did not return any results for the given query. - */ - int FAIL_REASON_FONT_NOT_FOUND = FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND; - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font - * provider found the queried font, but it is currently unavailable. - */ - int FAIL_REASON_FONT_UNAVAILABLE = FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE; - /** - * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given - * query was not supported by the provider. - */ - int FAIL_REASON_MALFORMED_QUERY = FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY; - - /** @hide */ - @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR, - FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE, - FAIL_REASON_MALFORMED_QUERY }) - @Retention(RetentionPolicy.SOURCE) - @interface FontRequestFailReason {} - - /** - * Called then a Typeface request done via {@link Typeface#create(FontRequest, - * FontRequestCallback)} is complete. Note that this method will not be called if - * {@link #onTypefaceRequestFailed(int)} is called instead. - * @param typeface The Typeface object retrieved. - */ - void onTypefaceRetrieved(Typeface typeface); - - /** - * Called when a Typeface request done via {@link Typeface#create(FontRequest, - * FontRequestCallback)} fails. - * @param reason May be one of {@link #FAIL_REASON_PROVIDER_NOT_FOUND}, - * {@link #FAIL_REASON_FONT_NOT_FOUND}, - * {@link #FAIL_REASON_FONT_LOAD_ERROR}, - * {@link #FAIL_REASON_FONT_UNAVAILABLE} or - * {@link #FAIL_REASON_MALFORMED_QUERY} if returned by the system. May also be - * a positive value greater than 0 defined by the font provider as an - * additional error code. Refer to the provider's documentation for more - * information on possible returned error codes. - */ - void onTypefaceRequestFailed(@FontRequestFailReason int reason); - } - - private static final FontRequestCallback NO_OP_REQUEST_CALLBACK = new FontRequestCallback() { - @Override - public void onTypefaceRetrieved(Typeface typeface) { - // Do nothing. - } - - @Override - public void onTypefaceRequestFailed(@FontRequestFailReason int reason) { - // Do nothing. - } - }; - /** * A builder class for creating new Typeface instance. * diff --git a/graphics/java/android/graphics/fonts/FontResult.java b/graphics/java/android/graphics/fonts/FontResult.java deleted file mode 100644 index 20e736eb1fc3..000000000000 --- a/graphics/java/android/graphics/fonts/FontResult.java +++ /dev/null @@ -1,115 +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 android.graphics.fonts; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.graphics.Paint; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; - -import com.android.internal.util.Preconditions; - -import java.io.FileDescriptor; -import java.io.IOException; - -/** - * Results returned from a Font Provider to the system. - * @hide - */ -public final class FontResult implements Parcelable { - private final ParcelFileDescriptor mFileDescriptor; - private final int mTtcIndex; - private final String mFontVariationSettings; - private final int mWeight; - private final boolean mItalic; - - /** - * Creates a FontResult with all the information needed about a provided font. - * @param fileDescriptor A ParcelFileDescriptor pointing to the font file. This shoult point to - * a real file or shared memory, as the client will mmap the given file - * descriptor. Pipes, sockets and other non-mmap-able file descriptors - * will fail to load in the client application. - * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0. - * @param fontVariationSettings If providing a variation font, the settings for it. May be null. - * @param weight An integer that indicates the font weight. - * @param italic A boolean that indicates the font is italic style or not. - */ - public FontResult(@NonNull ParcelFileDescriptor fileDescriptor, int ttcIndex, - @Nullable String fontVariationSettings, int weight, boolean italic) { - mFileDescriptor = Preconditions.checkNotNull(fileDescriptor); - mTtcIndex = ttcIndex; - mFontVariationSettings = fontVariationSettings; - mWeight = weight; - mItalic = italic; - } - - public ParcelFileDescriptor getFileDescriptor() { - return mFileDescriptor; - } - - public int getTtcIndex() { - return mTtcIndex; - } - - public String getFontVariationSettings() { - return mFontVariationSettings; - } - - public int getWeight() { - return mWeight; - } - - public boolean getItalic() { - return mItalic; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mFileDescriptor, flags); - dest.writeInt(mTtcIndex); - dest.writeString(mFontVariationSettings); - dest.writeInt(mWeight); - dest.writeBoolean(mItalic); - } - - private FontResult(Parcel in) { - mFileDescriptor = in.readParcelable(null); - mTtcIndex = in.readInt(); - mFontVariationSettings = in.readString(); - mWeight = in.readInt(); - mItalic = in.readBoolean(); - } - - public static final Parcelable.Creator<FontResult> CREATOR = - new Parcelable.Creator<FontResult>() { - @Override - public FontResult createFromParcel(Parcel in) { - return new FontResult(in); - } - - @Override - public FontResult[] newArray(int size) { - return new FontResult[size]; - } - }; -} diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 00d786a93626..244d6e5be6fd 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -93,6 +93,16 @@ public class KeyStore { */ public static final int FLAG_ENCRYPTED = 1; + /** + * A private flag that's only available to system server to indicate that this key is part of + * device encryption flow so it receives special treatment from keystore. For example this key + * will not be super encrypted, and it will be stored separately under an unique UID instead + * of the caller UID i.e. SYSTEM. + * + * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h + */ + public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3; + // States public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java index 64b10ab6eacb..bab4010b90e8 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java @@ -351,6 +351,9 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { } } else if (param instanceof KeyProtection) { spec = (KeyProtection) param; + if (spec.isCriticalToDeviceEncryption()) { + flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION; + } } else { throw new KeyStoreException( "Unsupported protection parameter class:" + param.getClass().getName() @@ -719,6 +722,10 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { } catch (IllegalArgumentException | IllegalStateException e) { throw new KeyStoreException(e); } + int flags = 0; + if (params.isCriticalToDeviceEncryption()) { + flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION; + } Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid); String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias; @@ -728,7 +735,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { KeymasterDefs.KM_KEY_FORMAT_RAW, keyMaterial, mUid, - 0, // flags + flags, new KeyCharacteristics()); if (errorCode != KeyStore.NO_ERROR) { throw new KeyStoreException("Failed to import secret key. Keystore error code: " diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index 2ec8d33ca530..0f983929b766 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -95,9 +95,6 @@ public abstract class AttestationUtils { * For privacy reasons, you cannot distinguish between (1) and (2). If attestation is * unsuccessful, the device may not support it in general or the user may have permanently * disabled it. - * <p> - * The caller must hold {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} - * permission. * * @param context the context to use for retrieving device identifiers. * @param idTypes the types of device identifiers to attest. diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index 2592a97468d3..2eb06631c228 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -227,6 +227,7 @@ public final class KeyProtection implements ProtectionParameter { private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mInvalidatedByBiometricEnrollment; private final long mBoundToSecureUserId; + private final boolean mCriticalToDeviceEncryption; private KeyProtection( Date keyValidityStart, @@ -242,7 +243,8 @@ public final class KeyProtection implements ProtectionParameter { int userAuthenticationValidityDurationSeconds, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, - long boundToSecureUserId) { + long boundToSecureUserId, + boolean criticalToDeviceEncryption) { mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); @@ -259,6 +261,7 @@ public final class KeyProtection implements ProtectionParameter { mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; mBoundToSecureUserId = boundToSecureUserId; + mCriticalToDeviceEncryption = criticalToDeviceEncryption; } /** @@ -458,6 +461,16 @@ public final class KeyProtection implements ProtectionParameter { } /** + * Return whether this key is critical to the device encryption flow. + * + * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION + * @hide + */ + public boolean isCriticalToDeviceEncryption() { + return mCriticalToDeviceEncryption; + } + + /** * Builder of {@link KeyProtection} instances. */ public final static class Builder { @@ -477,6 +490,7 @@ public final class KeyProtection implements ProtectionParameter { private boolean mInvalidatedByBiometricEnrollment = true; private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID; + private boolean mCriticalToDeviceEncryption = false; /** * Creates a new instance of the {@code Builder}. * @@ -817,6 +831,20 @@ public final class KeyProtection implements ProtectionParameter { } /** + * Set whether this key is critical to the device encryption flow + * + * This is a special flag only available to system servers to indicate the current key + * is part of the device encryption flow. + * + * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION + * @hide + */ + public Builder setCriticalToDeviceEncryption(boolean critical) { + mCriticalToDeviceEncryption = critical; + return this; + } + + /** * Builds an instance of {@link KeyProtection}. * * @throws IllegalArgumentException if a required field is missing @@ -837,7 +865,8 @@ public final class KeyProtection implements ProtectionParameter { mUserAuthenticationValidityDurationSeconds, mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, - mBoundToSecureUserId); + mBoundToSecureUserId, + mCriticalToDeviceEncryption); } } } diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java index 1dda6a4c77f7..8f4721f94e72 100644 --- a/media/java/android/media/VolumeShaper.java +++ b/media/java/android/media/VolumeShaper.java @@ -301,7 +301,7 @@ public final class VolumeShaper implements AutoCloseable { .setInterpolatorType(INTERPOLATOR_TYPE_LINEAR) .setCurve(new float[] {0.f, 1.f} /* times */, new float[] {0.f, 1.f} /* volumes */) - .setDurationMillis(1000.) + .setDuration(1000) .build(); /** @@ -314,7 +314,7 @@ public final class VolumeShaper implements AutoCloseable { .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC) .setCurve(new float[] {0.f, 1.f} /* times */, new float[] {0.f, 1.f} /* volumes */) - .setDurationMillis(1000.) + .setDuration(1000) .build(); /** @@ -348,12 +348,12 @@ public final class VolumeShaper implements AutoCloseable { SINE_RAMP = new VolumeShaper.Configuration.Builder() .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC) .setCurve(times, sines) - .setDurationMillis(1000.) + .setDuration(1000) .build(); SCURVE_RAMP = new VolumeShaper.Configuration.Builder() .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC) .setCurve(times, scurve) - .setDurationMillis(1000.) + .setDuration(1000) .build(); } @@ -569,8 +569,9 @@ public final class VolumeShaper implements AutoCloseable { /** * Returns the duration of the volume shape in milliseconds. */ - public double getDurationMillis() { - return mDurationMs; + public long getDuration() { + // casting is safe here as the duration was set as a long in the Builder + return (long) mDurationMs; } /** @@ -700,7 +701,7 @@ public final class VolumeShaper implements AutoCloseable { * .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR) * .setCurve(new float[] { 0.f, 1.f }, // times * new float[] { 0.f, 1.f }) // volumes - * .setDurationMillis(1000.) + * .setDuration(1000) * .build(); * </pre> * <p> @@ -731,7 +732,7 @@ public final class VolumeShaper implements AutoCloseable { mId = configuration.getId(); mOptionFlags = configuration.getAllOptionFlags(); mInterpolatorType = configuration.getInterpolatorType(); - mDurationMs = configuration.getDurationMillis(); + mDurationMs = configuration.getDuration(); mTimes = configuration.getTimes().clone(); mVolumes = configuration.getVolumes().clone(); } @@ -810,12 +811,12 @@ public final class VolumeShaper implements AutoCloseable { * @throws IllegalArgumentException if {@code durationMillis} * is not strictly positive. */ - public @NonNull Builder setDurationMillis(double durationMillis) { - if (durationMillis <= 0.) { + public @NonNull Builder setDuration(long durationMillis) { + if (durationMillis <= 0) { throw new IllegalArgumentException( "duration: " + durationMillis + " not positive"); } - mDurationMs = durationMillis; + mDurationMs = (double) durationMillis; return this; } @@ -833,7 +834,7 @@ public final class VolumeShaper implements AutoCloseable { * time (x) coordinates should be monotonically increasing, from 0.f to 1.f; * volume (y) coordinates must be within 0.f to 1.f. * <p> - * The time scale is set by {@link #setDurationMillis}. + * The time scale is set by {@link #setDuration}. * <p> * @param times an array of float values representing * the time line of the volume curve. diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 329514c0b7fc..0f0a7e9d1314 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -1469,6 +1469,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } break; } + } else { + if (finishDrawingRunnable != null) { + Log.w(TAG, "Warning, !readyToDraw() but waiting for " + + "draw finished! Early reporting draw finished."); + finishDrawingRunnable.run(); + finishDrawingRunnable = null; + } } // By design, this is the only place in a GLThread thread where we wait(). if (LOG_THREADS) { diff --git a/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml index 350a791ac30e..7de0035d0cc9 100644 --- a/packages/CompanionDeviceManager/res/layout/buttons.xml +++ b/packages/CompanionDeviceManager/res/layout/buttons.xml @@ -29,14 +29,14 @@ android:id="@+id/button_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/cancel" + android:text="@android:string/cancel" style="@android:style/Widget.Material.Light.Button.Borderless.Colored" /> <Button android:id="@+id/button_pair" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/pair" + android:text="@android:string/ok" style="@android:style/Widget.Material.Light.Button.Borderless.Colored" /> </LinearLayout>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index 469c1fbf22ad..c4372ebef663 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -20,15 +20,9 @@ <string name="app_label">Companion Device Manager</string> <!-- Title of the device selection dialog. --> - <string name="chooser_title">Pair with <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> via Bluetooth?</string> + <string name="chooser_title">Link with <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong></string> <!-- Title of the device pairing confirmation dialog. --> - <string name="confirmation_title">Pair <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> with <strong><xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g></strong> via Bluetooth?</string> - - <!-- Label on the pair button in a companion device chooser/confirmation dialog --> - <string name="pair">Pair</string> - - <!-- Label on the cancel button in a companion device chooser/confirmation dialog --> - <string name="cancel">Cancel</string> + <string name="confirmation_title">Link <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> with <strong><xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g></strong></string> </resources> diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml index f3d8983f74b3..f54b6fb4604c 100644 --- a/packages/ExtServices/AndroidManifest.xml +++ b/packages/ExtServices/AndroidManifest.xml @@ -21,6 +21,8 @@ android:versionName="1" coreApp="true"> + <uses-permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" /> + <application android:label="@string/app_name" android:defaultToDeviceProtectedStorage="true" android:directBootAware="true"> @@ -32,6 +34,14 @@ </intent-filter> </service> + <service android:name=".resolver.LRResolverRankerService" + android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE" + android:priority="-1" > + <intent-filter> + <action android:name="android.service.resolver.ResolverRankerService" /> + </intent-filter> + </service> + <library android:name="android.ext.services"/> </application> diff --git a/core/java/com/android/internal/app/LRResolverRankerService.java b/packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java index 1cad7c770b7c..9d7a5689dcd1 100644 --- a/core/java/com/android/internal/app/LRResolverRankerService.java +++ b/packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.app; +package android.ext.services.resolver; import android.content.Context; import android.content.Intent; diff --git a/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml b/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml new file mode 100644 index 000000000000..8196650e6911 --- /dev/null +++ b/packages/PrintSpooler/res/drawable/ic_pdf_printer.xml @@ -0,0 +1,25 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="36dp" + android:height="36dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0" + android:tint="@color/pdf_printer_color"> + <path + android:pathData="M40,4L16,4c-2.21,0 -4,1.79 -4,4v24c0,2.21 1.79,4 4,4h24c2.21,0 4,-1.79 4,-4L44,8c0,-2.21 -1.79,-4 -4,-4zM23,19c0,1.66 -1.34,3 -3,3h-2v4h-3L15,14h5c1.66,0 3,1.34 3,3v2zM33,23c0,1.66 -1.34,3 -3,3h-5L25,14h5c1.66,0 3,1.34 3,3v6zM41,17h-3v2h3v3h-3v4h-3L35,14h6v3zM18,19h2v-2h-2v2zM8,12L4,12v28c0,2.21 1.79,4 4,4h28v-4L8,40L8,12zM28,23h2v-6h-2v6z" + android:fillColor="@android:color/black"/> +</vector>
\ No newline at end of file diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml index d83d364b3309..a15fff587d3c 100644 --- a/packages/PrintSpooler/res/values/colors.xml +++ b/packages/PrintSpooler/res/values/colors.xml @@ -24,4 +24,5 @@ <color name="material_grey_500">#ffa3a3a3</color> + <color name="pdf_printer_color">#009688</color> </resources> diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index ccdec6216679..601491abfd7e 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -2442,7 +2442,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat if (position == 0 && getPdfPrinter() != null) { PrinterHolder printerHolder = (PrinterHolder) getItem(position); title = printerHolder.printer.getName(); - icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null); + icon = getResources().getDrawable(R.drawable.ic_pdf_printer, null); } else if (position == 1) { title = getMoreItemTitle(); } @@ -2450,7 +2450,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat if (position == 1 && getPdfPrinter() != null) { PrinterHolder printerHolder = (PrinterHolder) getItem(position); title = printerHolder.printer.getName(); - icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null); + icon = getResources().getDrawable(R.drawable.ic_pdf_printer, null); } else if (position == getCount() - 1) { title = getMoreItemTitle(); } else { diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml deleted file mode 100755 index 64f21b50c0bc..000000000000 --- a/packages/SettingsLib/res/values/config.xml +++ /dev/null @@ -1,49 +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. -*/ ---> -<resources> - <!-- Configuration for automotive --> - <bool name="enable_pbap_pce_profile">false</bool> - - <!-- Default data warning level in mb --> - <integer name="default_data_warning_level_mb">2048</integer> - - <!-- Whether to send a custom package name with the PSD.--> - <bool name="config_sendPackageName">false</bool> - - <!-- Name for the set of keys associating package names --> - <string name="config_helpPackageNameKey" translatable="false"></string> - - <!-- Name for the set of values of package names --> - <string name="config_helpPackageNameValue" translatable="false"></string> - - <!-- Intent key for the package name keys --> - <string name="config_helpIntentExtraKey" translatable="false"></string> - - <!-- Intent key for package name values --> - <string name="config_helpIntentNameKey" translatable="false"></string> - - <!-- Intent key for the package name keys --> - <string name="config_feedbackIntentExtraKey" translatable="false"></string> - - <!-- Intent key for package name values --> - <string name="config_feedbackIntentNameKey" translatable="false"></string> - - <!-- The apps that need to be hided when they are disabled --> - <string-array name="config_hideWhenDisabled_packageNames"></string-array> -</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index e15df142de94..044392cc4ad6 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -130,6 +130,12 @@ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). --> <string name="bluetooth_profile_sap">SIM Access</string> + <!-- Bluetooth settings. The user-visible string for the setting controlling whether to use a high-quality codec if the device supports it, along with the name of the codec (eg AAC, LDAC, aptX) --> + <string name="bluetooth_profile_a2dp_high_quality">Use high quality audio: <xliff:g id="codec_name">%1$s</xliff:g></string> + + <!-- Bluetooth settings. Similar to bluetooth_profile_a2dp_high_quality, but used when the device supports high quality audio but we don't know which codec that will be used. --> + <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">Use high quality audio</string> + <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. --> <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string> <!-- Bluetooth settings. Connection options screen. The summary for the headset checkbox preference when headset is connected. --> diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java index 58047bb8e3f3..2c2641079953 100644 --- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java @@ -180,21 +180,24 @@ public class HelpUtils { } Resources resources = context.getResources(); - boolean includePackageName = resources.getBoolean(R.bool.config_sendPackageName); + boolean includePackageName = + resources.getBoolean(com.android.internal.R.bool.config_sendPackageName); if (sendPackageName && includePackageName) { String[] packageNameKey = - {resources.getString(R.string.config_helpPackageNameKey)}; + {resources.getString(com.android.internal.R.string.config_helpPackageNameKey)}; String[] packageNameValue = - {resources.getString(R.string.config_helpPackageNameValue)}; + {resources.getString( + com.android.internal.R.string.config_helpPackageNameValue)}; String helpIntentExtraKey = - resources.getString(R.string.config_helpIntentExtraKey); + resources.getString(com.android.internal.R.string.config_helpIntentExtraKey); String helpIntentNameKey = - resources.getString(R.string.config_helpIntentNameKey); + resources.getString(com.android.internal.R.string.config_helpIntentNameKey); String feedbackIntentExtraKey = - resources.getString(R.string.config_feedbackIntentExtraKey); + resources.getString( + com.android.internal.R.string.config_feedbackIntentExtraKey); String feedbackIntentNameKey = - resources.getString(R.string.config_feedbackIntentNameKey); + resources.getString(com.android.internal.R.string.config_feedbackIntentNameKey); intent.putExtra(helpIntentExtraKey, packageNameKey); intent.putExtra(helpIntentNameKey, packageNameValue); intent.putExtra(feedbackIntentExtraKey, packageNameKey); diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index c10970467383..66dfecd2505f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -50,8 +50,8 @@ import android.util.IconDrawableFactory; import android.util.Log; import android.util.SparseArray; +import com.android.internal.R; import com.android.internal.util.ArrayUtils; -import com.android.settingslib.R; import java.io.File; import java.io.IOException; @@ -1276,8 +1276,7 @@ public class ApplicationsState { return true; } else { this.mounted = false; - this.icon = context.getDrawable( - com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon); + this.icon = context.getDrawable(R.drawable.sym_app_on_sd_unavailable_icon); } } else if (!this.mounted) { // If the app wasn't mounted but is now mounted, reload diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 1ea592d7785d..5a9a7496fa4f 100755 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -32,7 +32,7 @@ import android.content.Context; import android.content.Intent; import android.os.ParcelUuid; import android.util.Log; -import com.android.settingslib.R; +import com.android.internal.R; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index af247bdbb392..a0eadd0fa122 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -17,6 +17,7 @@ package com.android.settingslib.drawer; import android.annotation.LayoutRes; import android.annotation.Nullable; +import android.app.ActionBar; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -27,7 +28,6 @@ import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.os.AsyncTask; import android.os.Bundle; -import android.provider.Settings; import android.util.ArraySet; import android.util.Log; import android.view.LayoutInflater; @@ -117,14 +117,6 @@ public class SettingsDrawerActivity extends Activity { super.onPause(); } - /** - * Gets the name of the intent action of the default setting app. Used to launch setting app - * when Settings Home is clicked. - */ - public String getSettingAction() { - return Settings.ACTION_SETTINGS; - } - public void addCategoryListener(CategoryListener listener) { mCategoryListeners.add(listener); } @@ -142,7 +134,7 @@ public class SettingsDrawerActivity extends Activity { @Override public void setContentView(@LayoutRes int layoutResID) { - final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame); + final ViewGroup parent = findViewById(R.id.content_frame); if (parent != null) { parent.removeAllViews(); } @@ -159,11 +151,14 @@ public class SettingsDrawerActivity extends Activity { ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); } - public void showMenuIcon() { - getActionBar().setDisplayHomeAsUpEnabled(true); + private void showMenuIcon() { + final ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } } - protected void onCategoriesChanged() { + private void onCategoriesChanged() { final int N = mCategoryListeners.size(); for (int i = 0; i < N; i++) { mCategoryListeners.get(i).onCategoriesChanged(); diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index 994ea88a80dd..b69232c80f69 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -32,7 +32,7 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; -import com.android.settingslib.R; +import com.android.internal.R; import java.util.Date; import java.util.Locale; diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java index 752b5b0e152c..003f90579415 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java @@ -16,7 +16,12 @@ package com.android.settingslib.drawer; -import android.app.Activity; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; + import android.app.Instrumentation; import android.content.Intent; import android.support.test.InstrumentationRegistry; @@ -24,23 +29,12 @@ import android.support.test.filters.SmallTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; -import com.android.settingslib.R; - -import com.google.common.truth.Truth; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; -import static com.google.common.truth.Truth.assertThat; - @RunWith(AndroidJUnit4.class) @SmallTest public class SettingsDrawerActivityTest { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java index 56891f66b03c..fdc42bf6724a 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java @@ -27,6 +27,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.provider.Settings; import android.view.MenuItem; +import com.android.internal.R; import org.junit.Before; import org.junit.Test; diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 55f32d7d8b43..bf39bc4b96ea 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -22,9 +22,6 @@ android:sharedUserId="android.uid.systemui" coreApp="true"> - <protected-broadcast android:name="com.android.systemui.action.PLUGIN_CHANGED" /> - - <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index f809c683f12c..871ed679f4d9 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -31,6 +31,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" + android:textDirection="locale" android:textAppearance="@style/TextAppearance.QS.DetailHeader" /> <ImageView diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml index 6544f0d780df..97e82ffb92f4 100644 --- a/packages/SystemUI/res/layout/qs_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_detail_item.xml @@ -43,6 +43,7 @@ android:id="@android:id/title" android:layout_width="match_parent" android:layout_height="wrap_content" + android:textDirection="locale" android:ellipsize="end" android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" /> @@ -50,6 +51,7 @@ android:id="@android:id/summary" android:layout_width="match_parent" android:layout_height="wrap_content" + android:textDirection="locale" android:layout_marginTop="2dp" android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index 5766dc1c5b4f..5df50cdeba1a 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -32,6 +32,7 @@ android:layout_width="wrap_content" android:paddingEnd="6dp" android:src="@drawable/stat_sys_vpn_ic" + android:contentDescription="@string/accessibility_vpn_on" /> <FrameLayout android:id="@+id/ethernet_combo" diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml index b04b28c709f5..362c1d214b0e 100644 --- a/packages/SystemUI/res/values-sw410dp/config.xml +++ b/packages/SystemUI/res/values-sw410dp/config.xml @@ -21,6 +21,7 @@ for different hardware and product builds. --> <resources> <integer name="quick_settings_num_rows">2</integer> + <integer name="quick_settings_num_rows_portrait">3</integer> <bool name="quick_settings_show_full_alarm">true</bool> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index e9d6fec30aee..fd7e165e11a9 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -100,6 +100,7 @@ <!-- The number of rows in the QuickSettings --> <integer name="quick_settings_num_rows">1</integer> + <integer name="quick_settings_num_rows_portrait">2</integer> <!-- The number of columns that the top level tiles span in the QuickSettings --> <integer name="quick_settings_user_time_settings_tile_span">1</integer> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 9e8857875694..9fb884e958af 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -390,6 +390,9 @@ <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_airplane_mode">Airplane mode.</string> + <!-- Content description of the VPN icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_vpn_on">VPN on.</string> + <!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_no_sims">No SIM card.</string> diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java index a8daed531357..f66331525ab7 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java @@ -155,10 +155,6 @@ public class PluginInstanceManager<T extends Plugin> { new ComponentName(info.mPackage, info.mClass), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - final String pkg = info.mPackage; - final Intent intent = new Intent(PluginManager.PLUGIN_CHANGED, - pkg != null ? Uri.fromParts("package", pkg, null) : null); - mContext.sendBroadcast(intent); } public <T> boolean dependsOn(Plugin p, Class<T> cls) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index 9da52d08b88f..f3417dc078c2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -279,8 +279,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { private int getRows() { final Resources res = getContext().getResources(); if (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - // Always have 3 rows in portrait. - return 3; + return res.getInteger(R.integer.quick_settings_num_rows_portrait); } return Math.max(1, res.getInteger(R.integer.quick_settings_num_rows)); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 2725a329f6e0..5512993e10e7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -16,8 +16,14 @@ package com.android.systemui.qs.tiles; +import android.app.Dialog; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; import android.content.Intent; +import android.content.IntentFilter; +import android.os.UserHandle; import android.provider.Settings; import android.service.quicksettings.Tile; import android.support.v7.app.MediaRouteChooserDialog; @@ -61,6 +67,7 @@ public class CastTile extends QSTileImpl<BooleanState> { private final KeyguardMonitor mKeyguard; private final Callback mCallback = new Callback(); private final ActivityStarter mActivityStarter; + private Dialog mDialog; public CastTile(QSHost host) { super(host); @@ -128,9 +135,7 @@ public class CastTile extends QSTileImpl<BooleanState> { Context context = new ContextThemeWrapper(mContext, R.style.Theme_AppCompat_Light_Dialog_Alert); if (mState.value) { - MediaRouteControllerDialog dialog = new MediaRouteControllerDialog(context); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL); - dialog.show(); + mDialog = new MediaRouteControllerDialog(context); } else { // Instead of showing detail, show standard media routing UI. MediaRouteChooserDialog dialog = new MediaRouteChooserDialog(context); @@ -138,13 +143,21 @@ public class CastTile extends QSTileImpl<BooleanState> { .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO) .build(); dialog.setRouteSelector(selector); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL); - dialog.show(); + mDialog = dialog; } + mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL); + mDialog.show(); + registerReceiver(); mHost.collapsePanels(); }); } + private void registerReceiver() { + mContext.registerReceiverAsUser(mReceiver, UserHandle.CURRENT, + new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), null, null); + mDialog.setOnDismissListener(dialog -> mContext.unregisterReceiver(mReceiver)); + } + @Override public CharSequence getTileLabel() { return mContext.getString(R.string.quick_settings_cast_title); @@ -210,6 +223,15 @@ public class CastTile extends QSTileImpl<BooleanState> { } }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mDialog != null) { + mDialog.dismiss(); + } + } + }; + private final class CastDetailAdapter implements DetailAdapter, QSDetailItems.Callback { private final LinkedHashMap<String, CastDevice> mVisibleOrder = new LinkedHashMap<>(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 143d934dd002..7bc591f4832a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -192,8 +192,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // and the old last stack active time, they were not visible and in the // TaskStack so we don't need to remove any associated TaskViews but we do // need to load the task id's from the system - RecentsTaskLoadPlan loadPlan = Recents.getTaskLoader().createLoadPlan(ctx); - loadPlan.preloadRawTasks(false /* includeFrontMostExcludedTask */); + RecentsTaskLoader loader = Recents.getTaskLoader(); + RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(ctx); + loader.preloadRawTasks(loadPlan, false /* includeFrontMostExcludedTask */); List<ActivityManager.RecentTaskInfo> tasks = loadPlan.getRawTasks(); for (int i = tasks.size() - 1; i >= 0; i--) { ActivityManager.RecentTaskInfo task = tasks.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 164138e4b1d3..53a9eae17f41 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -108,36 +108,39 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener * task stacks and update recents accordingly. */ class TaskStackListenerImpl extends TaskStackListener { + @Override - public void onTaskStackChanged() { + public void onTaskStackChangedBackground() { // Preloads the next task RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { - RecentsTaskLoader loader = Recents.getTaskLoader(); - SystemServicesProxy ssp = Recents.getSystemServices(); - ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask(); // Load the next task only if we aren't svelte + SystemServicesProxy ssp = Recents.getSystemServices(); + ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask(); + RecentsTaskLoader loader = Recents.getTaskLoader(); RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); - RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); + // This callback is made when a new activity is launched and the old one is paused // so ignore the current activity and try and preload the thumbnail for the // previous one. - if (runningTaskInfo != null) { - launchOpts.runningTaskId = runningTaskInfo.id; + VisibilityReport visibilityReport; + synchronized (mDummyStackView) { + mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */); + updateDummyStackViewLayout(plan.getTaskStack(), + getWindowRect(null /* windowRectOverride */)); + + // Launched from app is always the worst case (in terms of how many + // thumbnails/tasks visible) + RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); + launchState.launchedFromApp = true; + mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState); + visibilityReport = mDummyStackView.computeStackVisibilityReport(); } - mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */); - updateDummyStackViewLayout(plan.getTaskStack(), - getWindowRect(null /* windowRectOverride */)); - // Launched from app is always the worst case (in terms of how many thumbnails/tasks - // visible) - RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); - launchState.launchedFromApp = true; - mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState); - - VisibilityReport visibilityReport = mDummyStackView.computeStackVisibilityReport(); + RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); + launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1; launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks; launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails; launchOpts.onlyLoadForCache = true; @@ -221,9 +224,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void onConfigurationChanged() { - Resources res = mContext.getResources(); reloadResources(); - mDummyStackView.reloadOnConfigurationChange(); + synchronized (mDummyStackView) { + mDummyStackView.reloadOnConfigurationChange(); + } } /** @@ -393,7 +397,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener RecentsTaskLoader loader = Recents.getTaskLoader(); sInstanceLoadPlan = loader.createLoadPlan(mContext); - sInstanceLoadPlan.preloadRawTasks(!isHomeStackVisible.value); loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value); TaskStack stack = sInstanceLoadPlan.getTaskStack(); if (stack.getTaskCount() > 0) { @@ -633,16 +636,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener calculateWindowStableInsets(systemInsets, windowRect); windowRect.offsetTo(0, 0); - TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); + synchronized (mDummyStackView) { + TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); - // Rebind the header bar and draw it for the transition - stackLayout.setSystemInsets(systemInsets); - if (stack != null) { - stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top, - systemInsets.left, systemInsets.right, mTaskStackBounds); - stackLayout.reset(); - stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, - TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); + // Rebind the header bar and draw it for the transition + stackLayout.setSystemInsets(systemInsets); + if (stack != null) { + stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top, + systemInsets.left, systemInsets.right, mTaskStackBounds); + stackLayout.reset(); + stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, + TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); + } } } @@ -663,47 +668,52 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener */ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { Rect windowRect = getWindowRect(windowRectOverride); - updateDummyStackViewLayout(stack, windowRect); - if (stack != null) { - TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); - mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); - // Get the width of a task view so that we know how wide to draw the header bar. - int taskViewWidth = 0; - if (mDummyStackView.useGridLayout()) { - TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm(); - gridLayout.initialize(windowRect); - taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */, - stack.getTaskCount(), new TaskViewTransform(), stackLayout).rect.width(); - } else { - Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); - if (!taskViewBounds.isEmpty()) { - taskViewWidth = taskViewBounds.width(); + int taskViewWidth = 0; + boolean useGridLayout = false; + synchronized (mDummyStackView) { + useGridLayout = mDummyStackView.useGridLayout(); + updateDummyStackViewLayout(stack, windowRect); + if (stack != null) { + TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); + mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); + // Get the width of a task view so that we know how wide to draw the header bar. + if (useGridLayout) { + TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm(); + gridLayout.initialize(windowRect); + taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */, + stack.getTaskCount(), new TaskViewTransform(), + stackLayout).rect.width(); + } else { + Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); + if (!taskViewBounds.isEmpty()) { + taskViewWidth = taskViewBounds.width(); + } } } + } - if (taskViewWidth > 0) { - synchronized (mHeaderBarLock) { - if (mHeaderBar.getMeasuredWidth() != taskViewWidth || - mHeaderBar.getMeasuredHeight() != mTaskBarHeight) { - if (mDummyStackView.useGridLayout()) { - mHeaderBar.setShouldDarkenBackgroundColor(true); - mHeaderBar.setNoUserInteractionState(); - } - mHeaderBar.forceLayout(); - mHeaderBar.measure( - MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY)); + if (stack != null && taskViewWidth > 0) { + synchronized (mHeaderBarLock) { + if (mHeaderBar.getMeasuredWidth() != taskViewWidth || + mHeaderBar.getMeasuredHeight() != mTaskBarHeight) { + if (useGridLayout) { + mHeaderBar.setShouldDarkenBackgroundColor(true); + mHeaderBar.setNoUserInteractionState(); } - mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); + mHeaderBar.forceLayout(); + mHeaderBar.measure( + MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY)); } + mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); + } - // Update the transition bitmap to match the new header bar height - if (mThumbTransitionBitmapCache == null || - (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) || - (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) { - mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth, - mTaskBarHeight, Bitmap.Config.ARGB_8888); - } + // Update the transition bitmap to match the new header bar height + if (mThumbTransitionBitmapCache == null || + (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) || + (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) { + mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth, + mTaskBarHeight, Bitmap.Config.ARGB_8888); } } } @@ -764,16 +774,21 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener * Creates the activity options for an app->recents transition. */ private ActivityOptions getThumbnailTransitionActivityOptions( - ActivityManager.RunningTaskInfo runningTask, TaskStackView stackView, - Rect windowOverrideRect) { + ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) { if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) { ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>(); - ArrayList<Task> tasks = stackView.getStack().getStackTasks(); - TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm(); - TaskStackViewScroller stackScroller = stackView.getScroller(); + ArrayList<Task> tasks; + TaskStackLayoutAlgorithm stackLayout; + TaskStackViewScroller stackScroller; - stackView.updateLayoutAlgorithm(true /* boundScroll */); - stackView.updateToInitialState(); + synchronized (mDummyStackView) { + tasks = mDummyStackView.getStack().getStackTasks(); + stackLayout = mDummyStackView.getStackAlgorithm(); + stackScroller = mDummyStackView.getScroller(); + + mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */); + mDummyStackView.updateToInitialState(); + } for (int i = tasks.size() - 1; i >= 0; i--) { Task task = tasks.get(i); @@ -795,7 +810,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } else { // Update the destination rect Task toTask = new Task(); - TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask, + TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask, windowOverrideRect); Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, mThumbTransitionBitmapCache); @@ -919,8 +934,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener updateHeaderBarLayout(stack, windowOverrideRect); // Prepare the dummy stack for the transition - TaskStackLayoutAlgorithm.VisibilityReport stackVr = - mDummyStackView.computeStackVisibilityReport(); + TaskStackLayoutAlgorithm.VisibilityReport stackVr; + synchronized (mDummyStackView) { + stackVr = mDummyStackView.computeStackVisibilityReport(); + } // Update the remaining launch state launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks; @@ -936,8 +953,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener opts = getUnknownTransitionActivityOptions(); } else if (useThumbnailTransition) { // Try starting with a thumbnail transition - opts = getThumbnailTransitionActivityOptions(runningTask, mDummyStackView, - windowOverrideRect); + opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect); } else { // If there is no thumbnail transition, but is launching from home into recents, then // use a quick home transition diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 2f122825fe73..a9e1f61b7d47 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -61,6 +61,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemProperties; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -149,6 +150,10 @@ public class SystemServicesProxy { * to reduce IPC calls from system services. These callbacks will be called on the main thread. */ public abstract static class TaskStackListener { + /** + * NOTE: This call is made of the thread that the binder call comes in on. + */ + public void onTaskStackChangedBackground() { } public void onTaskStackChanged() { } public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { } public void onActivityPinned(String packageName) { } @@ -187,8 +192,20 @@ public class SystemServicesProxy { * This simply passes callbacks to listeners through {@link H}. * */ private android.app.TaskStackListener mTaskStackListener = new android.app.TaskStackListener() { + + private final List<SystemServicesProxy.TaskStackListener> mTmpListeners = new ArrayList<>(); + @Override public void onTaskStackChanged() throws RemoteException { + // Call the task changed callback for the non-ui thread listeners first + synchronized (mTaskStackListeners) { + mTmpListeners.clear(); + mTmpListeners.addAll(mTaskStackListeners); + } + for (int i = mTmpListeners.size() - 1; i >= 0; i--) { + mTmpListeners.get(i).onTaskStackChangedBackground(); + } + mHandler.removeMessages(H.ON_TASK_STACK_CHANGED); mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED); } @@ -309,10 +326,7 @@ public class SystemServicesProxy { * Returns the single instance of the {@link SystemServicesProxy}. * This should only be called on the main thread. */ - public static SystemServicesProxy getInstance(Context context) { - if (!Looper.getMainLooper().isCurrentThread()) { - throw new RuntimeException("Must be called on the UI thread"); - } + public static synchronized SystemServicesProxy getInstance(Context context) { if (sSystemServicesProxy == null) { sSystemServicesProxy = new SystemServicesProxy(context); } @@ -1136,13 +1150,15 @@ public class SystemServicesProxy { public void registerTaskStackListener(TaskStackListener listener) { if (mIam == null) return; - mTaskStackListeners.add(listener); - if (mTaskStackListeners.size() == 1) { - // Register mTaskStackListener to IActivityManager only once if needed. - try { - mIam.registerTaskStackListener(mTaskStackListener); - } catch (Exception e) { - Log.w(TAG, "Failed to call registerTaskStackListener", e); + synchronized (mTaskStackListeners) { + mTaskStackListeners.add(listener); + if (mTaskStackListeners.size() == 1) { + // Register mTaskStackListener to IActivityManager only once if needed. + try { + mIam.registerTaskStackListener(mTaskStackListener); + } catch (Exception e) { + Log.w(TAG, "Failed to call registerTaskStackListener", e); + } } } } @@ -1245,74 +1261,80 @@ public class SystemServicesProxy { @Override public void handleMessage(Message msg) { - switch (msg.what) { - case ON_TASK_STACK_CHANGED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onTaskStackChanged(); + synchronized (mTaskStackListeners) { + switch (msg.what) { + case ON_TASK_STACK_CHANGED: { + Trace.beginSection("onTaskStackChanged"); + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onTaskStackChanged(); + } + Trace.endSection(); + break; } - break; - } - case ON_TASK_SNAPSHOT_CHANGED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, - (TaskSnapshot) msg.obj); + case ON_TASK_SNAPSHOT_CHANGED: { + Trace.beginSection("onTaskSnapshotChanged"); + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, + (TaskSnapshot) msg.obj); + } + Trace.endSection(); + break; } - break; - } - case ON_ACTIVITY_PINNED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityPinned((String) msg.obj); + case ON_ACTIVITY_PINNED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onActivityPinned((String) msg.obj); + } + break; } - break; - } - case ON_ACTIVITY_UNPINNED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityUnpinned(); + case ON_ACTIVITY_UNPINNED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onActivityUnpinned(); + } + break; } - break; - } - case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(); + case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(); + } + break; } - break; - } - case ON_PINNED_STACK_ANIMATION_STARTED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onPinnedStackAnimationStarted(); + case ON_PINNED_STACK_ANIMATION_STARTED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onPinnedStackAnimationStarted(); + } + break; } - break; - } - case ON_PINNED_STACK_ANIMATION_ENDED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onPinnedStackAnimationEnded(); + case ON_PINNED_STACK_ANIMATION_ENDED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onPinnedStackAnimationEnded(); + } + break; } - break; - } - case ON_ACTIVITY_FORCED_RESIZABLE: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityForcedResizable( - (String) msg.obj, msg.arg1, msg.arg2); + case ON_ACTIVITY_FORCED_RESIZABLE: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onActivityForcedResizable( + (String) msg.obj, msg.arg1, msg.arg2); + } + break; } - break; - } - case ON_ACTIVITY_DISMISSING_DOCKED_STACK: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityDismissingDockedStack(); + case ON_ACTIVITY_DISMISSING_DOCKED_STACK: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onActivityDismissingDockedStack(); + } + break; } - break; - } - case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed(); + case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed(); + } + break; } - break; - } - case ON_TASK_PROFILE_LOCKED: { - for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2); + case ON_TASK_PROFILE_LOCKED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onTaskProfileLocked(msg.arg1, msg.arg2); + } + break; } - break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 78c71a11f3f5..4b53cd112d96 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -103,8 +103,10 @@ public class RecentsTaskLoadPlan { /** * An optimization to preload the raw list of tasks. The raw tasks are saved in least-recent * to most-recent order. + * + * Note: Do not lock, callers should synchronize on the loader before making this call. */ - public synchronized void preloadRawTasks(boolean includeFrontMostExcludedTask) { + void preloadRawTasks(boolean includeFrontMostExcludedTask) { int currentUserId = UserHandle.USER_CURRENT; updateCurrentQuietProfilesCache(currentUserId); SystemServicesProxy ssp = Recents.getSystemServices(); @@ -123,8 +125,11 @@ public class RecentsTaskLoadPlan { * The tasks will be ordered by: * - least-recent to most-recent stack tasks * - least-recent to most-recent freeform tasks + * + * Note: Do not lock, since this can be calling back to the loader, which separately also drives + * this call (callers should synchronize on the loader before making this call). */ - public synchronized void preloadPlan(RecentsTaskLoader loader, int runningTaskId, + void preloadPlan(RecentsTaskLoader loader, int runningTaskId, boolean includeFrontMostExcludedTask) { Resources res = mContext.getResources(); ArrayList<Task> allTasks = new ArrayList<>(); @@ -223,8 +228,11 @@ public class RecentsTaskLoadPlan { /** * Called to apply the actual loading based on the specified conditions. + * + * Note: Do not lock, since this can be calling back to the loader, which separately also drives + * this call (callers should synchronize on the loader before making this call). */ - public synchronized void executePlan(Options opts, RecentsTaskLoader loader) { + void executePlan(Options opts, RecentsTaskLoader loader) { Resources res = mContext.getResources(); // Iterate through each of the tasks and load them according to the load conditions. diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 5e78b61e021c..0b4498c487a8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -31,6 +31,7 @@ import android.os.Looper; import android.util.Log; import android.util.LruCache; +import com.android.internal.annotations.GuardedBy; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; @@ -243,7 +244,9 @@ public class RecentsTaskLoader { private final TaskResourceLoadQueue mLoadQueue; private final BackgroundTaskLoader mLoader; private final HighResThumbnailLoader mHighResThumbnailLoader; + @GuardedBy("this") private final TaskKeyStrongCache<ThumbnailData> mThumbnailCache = new TaskKeyStrongCache<>(); + @GuardedBy("this") private final TaskKeyStrongCache<ThumbnailData> mTempCache = new TaskKeyStrongCache<>(); private final int mMaxThumbnailCacheSize; private final int mMaxIconCacheSize; @@ -318,14 +321,20 @@ public class RecentsTaskLoader { return plan; } + /** Preloads raw recents tasks using the specified plan to store the output. */ + public synchronized void preloadRawTasks(RecentsTaskLoadPlan plan, + boolean includeFrontMostExcludedTask) { + plan.preloadRawTasks(includeFrontMostExcludedTask); + } + /** Preloads recents tasks using the specified plan to store the output. */ - public void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId, + public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId, boolean includeFrontMostExcludedTask) { plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask); } /** Begins loading the heavy task data according to the specified options. */ - public void loadTasks(Context context, RecentsTaskLoadPlan plan, + public synchronized void loadTasks(Context context, RecentsTaskLoadPlan plan, RecentsTaskLoadPlan.Options opts) { if (opts == null) { throw new RuntimeException("Requires load options"); @@ -380,8 +389,7 @@ public class RecentsTaskLoader { * Handles signals from the system, trimming memory when requested to prevent us from running * out of memory. */ - public void onTrimMemory(int level) { - RecentsConfiguration config = Recents.getConfiguration(); + public synchronized void onTrimMemory(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: // Stop the loader immediately when the UI is no longer visible @@ -516,7 +524,7 @@ public class RecentsTaskLoader { /** * Returns the cached thumbnail if the task key is not expired, updating the cache if it is. */ - ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached, + synchronized ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached, boolean storeInCache) { SystemServicesProxy ssp = Recents.getSystemServices(); @@ -616,12 +624,15 @@ public class RecentsTaskLoader { } } - public void dump(String prefix, PrintWriter writer) { + public synchronized void dump(String prefix, PrintWriter writer) { String innerPrefix = prefix + " "; writer.print(prefix); writer.println(TAG); writer.print(prefix); writer.println("Icon Cache"); mIconCache.dump(innerPrefix, writer); + writer.print(prefix); writer.println("Thumbnail Cache"); mThumbnailCache.dump(innerPrefix, writer); + writer.print(prefix); writer.println("Temp Thumbnail Cache"); + mTempCache.dump(innerPrefix, writer); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 32e3df6a7295..18a9bab74084 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -1711,6 +1711,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } + private void clearPrefetchingTask() { + if (mPrefetchingTask != null) { + Recents.getTaskLoader().unloadTaskData(mPrefetchingTask); + } + mPrefetchingTask = null; + } + /**** TaskViewCallbacks Implementation ****/ @Override @@ -2201,6 +2208,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (!event.visible && mTaskViewFocusFrame != null) { mTaskViewFocusFrame.moveGridTaskViewFocus(null); } + if (!event.visible) { + List<TaskView> taskViews = new ArrayList<>(getTaskViews()); + for (int i = 0; i < taskViews.size(); i++) { + mViewPool.returnViewToPool(taskViews.get(i)); + } + clearPrefetchingTask(); + } } public void reloadOnConfigurationChange() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java index f3c7b8495a01..2cf06c2ab33f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java @@ -262,17 +262,15 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private boolean hasImportanceChanged() { return mSingleNotificationChannel != null && + mChannelEnabledSwitch != null && mStartingUserImportance != getSelectedImportance(); } private void saveImportance() { - if (mSingleNotificationChannel == null) { - return; - } - int selectedImportance = getSelectedImportance(); - if (selectedImportance == mStartingUserImportance) { + if (!hasImportanceChanged()) { return; } + final int selectedImportance = getSelectedImportance(); MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE, selectedImportance - mStartingUserImportance); mSingleNotificationChannel.setImportance(selectedImportance); @@ -329,12 +327,14 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private void updateSecondaryText() { final boolean disabled = mSingleNotificationChannel != null && getSelectedImportance() == IMPORTANCE_NONE; + final boolean isDefaultChannel = mSingleNotificationChannel != null && + mSingleNotificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID); if (disabled) { mChannelDisabledView.setVisibility(View.VISIBLE); mNumChannelsView.setVisibility(View.GONE); } else { mChannelDisabledView.setVisibility(View.GONE); - mNumChannelsView.setVisibility(View.VISIBLE); + mNumChannelsView.setVisibility(isDefaultChannel ? View.INVISIBLE : View.VISIBLE); } } @@ -384,7 +384,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G @Override public boolean willBeRemoved() { - return !mChannelEnabledSwitch.isChecked(); + return mChannelEnabledSwitch != null && !mChannelEnabledSwitch.isChecked(); } @Override 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 dd997493bb09..4339ade13ce0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -89,7 +89,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons)); Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager); mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area); - mSignalClusterView = reinflateSignalCluster(mStatusBar); + mSignalClusterView = mStatusBar.findViewById(R.id.signal_cluster); Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView); // Default to showing until we know otherwise. showSystemIconArea(false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index c85584e97386..646f3d8b8232 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -23,18 +23,25 @@ import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; import android.view.ViewStub; +import android.view.ViewStub.OnInflateListener; import android.view.WindowInsets; import android.widget.FrameLayout; import com.android.systemui.R; +import com.android.systemui.SysUiServiceProvider; import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.plugins.qs.QS; +import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.statusbar.NotificationData.Entry; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; /** * The container with notification stack scroller and quick settings inside. */ public class NotificationsQuickSettingsContainer extends FrameLayout - implements ViewStub.OnInflateListener, FragmentHostManager.FragmentListener { + implements OnInflateListener, FragmentListener, OnHeadsUpChangedListener { private FrameLayout mQsFrame; private View mUserSwitcher; @@ -46,6 +53,8 @@ public class NotificationsQuickSettingsContainer extends FrameLayout private int mBottomPadding; private int mStackScrollerMargin; + private boolean mHeadsUp; + private HeadsUpManager mHeadsUpManager; public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -67,12 +76,16 @@ public class NotificationsQuickSettingsContainer extends FrameLayout protected void onAttachedToWindow() { super.onAttachedToWindow(); FragmentHostManager.get(this).addTagListener(QS.TAG, this); + mHeadsUpManager = SysUiServiceProvider.getComponent(getContext(), StatusBar.class) + .mHeadsUpManager; + mHeadsUpManager.addListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); FragmentHostManager.get(this).removeTagListener(QS.TAG, this); + mHeadsUpManager.removeListener(this); } @Override @@ -101,7 +114,7 @@ public class NotificationsQuickSettingsContainer extends FrameLayout boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE; boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE; - final boolean qsBottom = mQsExpanded && !mCustomizerAnimating; + final boolean qsBottom = mHeadsUp; View stackQsTop = qsBottom ? mStackScroller : mQsFrame; View stackQsBottom = !qsBottom ? mStackScroller : mQsFrame; // Invert the order of the scroll view and user switcher such that the notifications receive @@ -176,4 +189,14 @@ public class NotificationsQuickSettingsContainer extends FrameLayout params.bottomMargin = bottomMargin; v.setLayoutParams(params); } + + @Override + public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { + boolean hasHeadsUp = mHeadsUpManager.getAllEntries().size() != 0; + if (mHeadsUp == hasHeadsUp) { + return; + } + mHeadsUp = hasHeadsUp; + invalidate(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java index dfa5cbdd3e12..6a573f593a92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java @@ -19,7 +19,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; /** - * For mocking because AccessibilyManager is final for some reason... + * For mocking because AccessibilityManager is final for some reason... */ public class AccessibilityManagerWrapper implements CallbackController<AccessibilityServicesStateChangeListener> { @@ -32,7 +32,7 @@ public class AccessibilityManagerWrapper implements @Override public void addCallback(AccessibilityServicesStateChangeListener listener) { - mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener); + mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener, null); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 96c70c491549..5f7ac5df10f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -170,6 +170,10 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL mListeners.add(listener); } + public void removeListener(OnHeadsUpChangedListener listener) { + mListeners.remove(listener); + } + public StatusBar getBar() { return mBar; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java index 66385a1dfb01..2b14b3128493 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java @@ -314,16 +314,14 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test - public void testBindNotification_NumChannelsTextUniqueWhenDefaultChannel() throws Exception { + public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, null, null, null); final TextView numChannelsView = (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc); - assertEquals(View.VISIBLE, numChannelsView.getVisibility()); - assertEquals(mContext.getString(R.string.notification_default_channel_desc), - numChannelsView.getText()); + assertEquals(View.INVISIBLE, numChannelsView.getVisibility()); } @Test @@ -780,4 +778,9 @@ public class NotificationInfoTest extends SysuiTestCase { enabledSwitch.setChecked(true); assertEquals(View.VISIBLE, settingsLink.getVisibility()); } + + @Test + public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception { + assertFalse(mNotificationInfo.willBeRemoved()); + } } diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index 7eefb7e667c3..debb1578451a 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -238,6 +238,9 @@ message WifiLog { // Histogram of the delta between scan result RSSI and RSSI polls repeated RssiPollCount rssi_poll_delta_count = 51; + + // List of events + repeated StaEvent sta_event_list = 52; } // Information that gets logged for every WiFi connection. @@ -460,3 +463,202 @@ message SoftApReturnCodeCount { // Result of attempt to start SoftAp optional SoftApStartResult start_result = 3; } + +message StaEvent { + message ConfigInfo { + // The set of key management protocols supported by this configuration. + optional uint32 allowed_key_management = 1 [default = 0]; + + // The set of security protocols supported by this configuration. + optional uint32 allowed_protocols = 2 [default = 0]; + + // The set of authentication protocols supported by this configuration. + optional uint32 allowed_auth_algorithms = 3 [default = 0]; + + // The set of pairwise ciphers for WPA supported by this configuration. + optional uint32 allowed_pairwise_ciphers = 4 [default = 0]; + + // The set of group ciphers supported by this configuration. + optional uint32 allowed_group_ciphers = 5; + + // Is this a 'hidden network' + optional bool hidden_ssid = 6; + + // Is this a Hotspot 2.0 / passpoint network + optional bool is_passpoint = 7; + + // Is this an 'ephemeral' network (Not in saved network list, recommended externally) + optional bool is_ephemeral = 8; + + // Has a successful connection ever been established using this WifiConfiguration + optional bool has_ever_connected = 9; + + // RSSI of the scan result candidate associated with this WifiConfiguration + optional int32 scan_rssi = 10 [default = -127]; + + // Frequency of the scan result candidate associated with this WifiConfiguration + optional int32 scan_freq = 11 [default = -1]; + } + + enum EventType { + // Default/Invalid event + TYPE_UNKNOWN = 0; + + // Supplicant Association Rejection event. Code contains the 802.11 + TYPE_ASSOCIATION_REJECTION_EVENT = 1; + + // Supplicant L2 event, + TYPE_AUTHENTICATION_FAILURE_EVENT = 2; + + // Supplicant L2 event + TYPE_NETWORK_CONNECTION_EVENT = 3; + + // Supplicant L2 event + TYPE_NETWORK_DISCONNECTION_EVENT = 4; + + // Supplicant L2 event + TYPE_SUPPLICANT_STATE_CHANGE_EVENT = 5; + + // Supplicant L2 event + TYPE_CMD_ASSOCIATED_BSSID = 6; + + // IP Manager successfully completed IP Provisioning + TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL = 7; + + // IP Manager failed to complete IP Provisioning + TYPE_CMD_IP_CONFIGURATION_LOST = 8; + + // IP Manager lost reachability to network neighbors + TYPE_CMD_IP_REACHABILITY_LOST = 9; + + // Indicator that Supplicant is targeting a BSSID for roam/connection + TYPE_CMD_TARGET_BSSID = 10; + + // Wifi framework is initiating a connection attempt + TYPE_CMD_START_CONNECT = 11; + + // Wifi framework is initiating a roaming connection attempt + TYPE_CMD_START_ROAM = 12; + + // SystemAPI connect() command, Settings App + TYPE_CONNECT_NETWORK = 13; + + // Network Agent has validated the internet connection (Captive Portal Check success, or user + // validation) + TYPE_NETWORK_AGENT_VALID_NETWORK = 14; + + // Framework initiated disconnect. Sometimes generated to give an extra reason for a disconnect + // Should typically be followed by a NETWORK_DISCONNECTION_EVENT with a local_gen = true + TYPE_FRAMEWORK_DISCONNECT = 15; + } + + enum FrameworkDisconnectReason { + // default/none/unknown value + DISCONNECT_UNKNOWN = 0; + + // API DISCONNECT + DISCONNECT_API = 1; + + // Some framework internal reason (generic) + DISCONNECT_GENERIC = 2; + + // Network Agent network validation failed, user signaled network unwanted + DISCONNECT_UNWANTED = 3; + + // Roaming timed out + DISCONNECT_ROAM_WATCHDOG_TIMER = 4; + + // P2P service requested wifi disconnect + DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST = 5; + + // SIM was removed while using a SIM config + DISCONNECT_RESET_SIM_NETWORKS = 6; + } + + // Authentication Failure reasons as reported through the API. + enum AuthFailureReason { + // Unknown default + AUTH_FAILURE_UNKNOWN = 0; + + // The reason code if there is no error during authentication. It could also imply that there no + // authentication in progress, + AUTH_FAILURE_NONE = 1; + + // The reason code if there was a timeout authenticating. + AUTH_FAILURE_TIMEOUT = 2; + + // The reason code if there was a wrong password while authenticating. + AUTH_FAILURE_WRONG_PSWD = 3; + + // The reason code if there was EAP failure while authenticating. + AUTH_FAILURE_EAP_FAILURE = 4; + } + + // What event was this + optional EventType type = 1; + + // 80211 death reason code, relevant to NETWORK_DISCONNECTION_EVENTs + optional int32 reason = 2 [default = -1]; + + // 80211 Association Status code, relevant to ASSOCIATION_REJECTION_EVENTs + optional int32 status = 3 [default = -1]; + + // Designates whether a NETWORK_DISCONNECT_EVENT was by the STA or AP + optional bool local_gen = 4 [default = false]; + + // Network information from the WifiConfiguration of a framework initiated connection attempt + optional ConfigInfo config_info = 5; + + // RSSI from the last rssi poll (Only valid for active connections) + optional int32 last_rssi = 6 [default = -127]; + + // Link speed from the last rssi poll (Only valid for active connections) + optional int32 last_link_speed = 7 [default = -1]; + + // Frequency from the last rssi poll (Only valid for active connections) + optional int32 last_freq = 8 [default = -1]; + + // Enum used to define bit positions in the supplicant_state_change_bitmask + // See {@code frameworks/base/wifi/java/android/net/wifi/SupplicantState.java} for documentation + enum SupplicantState { + STATE_DISCONNECTED = 0; + + STATE_INTERFACE_DISABLED = 1; + + STATE_INACTIVE = 2; + + STATE_SCANNING = 3; + + STATE_AUTHENTICATING = 4; + + STATE_ASSOCIATING = 5; + + STATE_ASSOCIATED = 6; + + STATE_FOUR_WAY_HANDSHAKE = 7; + + STATE_GROUP_HANDSHAKE = 8; + + STATE_COMPLETED = 9; + + STATE_DORMANT = 10; + + STATE_UNINITIALIZED = 11; + + STATE_INVALID = 12; + } + + // Bit mask of all supplicant state changes that occured since the last event + optional uint32 supplicant_state_changes_bitmask = 9 [default = 0]; + + // The number of milliseconds that have elapsed since the device booted + optional int64 start_time_millis = 10 [default = 0]; + + optional FrameworkDisconnectReason framework_disconnect_reason = 11 [default = DISCONNECT_UNKNOWN]; + + // Flag which indicates if an association rejection event occured due to a timeout + optional bool association_timed_out = 12 [default = false]; + + // Authentication failure reason, as reported by WifiManager (calculated from state & deauth code) + optional AuthFailureReason auth_failure_reason = 13 [default = AUTH_FAILURE_UNKNOWN]; +} diff --git a/rs/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java index 7a702e877a2e..a36873e34d8c 100644 --- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java +++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java @@ -59,6 +59,9 @@ public final class ScriptIntrinsicBlur extends ScriptIntrinsic { * @param ain The input allocation */ public void setInput(Allocation ain) { + if (ain.getType().getY() == 0) { + throw new RSIllegalArgumentException("Input set to a 1D Allocation"); + } mInput = ain; setVar(1, ain); } @@ -85,6 +88,9 @@ public final class ScriptIntrinsicBlur extends ScriptIntrinsic { * type. */ public void forEach(Allocation aout) { + if (aout.getType().getY() == 0) { + throw new RSIllegalArgumentException("Output is a 1D Allocation"); + } forEach(0, (Allocation) null, aout, null); } @@ -97,6 +103,9 @@ public final class ScriptIntrinsicBlur extends ScriptIntrinsic { * @param opt LaunchOptions for clipping */ public void forEach(Allocation aout, Script.LaunchOptions opt) { + if (aout.getType().getY() == 0) { + throw new RSIllegalArgumentException("Output is a 1D Allocation"); + } forEach(0, (Allocation) null, aout, null, opt); } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 1b5b2c65e5b2..88adbf420957 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -73,6 +73,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Entry point service for autofill management. @@ -81,7 +82,6 @@ import java.util.List; * {@link AutofillManagerServiceImpl} per user; the real work is done by * {@link AutofillManagerServiceImpl} itself. */ -// TODO(b/33197203): Handle removing of packages public final class AutofillManagerService extends SystemService { private static final String TAG = "AutofillManagerService"; @@ -109,10 +109,8 @@ public final class AutofillManagerService extends SystemService { @GuardedBy("mLock") private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray(); - // TODO(b/33197203): set a different max (or disable it) on low-memory devices. private final LocalLog mRequestsHistory = new LocalLog(20); - // TODO(b/33197203): is this still needed? private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -376,7 +374,6 @@ public final class AutofillManagerService extends SystemService { public int startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback, AutofillId autofillId, Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags, String packageName) { - // TODO(b/33197203): make sure it's called by resumed / focused activity activityToken = Preconditions.checkNotNull(activityToken, "activityToken"); appCallback = Preconditions.checkNotNull(appCallback, "appCallback"); @@ -487,6 +484,22 @@ public final class AutofillManagerService extends SystemService { } @Override + public boolean isServiceSupported(int userId) { + synchronized (mLock) { + return !mDisabledUsers.get(userId); + } + } + + @Override + public boolean isServiceEnabled(int userId, String packageName) { + synchronized (mLock) { + final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); + if (service == null) return false; + return Objects.equals(packageName, service.getPackageName()); + } + } + + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 85fc5800dad7..238cdd5efd5f 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -16,9 +16,6 @@ package com.android.server.autofill; -import static android.service.autofill.AutofillService.EXTRA_SESSION_ID; -import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS; -import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE; import static android.view.autofill.AutofillManager.FLAG_START_SESSION; import static android.view.autofill.AutofillManager.NO_SESSION; @@ -27,10 +24,7 @@ import static com.android.server.autofill.Helper.VERBOSE; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.Activity; -import android.app.ActivityManager; import android.app.AppGlobals; -import android.app.assist.AssistStructure; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -50,7 +44,6 @@ import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; import android.service.autofill.FillEventHistory; import android.service.autofill.FillEventHistory.Event; -import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; @@ -66,7 +59,6 @@ import android.view.autofill.IAutoFillManagerClient; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.HandlerCaller; -import com.android.internal.os.IResultReceiver; import com.android.server.autofill.ui.AutoFillUI; import java.io.PrintWriter; @@ -120,8 +112,6 @@ final class AutofillManagerServiceImpl { * <p>They're kept until the {@link AutofillService} finished handling a request, an error * occurs, or the session times out. */ - // TODO(b/33197203): need to make sure service is bound while callback is pending and/or - // use WeakReference @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); @@ -129,59 +119,6 @@ final class AutofillManagerServiceImpl { @GuardedBy("mLock") private FillEventHistory mEventHistory; - /** - * Receiver of assist data from the app's {@link Activity}. - */ - private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { - @Override - public void send(int resultCode, Bundle resultData) throws RemoteException { - if (VERBOSE) { - Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode); - } - - final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE); - if (structure == null) { - Slog.wtf(TAG, "no assist structure for id " + resultCode); - return; - } - - final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS); - if (receiverExtras == null) { - Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver"); - return; - } - - final int sessionId = receiverExtras.getInt(EXTRA_SESSION_ID); - final Session session; - synchronized (mLock) { - session = mSessions.get(sessionId); - if (session == null) { - Slog.w(TAG, "no server session for " + sessionId); - return; - } - // TODO(b/33197203): since service is fetching the data (to use for save later), - // we should optimize what's sent (for example, remove layout containers, - // color / font info, etc...) - session.setStructureLocked(structure); - } - - - // TODO(b/33197203, b/33269702): Must fetch the data so it's available later on - // handleSave(), even if if the activity is gone by then, but structure.ensureData() - // gives a ONE_WAY warning because system_service could block on app calls. - // We need to change AssistStructure so it provides a "one-way" writeToParcel() - // method that sends all the data - structure.ensureData(); - - // Sanitize structure before it's sent to service. - structure.sanitizeForParceling(true); - - // TODO(b/33197203): Need to pipe the bundle - FillRequest request = new FillRequest(structure, null, session.mFlags); - session.mRemoteFillService.onFillRequest(request); - } - }; - AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory, int userId, AutoFillUI ui, boolean disabled) { mContext = context; @@ -193,11 +130,10 @@ final class AutofillManagerServiceImpl { } CharSequence getServiceName() { - if (mInfo == null) { + final String packageName = getPackageName(); + if (packageName == null) { return null; } - final ComponentName serviceComponent = mInfo.getServiceInfo().getComponentName(); - final String packageName = serviceComponent.getPackageName(); try { final PackageManager pm = mContext.getPackageManager(); @@ -209,6 +145,14 @@ final class AutofillManagerServiceImpl { } } + String getPackageName() { + if (mInfo == null) { + return null; + } + final ComponentName serviceComponent = mInfo.getServiceInfo().getComponentName(); + return serviceComponent.getPackageName(); + } + private String getComponentNameFromSettings() { return Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, mUserId); @@ -398,28 +342,6 @@ final class AutofillManagerServiceImpl { mInfo.getServiceInfo().getComponentName(), packageName); mSessions.put(newSession.id, newSession); - /* - * TODO(b/33197203): apply security checks below: - * - checks if disabled by secure settings / device policy - * - log operation using noteOp() - * - check flags - * - display disclosure if needed - */ - try { - final Bundle receiverExtras = new Bundle(); - receiverExtras.putInt(EXTRA_SESSION_ID, sessionId); - final long identity = Binder.clearCallingIdentity(); - try { - if (!ActivityManager.getService().requestAutofillData(mAssistReceiver, - receiverExtras, activityToken)) { - Slog.w(TAG, "failed to request autofill data for " + activityToken); - } - } finally { - Binder.restoreCallingIdentity(identity); - } - } catch (RemoteException e) { - // Should not happen, it's a local call. - } return newSession; } diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index 70e97c4a5cb2..5964172e138a 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -16,7 +16,12 @@ package com.android.server.autofill; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.assist.AssistStructure; +import android.app.assist.AssistStructure.ViewNode; import android.os.Bundle; +import android.view.autofill.AutofillId; import java.util.Arrays; import java.util.Objects; @@ -24,7 +29,8 @@ import java.util.Set; final class Helper { - static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable + // TODO(b/36141126): set to false and remove guard from places that should always be on + static final boolean DEBUG = true; static final boolean VERBOSE = false; static void append(StringBuilder builder, Bundle bundle) { @@ -52,4 +58,37 @@ final class Helper { private Helper() { throw new UnsupportedOperationException("contains static members only"); } + + static ViewNode findViewNodeById(@NonNull AssistStructure structure, @NonNull AutofillId id) { + final int size = structure.getWindowNodeCount(); + for (int i = 0; i < size; i++) { + final AssistStructure.WindowNode window = structure.getWindowNodeAt(i); + final ViewNode root = window.getRootViewNode(); + if (id.equals(root.getAutofillId())) { + return root; + } + final ViewNode child = findViewNodeById(root, id); + if (child != null) { + return child; + } + } + return null; + } + + static ViewNode findViewNodeById(@NonNull ViewNode parent, @NonNull AutofillId id) { + final int childrenSize = parent.getChildCount(); + if (childrenSize > 0) { + for (int i = 0; i < childrenSize; i++) { + final ViewNode child = parent.getChildAt(i); + if (id.equals(child.getAutofillId())) { + return child; + } + final ViewNode grandChild = findViewNodeById(child, id); + if (grandChild != null && id.equals(grandChild.getAutofillId())) { + return grandChild; + } + } + } + return null; + } } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 4d0f38042276..432a092a9874 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -134,6 +134,23 @@ final class RemoteFillService implements DeathRecipient { mCallbacks.onServiceDied(this); } + /** + * Cancel the currently pending request. + * + * <p>This can be used when the request is unnecessary or will be superceeded by a request that + * will soon be queued. + */ + public void cancelCurrentRequest() { + if (mDestroyed) { + return; + } + + if (mPendingRequest != null) { + mPendingRequest.cancel(); + mPendingRequest = null; + } + } + public void onFillRequest(@NonNull FillRequest request) { cancelScheduledUnbind(); final PendingFillRequest pendingRequest = new PendingFillRequest(request, this); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 4bc3872f4ff0..a00a397ece08 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -18,6 +18,8 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; +import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS; +import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE; import static android.view.autofill.AutofillManager.FLAG_START_SESSION; import static android.view.autofill.AutofillManager.FLAG_VALUE_CHANGED; import static android.view.autofill.AutofillManager.FLAG_VIEW_ENTERED; @@ -25,19 +27,22 @@ import static android.view.autofill.AutofillManager.FLAG_VIEW_EXITED; import static com.android.server.autofill.Helper.DEBUG; import static com.android.server.autofill.Helper.VERBOSE; +import static com.android.server.autofill.Helper.findViewNodeById; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.Activity; +import android.app.ActivityManager; import android.app.assist.AssistStructure; import android.app.assist.AssistStructure.AutofillOverlay; import android.app.assist.AssistStructure.ViewNode; -import android.app.assist.AssistStructure.WindowNode; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.graphics.Rect; import android.metrics.LogMaker; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; @@ -64,14 +69,16 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.HandlerCaller; +import com.android.internal.os.IResultReceiver; +import com.android.internal.util.ArrayUtils; import com.android.server.autofill.ui.AutoFillUI; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; /** * A session for a given activity. @@ -85,14 +92,12 @@ import java.util.Map.Entry; * to fill the activity but it requires authentication first, that response need to be held * until the user authenticates or it times out. */ -// TODO(b/33197203): make sure sessions are removed (and tested by CTS): -// - On all authentication scenarios. -// - When user does not interact back after a while. -// - When service is unbound. final class Session implements RemoteFillService.FillServiceCallbacks, ViewState.Listener, AutoFillUI.AutoFillUiCallback { private static final String TAG = "AutofillSession"; + private static final String EXTRA_REQUEST_ID = "android.service.autofill.extra.REQUEST_ID"; + private final AutofillManagerServiceImpl mService; private final HandlerCaller mHandlerCaller; private final Object mLock; @@ -100,6 +105,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private final MetricsLogger mMetricsLogger = new MetricsLogger(); + private static AtomicInteger sIdCounter = new AtomicInteger(); + /** Id of the session */ public final int id; @@ -127,8 +134,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private IAutoFillManagerClient mClient; - @GuardedBy("mLock") - RemoteFillService mRemoteFillService; + private final RemoteFillService mRemoteFillService; @GuardedBy("mLock") private SparseArray<FillResponse> mResponses; @@ -167,7 +173,124 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * Flags used to start the session. */ - int mFlags; + private final int mFlags; + + /** + * Receiver of assist data from the app's {@link Activity}. + */ + private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { + @Override + public void send(int resultCode, Bundle resultData) throws RemoteException { + if (VERBOSE) { + Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode); + } + + final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE); + if (structure == null) { + Slog.wtf(TAG, "no assist structure for id " + resultCode); + return; + } + + final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS); + if (receiverExtras == null) { + Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver"); + return; + } + + final int requestId = receiverExtras.getInt(EXTRA_REQUEST_ID); + + if (DEBUG) { + Slog.d(TAG, "New structure for requestId " + requestId + ": " + structure); + } + + synchronized (mLock) { + // TODO(b/35708678): Must fetch the data so it's available later on handleSave(), + // even if if the activity is gone by then, but structure .ensureData() gives a + // ONE_WAY warning because system_service could block on app calls. We need to + // change AssistStructure so it provides a "one-way" writeToParcel() method that + // sends all the data + structure.ensureData(); + + // Sanitize structure before it's sent to service. + structure.sanitizeForParceling(true); + + mStructure = structure; + } + + fillStructureWithAllowedValues(mStructure); + + FillRequest request = new FillRequest(requestId, mStructure, mClientState, mFlags); + mRemoteFillService.onFillRequest(request); + } + }; + + /** + * Updates values of the nodes in the structure so that: + * - proper node is focused + * - autofillValue is sent back to service when it was previously autofilled + * + * @param structure The structure to be filled + */ + private void fillStructureWithAllowedValues(@NonNull AssistStructure structure) { + final int numViewStates = mViewStates.size(); + for (int i = 0; i < numViewStates; i++) { + final ViewState viewState = mViewStates.valueAt(i); + + final ViewNode node = findViewNodeById(structure, viewState.id); + if (node == null) { + if (DEBUG) { + Slog.w(TAG, "fillStructureWithAllowedValues(): no node for " + viewState.id); + } + continue; + } + + final AutofillValue initialValue = viewState.getInitialValue(); + final AutofillValue filledValue = viewState.getAutofilledValue(); + final AutofillOverlay overlay = new AutofillOverlay(); + if (filledValue != null && !filledValue.equals(initialValue)) { + overlay.value = filledValue; + } + if (mCurrentViewId != null) { + overlay.focused = mCurrentViewId.equals(viewState.id); + } + + node.setAutofillOverlay(overlay); + } + } + + /** + * Reads a new structure and then request a new fill response from the fill service. + */ + private void requestNewFillResponseLocked() { + final int requestId = sIdCounter.getAndIncrement(); + + if (DEBUG) { + Slog.d(TAG, "Requesting structure for requestId " + requestId); + } + + // If the focus changes very quickly before the first request is returned each focus change + // triggers a new partition and we end up with many duplicate partitions. This is + // enhanced as the focus change can be much faster than the taking of the assist structure. + // Hence remove the currently queued request and replace it with the one queued after the + // structure is taken. This causes only one fill request per bust of focus changes. + mRemoteFillService.cancelCurrentRequest(); + + try { + final Bundle receiverExtras = new Bundle(); + receiverExtras.putInt(EXTRA_REQUEST_ID, requestId); + final long identity = Binder.clearCallingIdentity(); + try { + if (!ActivityManager.getService().requestAutofillData(mAssistReceiver, + receiverExtras, mActivityToken)) { + Slog.w(TAG, "failed to request autofill data for " + mActivityToken); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } catch (RemoteException e) { + // Should not happen, it's a local call. + } + } Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui, @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId, @@ -251,7 +374,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } synchronized (mLock) { if (response.getAuthentication() != null) { - // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already + // TODO(b/37424539): proper implementation mResponseWaitingAuth = response; } processResponseLocked(response, requestId); @@ -326,7 +449,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void onServiceDied(RemoteFillService service) { - // TODO(b/33197203): implement + // TODO(b/337565347): implement } // AutoFillUiCallback @@ -437,10 +560,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mHasCallback = hasIt; } - public void setStructureLocked(AssistStructure structure) { - mStructure = structure; - } - /** * Shows the save UI, when session can be saved. * @@ -579,7 +698,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState continue; } final AutofillId id = entry.getKey(); - final ViewNode node = findViewNodeByIdLocked(id); + final ViewNode node = findViewNodeById(mStructure, id); if (node == null) { Slog.w(TAG, "callSaveLocked(): did not find node with id " + id); continue; @@ -599,7 +718,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mStructure.dump(); } - // TODO(b/33197203): Implement partitioning properly + // TODO(b/37426206): Implement partitioning properly final int lastResponseIdx = getLastResponseIndex(); final int requestId = mResponses.keyAt(lastResponseIdx); final FillContext fillContext = new FillContext(requestId, mStructure); @@ -610,24 +729,61 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mRemoteFillService.onSaveRequest(saveRequest); } + /** + * Determines if a new partition should be started for an id. + * + * @param id The id of the view that is entered + * + * @return {@code true} iff a new partition should be started + */ + private boolean shouldStartNewPartitionLocked(@NonNull AutofillId id) { + if (mResponses == null) { + return true; + } + + final int numResponses = mResponses.size(); + for (int responseNum = 0; responseNum < numResponses; responseNum++) { + final FillResponse response = mResponses.valueAt(responseNum); + + if (ArrayUtils.contains(response.getIgnoredIds(), id)) { + return false; + } + + final SaveInfo saveInfo = response.getSaveInfo(); + if (saveInfo != null) { + if (ArrayUtils.contains(saveInfo.getOptionalIds(), id) + || ArrayUtils.contains(saveInfo.getRequiredIds(), id)) { + return false; + } + } + + final ArrayList<Dataset> datasets = response.getDatasets(); + if (datasets != null) { + final int numDatasets = datasets.size(); + + for (int dataSetNum = 0; dataSetNum < numDatasets; dataSetNum++) { + final ArrayList fields = datasets.get(dataSetNum).getFieldIds(); + + if (fields != null && fields.contains(id)) { + return false; + } + } + } + } + + return true; + } + void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) { ViewState viewState = mViewStates.get(id); if (viewState == null) { - if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED)) != 0) { + if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED | FLAG_VIEW_ENTERED)) != 0) { if (DEBUG) { Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags)); } viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL); mViewStates.put(id, viewState); - } else if (mStructure != null && (flags & FLAG_VIEW_ENTERED) != 0) { - if (isIgnoredLocked(id)) { - if (DEBUG) { - Slog.d(TAG, "Not starting partition for ignored view id " + id); - } - return; - } - viewState = startPartitionLocked(id, value); } else { if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id); return; @@ -639,6 +795,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mCurrentViewId = viewState.id; viewState.update(value, virtualBounds); viewState.setState(ViewState.STATE_STARTED_SESSION); + requestNewFillResponseLocked(); return; } @@ -668,6 +825,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if ((flags & FLAG_VIEW_ENTERED) != 0) { + if (shouldStartNewPartitionLocked(id)) { + // TODO(b/37424539): proper implementation + if (mResponseWaitingAuth != null && ((flags & FLAG_START_SESSION) == 0)) { + viewState.setState(ViewState.STATE_WAITING_RESPONSE_AUTH); + } else if ((flags & FLAG_START_SESSION) == 0){ + if (DEBUG) { + Slog.d(TAG, "Starting partition for view id " + viewState.id); + } + viewState.setState(ViewState.STATE_STARTED_PARTITION); + requestNewFillResponseLocked(); + } + } + // Remove the UI if the ViewState has changed. if (mCurrentViewId != viewState.id) { mUi.hideFillUi(mCurrentViewId != null ? mCurrentViewId : null); @@ -691,49 +861,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags)); } - private ViewState startPartitionLocked(AutofillId id, AutofillValue value) { - // TODO(b/33197203 , b/35707731): temporary workaround until partitioning supports auth - if (mResponseWaitingAuth != null) { - final ViewState viewState = - new ViewState(this, id, value, this, ViewState.STATE_WAITING_RESPONSE_AUTH); - mViewStates.put(id, viewState); - return viewState; - } - if (DEBUG) { - Slog.d(TAG, "Starting partition for view id " + id); - } - final ViewState newViewState = - new ViewState(this, id, value, this,ViewState.STATE_STARTED_PARTITION); - mViewStates.put(id, newViewState); - - // Must update value of nodes so: - // - proper node is focused - // - autofillValue is sent back to service when it was previously autofilled - for (int i = 0; i < mViewStates.size(); i++) { - final ViewState viewState = mViewStates.valueAt(i); - - final ViewNode node = findViewNodeByIdLocked(viewState.id); - if (node == null) { - Slog.w(TAG, "startPartitionLocked(): no node for " + viewState.id); - continue; - } - - final AutofillValue initialValue = viewState.getInitialValue(); - final AutofillValue filledValue = viewState.getAutofilledValue(); - final AutofillOverlay overlay = new AutofillOverlay(); - if (filledValue != null && !filledValue.equals(initialValue)) { - overlay.value = filledValue; - } - overlay.focused = id.equals(viewState.id); - node.setAutofillOverlay(overlay); - } - - FillRequest request = new FillRequest(mStructure, mClientState, 0); - mRemoteFillService.onFillRequest(request); - - return newViewState; - } - @Override public void onFillReady(FillResponse response, AutofillId filledId, @Nullable AutofillValue value) { @@ -751,11 +878,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void notifyUnavailableToClient() { synchronized (mLock) { - if (mCurrentViewId == null) { - // TODO(b/33197203): temporary sanity check; should never happen - Slog.w(TAG, "notifyUnavailable(): mCurrentViewId is null"); - return; - } if (!mHasCallback) return; try { mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId); @@ -922,7 +1044,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } // ...or handle authentication. - // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already + // TODO(b/37424539): proper implementation mService.setDatasetAuthenticationSelected(dataset.getId()); mDatasetWaitingAuth = dataset; setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH); @@ -958,23 +1080,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private boolean isIgnoredLocked(@NonNull AutofillId id) { - if (mResponses == null) return false; - - for (int i = mResponses.size() - 1; i >= 0; i--) { - final FillResponse response = mResponses.valueAt(i); - final AutofillId[] ignoredIds = response.getIgnoredIds(); - if (ignoredIds == null) continue; - for (int j = 0; j < ignoredIds.length; j++) { - final AutofillId ignoredId = ignoredIds[j]; - if (ignoredId != null && ignoredId.equals(id)) { - return true; - } - } - } - return false; - } - void dumpLocked(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("id: "); pw.println(id); pw.print(prefix); pw.print("uid: "); pw.println(uid); @@ -992,7 +1097,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (VERBOSE) { pw.print(prefix); pw.print("mStructure: " ); - // TODO(b/33197203): add method do dump AssistStructure on pw + // TODO: add method on AssistStructure to dump on pw if (mStructure != null) { pw.println("look at logcat" ); mStructure.dump(); // dumps to logcat @@ -1027,39 +1132,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private ViewNode findViewNodeByIdLocked(AutofillId id) { - final int size = mStructure.getWindowNodeCount(); - for (int i = 0; i < size; i++) { - final WindowNode window = mStructure.getWindowNodeAt(i); - final ViewNode root = window.getRootViewNode(); - if (id.equals(root.getAutofillId())) { - return root; - } - final ViewNode child = findViewNodeByIdLocked(root, id); - if (child != null) { - return child; - } - } - return null; - } - - private ViewNode findViewNodeByIdLocked(ViewNode parent, AutofillId id) { - final int childrenSize = parent.getChildCount(); - if (childrenSize > 0) { - for (int i = 0; i < childrenSize; i++) { - final ViewNode child = parent.getChildAt(i); - if (id.equals(child.getAutofillId())) { - return child; - } - final ViewNode grandChild = findViewNodeByIdLocked(child, id); - if (grandChild != null && id.equals(grandChild.getAutofillId())) { - return grandChild; - } - } - } - return null; - } - void destroyLocked() { mRemoteFillService.destroy(); mUi.setCallback(null); diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java index ea5f1137568c..3967f59355c4 100644 --- a/services/autofill/java/com/android/server/autofill/ViewState.java +++ b/services/autofill/java/com/android/server/autofill/ViewState.java @@ -61,7 +61,7 @@ final class ViewState { public static final int STATE_STARTED_PARTITION = 0x20; /** User select a dataset in this view, but service must authenticate first. */ public static final int STATE_WAITING_DATASET_AUTH = 0x40; - // TODO(b/33197203 , b/35707731): temporary workaround until partitioning supports auth + // TODO(b/37424539): temporary workaround until partitioning supports auth public static final int STATE_WAITING_RESPONSE_AUTH = 0x80; public final AutofillId id; @@ -151,9 +151,9 @@ final class ViewState { mState &= ~state; } - // TODO(b/33197203): need to refactor / rename / document this method to make it clear that - // it can change the value and update the UI; similarly, should replace code that - // directly sets mAutoFilLValue to use encapsulation. + // TODO: refactor / rename / document this method (and maybeCallOnFillReady) to make it clear + // that it can change the value and update the UI; similarly, should replace code that + // directly sets mAutofillValue to use encapsulation. void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds) { if (autofillValue != null) { mCurrentValue = autofillValue; diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java index b68e3b1e2543..bb47e5b54863 100644 --- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java @@ -117,7 +117,7 @@ final class FillUi { final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); content.measure(widthMeasureSpec, heightMeasureSpec); decor.setOnClickListener(v -> mCallback.onResponsePicked(response)); - // TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width + // TODO(b/37567439): temporary limiting maximum height and minimum width mContentWidth = Math.max(content.getMeasuredWidth(), 1000); mContentHeight = Math.min(content.getMeasuredHeight(), 500); diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 913320d7d80f..9bba1ad810a8 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -185,7 +185,9 @@ final class SaveUi { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); window.setGravity(Gravity.BOTTOM | Gravity.CENTER); window.setCloseOnTouchOutside(true); - window.getAttributes().width = WindowManager.LayoutParams.MATCH_PARENT; + final WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title); mDialog.show(); } diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index aa5083dfeb15..930100627c2b 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -2625,8 +2625,12 @@ public class BackupManagerService { // Can't delete op from mCurrentOperations here. waitUntilOperationComplete may be // called after we receive cancel here. We need this op's state there. - // Remove all pending timeout messages for this operation type. - mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); + // Remove all pending timeout messages of types OP_TYPE_BACKUP_WAIT and + // OP_TYPE_RESTORE_WAIT. On the other hand, OP_TYPE_BACKUP cannot time out and + // doesn't require cancellation. + if (op.type == OP_TYPE_BACKUP_WAIT || op.type == OP_TYPE_RESTORE_WAIT) { + mBackupHandler.removeMessages(getMessageIdForOperationType(op.type)); + } } mCurrentOpLock.notifyAll(); } @@ -9187,6 +9191,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // state RESTORE_FINISHED : provide the "no more data" signpost callback at the end private void restoreFinished() { + if (DEBUG) { + Slog.d(TAG, "restoreFinished packageName=" + mCurrentPackage.packageName); + } try { prepareOperationTimeout(mEphemeralOpToken, TIMEOUT_RESTORE_FINISHED_INTERVAL, this, OP_TYPE_RESTORE_WAIT); diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 41b70a1312e8..9bb0f867f20a 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -36,6 +36,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.pm.FeatureInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.NetworkPolicyManager; @@ -203,13 +204,15 @@ public class CompanionDeviceManagerService extends SystemService implements Bind checkNotNull(request, "Request cannot be null"); checkNotNull(callback, "Callback cannot be null"); checkCallerIsSystemOr(callingPackage); + int userId = getCallingUserId(); + checkUsesFeature(callingPackage, userId); final long callingIdentity = Binder.clearCallingIdentity(); try { - //TODO bindServiceAsUser - getContext().bindService( + getContext().bindServiceAsUser( new Intent().setComponent(SERVICE_TO_BIND_TO), createServiceConnection(request, callback, callingPackage), - Context.BIND_AUTO_CREATE); + Context.BIND_AUTO_CREATE, + UserHandle.of(userId)); } finally { Binder.restoreCallingIdentity(callingIdentity); } @@ -219,6 +222,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind public List<String> getAssociations(String callingPackage, int userId) throws RemoteException { checkCallerIsSystemOr(callingPackage, userId); + checkUsesFeature(callingPackage, getCallingUserId()); return CollectionUtils.map( readAllAssociations(userId, callingPackage), a -> a.deviceAddress); @@ -230,6 +234,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind throws RemoteException { checkNotNull(deviceMacAddress); checkCallerIsSystemOr(callingPackage); + checkUsesFeature(callingPackage, getCallingUserId()); updateAssociations(associations -> CollectionUtils.remove(associations, new Association(getCallingUserId(), deviceMacAddress, callingPackage))); } @@ -282,11 +287,24 @@ public class CompanionDeviceManagerService extends SystemService implements Bind private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { checkCallerIsSystemOr(callingPackage); - checkState(!ArrayUtils.isEmpty(readAllAssociations(getCallingUserId(), callingPackage)), + int userId = getCallingUserId(); + checkState(!ArrayUtils.isEmpty(readAllAssociations(userId, callingPackage)), "App must have an association before calling this API"); + checkUsesFeature(callingPackage, userId); } - } + private void checkUsesFeature(String pkg, int userId) { + FeatureInfo[] reqFeatures = getPackageInfo(pkg, userId).reqFeatures; + String requiredFeature = PackageManager.FEATURE_COMPANION_DEVICE_SETUP; + int numFeatures = ArrayUtils.size(reqFeatures); + for (int i = 0; i < numFeatures; i++) { + if (requiredFeature.equals(reqFeatures[i].name)) return; + } + throw new IllegalStateException("Must declare uses-feature " + + requiredFeature + + " in manifest to use this API"); + } + } private int getCallingUserId() { return UserHandle.getUserId(Binder.getCallingUid()); @@ -398,7 +416,9 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return Binder.withCleanCallingIdentity(() -> { try { return getContext().getPackageManager().getPackageInfoAsUser( - packageName, PackageManager.GET_PERMISSIONS, userId); + packageName, + PackageManager.GET_PERMISSIONS | PackageManager.GET_CONFIGURATIONS, + userId); } catch (PackageManager.NameNotFoundException e) { Slog.e(LOG_TAG, "Failed to get PackageInfo for package " + packageName, e); return null; diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index d25b3cc68221..114d7619a024 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -16,9 +16,6 @@ package com.android.server; -import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; -import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE; - import android.Manifest.permission; import android.annotation.Nullable; import android.content.BroadcastReceiver; @@ -36,8 +33,6 @@ import android.net.INetworkScoreService; import android.net.NetworkKey; import android.net.NetworkScoreManager; import android.net.NetworkScorerAppData; -import android.net.RecommendationRequest; -import android.net.RecommendationResult; import android.net.ScoredNetwork; import android.net.Uri; import android.net.wifi.ScanResult; @@ -46,24 +41,18 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.os.Binder; import android.os.Build; -import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.Process; -import android.os.RemoteCallback; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.provider.Settings.Global; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; -import android.util.Pair; -import android.util.TimedRemoteCaller; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -80,9 +69,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; @@ -99,7 +85,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { private final Context mContext; private final NetworkScorerAppManager mNetworkScorerAppManager; - private final AtomicReference<RequestRecommendationCaller> mReqRecommendationCallerRef; @GuardedBy("mScoreCaches") private final Map<Integer, RemoteCallbackList<INetworkScoreCache>> mScoreCaches; /** Lock used to update mPackageMonitor when scorer package changes occur. */ @@ -113,7 +98,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { private NetworkScorerPackageMonitor mPackageMonitor; @GuardedBy("mServiceConnectionLock") private ScoringServiceConnection mServiceConnection; - private volatile long mRecommendationRequestTimeoutMs; private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() { @Override @@ -256,9 +240,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { mContext.registerReceiverAsUser( mUserIntentReceiver, UserHandle.SYSTEM, filter, null /* broadcastPermission*/, null /* scheduler */); - mReqRecommendationCallerRef = new AtomicReference<>( - new RequestRecommendationCaller(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS)); - mRecommendationRequestTimeoutMs = TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS; mHandler = new ServiceHandler(looper); mContentObserver = new DispatchingContentObserver(context, mHandler); mServiceConnProducer = serviceConnProducer; @@ -295,10 +276,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { mContentObserver.observe(packageNameUri, ServiceHandler.MSG_RECOMMENDATIONS_PACKAGE_CHANGED); - final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS); - mContentObserver.observe(timeoutUri, - ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED); - final Uri settingUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED); mContentObserver.observe(settingUri, ServiceHandler.MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED); @@ -827,87 +804,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } @Override - public RecommendationResult requestRecommendation(RecommendationRequest request) { - mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); - throwIfCalledOnMainThread(); - final long token = Binder.clearCallingIdentity(); - try { - final INetworkRecommendationProvider provider = getRecommendationProvider(); - if (provider != null) { - try { - final RequestRecommendationCaller caller = mReqRecommendationCallerRef.get(); - return caller.getRecommendationResult(provider, request); - } catch (RemoteException | TimeoutException e) { - Log.w(TAG, "Failed to request a recommendation.", e); - // TODO: 12/15/16 - Keep track of failures. - } - } - - if (DBG) { - Log.d(TAG, "Returning the default network recommendation."); - } - - if (request != null && request.getDefaultWifiConfig() != null) { - return RecommendationResult.createConnectRecommendation( - request.getDefaultWifiConfig()); - } - return RecommendationResult.createDoNotConnectRecommendation(); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** - * Request a recommendation for the best network to connect to - * taking into account the inputs from the {@link RecommendationRequest}. - * - * @param request a {@link RecommendationRequest} instance containing the details of the request - * @param remoteCallback a {@link IRemoteCallback} instance to invoke when the recommendation - * is available. - * @throws SecurityException if the caller is not the system - */ - @Override - public void requestRecommendationAsync(RecommendationRequest request, - RemoteCallback remoteCallback) { - mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); - - final OneTimeCallback oneTimeCallback = new OneTimeCallback(remoteCallback); - final Pair<RecommendationRequest, OneTimeCallback> pair = - Pair.create(request, oneTimeCallback); - final Message timeoutMsg = mHandler.obtainMessage( - ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT, pair); - final INetworkRecommendationProvider provider = getRecommendationProvider(); - final long token = Binder.clearCallingIdentity(); - try { - if (provider != null) { - try { - mHandler.sendMessageDelayed(timeoutMsg, mRecommendationRequestTimeoutMs); - provider.requestRecommendation(request, new IRemoteCallback.Stub() { - @Override - public void sendResult(Bundle data) throws RemoteException { - // Remove the timeout message - mHandler.removeMessages(timeoutMsg.what, pair); - oneTimeCallback.sendResult(data); - } - }, 0 /*sequence*/); - return; - } catch (RemoteException e) { - Log.w(TAG, "Failed to request a recommendation.", e); - // TODO: 12/15/16 - Keep track of failures. - // Remove the timeout message - mHandler.removeMessages(timeoutMsg.what, pair); - // Will fall through and send back the default recommendation. - } - } - } finally { - Binder.restoreCallingIdentity(token); - } - - // Else send back the default recommendation. - sendDefaultRecommendationResponse(request, oneTimeCallback); - } - - @Override public boolean requestScores(NetworkKey[] networks) { mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); final long token = Binder.clearCallingIdentity(); @@ -941,7 +837,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { return; } writer.println("Current scorer: " + currentScorer); - writer.println("RecommendationRequestTimeoutMs: " + mRecommendationRequestTimeoutMs); sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() { @Override @@ -996,12 +891,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } - private void throwIfCalledOnMainThread() { - if (Thread.currentThread() == mContext.getMainLooper().getThread()) { - throw new RuntimeException("Cannot invoke on the main thread"); - } - } - @Nullable private INetworkRecommendationProvider getRecommendationProvider() { synchronized (mServiceConnectionLock) { @@ -1012,19 +901,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { return null; } - @VisibleForTesting - public void refreshRecommendationRequestTimeoutMs() { - final ContentResolver cr = mContext.getContentResolver(); - long timeoutMs = Settings.Global.getLong(cr, - Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, -1L /*default*/); - if (timeoutMs < 0) { - timeoutMs = TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS; - } - if (DBG) Log.d(TAG, "Updating the recommendation request timeout to " + timeoutMs + " ms"); - mRecommendationRequestTimeoutMs = timeoutMs; - mReqRecommendationCallerRef.set(new RequestRecommendationCaller(timeoutMs)); - } - // The class and methods need to be public for Mockito to work. @VisibleForTesting public static class ScoringServiceConnection implements ServiceConnection { @@ -1114,93 +990,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } - /** - * Executes the async requestRecommendation() call with a timeout. - */ - private static final class RequestRecommendationCaller - extends TimedRemoteCaller<RecommendationResult> { - private final IRemoteCallback mCallback; - - RequestRecommendationCaller(long callTimeoutMillis) { - super(callTimeoutMillis); - mCallback = new IRemoteCallback.Stub() { - @Override - public void sendResult(Bundle data) throws RemoteException { - final RecommendationResult result = - data.getParcelable(EXTRA_RECOMMENDATION_RESULT); - final int sequence = data.getInt(EXTRA_SEQUENCE, -1); - if (VERBOSE) Log.v(TAG, "callback received for sequence " + sequence); - onRemoteMethodResult(result, sequence); - } - }; - } - - /** - * Runs the requestRecommendation() call on the given {@link INetworkRecommendationProvider} - * instance. - * - * @param target the {@link INetworkRecommendationProvider} to request a recommendation - * from - * @param request the {@link RecommendationRequest} from the calling client - * @return a {@link RecommendationResult} from the provider - * @throws RemoteException if the call failed - * @throws TimeoutException if the call took longer than the set timeout - */ - RecommendationResult getRecommendationResult(INetworkRecommendationProvider target, - RecommendationRequest request) throws RemoteException, TimeoutException { - final int sequence = onBeforeRemoteCall(); - if (VERBOSE) Log.v(TAG, "getRecommendationResult() seq=" + sequence); - target.requestRecommendation(request, mCallback, sequence); - return getResultTimed(sequence); - } - } - - /** - * A wrapper around {@link RemoteCallback} that guarantees - * {@link RemoteCallback#sendResult(Bundle)} will be invoked at most once. - */ - @VisibleForTesting - public static final class OneTimeCallback { - private final RemoteCallback mRemoteCallback; - private final AtomicBoolean mCallbackRun; - - public OneTimeCallback(RemoteCallback remoteCallback) { - mRemoteCallback = remoteCallback; - mCallbackRun = new AtomicBoolean(false); - } - - public void sendResult(Bundle data) { - if (mCallbackRun.compareAndSet(false, true)) { - mRemoteCallback.sendResult(data); - } - } - } - - private static void sendDefaultRecommendationResponse(RecommendationRequest request, - OneTimeCallback remoteCallback) { - if (DBG) { - Log.d(TAG, "Returning the default network recommendation."); - } - - final RecommendationResult result; - if (request != null && request.getDefaultWifiConfig() != null) { - result = RecommendationResult.createConnectRecommendation( - request.getDefaultWifiConfig()); - } else { - result = RecommendationResult.createDoNotConnectRecommendation(); - } - - final Bundle data = new Bundle(); - data.putParcelable(EXTRA_RECOMMENDATION_RESULT, result); - remoteCallback.sendResult(data); - } - @VisibleForTesting public final class ServiceHandler extends Handler { - public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1; - public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2; - public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3; - public static final int MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED = 4; + public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 1; + public static final int MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED = 2; public ServiceHandler(Looper looper) { super(looper); @@ -1210,26 +1003,11 @@ public class NetworkScoreService extends INetworkScoreService.Stub { public void handleMessage(Message msg) { final int what = msg.what; switch (what) { - case MSG_RECOMMENDATION_REQUEST_TIMEOUT: - if (DBG) { - Log.d(TAG, "Network recommendation request timed out."); - } - final Pair<RecommendationRequest, OneTimeCallback> pair = - (Pair<RecommendationRequest, OneTimeCallback>) msg.obj; - final RecommendationRequest request = pair.first; - final OneTimeCallback remoteCallback = pair.second; - sendDefaultRecommendationResponse(request, remoteCallback); - break; - case MSG_RECOMMENDATIONS_PACKAGE_CHANGED: case MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED: refreshBinding(); break; - case MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED: - refreshRecommendationRequestTimeoutMs(); - break; - default: Log.w(TAG,"Unknown message: " + what); } diff --git a/services/core/java/com/android/server/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/SyntheticPasswordCrypto.java index 12d91c57cdad..71ab2a554071 100644 --- a/services/core/java/com/android/server/SyntheticPasswordCrypto.java +++ b/services/core/java/com/android/server/SyntheticPasswordCrypto.java @@ -139,12 +139,14 @@ public class SyntheticPasswordCrypto { keyStore.load(null); KeyProtection.Builder builder = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE); + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setCriticalToDeviceEncryption(true); if (sid != 0) { builder.setUserAuthenticationRequired(true) .setBoundToSpecificSecureUserId(sid) .setUserAuthenticationValidityDurationSeconds(USER_AUTHENTICATION_VALIDITY); } + keyStore.setEntry(keyAlias, new KeyStore.SecretKeyEntry(secretKey), builder.build()); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index dd4d9065f126..4ce76f4b96fe 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1531,6 +1531,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); } + // Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast. + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + // Send broadcast twice, once for apps that have PRIVILEGED permission and once for those // that have the runtime one mContext.sendBroadcastAsUser(intent, UserHandle.ALL, diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 80f89fc938ad..feb9ce49bf08 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -83,6 +83,7 @@ public class Watchdog extends Thread { "android.hardware.audio@2.0::IDevicesFactory", "android.hardware.bluetooth@1.0::IBluetoothHci", "android.hardware.camera.provider@2.4::ICameraProvider", + "android.hardware.graphics.composer@2.1::IComposer", "android.hardware.vr@1.0::IVr", "android.hardware.media.omx@1.0::IOmx" ); diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index adb55b91c0ae..018e41b7bef1 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -112,6 +112,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -752,10 +753,12 @@ public class AccountManagerService synchronized (accounts.dbLock) { synchronized (accounts.cacheLock) { Map<String, Integer> packagesToVisibility; + List<String> accountRemovedReceivers; if (notify) { if (isSpecialPackageKey(packageName)) { packagesToVisibility = getRequestingPackages(account, accounts); + accountRemovedReceivers = getAccountRemovedReceivers(account, accounts); } else { if (!packageExistsForUser(packageName, accounts.userId)) { return false; // package is not installed. @@ -763,15 +766,20 @@ public class AccountManagerService packagesToVisibility = new HashMap<>(); packagesToVisibility.put(packageName, resolveAccountVisibility(account, packageName, accounts)); + accountRemovedReceivers = new ArrayList<>(); + if (shouldNotifyPackageOnAccountRemoval(account, packageName, accounts)) { + accountRemovedReceivers.add(packageName); + } } } else { - // Notifications will not be send. + // Notifications will not be send - only used during add account. if (!isSpecialPackageKey(packageName) && !packageExistsForUser(packageName, accounts.userId)) { // package is not installed and not meta value. return false; } - packagesToVisibility = new HashMap<>(); + packagesToVisibility = Collections.emptyMap(); + accountRemovedReceivers = Collections.emptyList(); } if (!updateAccountVisibilityLocked(account, packageName, newVisibility, accounts)) { @@ -781,11 +789,14 @@ public class AccountManagerService if (notify) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility .entrySet()) { - if (packageToVisibility.getValue() - != AccountManager.VISIBILITY_NOT_VISIBLE) { + if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(), + resolveAccountVisibility(account, packageName, accounts))) { notifyPackage(packageToVisibility.getKey(), accounts); } } + for (String packageNameToNotify : accountRemovedReceivers) { + sendAccountRemovedBroadcast(account, packageNameToNotify, accounts.userId); + } sendAccountsChangedBroadcast(accounts.userId); } return true; @@ -889,10 +900,11 @@ public class AccountManagerService // Send notification to all packages which can potentially see the account private void sendNotificationAccountUpdated(Account account, UserAccounts accounts) { Map<String, Integer> packagesToVisibility = getRequestingPackages(account, accounts); - // packages with VISIBILITY_USER_MANAGED_NOT_VISIBL still get notification. - // Should we notify VISIBILITY_NOT_VISIBLE packages when account is added? + for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { - if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { + if ((packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) + && (packageToVisibility.getValue() + != AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE)) { notifyPackage(packageToVisibility.getKey(), accounts); } } @@ -931,6 +943,44 @@ public class AccountManagerService return result; } + // Returns a list of packages listening to ACTION_ACCOUNT_REMOVED able to see the account. + private List<String> getAccountRemovedReceivers(Account account, UserAccounts accounts) { + Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED); + intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + List<ResolveInfo> receivers = + mPackageManager.queryBroadcastReceiversAsUser(intent, 0, accounts.userId); + List<String> result = new ArrayList<>(); + if (receivers == null) { + return result; + } + for (ResolveInfo resolveInfo: receivers) { + String packageName = resolveInfo.activityInfo.applicationInfo.packageName; + int visibility = resolveAccountVisibility(account, packageName, accounts); + if (visibility == AccountManager.VISIBILITY_VISIBLE + || visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE) { + result.add(packageName); + } + } + return result; + } + + // Returns true if given package is listening to ACTION_ACCOUNT_REMOVED and can see the account. + private boolean shouldNotifyPackageOnAccountRemoval(Account account, + String packageName, UserAccounts accounts) { + int visibility = resolveAccountVisibility(account, packageName, accounts); + if (visibility != AccountManager.VISIBILITY_VISIBLE + && visibility != AccountManager.VISIBILITY_USER_MANAGED_VISIBLE) { + return false; + } + + Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED); + intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + intent.setPackage(packageName); + List<ResolveInfo> receivers = + mPackageManager.queryBroadcastReceiversAsUser(intent, 0, accounts.userId); + return (receivers != null && receivers.size() > 0); + } + private boolean packageExistsForUser(String packageName, int userId) { try { long identityToken = clearCallingIdentity(); @@ -959,9 +1009,12 @@ public class AccountManagerService mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId)); } - private void sendAccountRemovedBroadcast(int userId) { + private void sendAccountRemovedBroadcast(Account account, String packageName, int userId) { Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED); intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + intent.setPackage(packageName); + intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name); + intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, account.type); mContext.sendBroadcastAsUser(intent, new UserHandle(userId)); } @@ -1087,6 +1140,8 @@ public class AccountManagerService + "'s registered authenticator no longer exist."); Map<String, Integer> packagesToVisibility = getRequestingPackages(account, accounts); + List<String> accountRemovedReceivers = + getAccountRemovedReceivers(account, accounts); accountsDb.beginTransaction(); try { accountsDb.deleteDeAccount(accountId); @@ -1112,12 +1167,14 @@ public class AccountManagerService for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { - if (packageToVisibility.getValue() - != AccountManager.VISIBILITY_NOT_VISIBLE) { + if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(), + AccountManager.VISIBILITY_NOT_VISIBLE)) { notifyPackage(packageToVisibility.getKey(), accounts); } } - sendAccountRemovedBroadcast(accounts.userId); + for (String packageName : accountRemovedReceivers) { + sendAccountRemovedBroadcast(account, packageName, accounts.userId); + } } else { ArrayList<String> accountNames = accountNamesByType.get(account.type); if (accountNames == null) { @@ -1147,6 +1204,14 @@ public class AccountManagerService } } + private boolean shouldNotifyOnVisibilityChange(int oldVisibility, int newVisibility) { + boolean oldVisible = (oldVisibility == AccountManager.VISIBILITY_VISIBLE) || + (oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + boolean newVisible = (newVisibility == AccountManager.VISIBILITY_VISIBLE) || + (newVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + return oldVisible == newVisible; + } + private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) { // Get the UIDs of all apps that might have data on the device. We want // to preserve user data if the app might otherwise be storing data. @@ -1911,6 +1976,8 @@ public class AccountManagerService } synchronized (accounts.dbLock) { synchronized (accounts.cacheLock) { + List<String> accountRemovedReceivers = + getAccountRemovedReceivers(accountToRename, accounts); accounts.accountsDb.beginTransaction(); Account renamedAccount = new Account(newName, accountToRename.type); if ((accounts.accountsDb.findCeAccountId(renamedAccount) >= 0)) { @@ -1978,7 +2045,9 @@ public class AccountManagerService sendNotificationAccountUpdated(resultAccount, accounts); sendAccountsChangedBroadcast(accounts.userId); - sendAccountRemovedBroadcast(accounts.userId); + for (String packageName : accountRemovedReceivers) { + sendAccountRemovedBroadcast(accountToRename, packageName, accounts.userId); + } } } return resultAccount; @@ -2181,6 +2250,8 @@ public class AccountManagerService synchronized (accounts.cacheLock) { Map<String, Integer> packagesToVisibility = getRequestingPackages(account, accounts); + List<String> accountRemovedReceivers = + getAccountRemovedReceivers(account, accounts); accounts.accountsDb.beginTransaction(); // Set to a dummy value, this will only be used if the database // transaction succeeds. @@ -2206,15 +2277,18 @@ public class AccountManagerService removeAccountFromCacheLocked(accounts, account); for (Entry<String, Integer> packageToVisibility : packagesToVisibility .entrySet()) { - if (packageToVisibility.getValue() - != AccountManager.VISIBILITY_NOT_VISIBLE) { + if ((packageToVisibility.getValue() == AccountManager.VISIBILITY_VISIBLE) + || (packageToVisibility.getValue() + == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE)) { notifyPackage(packageToVisibility.getKey(), accounts); } } // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occurred. sendAccountsChangedBroadcast(accounts.userId); - sendAccountRemovedBroadcast(accounts.userId); + for (String packageName : accountRemovedReceivers) { + sendAccountRemovedBroadcast(account, packageName, accounts.userId); + } String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE : AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE_DE; logRecord(action, AccountsDb.TABLE_ACCOUNTS, accountId, accounts); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 3fe8a1efa4eb..c6e44e0d424c 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1728,7 +1728,7 @@ public final class ActiveServices { return null; } - if (!whileRestarting && r.restartDelay > 0) { + if (!whileRestarting && mRestartingServices.contains(r)) { // If waiting for a restart, then do nothing. return null; } @@ -1740,7 +1740,6 @@ public final class ActiveServices { // We are now bringing the service up, so no longer in the // restarting state. if (mRestartingServices.remove(r)) { - r.resetRestartCounter(); clearRestartingIfNeededLocked(r); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d99601c815f7..45c2054d6587 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -19146,6 +19146,12 @@ public class ActivityManagerService extends IActivityManager.Stub case android.security.KeyChain.ACTION_TRUST_STORE_CHANGED: mHandler.sendEmptyMessage(HANDLE_TRUST_STORAGE_UPDATE_MSG); break; + case "com.android.launcher.action.INSTALL_SHORTCUT": + // As of O, we no longer support this broadcasts, even for pre-O apps. + // Apps should now be using ShortcutManager.pinRequestShortcut(). + Log.w(TAG, "Broadcast " + action + + " no longer supported. It will not be delivered."); + return ActivityManager.BROADCAST_SUCCESS; } if (Intent.ACTION_PACKAGE_ADDED.equals(action) || diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 494aaa766b94..08ff7de87c9f 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -254,8 +254,7 @@ class ActivityMetricsLogger { * ActivityManagerInternal.APP_TRANSITION_* reasons. */ void notifyTransitionStarting(SparseIntArray stackIdReasons) { - // TODO (b/36339388): Figure out why stackIdReasons can be null - if (stackIdReasons == null || !isAnyTransitionActive() || mLoggedTransitionStarting) { + if (!isAnyTransitionActive() || mLoggedTransitionStarting) { return; } mCurrentTransitionDelayMs = calculateCurrentDelay(); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 6e84ed6f3c79..eeedab8856e5 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1568,17 +1568,21 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void setVisibility(boolean visible) { - mWindowContainerController.setVisibility(visible); + mWindowContainerController.setVisibility(visible, false /* deferHidingClient */); } - // TODO: Look into merging with #setVisibility() void setVisible(boolean newVisible) { + setVisible(newVisible, false /* deferHidingClient */); + } + + // TODO: Look into merging with #setVisibility() + void setVisible(boolean newVisible, boolean deferHidingClient) { visible = newVisible; if (!visible && mUpdateTaskThumbnailWhenHidden) { updateThumbnailLocked(screenshotActivityLocked(), null /* description */); mUpdateTaskThumbnailWhenHidden = false; } - mWindowContainerController.setVisibility(visible); + mWindowContainerController.setVisibility(visible, deferHidingClient); final ArrayList<ActivityContainer> containers = mChildContainers; for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) { final ActivityContainer container = containers.get(containerNdx); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 824ec68a8660..1e8a5878649c 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -23,6 +23,7 @@ import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; @@ -800,6 +801,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return mStackId == HOME_STACK_ID; } + final boolean isRecentsStack() { + return mStackId == RECENTS_STACK_ID; + } + final boolean isHomeOrRecentsStack() { return StackId.isHomeOrRecentsStack(mStackId); } @@ -1402,7 +1407,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } else if ((!prev.visible && !hasVisibleBehindActivity()) || mService.isSleepingOrShuttingDownLocked()) { // If we were visible then resumeTopActivities will release resources before - // stopping. + // stopping. Also, set visibility to false to flush any client hide that might have + // been deferred. + prev.setVisibility(false); addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */); } } else { @@ -2019,11 +2026,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai try { final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( "makeInvisible", true /* noThrow */, true /* beforeStopping */); - // We don't want to call setVisible(false) to avoid notifying the client of this - // intermittent invisible state if it can enter Pip and isn't stopped or stopping. - if (!canEnterPictureInPicture || r.state == STOPPING || r.state == STOPPED) { - r.setVisible(false); - } + // Defer telling the client it is hidden if it can enter Pip and isn't current stopped + // or stopping. This gives it a chance to enter Pip in onPause(). + final boolean deferHidingClient = canEnterPictureInPicture + && r.state != STOPPING && r.state != STOPPED; + r.setVisible(false, deferHidingClient); switch (r.state) { case STOPPING: @@ -2048,15 +2055,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (visibleBehind == r) { releaseBackgroundResources(r); } else { - // If this activity is in a state where it can currently enter - // picture-in-picture, then don't immediately schedule the idle now in case - // the activity tries to enterPictureInPictureMode() later. Otherwise, - // we will try and stop the activity next time idle is processed. - - if (canEnterPictureInPicture) { - // We set r.visible=false so that Stop will later call setVisible for us - r.visible = false; - } addToStopping(r, true /* scheduleIdle */, canEnterPictureInPicture /* idleDelayed */); } @@ -2338,20 +2336,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); - final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState( - "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */); + boolean lastResumedCanPip = false; + final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack(); + if (lastFocusedStack != null && lastFocusedStack != this) { + // So, why aren't we using prev here??? See the param comment on the method. prev doesn't + // represent the last resumed activity. However, the last focus stack does if it isn't null. + final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity; + lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( + "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */); + } // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity // to be paused, while at the same time resuming the new resume activity only if the // previous activity can't go into Pip since we want to give Pip activities a chance to // enter Pip before resuming the next activity. - final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0; - // TODO: This would be go to have however, the various call points that pass in - // prev need to be corrected first. In some cases the prev is equal to the next e.g. launch - // an app from home. And, is come other cases it is null e.g. press home button after - // launching an app. The doc on the method says prev. is null expect for the case we are - // coming from pause. We need to see if that is a valid thing and also if all the code in - // this method using prev. are setup to function like that. - //&& !prevCanPip; + final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 + && !lastResumedCanPip; + boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 6010befc1171..fb8c161ea35d 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3025,8 +3025,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (!r.isApplicationActivity() && !stack.isHomeOrRecentsStack()) { - if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack); + if (!checkActivityBelongsInStack(r, stack)) { + if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + + stack); continue; } if (!stack.mActivityContainer.isEligibleForNewTasks()) { @@ -3053,6 +3054,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return affinityMatch; } + /** + * Checks that for the given activity {@param r}, its activity type matches the {@param stack} + * type. + */ + private boolean checkActivityBelongsInStack(ActivityRecord r, ActivityStack stack) { + if (r.isHomeActivity()) { + return stack.isHomeStack(); + } else if (r.isRecentsActivity()) { + return stack.isRecentsStack(); + } else if (r.isAssistantActivity()) { + return stack.isAssistantStack(); + } + return true; + } + ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters) { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 2bd119ec177d..dd16e228cbe3 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -204,12 +204,11 @@ class KeyguardController { mOccluded = false; mDismissingKeyguardActivity = null; final ArrayList<ActivityStack> stacks = mStackSupervisor.getStacksOnDefaultDisplay(); - final int topStackNdx = stacks.size() - 1; - for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) { + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - // Only the very top activity may control occluded state - if (stackNdx == topStackNdx) { + // Only the focused stack top activity may control occluded state + if (mStackSupervisor.isFocusedStack(stack)) { // A dismissing activity occludes Keyguard in the insecure case for legacy reasons. final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity(); diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index dc636e53b18c..056fec526502 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -2212,11 +2212,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta /** Returns the bounds that should be used to launch this task. */ Rect getLaunchBounds() { - // If we're over lockscreen, forget about stack bounds and use fullscreen. - if (mService.mStackSupervisor.mKeyguardController.isKeyguardShowing()) { - return null; - } - if (mStack == null) { return null; } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index eea5473484f8..457cf871443a 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6044,8 +6044,8 @@ public class AudioService extends IAudioService.Stub (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled()); updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive()); - accessibilityManager.addTouchExplorationStateChangeListener(this); - accessibilityManager.addAccessibilityServicesStateChangeListener(this); + accessibilityManager.addTouchExplorationStateChangeListener(this, null); + accessibilityManager.addAccessibilityServicesStateChangeListener(this, null); } //--------------------------------------------------------------------------------- diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 9eda9294031e..b0f84fe36977 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -46,32 +46,28 @@ import java.util.Set; public final class PlaybackActivityMonitor implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer { - public final static String TAG = "AudioService.PlaybackActivityMonitor"; + public static final String TAG = "AudioService.PlaybackActivityMonitor"; - private final static boolean DEBUG = false; - private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1; + private static final boolean DEBUG = false; + private static final int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1; - private final VolumeShaper.Configuration DUCK_VSHAPE = + private static final VolumeShaper.Configuration DUCK_VSHAPE = new VolumeShaper.Configuration.Builder() .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID) .setCurve(new float[] { 0.f, 1.f } /* times */, new float[] { 1.f, 0.2f } /* volumes */) .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME) - .setDurationMillis(MediaFocusControl.getFocusRampTimeMs( + .setDuration(MediaFocusControl.getFocusRampTimeMs( AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION) .build())) .build(); - private final VolumeShaper.Configuration DUCK_ID = + private static final VolumeShaper.Configuration DUCK_ID = new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID); - private final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED = + private static final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED = new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY) .createIfNeeded() .build(); - private final VolumeShaper.Operation TERMINATE = - new VolumeShaper.Operation.Builder() - .terminate() - .build(); private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); // a public client is one that needs an anonymized version of the playback configurations, we @@ -166,14 +162,7 @@ public final class PlaybackActivityMonitor synchronized(mPlayerLock) { final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid)); if (checkConfigurationCaller(piid, apc, binderUid)) { - try { - apc.getPlayerProxy().applyVolumeShaper( - DUCK_ID, - TERMINATE); - } catch (Exception e) { /* silent failure, happens with binder failure */ } mPlayers.remove(new Integer(piid)); - } else { - Log.e(TAG, "Error releasing player " + piid); } } } @@ -206,16 +195,16 @@ public final class PlaybackActivityMonitor } /** - * Check that piid and uid are valid for the given configuration. + * Check that piid and uid are valid for the given valid configuration. * @param piid the piid of the player. * @param apc the configuration found for this piid. * @param binderUid actual uid of client trying to signal a player state/event/attributes. - * @return true if the call is valid and the change should proceed, false otherwise. + * @return true if the call is valid and the change should proceed, false otherwise. Always + * returns false when apc is null. */ private static boolean checkConfigurationCaller(int piid, final AudioPlaybackConfiguration apc, int binderUid) { if (apc == null) { - Log.e(TAG, "Invalid operation: unknown player " + piid); return false; } else if ((binderUid != 0) && (apc.getClientUid() != binderUid)) { Log.e(TAG, "Forbidden operation from uid " + binderUid + " for player " + piid); @@ -509,7 +498,7 @@ public final class PlaybackActivityMonitor /** * Inner class to track clients that want to be notified of playback updates */ - private final static class PlayMonitorClient implements IBinder.DeathRecipient { + private static final class PlayMonitorClient implements IBinder.DeathRecipient { // can afford to be static because only one PlaybackActivityMonitor ever instantiated static PlaybackActivityMonitor sListenerDeathMonitor; diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 9d8b3d477659..ac5fb43f9344 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -138,7 +138,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering public boolean isCurrentlyServing() { switch (lastState) { case IControlsTethering.STATE_TETHERED: - case IControlsTethering.STATE_LOCAL_HOTSPOT: + case IControlsTethering.STATE_LOCAL_ONLY: return true; default: return false; @@ -617,7 +617,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering erroredList.add(iface); } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) { availableList.add(iface); - } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_HOTSPOT) { + } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) { localOnlyList.add(iface); } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) { if (cfg.isUsb(iface)) { @@ -795,7 +795,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering // Otherwise, assume it's a local-only hotspot request. final int state = mWifiTetherRequested ? IControlsTethering.STATE_TETHERED - : IControlsTethering.STATE_LOCAL_HOTSPOT; + : IControlsTethering.STATE_LOCAL_ONLY; tetherMatchingInterfaces(state, ConnectivityManager.TETHERING_WIFI); break; case WifiManager.WIFI_AP_STATE_DISABLED: @@ -865,7 +865,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering result = untether(chosenIface); break; case IControlsTethering.STATE_TETHERED: - case IControlsTethering.STATE_LOCAL_HOTSPOT: + case IControlsTethering.STATE_LOCAL_ONLY: result = tether(chosenIface, requestedState); break; default: @@ -1723,7 +1723,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering case IControlsTethering.STATE_TETHERED: pw.print("TetheredState"); break; - case IControlsTethering.STATE_LOCAL_HOTSPOT: + case IControlsTethering.STATE_LOCAL_ONLY: pw.print("LocalHotspotState"); break; default: @@ -1778,7 +1778,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE; break; case IControlsTethering.STATE_TETHERED: - case IControlsTethering.STATE_LOCAL_HOTSPOT: + case IControlsTethering.STATE_LOCAL_ONLY: which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE; break; default: diff --git a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java index f3914b7cb299..c5c86bd1c3bb 100644 --- a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java +++ b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java @@ -23,9 +23,9 @@ package com.android.server.connectivity.tethering; */ public interface IControlsTethering { public final int STATE_UNAVAILABLE = 0; - public final int STATE_AVAILABLE = 1; - public final int STATE_TETHERED = 2; - public final int STATE_LOCAL_HOTSPOT = 3; + public final int STATE_AVAILABLE = 1; + public final int STATE_TETHERED = 2; + public final int STATE_LOCAL_ONLY = 3; /** * Notify that |who| has changed its tethering state. This may be called from any thread. diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java index 5f496ca59e6a..248565405e5e 100644 --- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java +++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java @@ -172,7 +172,7 @@ public class IPv6TetheringCoordinator { final Downstream ds = findDownstream(sm); if (ds == null) return null; - if (ds.mode == IControlsTethering.STATE_LOCAL_HOTSPOT) { + if (ds.mode == IControlsTethering.STATE_LOCAL_ONLY) { // Build a Unique Locally-assigned Prefix configuration. return getUniqueLocalConfig(mUniqueLocalPrefix, ds.subnetId); } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java index 601ed010a696..e21349af8649 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java @@ -194,7 +194,7 @@ public class TetherInterfaceStateMachine extends StateMachine { case CMD_TETHER_REQUESTED: mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; switch (message.arg1) { - case IControlsTethering.STATE_LOCAL_HOTSPOT: + case IControlsTethering.STATE_LOCAL_ONLY: transitionTo(mLocalHotspotState); break; case IControlsTethering.STATE_TETHERED: @@ -304,7 +304,7 @@ public class TetherInterfaceStateMachine extends StateMachine { } if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName); - sendInterfaceState(IControlsTethering.STATE_LOCAL_HOTSPOT); + sendInterfaceState(IControlsTethering.STATE_LOCAL_ONLY); } @Override diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 64ab848a052e..0db1b5d547dc 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -965,7 +965,7 @@ public class MediaSessionService extends SystemService implements Monitor { final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - if (uid != Process.BLUETOOTH_UID) { + if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) { throw new SecurityException("Only Bluetooth service processes can set" + " Callback"); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 9f693df9e1e6..1e7d07626782 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3648,7 +3648,7 @@ public class NotificationManagerService extends SystemService { if (DBG) Slog.v(TAG, "Interrupting!"); Uri soundUri = record.getSound(); - hasValidSound = (soundUri != null); + hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); long[] vibration = record.getVibration(); // Demote sound to vibration if vibration missing & phone in vibration mode. if (vibration == null @@ -3659,10 +3659,7 @@ public class NotificationManagerService extends SystemService { } hasValidVibrate = vibration != null; - // We can alert, and we're allowed to alert, but if the developer asked us to only do - // it once, and we already have, then don't. - if (!(record.isUpdate - && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)) { + if (!shouldMuteNotificationLocked(record)) { sendAccessibilityEvent(notification, record.sbn.getPackageName()); if (hasValidSound) { @@ -3716,6 +3713,24 @@ public class NotificationManagerService extends SystemService { } } + boolean shouldMuteNotificationLocked(final NotificationRecord record) { + final Notification notification = record.getNotification(); + if(record.isUpdate + && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) { + return true; + } + if (record.sbn.isGroup()) { + if (notification.isGroupSummary() + && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) { + return true; + } else if (notification.isGroupChild() + && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) { + return true; + } + } + return false; + } + private boolean playSound(final NotificationRecord record, Uri soundUri) { boolean looping = (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0; // do not play notifications if there is a user of exclusive audio focus diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 221b2bb0886a..32de3166faae 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -561,7 +561,7 @@ public class RankingHelper implements RankingConfig { updateConfig(); return; } - if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE + if (channel.getImportance() < NotificationManager.IMPORTANCE_MIN || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) { throw new IllegalArgumentException("Invalid importance level"); } diff --git a/services/core/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java index a8bb80905cd2..46be232e61c3 100644 --- a/services/core/java/com/android/server/os/SchedulingPolicyService.java +++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java @@ -20,6 +20,7 @@ import android.content.pm.PackageManager; import android.os.Binder; import android.os.ISchedulingPolicyService; import android.os.Process; +import android.util.Log; /** * The implementation of the scheduling policy service interface. @@ -50,16 +51,24 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { // since if not the case then the getThreadGroupLeader() test will also fail. if (!isPermitted() || prio < PRIORITY_MIN || prio > PRIORITY_MAX || Process.getThreadGroupLeader(tid) != pid) { - return PackageManager.PERMISSION_DENIED; + return PackageManager.PERMISSION_DENIED; + } + if (Binder.getCallingUid() != Process.BLUETOOTH_UID) { + try { + // make good use of our CAP_SYS_NICE capability + Process.setThreadGroup(tid, !isForApp ? + Process.THREAD_GROUP_AUDIO_SYS : Process.THREAD_GROUP_AUDIO_APP); + } catch (RuntimeException e) { + Log.e(TAG, "Failed setThreadGroup: " + e); + return PackageManager.PERMISSION_DENIED; + } } try { - // make good use of our CAP_SYS_NICE capability - Process.setThreadGroup(tid, !isForApp ? - Process.THREAD_GROUP_AUDIO_SYS : Process.THREAD_GROUP_AUDIO_APP); // must be in this order or it fails the schedulability constraint Process.setThreadScheduler(tid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, - prio); + prio); } catch (RuntimeException e) { + Log.e(TAG, "Failed setThreadScheduler: " + e); return PackageManager.PERMISSION_DENIED; } return PackageManager.PERMISSION_GRANTED; @@ -74,6 +83,7 @@ public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { switch (Binder.getCallingUid()) { case Process.AUDIOSERVER_UID: // fastcapture, fastmixer case Process.CAMERASERVER_UID: // camera high frame rate recording + case Process.BLUETOOTH_UID: // Bluetooth audio playback return true; default: return false; diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java index 21d78ee3a07a..9d08004c579a 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java +++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java @@ -35,6 +35,7 @@ import android.os.UserHandle; import android.util.Slog; import android.util.TimedRemoteCaller; +import com.android.internal.annotations.GuardedBy; import com.android.internal.os.TransferPipe; import java.io.FileDescriptor; @@ -53,7 +54,9 @@ final class EphemeralResolverConnection implements DeathRecipient { private static final String TAG = "PackageManager"; // This is running in a critical section and the timeout must be sufficiently low private static final long BIND_SERVICE_TIMEOUT_MS = - ("eng".equals(Build.TYPE)) ? 300 : 200; + ("eng".equals(Build.TYPE)) ? 500 : 300; + private static final long CALL_SERVICE_TIMEOUT_MS = + ("eng".equals(Build.TYPE)) ? 200 : 100; private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; private final Object mLock = new Object(); @@ -64,7 +67,9 @@ final class EphemeralResolverConnection implements DeathRecipient { /** Intent used to bind to the service */ private final Intent mIntent; - private volatile boolean mBindRequested; + @GuardedBy("mLock") + private volatile boolean mIsBinding; + @GuardedBy("mLock") private IInstantAppResolver mRemoteInstance; public EphemeralResolverConnection( @@ -76,11 +81,18 @@ final class EphemeralResolverConnection implements DeathRecipient { public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[], String token) { throwIfCalledOnMainThread(); + IInstantAppResolver target = null; try { - return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList( - getRemoteInstanceLazy(), hashPrefix, token); - } catch (RemoteException re) { - } catch (TimeoutException te) { + target = getRemoteInstanceLazy(token); + return mGetEphemeralResolveInfoCaller + .getEphemeralResolveInfoList(target, hashPrefix, token); + } catch (RemoteException e) { + } catch (InterruptedException | TimeoutException e) { + if (target == null) { + Slog.w(TAG, "[" + token + "] Timeout! Phase1 binding to instant app resolver"); + } else { + Slog.w(TAG, "[" + token + "] Timeout! Phase1 resolving instant app"); + } } finally { synchronized (mLock) { mLock.notifyAll(); @@ -107,70 +119,73 @@ final class EphemeralResolverConnection implements DeathRecipient { } }; try { - getRemoteInstanceLazy() + getRemoteInstanceLazy(token) .getInstantAppIntentFilterList(hashPrefix, token, hostName, remoteCallback); - } catch (RemoteException re) { - } catch (TimeoutException te) { + } catch (RemoteException e) { + } catch (InterruptedException | TimeoutException e) { + Slog.w(TAG, "[" + token + "] Timeout! Phase2 binding to instant app resolver"); } } - public void dump(FileDescriptor fd, PrintWriter pw, String prefix) { - synchronized (mLock) { - pw.append(prefix).append("bound=") - .append((mRemoteInstance != null) ? "true" : "false").println(); - - pw.flush(); - try { - TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd, - new String[] { prefix }); - } catch (IOException | TimeoutException | RemoteException e) { - pw.println("Failed to dump remote instance: " + e); - } - } - } - - private IInstantAppResolver getRemoteInstanceLazy() throws TimeoutException { + private IInstantAppResolver getRemoteInstanceLazy(String token) + throws TimeoutException, InterruptedException { synchronized (mLock) { if (mRemoteInstance != null) { return mRemoteInstance; } - bindLocked(); + bindLocked(token); return mRemoteInstance; } } - private void bindLocked() throws TimeoutException { - if (mRemoteInstance != null) { - return; - } - - if (!mBindRequested) { - mBindRequested = true; - if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Binding to resolver service"); - } - mContext.bindServiceAsUser(mIntent, mServiceConnection, - Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.SYSTEM); - } - + private void waitForBind(String token) throws TimeoutException, InterruptedException { final long startMillis = SystemClock.uptimeMillis(); - while (true) { + while (mIsBinding) { if (mRemoteInstance != null) { break; } final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; final long remainingMillis = BIND_SERVICE_TIMEOUT_MS - elapsedMillis; if (remainingMillis <= 0) { - throw new TimeoutException("Didn't bind to resolver in time."); - } - try { - mLock.wait(remainingMillis); - } catch (InterruptedException ie) { - /* ignore */ + throw new TimeoutException("[" + token + "] Didn't bind to resolver in time!"); } + mLock.wait(remainingMillis); } + } - mLock.notifyAll(); + private void bindLocked(String token) throws TimeoutException, InterruptedException { + if (DEBUG_EPHEMERAL && mIsBinding && mRemoteInstance == null) { + Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection"); + } + try { + waitForBind(token); + } catch (TimeoutException e) { + if (DEBUG_EPHEMERAL) { + Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding"); + } + mContext.unbindService(mServiceConnection); + } + if (mRemoteInstance != null) { + return; + } + mIsBinding = true; + if (DEBUG_EPHEMERAL) { + Slog.v(TAG, "[" + token + "] Binding to instant app resolver"); + } + boolean wasBound = false; + try { + final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; + wasBound = mContext + .bindServiceAsUser(mIntent, mServiceConnection, flags, UserHandle.SYSTEM); + if (wasBound) { + waitForBind(token); + } else { + Slog.w(TAG, "[" + token + "] Failed to bind to: " + mIntent); + } + } finally { + mIsBinding = wasBound && mRemoteInstance == null; + mLock.notifyAll(); + } } private void throwIfCalledOnMainThread() { @@ -182,13 +197,18 @@ final class EphemeralResolverConnection implements DeathRecipient { @Override public void binderDied() { if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Binder died"); + Slog.d(TAG, "Binder to instant app resolver died"); } + synchronized (mLock) { + handleBinderDiedLocked(); + } + } + + private void handleBinderDiedLocked() { if (mRemoteInstance != null) { mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/); } mRemoteInstance = null; - mBindRequested = false; } /** @@ -203,13 +223,15 @@ final class EphemeralResolverConnection implements DeathRecipient { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Service connected"); + Slog.d(TAG, "Connected to instant app resolver"); } synchronized (mLock) { + mRemoteInstance = IInstantAppResolver.Stub.asInterface(service); + mIsBinding = false; try { service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/); - mRemoteInstance = IInstantAppResolver.Stub.asInterface(service); } catch (RemoteException e) { + handleBinderDiedLocked(); } mLock.notifyAll(); } @@ -218,10 +240,10 @@ final class EphemeralResolverConnection implements DeathRecipient { @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG_EPHEMERAL) { - Slog.d(TAG, "Service disconnected"); + Slog.d(TAG, "Disconnected from instant app resolver"); } synchronized (mLock) { - mRemoteInstance = null; + handleBinderDiedLocked(); } } } @@ -231,7 +253,7 @@ final class EphemeralResolverConnection implements DeathRecipient { private final IRemoteCallback mCallback; public GetEphemeralResolveInfoCaller() { - super(BIND_SERVICE_TIMEOUT_MS); + super(CALL_SERVICE_TIMEOUT_MS); mCallback = new IRemoteCallback.Stub() { @Override public void sendResult(Bundle data) throws RemoteException { diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index 6f593b08e258..b56db047fd30 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -74,11 +74,11 @@ public abstract class InstantAppResolver { public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(Context context, EphemeralResolverConnection connection, InstantAppRequest requestObj) { - if (DEBUG_EPHEMERAL) { - Log.d(TAG, "Resolving phase 1"); - } final long startTime = System.currentTimeMillis(); final String token = UUID.randomUUID().toString(); + if (DEBUG_EPHEMERAL) { + Log.d(TAG, "[" + token + "] Resolving phase 1"); + } final Intent intent = requestObj.origIntent; final InstantAppDigest digest = new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/); @@ -89,7 +89,7 @@ public abstract class InstantAppResolver { if (instantAppResolveInfoList == null || instantAppResolveInfoList.size() == 0) { // No hash prefix match; there are no instant apps for this domain. if (DEBUG_EPHEMERAL) { - Log.d(TAG, "No results returned"); + Log.d(TAG, "[" + token + "] No results returned"); } return null; } @@ -98,21 +98,24 @@ public abstract class InstantAppResolver { intent.getPackage(), digest, token); logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, RESOLUTION_SUCCESS); + if (DEBUG_EPHEMERAL && resolveInfo == null) { + Log.d(TAG, "[" + token + "] No results matched"); + } return resolveInfo; } public static void doInstantAppResolutionPhaseTwo(Context context, EphemeralResolverConnection connection, InstantAppRequest requestObj, ActivityInfo instantAppInstaller, Handler callbackHandler) { + final long startTime = System.currentTimeMillis(); + final String token = requestObj.responseObj.token; if (DEBUG_EPHEMERAL) { - Log.d(TAG, "Resolving phase 2"); + Log.d(TAG, "[" + token + "] Resolving phase 2"); } - final long startTime = System.currentTimeMillis(); final Intent intent = requestObj.origIntent; final String hostName = intent.getData().getHost(); final InstantAppDigest digest = new InstantAppDigest(hostName, 5 /*maxDigests*/); final int[] shaPrefix = digest.getDigestPrefix(); - final String token = requestObj.responseObj.token; final PhaseTwoCallback callback = new PhaseTwoCallback() { @Override @@ -285,12 +288,16 @@ public abstract class InstantAppResolver { if (!matchedResolveInfoList.isEmpty()) { if (DEBUG_EPHEMERAL) { final AuxiliaryResolveInfo info = matchedResolveInfoList.get(0); - Log.d(TAG, "Found match;" + Log.d(TAG, "[" + token + "] Found match;" + " package: " + info.packageName + ", split: " + info.splitName + ", versionCode: " + info.versionCode); } return matchedResolveInfoList.get(0); + } else if (DEBUG_EPHEMERAL) { + Log.d(TAG, "[" + token + "] No matches found" + + " package: " + instantAppInfo.getPackageName() + + ", versionCode: " + instantAppInfo.getVersionCode()); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4d026e3d0f89..faa99342b9dc 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -96,7 +96,7 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; -import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter; +import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS; @@ -536,9 +536,8 @@ public class PackageManagerService extends IPackageManager.Stub public static final int REASON_INSTALL = 2; public static final int REASON_BACKGROUND_DEXOPT = 3; public static final int REASON_AB_OTA = 4; - public static final int REASON_FORCED_DEXOPT = 5; - public static final int REASON_LAST = REASON_FORCED_DEXOPT; + public static final int REASON_LAST = REASON_AB_OTA; /** All dangerous permission names in the same order as the events in MetricsEvent */ private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList( @@ -1780,6 +1779,8 @@ public class PackageManagerService extends IPackageManager.Stub final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; + final String origInstallerPackageName = res.removedInfo != null + ? res.removedInfo.installerPackageName : null; // If this is the first time we have child packages for a disabled privileged // app that had no children, we grant requested runtime permissions to the new @@ -1841,8 +1842,13 @@ public class PackageManagerService extends IPackageManager.Stub extras.putBoolean(Intent.EXTRA_REPLACING, true); } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, - extras, 0 /*flags*/, null /*targetPackage*/, - null /*finishedReceiver*/, updateUsers); + extras, 0 /*flags*/, + null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); + if (origInstallerPackageName != null) { + sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, + extras, 0 /*flags*/, + origInstallerPackageName, null /*finishedReceiver*/, updateUsers); + } // Send replaced for users that don't see the package for the first time if (update) { @@ -1850,6 +1856,11 @@ public class PackageManagerService extends IPackageManager.Stub packageName, extras, 0 /*flags*/, null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); + if (origInstallerPackageName != null) { + sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, + extras, 0 /*flags*/, + origInstallerPackageName, null /*finishedReceiver*/, updateUsers); + } sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null /*package*/, null /*extras*/, 0 /*flags*/, packageName /*targetPackage*/, @@ -7672,6 +7683,7 @@ public class PackageManagerService extends IPackageManager.Stub } // instant application; filter out non-exposed provider if (instantAppPkgName != null + && !isInstantApp && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) { return null; } @@ -8580,14 +8592,6 @@ public class PackageManagerService extends IPackageManager.Stub mDexManager.notifyDexLoad(ai, dexPaths, loaderIsa, userId); } - // TODO: this is not used nor needed. Delete it. - @Override - public boolean performDexOptIfNeeded(String packageName) { - int dexOptStatus = performDexOptTraced(packageName, - false /* checkProfiles */, getFullCompilerFilter(), false /* force */); - return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED; - } - @Override public boolean performDexOpt(String packageName, boolean checkProfiles, int compileReason, boolean force) { @@ -8864,10 +8868,10 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstallLock) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); - // Whoever is calling forceDexOpt wants a fully compiled package. + // Whoever is calling forceDexOpt wants a compiled package. // Don't use profiles since that may cause compilation to be skipped. final int res = performDexOptInternalWithDependenciesLI(pkg, - false /* checkProfiles */, getCompilerFilterForReason(REASON_FORCED_DEXOPT), + false /* checkProfiles */, getDefaultCompilerFilter(), true /* force */); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); @@ -13521,6 +13525,7 @@ public class PackageManagerService extends IPackageManager.Stub int userId) { final PackageRemovedInfo info = new PackageRemovedInfo(this); info.removedPackage = packageName; + info.installerPackageName = pkgSetting.installerPackageName; info.removedUsers = new int[] {userId}; info.broadcastUsers = new int[] {userId}; info.uid = UserHandle.getUid(userId, pkgSetting.appId); @@ -16052,6 +16057,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final PackageParser.Package oldPackage; + final PackageSetting ps; final String pkgName = pkg.packageName; final int[] allUsers; final int[] installedUsers; @@ -16073,7 +16079,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } - final PackageSetting ps = mSettings.mPackages.get(pkgName); + ps = mSettings.mPackages.get(pkgName); // verify signatures are valid if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) { @@ -16159,10 +16165,10 @@ public class PackageManagerService extends IPackageManager.Stub res.removedInfo = new PackageRemovedInfo(this); res.removedInfo.uid = oldPackage.applicationInfo.uid; res.removedInfo.removedPackage = oldPackage.packageName; + res.removedInfo.installerPackageName = ps.installerPackageName; res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null; res.removedInfo.isUpdate = true; res.removedInfo.origUsers = installedUsers; - final PackageSetting ps = mSettings.getPackageLPr(pkgName); res.removedInfo.installReasons = new SparseArray<>(installedUsers.length); for (int i = 0; i < installedUsers.length; i++) { final int userId = installedUsers[i]; @@ -16180,6 +16186,9 @@ public class PackageManagerService extends IPackageManager.Stub if (childRes != null) { childRes.removedInfo.uid = childPkg.applicationInfo.uid; childRes.removedInfo.removedPackage = childPkg.packageName; + if (childPs != null) { + childRes.removedInfo.installerPackageName = childPs.installerPackageName; + } childRes.removedInfo.isUpdate = true; childRes.removedInfo.installReasons = res.removedInfo.installReasons; childPackageUpdated = true; @@ -16188,6 +16197,9 @@ public class PackageManagerService extends IPackageManager.Stub if (!childPackageUpdated) { PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this); childRemovedRes.removedPackage = childPkg.packageName; + if (childPs != null) { + childRemovedRes.installerPackageName = childPs.installerPackageName; + } childRemovedRes.isUpdate = false; childRemovedRes.dataRemoved = true; synchronized (mPackages) { @@ -16878,6 +16890,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((mPackages.containsKey(childPkg.packageName))) { childRes.removedInfo = new PackageRemovedInfo(this); childRes.removedInfo.removedPackage = childPkg.packageName; + childRes.removedInfo.installerPackageName = childPs.installerPackageName; } if (res.addedChildPackages == null) { res.addedChildPackages = new ArrayMap<>(); @@ -17826,6 +17839,7 @@ public class PackageManagerService extends IPackageManager.Stub static class PackageRemovedInfo { final PackageSender packageSender; String removedPackage; + String installerPackageName; int uid = -1; int removedAppId = -1; int[] origUsers; @@ -17885,11 +17899,19 @@ public class PackageManagerService extends IPackageManager.Stub extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid); extras.putBoolean(Intent.EXTRA_REPLACING, true); packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, - removedPackage, extras, 0, null, null, null); + removedPackage, extras, 0, null /*targetPackage*/, null, null); packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, - removedPackage, extras, 0, null, null, null); + removedPackage, extras, 0, null /*targetPackage*/, null, null); packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0, removedPackage, null, null); + if (installerPackageName != null) { + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, + removedPackage, extras, 0 /*flags*/, + installerPackageName, null, null); + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, + removedPackage, extras, 0 /*flags*/, + installerPackageName, null, null); + } } private void sendPackageRemovedBroadcastInternal(boolean killApp) { @@ -17909,7 +17931,12 @@ public class PackageManagerService extends IPackageManager.Stub extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers); if (removedPackage != null) { packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, - removedPackage, extras, 0, null, null, broadcastUsers); + removedPackage, extras, 0, null /*targetPackage*/, null, broadcastUsers); + if (installerPackageName != null) { + packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, + removedPackage, extras, 0 /*flags*/, + installerPackageName, null, broadcastUsers); + } if (dataRemoved && !isRemovedPackageSystemUpdate) { packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage, extras, @@ -17960,6 +17987,7 @@ public class PackageManagerService extends IPackageManager.Stub deletedPs = mSettings.mPackages.get(packageName); if (outInfo != null) { outInfo.removedPackage = packageName; + outInfo.installerPackageName = ps.installerPackageName; outInfo.isStaticSharedLib = deletedPkg != null && deletedPkg.staticSharedLibName != null; outInfo.populateUsers(deletedPs == null ? null @@ -18448,6 +18476,7 @@ public class PackageManagerService extends IPackageManager.Stub String childPackageName = ps.childPackageNames.get(i); PackageRemovedInfo childInfo = new PackageRemovedInfo(this); childInfo.removedPackage = childPackageName; + childInfo.installerPackageName = ps.installerPackageName; outInfo.removedChildPackages.put(childPackageName, childInfo); PackageSetting childPs = mSettings.getPackageLPr(childPackageName); if (childPs != null) { @@ -18572,6 +18601,7 @@ public class PackageManagerService extends IPackageManager.Stub if (outInfo != null) { outInfo.removedPackage = ps.name; + outInfo.installerPackageName = ps.installerPackageName; outInfo.isStaticSharedLib = pkg != null && pkg.staticSharedLibName != null; outInfo.removedAppId = ps.appId; outInfo.removedUsers = userIds; diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java index f6872e4373fd..284bb3f1f69b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java @@ -26,7 +26,7 @@ import dalvik.system.DexFile; public class PackageManagerServiceCompilerMapping { // Names for compilation reasons. static final String REASON_STRINGS[] = { - "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "forced-dexopt" + "first-boot", "boot", "install", "bg-dexopt", "ab-ota" }; // Static block to ensure the strings array is of the right length. @@ -54,16 +54,6 @@ public class PackageManagerServiceCompilerMapping { + "(reason " + REASON_STRINGS[reason] + ")"); } - // Ensure that some reasons are not mapped to profile-guided filters. - switch (reason) { - case PackageManagerService.REASON_FORCED_DEXOPT: - if (DexFile.isProfileGuidedCompilerFilter(sysPropValue)) { - throw new IllegalStateException("\"" + sysPropValue + "\" is profile-guided, " - + "but not allowed for " + REASON_STRINGS[reason]); - } - break; - } - return sysPropValue; } @@ -103,12 +93,12 @@ public class PackageManagerServiceCompilerMapping { } /** - * Return the compiler filter for "full" compilation. + * Return the default compiler filter for compilation. * * We derive that from the traditional "dalvik.vm.dex2oat-filter" property and just make * sure this isn't profile-guided. Returns "speed" in case of invalid (or missing) values. */ - public static String getFullCompilerFilter() { + public static String getDefaultCompilerFilter() { String value = SystemProperties.get("dalvik.vm.dex2oat-filter"); if (value == null || value.isEmpty()) { return "speed"; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 886fd9a85117..1d064ded4292 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5493,9 +5493,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { */ private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) { if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded); - boolean wasOccluded = mKeyguardOccluded; - boolean showing = mKeyguardDelegate.isShowing(); - if (wasOccluded && !isOccluded && showing) { + final boolean wasOccluded = mKeyguardOccluded; + final boolean showing = mKeyguardDelegate.isShowing(); + final boolean changed = wasOccluded != isOccluded || force; + if (!isOccluded && changed && showing) { mKeyguardOccluded = false; mKeyguardDelegate.setOccluded(false, true /* animate */); if (mStatusBar != null) { @@ -5505,7 +5506,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } return true; - } else if (!wasOccluded && isOccluded && showing) { + } else if (isOccluded && changed && showing) { mKeyguardOccluded = true; mKeyguardDelegate.setOccluded(true, false /* animate */); if (mStatusBar != null) { @@ -5513,7 +5514,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; } return true; - } else if (wasOccluded != isOccluded) { + } else if (changed) { mKeyguardOccluded = isOccluded; mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); return false; diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java index ee615fd6fde4..d7cdf085bfb7 100644 --- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java +++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java @@ -3,6 +3,7 @@ package com.android.server.vr; import static android.view.Display.INVALID_DISPLAY; import android.app.ActivityManagerInternal; +import android.app.CompatibilityDisplayProperties; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; @@ -35,9 +36,9 @@ class CompatibilityDisplay { private final static boolean DEBUG = false; // TODO: Go over these values and figure out what is best - private final static int HEIGHT = 1800; - private final static int WIDTH = 1400; - private final static int DPI = 320; + private int mVirtualDisplayHeight; + private int mVirtualDisplayWidth; + private int mVirtualDisplayDpi; private final static int STOP_VIRTUAL_DISPLAY_DELAY_MILLIS = 2000; private final static String DEBUG_ACTION_SET_MODE = @@ -49,6 +50,28 @@ class CompatibilityDisplay { private final static String DEBUG_EXTRA_SURFACE = "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE"; + /** + * The default width of the VR virtual display + */ + public static final int DEFAULT_VR_DISPLAY_WIDTH = 1400; + + /** + * The default height of the VR virtual display + */ + public static final int DEFAULT_VR_DISPLAY_HEIGHT = 1800; + + /** + * The default height of the VR virtual dpi. + */ + public static final int DEFAULT_VR_DISPLAY_DPI = 320; + + /** + * The minimum height, width and dpi of VR virtual display. + */ + public static final int MIN_VR_DISPLAY_WIDTH = 1; + public static final int MIN_VR_DISPLAY_HEIGHT = 1; + public static final int MIN_VR_DISPLAY_DPI = 1; + private final ActivityManagerInternal mActivityManagerInternal; private final DisplayManager mDisplayManager; private final IVrManager mVrManager; @@ -81,6 +104,9 @@ class CompatibilityDisplay { mDisplayManager = displayManager; mActivityManagerInternal = activityManagerInternal; mVrManager = vrManager; + mVirtualDisplayWidth = DEFAULT_VR_DISPLAY_WIDTH; + mVirtualDisplayHeight = DEFAULT_VR_DISPLAY_HEIGHT; + mVirtualDisplayDpi = DEFAULT_VR_DISPLAY_DPI; } /** @@ -107,7 +133,6 @@ class CompatibilityDisplay { // TODO: STOPSHIP Remove createVirtualDisplay conditional before launching. if (createVirtualDisplay) { startVirtualDisplay(); - startImageReader(); } } else { // Stop virtual display to test exit condition @@ -165,6 +190,47 @@ class CompatibilityDisplay { } /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProperties Properties of the virtual display for 2D applications + * in VR mode. + */ + public void setVirtualDisplayProperties(CompatibilityDisplayProperties compatDisplayProperties) { + synchronized(mVdLock) { + if (DEBUG) { + Log.i(TAG, "VD setVirtualDisplayProperties: res = " + + compatDisplayProperties.getWidth() + "X" + compatDisplayProperties.getHeight() + + ", dpi = " + compatDisplayProperties.getDpi()); + } + + if (compatDisplayProperties.getWidth() < MIN_VR_DISPLAY_WIDTH || + compatDisplayProperties.getHeight() < MIN_VR_DISPLAY_HEIGHT || + compatDisplayProperties.getDpi() < MIN_VR_DISPLAY_DPI) { + throw new IllegalArgumentException ( + "Illegal argument: height, width, dpi cannot be negative. res = " + + compatDisplayProperties.getWidth() + "X" + compatDisplayProperties.getHeight() + + ", dpi = " + compatDisplayProperties.getDpi()); + } + + mVirtualDisplayWidth = compatDisplayProperties.getWidth(); + mVirtualDisplayHeight = compatDisplayProperties.getHeight(); + mVirtualDisplayDpi = compatDisplayProperties.getDpi(); + + if (mVirtualDisplay != null) { + mVirtualDisplay.resize(mVirtualDisplayWidth, mVirtualDisplayHeight, + mVirtualDisplayDpi); + ImageReader oldImageReader = mImageReader; + mImageReader = null; + startImageReader(); + oldImageReader.close(); + } + } + } + + /** * Returns the virtual display ID if one currently exists, otherwise returns * {@link INVALID_DISPLAY_ID}. * @@ -175,7 +241,7 @@ class CompatibilityDisplay { if (mVirtualDisplay != null) { int virtualDisplayId = mVirtualDisplay.getDisplay().getDisplayId(); if (DEBUG) { - Log.e(TAG, "VD id: " + virtualDisplayId); + Log.i(TAG, "VD id: " + virtualDisplayId); } return virtualDisplayId; } @@ -202,12 +268,15 @@ class CompatibilityDisplay { return; } - mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT, - DPI, null /* Surface */, 0 /* flags */); + mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", + mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi, + null /* Surface */, 0 /* flags */); if (mVirtualDisplay != null) { mActivityManagerInternal.setVrCompatibilityDisplayId( mVirtualDisplay.getDisplay().getDisplayId()); + // Now create the ImageReader to supply a Surface to the new virtual display. + startImageReader(); } else { Log.w(TAG, "Virtual display id is null after createVirtualDisplay"); mActivityManagerInternal.setVrCompatibilityDisplayId(INVALID_DISPLAY); @@ -215,9 +284,7 @@ class CompatibilityDisplay { } } - if (DEBUG) { - Log.d(TAG, "VD created: " + mVirtualDisplay); - } + Log.i(TAG, "VD created: " + mVirtualDisplay); } /** @@ -241,6 +308,7 @@ class CompatibilityDisplay { mVirtualDisplay.release(); mVirtualDisplay = null; } + stopImageReader(); } } } @@ -279,11 +347,23 @@ class CompatibilityDisplay { */ private void startImageReader() { if (mImageReader == null) { - mImageReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, - 2 /* maxImages */); + mImageReader = ImageReader.newInstance(mVirtualDisplayWidth, mVirtualDisplayHeight, + PixelFormat.RGBA_8888, 2 /* maxImages */); + Log.i(TAG, "VD startImageReader: res = " + mVirtualDisplayWidth + "X" + + mVirtualDisplayHeight + ", dpi = " + mVirtualDisplayDpi); } synchronized (mVdLock) { setSurfaceLocked(mImageReader.getSurface()); } } + + /** + * Cleans up the ImageReader. + */ + private void stopImageReader() { + if (mImageReader != null) { + mImageReader.close(); + mImageReader = null; + } + } } diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java index 358861d0c9c4..63c61955bcd7 100644 --- a/services/core/java/com/android/server/vr/VrManagerInternal.java +++ b/services/core/java/com/android/server/vr/VrManagerInternal.java @@ -16,6 +16,7 @@ package com.android.server.vr; import android.annotation.NonNull; +import android.app.CompatibilityDisplayProperties; import android.content.ComponentName; import android.service.vr.IPersistentVrStateCallbacks; @@ -82,6 +83,18 @@ public abstract class VrManagerInternal { public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId); /** + * Sets the resolution and DPI of the compatibility virtual display used to display + * 2D applications in VR mode. + * + * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p> + * + * @param compatDisplayProp Properties of the virtual display for 2D applications + * in VR mode. + */ + public abstract void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp); + + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used * by VR viewers to indicate that a device is placed in a VR viewer. diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index cc089184d2ed..860b2419327a 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -21,6 +21,7 @@ import android.Manifest; import android.app.ActivityManagerInternal; import android.app.ActivityManager; import android.app.AppOpsManager; +import android.app.CompatibilityDisplayProperties; import android.app.NotificationManager; import android.annotation.NonNull; import android.content.ComponentName; @@ -427,6 +428,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC } @Override + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS); + VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp); + } + + @Override public int getCompatibilityDisplayId() { return VrManagerService.this.getCompatibilityDisplayId(); } @@ -541,6 +549,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC } @Override + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp); + } + + @Override public int getCompatibilityDisplayId() { return VrManagerService.this.getCompatibilityDisplayId(); } @@ -642,16 +656,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC false, mOverlayToken, null, oldUserId); } - if (!mVrModeEnabled) { - return; - } - // Apply the restrictions for the current user based on vr state String[] exemptions = (exemptedPackage == null) ? new String[0] : new String[] { exemptedPackage }; appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, - true, mOverlayToken, exemptions, newUserId); + mVrModeEnabled, mOverlayToken, exemptions, newUserId); } private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId, @@ -1106,6 +1116,15 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } + public void setCompatibilityDisplayProperties( + CompatibilityDisplayProperties compatDisplayProp) { + if (mCompatibilityDisplay != null) { + mCompatibilityDisplay.setVirtualDisplayProperties(compatDisplayProp); + return; + } + Slog.w(TAG, "CompatibilityDisplay is null!"); + } + private int getCompatibilityDisplayId() { if (mCompatibilityDisplay != null) { return mCompatibilityDisplay.getVirtualDisplayId(); diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 292734db74a8..c625cbea1fa4 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -323,7 +323,7 @@ public class AppWindowContainerController } } - public void setVisibility(boolean visible) { + public void setVisibility(boolean visible, boolean deferHidingClient) { synchronized(mWindowMap) { if (mContainer == null) { Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " @@ -342,6 +342,7 @@ public class AppWindowContainerController mService.mClosingApps.remove(wtoken); wtoken.waitingToShow = false; wtoken.hiddenRequested = !visible; + wtoken.mDeferHidingClient = deferHidingClient; if (!visible) { // If the app is dead while it was visible, we kept its dead window on screen. @@ -368,15 +369,12 @@ public class AppWindowContainerController wtoken.waitingToShow = true; } - if (wtoken.clientHidden) { - // In the case where we are making an app visible - // but holding off for a transition, we still need - // to tell the client to make its windows visible so - // they get drawn. Otherwise, we will wait on - // performing the transition until all windows have - // been drawn, they never will be, and we are sad. - wtoken.clientHidden = false; - wtoken.sendAppVisibilityToClients(); + if (wtoken.isClientHidden()) { + // In the case where we are making an app visible but holding off for a + // transition, we still need to tell the client to make its windows visible + // so they get drawn. Otherwise, we will wait on performing the transition + // until all windows have been drawn, they never will be, and we are sad. + wtoken.setClientHidden(false); } } wtoken.requestUpdateWallpaperIfNeeded(); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 763464422e56..3c2dfa51d8f6 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -95,6 +95,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // change. private boolean mReparenting; + // True if we are current in the process of removing this app token from the display + private boolean mRemovingFromDisplay = false; + // The input dispatching timeout for this application token in nanoseconds. long mInputDispatchingTimeoutNanos; @@ -126,7 +129,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree boolean hiddenRequested; // Have we told the window clients to hide themselves? - boolean clientHidden; + private boolean mClientHidden; + + // If true we will defer setting mClientHidden to true and reporting to the client that it is + // hidden. + boolean mDeferHidingClient; // Last visibility state we reported to the app token. boolean reportedVisible; @@ -175,6 +182,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private boolean mDisbalePreviewScreenshots; + Task mLastParent; + AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, @@ -307,16 +316,25 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } + boolean isClientHidden() { + return mClientHidden; + } + + void setClientHidden(boolean hideClient) { + if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) { + return; + } + mClientHidden = hideClient; + sendAppVisibilityToClients(); + } + boolean setVisibility(WindowManager.LayoutParams lp, boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) { boolean delayed = false; inPendingTransaction = false; - if (clientHidden == visible) { - clientHidden = !visible; - sendAppVisibilityToClients(); - } + setClientHidden(!visible); // Allow for state changes and animation to be applied if: // * token is transitioning visibility state @@ -465,6 +483,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } @Override + void removeImmediately() { + onRemovedFromDisplay(); + super.removeImmediately(); + } + + @Override void removeIfPossible() { mIsExiting = false; removeAllWindowsIfPossible(); @@ -480,6 +504,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } void onRemovedFromDisplay() { + if (mRemovingFromDisplay) { + return; + } + mRemovingFromDisplay = true; + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this); boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction); @@ -512,12 +541,14 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mService.mNoAnimationNotifyOnTransitionFinished.add(token); } - final TaskStack stack = getTask().mStack; + final TaskStack stack = getStack(); if (delayed && !isEmpty()) { // set the token aside because it has an active animation to be finished if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken make exiting: " + this); - stack.mExitingAppTokens.add(this); + if (stack != null) { + stack.mExitingAppTokens.add(this); + } mIsExiting = true; } else { // Make sure there is no animation running on this token, so any windows associated @@ -540,6 +571,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (!delayed) { updateReportedVisibilityLocked(); } + + mRemovingFromDisplay = false; } void clearAnimatingFlags() { @@ -725,19 +758,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree void onParentSet() { super.onParentSet(); + final Task task = getTask(); + // When the associated task is {@code null}, the {@link AppWindowToken} can no longer // access visual elements like the {@link DisplayContent}. We must remove any associations // such as animations. if (!mReparenting) { - final Task task = getTask(); if (task == null) { // It is possible we have been marked as a closing app earlier. We must remove ourselves // from this list so we do not participate in any future animations. mService.mClosingApps.remove(this); - } else if (task.mStack != null) { + } else if (mLastParent != null && mLastParent.mStack != null) { task.mStack.mExitingAppTokens.remove(this); } } + mLastParent = task; } void postWindowRemoveStartingWindowCleanup(WindowState win) { @@ -1143,10 +1178,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree hidden = false; hiddenRequested = false; } - if (clientHidden != fromToken.clientHidden) { - clientHidden = fromToken.clientHidden; - sendAppVisibilityToClients(); - } + setClientHidden(fromToken.mClientHidden); fromToken.mAppAnimator.transferCurrentAnimation( mAppAnimator, tStartingWindow.mWinAnimator); @@ -1511,10 +1543,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree pw.print(prefix); pw.print("task="); pw.println(getTask()); pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent); pw.print(" mOrientation="); pw.println(mOrientation); - pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); - pw.print(" clientHidden="); pw.print(clientHidden); - pw.print(" reportedDrawn="); pw.print(reportedDrawn); - pw.print(" reportedVisible="); pw.println(reportedVisible); + pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden + + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "") + + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible); if (paused) { pw.print(prefix); pw.print("paused="); pw.println(paused); } @@ -1558,6 +1589,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (getController() != null) { pw.print(prefix); pw.print("controller="); pw.println(getController()); } + if (mRemovingFromDisplay) { + pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay); + } } @Override diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 182361015a05..e2f313a37dbf 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2245,7 +2245,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo wsa.destroySurface(); mService.mForceRemoves.add(w); mTmpWindow = w; - } else if (w.mAppToken != null && w.mAppToken.clientHidden) { + } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) { Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " + w + " surface=" + wsa.mSurfaceController + " token=" + w.mAppToken diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 4262d124ed0a..bc749e16fe6b 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -439,7 +439,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU for (int i = mChildren.size() - 1; i >= 0; i--) { final AppWindowToken token = mChildren.get(i); // skip hidden (or about to hide) apps - if (token.mIsExiting || token.clientHidden || token.hiddenRequested) { + if (token.mIsExiting || token.isClientHidden() || token.hiddenRequested) { continue; } final WindowState win = token.findMainWindow(); @@ -607,7 +607,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU for (int i = mChildren.size() - 1; i >= 0; i--) { final AppWindowToken token = mChildren.get(i); // skip hidden (or about to hide) apps - if (!token.mIsExiting && !token.clientHidden && !token.hiddenRequested) { + if (!token.mIsExiting && !token.isClientHidden() && !token.hiddenRequested) { return token; } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 1feb743b66dc..da7a9f0ec58f 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -733,10 +733,17 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye outTempTaskBounds.setEmpty(); // When the home stack is resizable, should always have the same stack and task bounds - if (mStackId == HOME_STACK_ID && findHomeTask().isResizeable()) { - // Calculate the home stack bounds when in docked mode - getDisplayContent().mDividerControllerLocked - .getHomeStackBoundsInDockedMode(outStackBounds); + if (mStackId == HOME_STACK_ID) { + if (findHomeTask().isResizeable()) { + // Calculate the home stack bounds when in docked mode and the home stack is + // resizeable. + getDisplayContent().mDividerControllerLocked + .getHomeStackBoundsInDockedMode(outStackBounds); + } else { + // Home stack isn't resizeable, so don't specify stack bounds. + outStackBounds.setEmpty(); + } + outTempTaskBounds.set(outStackBounds); return; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 252b4d4e0473..9d6e0334a5be 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1470,7 +1470,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mInTouchMode) { res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; } - if (win.mAppToken == null || !win.mAppToken.clientHidden) { + if (win.mAppToken == null || !win.mAppToken.isClientHidden()) { res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; } @@ -1950,7 +1950,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (viewVisibility == View.VISIBLE && (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING - || !win.mAppToken.clientHidden)) { + || !win.mAppToken.isClientHidden())) { result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges, oldVisibility); try { @@ -5035,6 +5035,7 @@ public class WindowManagerService extends IWindowManager.Stub if (callback != null) { callback.run(); } + break; } case NEW_ANIMATOR_SCALE: { float scale = getCurrentAnimatorScale(); @@ -5087,6 +5088,7 @@ public class WindowManagerService extends IWindowManager.Stub } } } + break; case UPDATE_DOCKED_STACK_DIVIDER: { synchronized (mWindowMap) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); @@ -5104,6 +5106,7 @@ public class WindowManagerService extends IWindowManager.Stub mWindowReplacementTimeouts.clear(); } } + break; case NOTIFY_APP_TRANSITION_STARTING: { mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj); } @@ -5606,22 +5609,19 @@ public class WindowManagerService extends IWindowManager.Stub WindowState win = mWindowMap.get(client); if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win); if (win == null) { - RuntimeException ex = new IllegalArgumentException( - "Requested window " + client + " does not exist"); if (throwOnError) { - throw ex; + throw new IllegalArgumentException( + "Requested window " + client + " does not exist"); } - Slog.w(TAG_WM, "Failed looking up window", ex); + Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3)); return null; } if (session != null && win.mSession != session) { - RuntimeException ex = new IllegalArgumentException( - "Requested window " + client + " is in session " + - win.mSession + ", not " + session); if (throwOnError) { - throw ex; + throw new IllegalArgumentException("Requested window " + client + " is in session " + + win.mSession + ", not " + session); } - Slog.w(TAG_WM, "Failed looking up window", ex); + Slog.w(TAG_WM, "Failed looking up window callers=" + Debug.getCallers(3)); return null; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b9776a362b8b..9bdcc3603564 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1399,7 +1399,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * @return true if the window should be considered while evaluating allDrawn flags. */ boolean mightAffectAllDrawn(boolean visibleOnly) { - final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden) + final boolean isViewVisible = (mAppToken == null || !mAppToken.isClientHidden()) && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed; return (isOnScreen() && (!visibleOnly || isViewVisible) || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION @@ -2312,7 +2312,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * interacts with it. */ boolean shouldKeepVisibleDeadAppWindow() { - if (!isWinVisibleLw() || mAppToken == null || mAppToken.clientHidden) { + if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) { // Not a visible app window or the app isn't dead. return false; } @@ -2570,12 +2570,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void sendAppVisibilityToClients() { super.sendAppVisibilityToClients(); - final boolean clientHidden = mAppToken.clientHidden; + final boolean clientHidden = mAppToken.isClientHidden(); if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) { // Don't hide the starting window. return; } + if (clientHidden) { + // Once we are notifying the client that it's visibility has changed, we need to prevent + // it from destroying child surfaces until the animation has finished. We do this by + // detaching any surface control the client added from the client. + for (int i = mChildren.size() - 1; i >= 0; --i) { + final WindowState c = mChildren.get(i); + c.mWinAnimator.detachChildren(); + } + + mWinAnimator.detachChildren(); + } + try { if (DEBUG_VISIBILITY) Slog.v(TAG, "Setting visibility of " + this + ": " + (!clientHidden)); diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java index d383aea5a679..d4904f5aecf7 100644 --- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -15,6 +15,11 @@ */ package com.android.server.notification; +import static android.app.Notification.GROUP_ALERT_ALL; +import static android.app.Notification.GROUP_ALERT_CHILDREN; +import static android.app.Notification.GROUP_ALERT_SUMMARY; +import static android.app.NotificationManager.IMPORTANCE_HIGH; + import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; @@ -186,19 +191,26 @@ public class BuzzBeepBlinkTest { private NotificationRecord getCustomLightsNotification() { return getNotificationRecord(mId, false /* insistent */, true /* once */, false /* noisy */, true /* buzzy*/, true /* lights */, - true /* defaultVibration */, true /* defaultSound */, false /* defaultLights */); + true /* defaultVibration */, true /* defaultSound */, false /* defaultLights */, + null, Notification.GROUP_ALERT_ALL); } private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once, boolean noisy, boolean buzzy, boolean lights) { - return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true); + return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true, + null, Notification.GROUP_ALERT_ALL); + } + + private NotificationRecord getBeepyNotificationRecord(String groupKey, int groupAlertBehavior) { + return getNotificationRecord(mId, false, false, true, false, false, true, true, true, + groupKey, groupAlertBehavior); } private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once, boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration, - boolean defaultSound, boolean defaultLights) { + boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior) { NotificationChannel channel = - new NotificationChannel("test", "test", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("test", "test", IMPORTANCE_HIGH); final Builder builder = new Builder(getContext()) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon) @@ -237,6 +249,9 @@ public class BuzzBeepBlinkTest { } builder.setDefaults(defaults); + builder.setGroup(groupKey); + builder.setGroupAlertBehavior(groupAlertBehavior); + Notification n = builder.build(); if (insistent) { n.flags |= Notification.FLAG_INSISTENT; @@ -544,7 +559,7 @@ public class BuzzBeepBlinkTest { } @Test - public void testInsistenteVibrate() throws Exception { + public void testInsistentVibrate() throws Exception { NotificationRecord r = getInsistentBuzzyNotification(); mService.buzzBeepBlinkLocked(r); @@ -566,6 +581,71 @@ public class BuzzBeepBlinkTest { } @Test + public void testGroupAlertSummarySilenceChild() throws Exception { + NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); + + mService.buzzBeepBlinkLocked(child); + + verifyNeverBeep(); + } + + @Test + public void testGroupAlertSummaryNoSilenceSummary() throws Exception { + NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY); + summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; + + mService.buzzBeepBlinkLocked(summary); + + verifyBeepLooped(); + } + + @Test + public void testGroupAlertSummaryNoSilenceNonGroupChild() throws Exception { + NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_SUMMARY); + + mService.buzzBeepBlinkLocked(nonGroup); + + verifyBeepLooped(); + } + + @Test + public void testGroupAlertChildSilenceSummary() throws Exception { + NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); + summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; + + mService.buzzBeepBlinkLocked(summary); + + verifyNeverBeep(); + } + + @Test + public void testGroupAlertChildNoSilenceChild() throws Exception { + NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN); + + mService.buzzBeepBlinkLocked(child); + + verifyBeepLooped(); + } + + @Test + public void testGroupAlertChildNoSilenceNonGroupSummary() throws Exception { + NotificationRecord nonGroup = getBeepyNotificationRecord(null, GROUP_ALERT_CHILDREN); + + mService.buzzBeepBlinkLocked(nonGroup); + + verifyBeepLooped(); + } + + @Test + public void testGroupAlertAllNoSilenceGroup() throws Exception { + NotificationRecord group = getBeepyNotificationRecord("a", GROUP_ALERT_ALL); + + mService.buzzBeepBlinkLocked(group); + + verifyBeepLooped(); + } + + @Test public void testHonorAlertOnlyOnceForBuzz() throws Exception { NotificationRecord r = getBuzzyNotification(); NotificationRecord s = getBuzzyOnceNotification(); @@ -680,6 +760,23 @@ public class BuzzBeepBlinkTest { verifyStopVibrate(); } + @Test + public void testEmptyUriSoundTreatedAsNoSound() throws Exception { + NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH); + channel.setSound(Uri.EMPTY, null); + final Notification n = new Builder(getContext(), "test") + .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); + + StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid, + mPid, n, mUser, null, System.currentTimeMillis()); + NotificationRecord r = new NotificationRecord(getContext(), sbn, channel); + mService.addNotification(r); + + mService.buzzBeepBlinkLocked(r); + + verifyNeverBeep(); + } + static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> { private final int mRepeatIndex; diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index 303054e77793..bc5c29d514a5 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -18,6 +18,7 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.app.NotificationManager.IMPORTANCE_NONE; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.fail; @@ -504,12 +505,23 @@ public class RankingHelperTest { @Test public void testCreateChannel_blocked() throws Exception { - mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_NONE); + mHelper.setImportance(PKG, UID, IMPORTANCE_NONE); mHelper.createNotificationChannel(PKG, UID, new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true); } + @Test + public void testCreateChannel_ImportanceNone() throws Exception { + try { + mHelper.createNotificationChannel(PKG, UID, + new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true); + fail("Was allowed to create a blocked channel"); + } catch (IllegalArgumentException e) { + // yay + } + } + @Test public void testUpdate() throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index 985e5eaee256..c78488f9d8d9 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -16,25 +16,18 @@ package com.android.server; -import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; -import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE; import static android.net.NetworkScoreManager.CACHE_FILTER_NONE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -55,8 +48,6 @@ import android.net.INetworkScoreCache; import android.net.NetworkKey; import android.net.NetworkScoreManager; import android.net.NetworkScorerAppData; -import android.net.RecommendationRequest; -import android.net.RecommendationResult; import android.net.ScoredNetwork; import android.net.Uri; import android.net.WifiKey; @@ -69,13 +60,11 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.runner.AndroidJUnit4; @@ -145,9 +134,6 @@ public class NetworkScoreServiceTest { private ContentResolver mContentResolver; private NetworkScoreService mNetworkScoreService; - private RecommendationRequest mRecommendationRequest; - private RemoteCallback mRemoteCallback; - private OnResultListener mOnResultListener; private HandlerThread mHandlerThread; private List<ScanResult> mScanResults; @@ -177,13 +163,6 @@ public class NetworkScoreServiceTest { WifiConfiguration configuration = new WifiConfiguration(); configuration.SSID = "NetworkScoreServiceTest_SSID"; configuration.BSSID = "NetworkScoreServiceTest_BSSID"; - mRecommendationRequest = new RecommendationRequest.Builder() - .setDefaultWifiConfig(configuration).build(); - mOnResultListener = new OnResultListener(); - mRemoteCallback = new RemoteCallback(mOnResultListener); - Settings.Global.putLong(mContentResolver, - Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, -1L); - mNetworkScoreService.refreshRecommendationRequestTimeoutMs(); populateScanResults(); } @@ -215,7 +194,6 @@ public class NetworkScoreServiceTest { verify(mNetworkScorerAppManager).updateState(); verify(mNetworkScorerAppManager).migrateNetworkScorerAppSettingIfNeeded(); verify(mServiceConnection).bind(mContext); - } @Test @@ -256,160 +234,6 @@ public class NetworkScoreServiceTest { } @Test - public void testRequestRecommendation_noPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), - anyString()); - try { - mNetworkScoreService.requestRecommendation(mRecommendationRequest); - fail("REQUEST_NETWORK_SCORES not enforced."); - } catch (SecurityException e) { - // expected - } - } - - @Test - public void testRequestRecommendation_mainThread() throws Exception { - when(mContext.getMainLooper()).thenReturn(Looper.myLooper()); - try { - mNetworkScoreService.requestRecommendation(mRecommendationRequest); - fail("requestRecommendation run on main thread."); - } catch (RuntimeException e) { - // expected - } - } - - @Test - public void testRequestRecommendation_providerNotConnected() throws Exception { - when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); - - final RecommendationResult result = - mNetworkScoreService.requestRecommendation(mRecommendationRequest); - assertNotNull(result); - assertEquals(mRecommendationRequest.getDefaultWifiConfig(), - result.getWifiConfiguration()); - } - - @Test - public void testRequestRecommendation_providerThrowsRemoteException() throws Exception { - when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); - doThrow(new RemoteException()).when(mRecommendationProvider) - .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), - anyInt()); - mNetworkScoreService.onUserUnlocked(0); - - final RecommendationResult result = - mNetworkScoreService.requestRecommendation(mRecommendationRequest); - assertNotNull(result); - assertEquals(mRecommendationRequest.getDefaultWifiConfig(), - result.getWifiConfiguration()); - } - - @Test - public void testRequestRecommendation_resultReturned() throws Exception { - when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); - final WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID"; - wifiConfiguration.BSSID = "testRequestRecommendation_resultReturned_BSSID"; - final RecommendationResult providerResult = RecommendationResult - .createConnectRecommendation(wifiConfiguration); - final Bundle bundle = new Bundle(); - bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult); - doAnswer(invocation -> { - bundle.putInt(EXTRA_SEQUENCE, invocation.getArgument(2)); - invocation.<IRemoteCallback>getArgument(1).sendResult(bundle); - return null; - }).when(mRecommendationProvider) - .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), - anyInt()); - mNetworkScoreService.onUserUnlocked(0); - - final RecommendationResult result = - mNetworkScoreService.requestRecommendation(mRecommendationRequest); - assertNotNull(result); - assertEquals(providerResult.getWifiConfiguration().SSID, - result.getWifiConfiguration().SSID); - assertEquals(providerResult.getWifiConfiguration().BSSID, - result.getWifiConfiguration().BSSID); - } - - @Test - public void testRequestRecommendationAsync_noPermission() throws Exception { - doThrow(new SecurityException()).when(mContext) - .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), - anyString()); - try { - mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest, - mRemoteCallback); - fail("REQUEST_NETWORK_SCORES not enforced."); - } catch (SecurityException e) { - // expected - } - } - - @Test - public void testRequestRecommendationAsync_providerNotConnected() throws Exception { - mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest, - mRemoteCallback); - boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS); - assertTrue(callbackRan); - verifyZeroInteractions(mRecommendationProvider); - } - - @Test - public void testRequestRecommendationAsync_requestTimesOut() throws Exception { - mNetworkScoreService.onUserUnlocked(0); - Settings.Global.putLong(mContentResolver, - Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L); - mNetworkScoreService.refreshRecommendationRequestTimeoutMs(); - mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest, - mRemoteCallback); - boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS); - assertTrue(callbackRan); - verify(mRecommendationProvider).requestRecommendation(eq(mRecommendationRequest), - isA(IRemoteCallback.Stub.class), anyInt()); - - assertTrue(mOnResultListener.receivedBundle.containsKey(EXTRA_RECOMMENDATION_RESULT)); - RecommendationResult result = - mOnResultListener.receivedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT); - assertTrue(result.hasRecommendation()); - assertEquals(mRecommendationRequest.getDefaultWifiConfig().SSID, - result.getWifiConfiguration().SSID); - } - - @Test - public void testRequestRecommendationAsync_requestSucceeds() throws Exception { - mNetworkScoreService.onUserUnlocked(0); - final Bundle bundle = new Bundle(); - doAnswer(invocation -> { - invocation.<IRemoteCallback>getArgument(1).sendResult(bundle); - return null; - }).when(mRecommendationProvider) - .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), - anyInt()); - - mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest, - mRemoteCallback); - boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS); - assertTrue(callbackRan); - // If it's not the same instance then something else ran the callback. - assertSame(bundle, mOnResultListener.receivedBundle); - } - - @Test - public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception { - mNetworkScoreService.onUserUnlocked(0); - doThrow(new RemoteException()).when(mRecommendationProvider) - .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), - anyInt()); - - mNetworkScoreService.requestRecommendationAsync(mRecommendationRequest, - mRemoteCallback); - boolean callbackRan = mOnResultListener.countDownLatch.await(3, TimeUnit.SECONDS); - assertTrue(callbackRan); - } - - @Test public void dispatchingContentObserver_nullUri() throws Exception { NetworkScoreService.DispatchingContentObserver observer = new NetworkScoreService.DispatchingContentObserver(mContext, null /*handler*/); @@ -435,15 +259,6 @@ public class NetworkScoreServiceTest { } @Test - public void oneTimeCallback_multipleCallbacks() throws Exception { - NetworkScoreService.OneTimeCallback callback = - new NetworkScoreService.OneTimeCallback(mRemoteCallback); - callback.sendResult(null); - callback.sendResult(null); - assertEquals(1, mOnResultListener.resultCount); - } - - @Test public void testUpdateScores_notActiveScorer() { bindToScorer(false /*callerIsScorer*/); @@ -1088,19 +903,6 @@ public class NetworkScoreServiceTest { mNetworkScoreService.onUserUnlocked(0); } - private static class OnResultListener implements RemoteCallback.OnResultListener { - private final CountDownLatch countDownLatch = new CountDownLatch(1); - private int resultCount; - private Bundle receivedBundle; - - @Override - public void onResult(Bundle result) { - countDownLatch.countDown(); - resultCount++; - receivedBundle = result; - } - } - private static class CountDownHandler extends Handler { CountDownLatch latch = new CountDownLatch(1); int receivedWhat; diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java index 20839c5f7a18..36e9b3f8a9e4 100644 --- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java @@ -22,6 +22,7 @@ import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.never; import static org.mockito.Mockito.nullable; import static org.mockito.Mockito.times; @@ -80,6 +81,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; @@ -2443,7 +2445,6 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testGetAccountsByFeaturesError() throws Exception { unlockSystemUser(); - mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_ERROR, "p12", null); @@ -2511,28 +2512,37 @@ public class AccountManagerServiceTest extends AndroidTestCase { updateBroadcastCounters(2); assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent assertEquals(mLoginAccountsChangedBroadcasts, 2); - assertEquals(mAccountRemovedBroadcasts, 0); } @SmallTest public void testRegisterAccountListenerWithAddingTwoAccounts() throws Exception { unlockSystemUser(); + + HashMap<String, Integer> visibility = new HashMap<>(); + visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE, + AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, - "testpackage"); // opPackageName - mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); + AccountManagerServiceTestFixtures.CALLER_PACKAGE); + mAms.addAccountExplicitlyWithVisibility( + AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); mAms.unregisterAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, - "testpackage"); // opPackageName - mAms.addAccountExplicitly( - AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p11", null); + AccountManagerServiceTestFixtures.CALLER_PACKAGE); + + addAccountRemovedReceiver(AccountManagerServiceTestFixtures.CALLER_PACKAGE); + mAms.addAccountExplicitlyWithVisibility( + AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p11", null, visibility); updateBroadcastCounters(3); assertEquals(mVisibleAccountsChangedBroadcasts, 1); assertEquals(mLoginAccountsChangedBroadcasts, 2); + assertEquals(mAccountRemovedBroadcasts, 0); mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS); - mAms.registerAccountListener( null /* accountTypes */, "testpackage"); + mAms.registerAccountListener( null /* accountTypes */, + AccountManagerServiceTestFixtures.CALLER_PACKAGE); mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE); updateBroadcastCounters(8); @@ -2544,6 +2554,13 @@ public class AccountManagerServiceTest extends AndroidTestCase { @SmallTest public void testRegisterAccountListenerForThreePackages() throws Exception { unlockSystemUser(); + + addAccountRemovedReceiver("testpackage1"); + HashMap<String, Integer> visibility = new HashMap<>(); + visibility.put("testpackage1", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + visibility.put("testpackage2", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + visibility.put("testpackage3", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage1"); // opPackageName @@ -2553,7 +2570,8 @@ public class AccountManagerServiceTest extends AndroidTestCase { mAms.registerAccountListener( new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, "testpackage3"); // opPackageName - mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null); + mAms.addAccountExplicitlyWithVisibility( + AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); updateBroadcastCounters(4); assertEquals(mVisibleAccountsChangedBroadcasts, 3); assertEquals(mLoginAccountsChangedBroadcasts, 1); @@ -2572,13 +2590,47 @@ public class AccountManagerServiceTest extends AndroidTestCase { mAms.addAccountExplicitly( AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_TYPE_2, "p11", null); - updateBroadcastCounters(9); + updateBroadcastCounters(8); assertEquals(mVisibleAccountsChangedBroadcasts, 5); assertEquals(mLoginAccountsChangedBroadcasts, 3); assertEquals(mAccountRemovedBroadcasts, 1); } @SmallTest + public void testRegisterAccountListenerForAddingAccountWithVisibility() throws Exception { + unlockSystemUser(); + + HashMap<String, Integer> visibility = new HashMap<>(); + visibility.put("testpackage1", AccountManager.VISIBILITY_NOT_VISIBLE); + visibility.put("testpackage2", AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE); + visibility.put("testpackage3", AccountManager.VISIBILITY_USER_MANAGED_VISIBLE); + + addAccountRemovedReceiver("testpackage1"); + mAms.registerAccountListener( + new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, + "testpackage1"); // opPackageName + mAms.registerAccountListener( + new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, + "testpackage2"); // opPackageName + mAms.registerAccountListener( + new String [] {AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1}, + "testpackage3"); // opPackageName + mAms.addAccountExplicitlyWithVisibility( + AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility); + + updateBroadcastCounters(2); + assertEquals(mVisibleAccountsChangedBroadcasts, 1); + assertEquals(mLoginAccountsChangedBroadcasts, 1); + + mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS); + + updateBroadcastCounters(4); + assertEquals(mVisibleAccountsChangedBroadcasts, 2); + assertEquals(mLoginAccountsChangedBroadcasts, 2); + assertEquals(mAccountRemovedBroadcasts, 0); // account was never visible. + } + + @SmallTest public void testRegisterAccountListenerCredentialsUpdate() throws Exception { unlockSystemUser(); mAms.registerAccountListener( @@ -2609,21 +2661,31 @@ public class AccountManagerServiceTest extends AndroidTestCase { mLoginAccountsChangedBroadcasts = 0; mAccountRemovedBroadcasts = 0; ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); - verify(mMockContext, times(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(), + verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(), any(UserHandle.class)); for (Intent intent : captor.getAllValues()) { if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) { mVisibleAccountsChangedBroadcasts++; - } - if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) { + } else if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) { mLoginAccountsChangedBroadcasts++; - } - if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) { + } else if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) { mAccountRemovedBroadcasts++; } } } + private void addAccountRemovedReceiver(String packageName) { + ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = new ActivityInfo(); + resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); + resolveInfo.activityInfo.applicationInfo.packageName = packageName; + + List<ResolveInfo> accountRemovedReceivers = new ArrayList<>(); + accountRemovedReceivers.add(resolveInfo); + when(mMockPackageManager.queryBroadcastReceiversAsUser(any(Intent.class), anyInt(), + anyInt())).thenReturn(accountRemovedReceivers); + } + @SmallTest public void testConcurrencyReadWrite() throws Exception { // Test 2 threads calling getAccounts and 1 thread setAuthToken diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 31595a69fc65..3f6f8ec277bf 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -63,6 +63,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Random; import java.util.Scanner; import java.util.Set; @@ -537,6 +538,7 @@ public class UsbDeviceManager { oldFunctions = UsbManager.USB_FUNCTION_NONE; } + Slog.i(TAG, "Setting adb to " + String.valueOf(enable)); setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked); updateAdbNotification(); } @@ -764,15 +766,16 @@ public class UsbDeviceManager { // send broadcast intent only if the USB state has changed if (!isUsbStateChanged(intent)) { - if (DEBUG) { - Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras()); - } + Slog.i(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras()); return; } + mBroadcastedIntent = intent; - if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras()); + Random rand = new Random(); + intent.putExtra("random_tag", rand.nextInt(1000)); + Slog.i(TAG, "broadcasting " + intent + " extras: " + intent.getExtras()); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - mBroadcastedIntent = intent; + intent.removeExtra("random_tag"); } private void updateUsbFunctions() { @@ -845,8 +848,10 @@ public class UsbDeviceManager { updateCurrentAccessory(); } if (mBootCompleted) { + Slog.i(TAG, "update state " + mConnected + " " + mConfigured); if (!mConnected) { // restore defaults when USB is disconnected + Slog.i(TAG, "Disconnect, setting usb functions to null"); setEnabledFunctions(null, false, false); } updateUsbStateBroadcastIfNeeded(false); @@ -880,6 +885,7 @@ public class UsbDeviceManager { break; case MSG_SET_CURRENT_FUNCTIONS: String functions = (String) msg.obj; + Slog.i(TAG, "Getting setFunction command for " + functions); setEnabledFunctions(functions, false, msg.arg1 == 1); break; case MSG_UPDATE_USER_RESTRICTIONS: @@ -887,6 +893,8 @@ public class UsbDeviceManager { final boolean forceRestart = mUsbDataUnlocked && isUsbDataTransferActive() && !isUsbTransferAllowed(); + Slog.i(TAG, "Updating user restrictions, force restart is " + + String.valueOf(forceRestart)); setEnabledFunctions( mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart); break; @@ -901,6 +909,7 @@ public class UsbDeviceManager { updateUsbStateBroadcastIfNeeded(false); mPendingBootBroadcast = false; } + Slog.i(TAG, "Boot complete, setting default functions"); setEnabledFunctions(null, false, false); if (mCurrentAccessory != null) { getCurrentSettings().accessoryAttached(mCurrentAccessory); @@ -918,6 +927,7 @@ public class UsbDeviceManager { Slog.v(TAG, "Current user switched to " + msg.arg1 + "; resetting USB host stack for MTP or PTP"); // avoid leaking sensitive data from previous user + Slog.i(TAG, "User Switched, kicking usb stack"); setEnabledFunctions(mCurrentFunctions, true, false); } mCurrentUser = msg.arg1; diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 0342da7aa6ef..0a47a9890c8d 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -16,6 +16,7 @@ package android.telecom; import android.Manifest; import android.annotation.RequiresPermission; +import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; @@ -46,6 +47,7 @@ import java.util.List; * permissions declared in its manifest file. Where permissions apply, they are noted in the method * descriptions. */ +@SuppressAutoDoc public class TelecomManager { /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 8ee6454ebd66..1ef9e494be68 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -45,6 +45,7 @@ import android.provider.Settings.SettingNotFoundException; import android.service.carrier.CarrierIdentifier; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.telephony.VisualVoicemailService.VisualVoicemailTask; import android.telephony.ims.feature.ImsFeature; import android.util.Log; @@ -883,16 +884,24 @@ public class TelephonyManager { /** * USSD return code success. + * @hide */ public static final int USSD_RETURN_SUCCESS = 100; /** - * USSD return code for failure case. + * Failed code returned when the mobile network has failed to complete a USSD request. + * <p> + * Returned via {@link TelephonyManager.UssdResponseCallback#onReceiveUssdResponseFailed( + * TelephonyManager, String, int)}. */ public static final int USSD_RETURN_FAILURE = -1; /** - * USSD return code for failure case. + * Failure code returned when a USSD request has failed to execute because the Telephony + * service is unavailable. + * <p> + * Returned via {@link TelephonyManager.UssdResponseCallback#onReceiveUssdResponseFailed( + * TelephonyManager, String, int)}. */ public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; @@ -2766,6 +2775,54 @@ public class TelephonyManager { } /** + * Set the visual voicemail SMS filter settings for the subscription ID pinned + * to the TelephonyManager. + * When the filter is enabled, {@link + * VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be + * called when a SMS matching the settings is received. The caller should have + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} and implement a + * VisualVoicemailService. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param settings The settings for the filter, or {@code null} to disable the filter. + */ + public void setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings settings) { + if (settings == null) { + disableVisualVoicemailSmsFilter(mSubId); + } else { + enableVisualVoicemailSmsFilter(mSubId, settings); + } + } + + /** + * Send a visual voicemail SMS. The caller must be the current default dialer. + * A {@link VisualVoicemailService} uses this method to send a command via SMS to the carrier's + * visual voicemail server. Some examples for carriers using the OMTP standard include + * activating and deactivating visual voicemail, or requesting the current visual voicemail + * provisioning status. See the OMTP Visual Voicemail specification for more information on the + * format of these SMS messages. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#SEND_SMS SEND_SMS} + * + * @param number The destination number. + * @param port The destination port for data SMS, or 0 for text SMS. + * @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream. + * @param sentIntent The sent intent passed to the {@link SmsManager} + * + * @throws SecurityException if the caller is not the current default dialer + * + * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent) + * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent) + */ + public void sendVisualVoicemailSms(String number, int port, String text, + PendingIntent sentIntent) { + sendVisualVoicemailSmsForSubscriber(mSubId, number, port, text, sentIntent); + } + + /** * Enables the visual voicemail SMS filter for a phone account. When the filter is * enabled, Incoming SMS messages matching the OMTP VVM SMS interface will be redirected to the * visual voicemail client with @@ -5133,27 +5190,39 @@ public class TelephonyManager { return new int[0]; } - /* The caller of {@link #sendUssdRequest(String, UssdResponseCallback, Handler} provides - * once the network returns a USSD message or if there is failure. - * Either {@link #onReceiveUssdResponse(TelephonyManager, String, CharSequence} or - * {@link #onReceiveUssdResponseFailed(TelephonyManager, String, int} will be called. + /** + * Used to notify callers of + * {@link TelephonyManager#sendUssdRequest(String, UssdResponseCallback, Handler)} when the + * network either successfully executes a USSD request, or if there was a failure while + * executing the request. + * <p> + * {@link #onReceiveUssdResponse(TelephonyManager, String, CharSequence)} will be called if the + * USSD request has succeeded. + * {@link #onReceiveUssdResponseFailed(TelephonyManager, String, int)} will be called if the + * USSD request has failed. */ public static abstract class UssdResponseCallback { /** - * Called when USSD has succeeded. The calling app can choose to either display the message - * or interpret the message. + * Called when a USSD request has succeeded. The {@code response} contains the USSD + * response received from the network. The calling app can choose to either display the + * response to the user or perform some operation based on the response. + * <p> + * USSD responses are unstructured text and their content is determined by the mobile network + * operator. + * * @param telephonyManager the TelephonyManager the callback is registered to. - * @param request the ussd code sent to the network. - * @param response the response from the network. + * @param request the USSD request sent to the mobile network. + * @param response the response to the USSD request provided by the mobile network. **/ public void onReceiveUssdResponse(final TelephonyManager telephonyManager, String request, CharSequence response) {}; /** - * Called when USSD has failed. - * @param telephonyManager the TelephonyManager the callback is registered to - * @param request the ussd code. - * @param failureCode failure code, should be either of + * Called when a USSD request has failed to complete. + * + * @param telephonyManager the TelephonyManager the callback is registered to. + * @param request the USSD request sent to the mobile network. + * @param failureCode failure code indicating why the request failed. Will be either * {@link TelephonyManager#USSD_RETURN_FAILURE} or * {@link TelephonyManager#USSD_ERROR_SERVICE_UNAVAIL}. **/ @@ -5162,8 +5231,8 @@ public class TelephonyManager { } /** - * Sends an Unstructured Supplementary Service Data (USSD) request to the cellular network and - * informs the caller of the response via {@code callback}. + * Sends an Unstructured Supplementary Service Data (USSD) request to the mobile network and + * informs the caller of the response via the supplied {@code callback}. * <p>Carriers define USSD codes which can be sent by the user to request information such as * the user's current data balance or minutes balance. * <p>Requires permission: diff --git a/telephony/java/android/telephony/VisualVoicemailService.java b/telephony/java/android/telephony/VisualVoicemailService.java index e211f76beccf..fe30eb7bb005 100644 --- a/telephony/java/android/telephony/VisualVoicemailService.java +++ b/telephony/java/android/telephony/VisualVoicemailService.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.MainThread; import android.annotation.SdkConstant; +import android.annotation.SystemApi; import android.app.PendingIntent; import android.app.Service; import android.content.Context; @@ -199,7 +200,8 @@ public abstract class VisualVoicemailService extends Service { /** * Called when a SMS matching the {@link VisualVoicemailSmsFilterSettings} set by - * {@link #setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings)} + * {@link TelephonyManager#setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings) + * } * is received. * * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be @@ -240,8 +242,11 @@ public abstract class VisualVoicemailService extends Service { * * @param phoneAccountHandle The account to apply the settings to. * @param settings The settings for the filter, or {@code null} to disable the filter. + * + * @hide */ - public final static void setSmsFilterSettings(Context context, + @SystemApi + public static final void setSmsFilterSettings(Context context, PhoneAccountHandle phoneAccountHandle, VisualVoicemailSmsFilterSettings settings) { TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); @@ -269,8 +274,11 @@ public abstract class VisualVoicemailService extends Service { * * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent) * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent) + * + * @hide */ - public final static void sendVisualVoicemailSms(Context context, + @SystemApi + public static final void sendVisualVoicemailSms(Context context, PhoneAccountHandle phoneAccountHandle, String number, short port, String text, PendingIntent sentIntent) { TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java index 56a8c6255824..8ed96a3a4f36 100644 --- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java +++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java @@ -38,7 +38,7 @@ import java.util.List; * <p>Use {@link android.telephony.VisualVoicemailSmsFilterSettings.Builder} to construct this * class. * - * @see VisualVoicemailService#setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings) + * @see TelephonyManager#setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings) */ public final class VisualVoicemailSmsFilterSettings implements Parcelable { diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java index caf1a5583a5b..a3f33dc13441 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java @@ -32,7 +32,6 @@ import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import static com.android.server.connectivity.tethering.IControlsTethering.STATE_AVAILABLE; -import static com.android.server.connectivity.tethering.IControlsTethering.STATE_LOCAL_HOTSPOT; import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED; import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE; diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 578a8fb423dc..b93c6ecea274 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -365,6 +365,21 @@ static bool FlattenXmlToOutStream(IAaptContext* context, const StringPiece& outp return true; } +static bool IsValidFile(IAaptContext* context, const StringPiece& input_path) { + const file::FileType file_type = file::GetFileType(input_path); + if (file_type != file::FileType::kRegular && file_type != file::FileType::kSymlink) { + if (file_type == file::FileType::kDirectory) { + context->GetDiagnostics()->Error(DiagMessage(input_path) + << "resource file cannot be a directory"); + } else { + context->GetDiagnostics()->Error(DiagMessage(input_path) + << "not a valid resource file"); + } + return false; + } + return true; +} + static bool CompileXml(IAaptContext* context, const CompileOptions& options, const ResourcePathData& path_data, IArchiveWriter* writer, const std::string& output_path) { @@ -569,7 +584,8 @@ static bool CompileFile(IAaptContext* context, const CompileOptions& options, std::string error_str; Maybe<android::FileMap> f = file::MmapPath(path_data.source.path, &error_str); if (!f) { - context->GetDiagnostics()->Error(DiagMessage(path_data.source) << error_str); + context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to mmap file: " + << error_str); return false; } @@ -582,6 +598,11 @@ static bool CompileFile(IAaptContext* context, const CompileOptions& options, class CompileContext : public IAaptContext { public: + PackageType GetPackageType() override { + // Every compilation unit starts as an app and then gets linked as potentially something else. + return PackageType::kApp; + } + void SetVerbose(bool val) { verbose_ = val; } @@ -692,6 +713,11 @@ int Compile(const std::vector<StringPiece>& args) { context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing"); } + if (!IsValidFile(&context, path_data.source.path)) { + error = true; + continue; + } + if (path_data.resource_dir == "values") { // Overwrite the extension. path_data.extension = "arsc"; diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp index fdc89b2b24bd..1a6f348a3edc 100644 --- a/tools/aapt2/cmd/Diff.cpp +++ b/tools/aapt2/cmd/Diff.cpp @@ -31,6 +31,11 @@ class DiffContext : public IAaptContext { DiffContext() : name_mangler_({}), symbol_table_(&name_mangler_) { } + PackageType GetPackageType() override { + // Doesn't matter. + return PackageType::kApp; + } + const std::string& GetCompilationPackage() override { return empty_; } diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 1bbfb28a7870..57c457425e51 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -144,6 +144,11 @@ void TryDumpFile(IAaptContext* context, const std::string& file_path) { class DumpContext : public IAaptContext { public: + PackageType GetPackageType() override { + // Doesn't matter. + return PackageType::kApp; + } + IDiagnostics* GetDiagnostics() override { return &diagnostics_; } diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index b86188fa8503..258516db2ac9 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -65,16 +65,7 @@ using android::base::StringPrintf; namespace aapt { -// The type of package to build. -enum class PackageType { - kApp, - kSharedLib, - kStaticLib, -}; - struct LinkOptions { - PackageType package_type = PackageType::kApp; - std::string output_path; std::string manifest_path; std::vector<std::string> include_paths; @@ -130,6 +121,14 @@ class LinkContext : public IAaptContext { LinkContext() : name_mangler_({}), symbols_(&name_mangler_) { } + PackageType GetPackageType() override { + return package_type_; + } + + void SetPackageType(PackageType type) { + package_type_ = type; + } + IDiagnostics* GetDiagnostics() override { return &diagnostics_; } @@ -181,6 +180,7 @@ class LinkContext : public IAaptContext { private: DISALLOW_COPY_AND_ASSIGN(LinkContext); + PackageType package_type_ = PackageType::kApp; StdErrDiagnostics diagnostics_; NameMangler name_mangler_; std::string compilation_package_; @@ -627,7 +627,7 @@ class LinkCommand { std::string error_str; std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str); if (include_static) { - if (options_.package_type != PackageType::kStaticLib) { + if (context_->GetPackageType() != PackageType::kStaticLib) { // Can't include static libraries when not building a static library (they have no IDs // assigned). context_->GetDiagnostics()->Error( @@ -1300,7 +1300,7 @@ class LinkCommand { */ bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest, ResourceTable* table) { - const bool keep_raw_values = options_.package_type == PackageType::kStaticLib; + const bool keep_raw_values = context_->GetPackageType() == PackageType::kStaticLib; bool result = FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_); if (!result) { @@ -1325,7 +1325,7 @@ class LinkCommand { return false; } - if (options_.package_type == PackageType::kStaticLib) { + if (context_->GetPackageType() == PackageType::kStaticLib) { if (!FlattenTableToPb(table, writer)) { return false; } @@ -1374,7 +1374,7 @@ class LinkCommand { context_->SetPackageId(0x01); // Verify we're building a regular app. - if (options_.package_type != PackageType::kApp) { + if (context_->GetPackageType() != PackageType::kApp) { context_->GetDiagnostics()->Error( DiagMessage() << "package 'android' can only be built as a regular app"); return 1; @@ -1414,7 +1414,7 @@ class LinkCommand { return 1; } - if (options_.package_type != PackageType::kStaticLib) { + if (context_->GetPackageType() != PackageType::kStaticLib) { PrivateAttributeMover mover; if (!mover.Consume(context_, &final_table_)) { context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes"); @@ -1469,7 +1469,7 @@ class LinkCommand { return 1; } - if (options_.package_type == PackageType::kStaticLib) { + if (context_->GetPackageType() == PackageType::kStaticLib) { if (!options_.products.empty()) { context_->GetDiagnostics()->Warn(DiagMessage() << "can't select products when building static library"); @@ -1490,7 +1490,7 @@ class LinkCommand { } } - if (options_.package_type != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) { + if (context_->GetPackageType() != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) { if (context_->IsVerbose()) { context_->GetDiagnostics()->Note(DiagMessage() << "collapsing resource versions for minimum SDK " @@ -1514,7 +1514,7 @@ class LinkCommand { proguard::KeepSet proguard_keep_set; proguard::KeepSet proguard_main_dex_keep_set; - if (options_.package_type == PackageType::kStaticLib) { + if (context_->GetPackageType() == PackageType::kStaticLib) { if (options_.table_splitter_options.config_filter != nullptr || !options_.table_splitter_options.preferred_densities.empty()) { context_->GetDiagnostics()->Warn(DiagMessage() @@ -1641,11 +1641,12 @@ class LinkCommand { template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; template_options.javadoc_annotations = options_.javadoc_annotations; - if (options_.package_type == PackageType::kStaticLib || options_.generate_non_final_ids) { + if (context_->GetPackageType() == PackageType::kStaticLib || + options_.generate_non_final_ids) { template_options.use_final = false; } - if (options_.package_type == PackageType::kSharedLib) { + if (context_->GetPackageType() == PackageType::kSharedLib) { template_options.use_final = false; template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{}; } @@ -1922,18 +1923,18 @@ int Link(const std::vector<StringPiece>& args) { } if (shared_lib) { - options.package_type = PackageType::kSharedLib; + context.SetPackageType(PackageType::kSharedLib); context.SetPackageId(0x00); } else if (static_lib) { - options.package_type = PackageType::kStaticLib; + context.SetPackageType(PackageType::kStaticLib); context.SetPackageId(kAppPackageId); } else { - options.package_type = PackageType::kApp; + context.SetPackageType(PackageType::kApp); context.SetPackageId(kAppPackageId); } if (package_id) { - if (options.package_type != PackageType::kApp) { + if (context.GetPackageType() != PackageType::kApp) { context.GetDiagnostics()->Error( DiagMessage() << "can't specify --package-id when not building a regular app"); return 1; @@ -2000,7 +2001,7 @@ int Link(const std::vector<StringPiece>& args) { } } - if (options.package_type != PackageType::kStaticLib && stable_id_file_path) { + if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path) { if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(), &options.stable_id_map)) { return 1; @@ -2015,7 +2016,7 @@ int Link(const std::vector<StringPiece>& args) { ".3gpp2", ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"}); // Turn off auto versioning for static-libs. - if (options.package_type == PackageType::kStaticLib) { + if (context.GetPackageType() == PackageType::kStaticLib) { options.no_auto_version = true; options.no_version_vectors = true; options.no_version_transitions = true; diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index e99ee8aa93c2..78ed49b64dd2 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -59,6 +59,14 @@ struct OptimizeOptions { class OptimizeContext : public IAaptContext { public: + OptimizeContext() = default; + + PackageType GetPackageType() override { + // Not important here. Using anything other than kApp adds EXTRA validation, which we want to + // avoid. + return PackageType::kApp; + } + IDiagnostics* GetDiagnostics() override { return &diagnostics_; } @@ -99,6 +107,8 @@ class OptimizeContext : public IAaptContext { } private: + DISALLOW_COPY_AND_ASSIGN(OptimizeContext); + StdErrDiagnostics diagnostics_; bool verbose_ = false; int sdk_version_ = 0; diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp index 3098458e4e4f..d44b3e095c0f 100644 --- a/tools/aapt2/flatten/TableFlattener.cpp +++ b/tools/aapt2/flatten/TableFlattener.cpp @@ -230,15 +230,18 @@ class PackageFlattener { ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE); pkg_header->id = util::HostToDevice32(package_->id.value()); - if (package_->name.size() >= arraysize(pkg_header->name)) { + // AAPT truncated the package name, so do the same. + // Shared libraries require full package names, so don't truncate theirs. + if (context_->GetPackageType() != PackageType::kApp && + package_->name.size() >= arraysize(pkg_header->name)) { diag_->Error(DiagMessage() << "package name '" << package_->name - << "' is too long"); + << "' is too long. " + "Shared libraries cannot have truncated package names"); return false; } // Copy the package name in device endianness. - strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), - util::Utf8ToUtf16(package_->name)); + strcpy16_htod(pkg_header->name, arraysize(pkg_header->name), util::Utf8ToUtf16(package_->name)); // Serialize the types. We do this now so that our type and key strings // are populated. We write those first. diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp index 419618749a95..8dff3a27b79f 100644 --- a/tools/aapt2/flatten/TableFlattener_test.cpp +++ b/tools/aapt2/flatten/TableFlattener_test.cpp @@ -411,4 +411,40 @@ TEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) { EXPECT_EQ(0x03u, entries.valueAt(idx)); } +TEST_F(TableFlattenerTest, LongPackageNameIsTruncated) { + std::string kPackageName(256, 'F'); + + std::unique_ptr<IAaptContext> context = + test::ContextBuilder().SetCompilationPackage(kPackageName).SetPackageId(0x7f).Build(); + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .SetPackageId(kPackageName, 0x7f) + .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000)) + .Build(); + + ResTable result; + ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result)); + + ASSERT_EQ(1u, result.getBasePackageCount()); + EXPECT_EQ(127u, result.getBasePackageName(0).size()); +} + +TEST_F(TableFlattenerTest, LongSharedLibraryPackageNameIsIllegal) { + std::string kPackageName(256, 'F'); + + std::unique_ptr<IAaptContext> context = test::ContextBuilder() + .SetCompilationPackage(kPackageName) + .SetPackageId(0x7f) + .SetPackageType(PackageType::kSharedLib) + .Build(); + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .SetPackageId(kPackageName, 0x7f) + .AddSimple(kPackageName + ":id/foo", ResourceId(0x7f010000)) + .Build(); + + ResTable result; + ASSERT_FALSE(Flatten(context.get(), {}, table.get(), &result)); +} + } // namespace aapt diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 0c19c7ad7f32..27ab22bb0010 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -333,7 +333,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, // Provider actions. application_action["provider"] = component_action; application_action["provider"]["grant-uri-permissions"]; - application_action["provider"]["path-permissions"]; + application_action["provider"]["path-permission"]; return true; } diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h index 4526a79577d9..30dad8025900 100644 --- a/tools/aapt2/process/IResourceTableConsumer.h +++ b/tools/aapt2/process/IResourceTableConsumer.h @@ -32,9 +32,17 @@ namespace aapt { class ResourceTable; class SymbolTable; +// The type of package to build. +enum class PackageType { + kApp, + kSharedLib, + kStaticLib, +}; + struct IAaptContext { virtual ~IAaptContext() = default; + virtual PackageType GetPackageType() = 0; virtual SymbolTable* GetExternalSymbols() = 0; virtual IDiagnostics* GetDiagnostics() = 0; virtual const std::string& GetCompilationPackage() = 0; diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h index 557cd1b646e3..29d183876c4c 100644 --- a/tools/aapt2/test/Context.h +++ b/tools/aapt2/test/Context.h @@ -35,9 +35,17 @@ class Context : public IAaptContext { public: Context() : name_mangler_({}), symbols_(&name_mangler_), min_sdk_version_(0) {} - SymbolTable* GetExternalSymbols() override { return &symbols_; } + PackageType GetPackageType() override { + return package_type_; + } + + SymbolTable* GetExternalSymbols() override { + return &symbols_; + } - IDiagnostics* GetDiagnostics() override { return &diagnostics_; } + IDiagnostics* GetDiagnostics() override { + return &diagnostics_; + } const std::string& GetCompilationPackage() override { CHECK(bool(compilation_package_)) << "package name not set"; @@ -49,17 +57,24 @@ class Context : public IAaptContext { return package_id_.value(); } - NameMangler* GetNameMangler() override { return &name_mangler_; } + NameMangler* GetNameMangler() override { + return &name_mangler_; + } - bool IsVerbose() override { return false; } + bool IsVerbose() override { + return false; + } - int GetMinSdkVersion() override { return min_sdk_version_; } + int GetMinSdkVersion() override { + return min_sdk_version_; + } private: DISALLOW_COPY_AND_ASSIGN(Context); friend class ContextBuilder; + PackageType package_type_ = PackageType::kApp; Maybe<std::string> compilation_package_; Maybe<uint8_t> package_id_; StdErrDiagnostics diagnostics_; @@ -70,6 +85,11 @@ class Context : public IAaptContext { class ContextBuilder { public: + ContextBuilder& SetPackageType(PackageType type) { + context_->package_type_ = type; + return *this; + } + ContextBuilder& SetCompilationPackage(const android::StringPiece& package) { context_->compilation_package_ = package.to_string(); return *this; @@ -123,15 +143,16 @@ class StaticSymbolSourceBuilder { return *this; } - std::unique_ptr<ISymbolSource> Build() { return std::move(symbol_source_); } + std::unique_ptr<ISymbolSource> Build() { + return std::move(symbol_source_); + } private: class StaticSymbolSource : public ISymbolSource { public: StaticSymbolSource() = default; - std::unique_ptr<SymbolTable::Symbol> FindByName( - const ResourceName& name) override { + std::unique_ptr<SymbolTable::Symbol> FindByName(const ResourceName& name) override { auto iter = name_map_.find(name); if (iter != name_map_.end()) { return CloneSymbol(iter->second); @@ -153,12 +174,10 @@ class StaticSymbolSourceBuilder { private: std::unique_ptr<SymbolTable::Symbol> CloneSymbol(SymbolTable::Symbol* sym) { - std::unique_ptr<SymbolTable::Symbol> clone = - util::make_unique<SymbolTable::Symbol>(); + std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>(); clone->id = sym->id; if (sym->attribute) { - clone->attribute = - std::unique_ptr<Attribute>(sym->attribute->Clone(nullptr)); + clone->attribute = std::unique_ptr<Attribute>(sym->attribute->Clone(nullptr)); } clone->is_public = sym->is_public; return clone; @@ -167,8 +186,7 @@ class StaticSymbolSourceBuilder { DISALLOW_COPY_AND_ASSIGN(StaticSymbolSource); }; - std::unique_ptr<StaticSymbolSource> symbol_source_ = - util::make_unique<StaticSymbolSource>(); + std::unique_ptr<StaticSymbolSource> symbol_source_ = util::make_unique<StaticSymbolSource>(); }; } // namespace test diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp index 20a45312993d..42786b5387cf 100644 --- a/tools/aapt2/unflatten/BinaryResourceParser.cpp +++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp @@ -22,6 +22,7 @@ #include "android-base/logging.h" #include "android-base/macros.h" +#include "android-base/stringprintf.h" #include "androidfw/ResourceTypes.h" #include "androidfw/TypeWrappers.h" @@ -37,6 +38,8 @@ namespace aapt { using namespace android; +using android::base::StringPrintf; + namespace { /* @@ -87,26 +90,35 @@ BinaryResourceParser::BinaryResourceParser(IAaptContext* context, ResourceTable* bool BinaryResourceParser::Parse() { ResChunkPullParser parser(data_, data_len_); - bool error = false; - while (ResChunkPullParser::IsGoodEvent(parser.Next())) { - if (parser.chunk()->type != android::RES_TABLE_TYPE) { - context_->GetDiagnostics()->Warn(DiagMessage(source_) - << "unknown chunk of type '" - << (int)parser.chunk()->type << "'"); - continue; - } + if (!ResChunkPullParser::IsGoodEvent(parser.Next())) { + context_->GetDiagnostics()->Error(DiagMessage(source_) + << "corrupt resources.arsc: " << parser.error()); + return false; + } - if (!ParseTable(parser.chunk())) { - error = true; - } + if (parser.chunk()->type != android::RES_TABLE_TYPE) { + context_->GetDiagnostics()->Error(DiagMessage(source_) + << StringPrintf("unknown chunk of type 0x%02x", + (int)parser.chunk()->type)); + return false; } - if (parser.event() == ResChunkPullParser::Event::kBadDocument) { - context_->GetDiagnostics()->Error( - DiagMessage(source_) << "corrupt resource table: " << parser.error()); + if (!ParseTable(parser.chunk())) { return false; } - return !error; + + if (parser.Next() != ResChunkPullParser::Event::kEndDocument) { + if (parser.event() == ResChunkPullParser::Event::kBadDocument) { + context_->GetDiagnostics()->Warn( + DiagMessage(source_) << "invalid chunk trailing RES_TABLE_TYPE: " << parser.error()); + } else { + context_->GetDiagnostics()->Warn( + DiagMessage(source_) << StringPrintf( + "unexpected chunk of type 0x%02x trailing RES_TABLE_TYPE", + (int)parser.chunk()->type)); + } + } + return true; } /** diff --git a/tools/aapt2/unflatten/ResChunkPullParser.cpp b/tools/aapt2/unflatten/ResChunkPullParser.cpp index 5d71ff315874..8d92bd94b0ae 100644 --- a/tools/aapt2/unflatten/ResChunkPullParser.cpp +++ b/tools/aapt2/unflatten/ResChunkPullParser.cpp @@ -16,9 +16,11 @@ #include "unflatten/ResChunkPullParser.h" +#include <inttypes.h> #include <cstddef> #include "android-base/logging.h" +#include "android-base/stringprintf.h" #include "androidfw/ResourceTypes.h" #include "util/Util.h" @@ -26,6 +28,13 @@ namespace aapt { using android::ResChunk_header; +using android::base::StringPrintf; + +static std::string ChunkHeaderDump(const ResChunk_header* header) { + return StringPrintf("(type=%02" PRIx16 " header_size=%" PRIu16 " size=%" PRIu32 ")", + util::DeviceToHost16(header->type), util::DeviceToHost16(header->headerSize), + util::DeviceToHost32(header->size)); +} ResChunkPullParser::Event ResChunkPullParser::Next() { if (!IsGoodEvent(event_)) { @@ -53,18 +62,17 @@ ResChunkPullParser::Event ResChunkPullParser::Next() { return (event_ = Event::kBadDocument); } - if (util::DeviceToHost16(current_chunk_->headerSize) < - sizeof(ResChunk_header)) { + if (util::DeviceToHost16(current_chunk_->headerSize) < sizeof(ResChunk_header)) { error_ = "chunk has too small header"; current_chunk_ = nullptr; return (event_ = Event::kBadDocument); } else if (util::DeviceToHost32(current_chunk_->size) < util::DeviceToHost16(current_chunk_->headerSize)) { - error_ = "chunk's total size is smaller than header"; + error_ = "chunk's total size is smaller than header " + ChunkHeaderDump(current_chunk_); current_chunk_ = nullptr; return (event_ = Event::kBadDocument); } else if (offset + util::DeviceToHost32(current_chunk_->size) > len_) { - error_ = "chunk's data extends past the end of the document"; + error_ = "chunk's data extends past the end of the document " + ChunkHeaderDump(current_chunk_); current_chunk_ = nullptr; return (event_ = Event::kBadDocument); } diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py index 3fedea2cc08a..53501f96d0b8 100644 --- a/tools/apilint/apilint.py +++ b/tools/apilint/apilint.py @@ -259,14 +259,19 @@ def error(clazz, detail, rule, msg): def verify_constants(clazz): """All static final constants must be FOO_NAME style.""" if re.match("android\.R\.[a-z]+", clazz.fullname): return + if clazz.fullname.startswith("android.os.Build"): return + if clazz.fullname == "android.system.OsConstants": return + req = ["java.lang.String","byte","short","int","long","float","double","boolean","char"] for f in clazz.fields: if "static" in f.split and "final" in f.split: if re.match("[A-Z0-9_]+", f.name) is None: error(clazz, f, "C2", "Constant field names must be FOO_NAME") - elif f.typ != "java.lang.String": + if f.typ != "java.lang.String": if f.name.startswith("MIN_") or f.name.startswith("MAX_"): warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods") + if f.typ in req and f.value is None: + error(clazz, f, None, "All constants must be defined at compile time") def verify_enums(clazz): @@ -352,6 +357,7 @@ def verify_actions(clazz): if f.value is None: continue if f.name.startswith("EXTRA_"): continue if f.name == "SERVICE_INTERFACE" or f.name == "PROVIDER_INTERFACE": continue + if "INTERACTION" in f.name: continue if "static" in f.split and "final" in f.split and f.typ == "java.lang.String": if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower(): @@ -447,10 +453,14 @@ def verify_fields(clazz): "android.app.Notification", "android.content.pm.ActivityInfo", "android.content.pm.ApplicationInfo", + "android.content.pm.ComponentInfo", + "android.content.pm.ResolveInfo", "android.content.pm.FeatureGroupInfo", "android.content.pm.InstrumentationInfo", "android.content.pm.PackageInfo", "android.content.pm.PackageItemInfo", + "android.content.res.Configuration", + "android.graphics.BitmapFactory.Options", "android.os.Message", "android.system.StructPollfd", ] @@ -786,6 +796,10 @@ def verify_manager(clazz): for c in clazz.ctors: error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors") + for m in clazz.methods: + if m.typ == clazz.fullname: + error(clazz, m, None, "Managers must always be obtained from Context") + def verify_boxed(clazz): """Verifies that methods avoid boxed primitives.""" @@ -812,17 +826,19 @@ def verify_boxed(clazz): def verify_static_utils(clazz): """Verifies that helper classes can't be constructed.""" if clazz.fullname.startswith("android.opengl"): return - if re.match("android\.R\.[a-z]+", clazz.fullname): return + if clazz.fullname.startswith("android.R"): return - if len(clazz.fields) > 0: return - if len(clazz.methods) == 0: return + # Only care about classes with default constructors + if len(clazz.ctors) == 1 and len(clazz.ctors[0].args) == 0: + test = [] + test.extend(clazz.fields) + test.extend(clazz.methods) - for m in clazz.methods: - if "static" not in m.split: - return + if len(test) == 0: return + for t in test: + if "static" not in t.split: + return - # At this point, we have no fields, and all methods are static - if len(clazz.ctors) > 0: error(clazz, None, None, "Fully-static utility classes must not have constructor") @@ -920,6 +936,9 @@ def verify_context_first(clazz): if len(m.args) > 1 and m.args[0] != "android.content.Context": if "android.content.Context" in m.args[1:]: error(clazz, m, "M3", "Context is distinct, so it must be the first argument") + if len(m.args) > 1 and m.args[0] != "android.content.ContentResolver": + if "android.content.ContentResolver" in m.args[1:]: + error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument") def verify_listener_last(clazz): @@ -1001,6 +1020,112 @@ def verify_abstract_inner(clazz): warn(clazz, None, None, "Abstract inner classes should be static to improve testability") +def verify_runtime_exceptions(clazz): + """Verifies that runtime exceptions aren't listed in throws.""" + + banned = [ + "java.lang.NullPointerException", + "java.lang.ClassCastException", + "java.lang.IndexOutOfBoundsException", + "java.lang.reflect.UndeclaredThrowableException", + "java.lang.reflect.MalformedParametersException", + "java.lang.reflect.MalformedParameterizedTypeException", + "java.lang.invoke.WrongMethodTypeException", + "java.lang.EnumConstantNotPresentException", + "java.lang.IllegalMonitorStateException", + "java.lang.SecurityException", + "java.lang.UnsupportedOperationException", + "java.lang.annotation.AnnotationTypeMismatchException", + "java.lang.annotation.IncompleteAnnotationException", + "java.lang.TypeNotPresentException", + "java.lang.IllegalStateException", + "java.lang.ArithmeticException", + "java.lang.IllegalArgumentException", + "java.lang.ArrayStoreException", + "java.lang.NegativeArraySizeException", + "java.util.MissingResourceException", + "java.util.EmptyStackException", + "java.util.concurrent.CompletionException", + "java.util.concurrent.RejectedExecutionException", + "java.util.IllformedLocaleException", + "java.util.ConcurrentModificationException", + "java.util.NoSuchElementException", + "java.io.UncheckedIOException", + "java.time.DateTimeException", + "java.security.ProviderException", + "java.nio.BufferUnderflowException", + "java.nio.BufferOverflowException", + ] + + test = [] + test.extend(clazz.ctors) + test.extend(clazz.methods) + + for t in test: + if " throws " not in t.raw: continue + throws = t.raw[t.raw.index(" throws "):] + for b in banned: + if b in throws: + error(clazz, t, None, "Methods must not mention RuntimeException subclasses in throws clauses") + + +def verify_error(clazz): + """Verifies that we always use Exception instead of Error.""" + if not clazz.extends: return + if clazz.extends.endswith("Error"): + error(clazz, None, None, "Trouble must be reported through an Exception, not Error") + if clazz.extends.endswith("Exception") and not clazz.name.endswith("Exception"): + error(clazz, None, None, "Exceptions must be named FooException") + + +def verify_units(clazz): + """Verifies that we use consistent naming for units.""" + + # If we find K, recommend replacing with V + bad = { + "Ns": "Nanos", + "Ms": "Millis or Micros", + "Sec": "Seconds", "Secs": "Seconds", + "Hr": "Hours", "Hrs": "Hours", + "Mo": "Months", "Mos": "Months", + "Yr": "Years", "Yrs": "Years", + "Byte": "Bytes", "Space": "Bytes", + } + + for m in clazz.methods: + if m.typ not in ["short","int","long"]: continue + for k, v in bad.iteritems(): + if m.name.endswith(k): + error(clazz, m, None, "Expected method name units to be " + v) + if m.name.endswith("Nanos") or m.name.endswith("Micros"): + warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision") + if m.name.endswith("Seconds"): + error(clazz, m, None, "Returned time values must be in milliseconds") + + for m in clazz.methods: + typ = m.typ + if typ == "void": + if len(m.args) != 1: continue + typ = m.args[0] + + if m.name.endswith("Fraction") and typ != "float": + error(clazz, m, None, "Fractions must use floats") + if m.name.endswith("Percentage") and typ != "int": + error(clazz, m, None, "Percentage must use ints") + + +def verify_closable(clazz): + """Verifies that classes are AutoClosable.""" + if "implements java.lang.AutoCloseable" in clazz.raw: return + if "implements java.io.Closeable" in clazz.raw: return + + for m in clazz.methods: + if len(m.args) > 0: continue + if m.name in ["close","release","destroy","finish","finalize","disconnect","shutdown","stop","free","quit"]: + warn(clazz, m, None, "Classes that release resources should implement AutoClosable and CloseGuard") + return + + def examine_clazz(clazz): """Find all style issues in the given class.""" if clazz.pkg.name.startswith("java"): return @@ -1048,6 +1173,10 @@ def examine_clazz(clazz): verify_files(clazz) verify_manager_list(clazz) verify_abstract_inner(clazz) + verify_runtime_exceptions(clazz) + verify_error(clazz) + verify_units(clazz) + verify_closable(clazz) def examine_stream(stream): diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py index f5b904220f76..c0475eeb0c7e 100755 --- a/tools/fonts/fontchain_lint.py +++ b/tools/fonts/fontchain_lint.py @@ -428,7 +428,8 @@ def parse_ucd(ucd_path): _text_variation_sequences, _emoji_variation_sequences = sequences _emoji_sequences = parse_unicode_datafile( path.join(ucd_path, 'emoji-sequences.txt')) - + _emoji_sequences.update(parse_unicode_datafile( + path.join(ucd_path, 'additions', 'emoji-sequences.txt'))) _emoji_zwj_sequences = parse_unicode_datafile( path.join(ucd_path, 'emoji-zwj-sequences.txt')) _emoji_zwj_sequences.update(parse_unicode_datafile( diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java index bf5c42b8ca1c..c7e1fc739046 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySession.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java @@ -38,10 +38,10 @@ import java.lang.ref.WeakReference; * {@link #createNetworkSpecifierOpen(PeerHandle)} or * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)}. * </ul> - * The {@link #destroy()} method must be called to destroy discovery sessions once they are + * The {@link #close()} method must be called to destroy discovery sessions once they are * no longer needed. */ -public class DiscoverySession { +public class DiscoverySession implements AutoCloseable { private static final String TAG = "DiscoverySession"; private static final boolean DBG = false; private static final boolean VDBG = false; // STOPSHIP if true @@ -96,7 +96,8 @@ public class DiscoverySession { * exception is a session for which we received a termination callback, * {@link DiscoverySessionCallback#onSessionTerminated()}. */ - public void destroy() { + @Override + public void close() { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.w(TAG, "destroy: called post GC on WifiAwareManager"); @@ -131,7 +132,7 @@ public class DiscoverySession { try { if (!mTerminated) { mCloseGuard.warnIfOpen(); - destroy(); + close(); } } finally { super.finalize(); diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java index 334205b13bba..d8667e6cfcb6 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java @@ -84,7 +84,7 @@ public class DiscoverySessionCallback { /** * Called when a discovery session (publish or subscribe) terminates. Termination may be due - * to user-request (either directly through {@link DiscoverySession#destroy()} or + * to user-request (either directly through {@link DiscoverySession#close()} or * application-specified expiration, e.g. {@link PublishConfig.Builder#setTtlSec(int)} * or {@link SubscribeConfig.Builder#setTtlSec(int)}). */ diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java index 1ce12f30a25e..0f1e99295bc1 100644 --- a/wifi/java/android/net/wifi/aware/PublishConfig.java +++ b/wifi/java/android/net/wifi/aware/PublishConfig.java @@ -314,7 +314,7 @@ public final class PublishConfig implements Parcelable { * {@link #setTerminateNotificationEnabled(boolean)} disables the callback]. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link DiscoverySession#destroy()} is + * Session will be terminated when {@link DiscoverySession#close()} is * called. * * @param ttlSec Lifetime of a publish session in seconds. diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java index 97a6a3f91e86..31e7e8e86c90 100644 --- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java +++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java @@ -61,27 +61,6 @@ public final class SubscribeConfig implements Parcelable { public static final int SUBSCRIBE_TYPE_ACTIVE = 1; /** @hide */ - @IntDef({ - MATCH_STYLE_FIRST_ONLY, MATCH_STYLE_ALL }) - @Retention(RetentionPolicy.SOURCE) - public @interface MatchStyles { - } - - /** - * Specifies that only the first match of a set of identical matches (same - * publish) will be reported to the subscriber. Configuration is done using - * {@link SubscribeConfig.Builder#setMatchStyle(int)}. - */ - public static final int MATCH_STYLE_FIRST_ONLY = 0; - - /** - * Specifies that all matches of a set of identical matches (same publish) - * will be reported to the subscriber. Configuration is done using - * {@link SubscribeConfig.Builder#setMatchStyle(int)}. - */ - public static final int MATCH_STYLE_ALL = 1; - - /** @hide */ public final byte[] mServiceName; /** @hide */ @@ -97,21 +76,17 @@ public final class SubscribeConfig implements Parcelable { public final int mTtlSec; /** @hide */ - public final int mMatchStyle; - - /** @hide */ public final boolean mEnableTerminateNotification; /** @hide */ public SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter, - int subscribeType, int ttlSec, int matchStyle, + int subscribeType, int ttlSec, boolean enableTerminateNotification) { mServiceName = serviceName; mServiceSpecificInfo = serviceSpecificInfo; mMatchFilter = matchFilter; mSubscribeType = subscribeType; mTtlSec = ttlSec; - mMatchStyle = matchStyle; mEnableTerminateNotification = enableTerminateNotification; } @@ -121,8 +96,8 @@ public final class SubscribeConfig implements Parcelable { (mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo)) + ", mMatchFilter=" + (new TlvBufferUtils.TlvIterable(0, 1, mMatchFilter)).toString() + ", mSubscribeType=" + mSubscribeType - + ", mTtlSec=" + mTtlSec + ", mMatchType=" - + mMatchStyle + ", mEnableTerminateNotification=" + mEnableTerminateNotification + + ", mTtlSec=" + mTtlSec + + ", mEnableTerminateNotification=" + mEnableTerminateNotification + "]"; } @@ -138,7 +113,6 @@ public final class SubscribeConfig implements Parcelable { dest.writeByteArray(mMatchFilter); dest.writeInt(mSubscribeType); dest.writeInt(mTtlSec); - dest.writeInt(mMatchStyle); dest.writeInt(mEnableTerminateNotification ? 1 : 0); } @@ -155,11 +129,10 @@ public final class SubscribeConfig implements Parcelable { byte[] matchFilter = in.createByteArray(); int subscribeType = in.readInt(); int ttlSec = in.readInt(); - int matchStyle = in.readInt(); boolean enableTerminateNotification = in.readInt() != 0; return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType, - ttlSec, matchStyle, enableTerminateNotification); + ttlSec, enableTerminateNotification); } }; @@ -178,7 +151,7 @@ public final class SubscribeConfig implements Parcelable { return Arrays.equals(mServiceName, lhs.mServiceName) && Arrays.equals(mServiceSpecificInfo, lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter, lhs.mMatchFilter) && mSubscribeType == lhs.mSubscribeType - && mTtlSec == lhs.mTtlSec && mMatchStyle == lhs.mMatchStyle + && mTtlSec == lhs.mTtlSec && mEnableTerminateNotification == lhs.mEnableTerminateNotification; } @@ -191,7 +164,6 @@ public final class SubscribeConfig implements Parcelable { result = 31 * result + Arrays.hashCode(mMatchFilter); result = 31 * result + mSubscribeType; result = 31 * result + mTtlSec; - result = 31 * result + mMatchStyle; result = 31 * result + (mEnableTerminateNotification ? 1 : 0); return result; @@ -217,10 +189,6 @@ public final class SubscribeConfig implements Parcelable { if (mTtlSec < 0) { throw new IllegalArgumentException("Invalid ttlSec - must be non-negative"); } - if (mMatchStyle != MATCH_STYLE_FIRST_ONLY && mMatchStyle != MATCH_STYLE_ALL) { - throw new IllegalArgumentException( - "Invalid matchType - must be MATCH_FIRST_ONLY or MATCH_ALL"); - } if (characteristics != null) { int maxServiceNameLength = characteristics.getMaxServiceNameLength(); @@ -252,7 +220,6 @@ public final class SubscribeConfig implements Parcelable { private byte[] mMatchFilter; private int mSubscribeType = SUBSCRIBE_TYPE_PASSIVE; private int mTtlSec = 0; - private int mMatchStyle = MATCH_STYLE_ALL; private boolean mEnableTerminateNotification = true; /** @@ -346,7 +313,7 @@ public final class SubscribeConfig implements Parcelable { * {@link DiscoverySessionCallback#onSessionTerminated()}. * <p> * Optional. 0 by default - indicating the session doesn't terminate on its own. - * Session will be terminated when {@link DiscoverySession#destroy()} is + * Session will be terminated when {@link DiscoverySession#close()} is * called. * * @param ttlSec Lifetime of a subscribe session in seconds. @@ -363,28 +330,6 @@ public final class SubscribeConfig implements Parcelable { } /** - * Sets the match style of the subscription - how are matches from a - * single match session (corresponding to the same publish action on the - * peer) reported to the host (using the - * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], - * java.util.List)}). The options are: only report the first match and ignore the rest - * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single - * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default). - * - * @param matchStyle The reporting style for the discovery match. - * @return The builder to facilitate chaining - * {@code builder.setXXX(..).setXXX(..)}. - */ - public Builder setMatchStyle(@MatchStyles int matchStyle) { - if (matchStyle != MATCH_STYLE_FIRST_ONLY && matchStyle != MATCH_STYLE_ALL) { - throw new IllegalArgumentException( - "Invalid matchType - must be MATCH_FIRST_ONLY or MATCH_ALL"); - } - mMatchStyle = matchStyle; - return this; - } - - /** * Configure whether a subscribe terminate notification * {@link DiscoverySessionCallback#onSessionTerminated()} is reported * back to the callback. @@ -406,7 +351,7 @@ public final class SubscribeConfig implements Parcelable { */ public SubscribeConfig build() { return new SubscribeConfig(mServiceName, mServiceSpecificInfo, mMatchFilter, - mSubscribeType, mTtlSec, mMatchStyle, + mSubscribeType, mTtlSec, mEnableTerminateNotification); } } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index 3fcbd4b60259..d3ed79245426 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -82,7 +82,7 @@ import java.util.List; * discovery or connection setup only after receiving confirmation that Aware attach * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an * application is finished using Aware it <b>must</b> use the - * {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device + * {@link WifiAwareSession#close()} API to indicate to the Aware service that the device * may detach from the Aware cluster. The device will actually disable Aware once the last * application detaches. * <p> @@ -104,7 +104,7 @@ import java.util.List; * also be used to send messages using the * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an * application is finished with a discovery session it <b>must</b> terminate it using the - * {@link DiscoverySession#destroy()} API. + * {@link DiscoverySession#close()} API. * <p> * Creating connections between Aware devices is managed by the standard * {@link ConnectivityManager#requestNetwork(NetworkRequest, @@ -215,7 +215,7 @@ public class WifiAwareManager { * create connections to peers. The device will attach to an existing cluster if it can find * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object. - * An application <b>must</b> call {@link WifiAwareSession#destroy()} when done with the + * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the * Wi-Fi Aware object. * <p> * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster @@ -237,7 +237,7 @@ public class WifiAwareManager { * create connections to peers. The device will attach to an existing cluster if it can find * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object. - * An application <b>must</b> call {@link WifiAwareSession#destroy()} when done with the + * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the * Wi-Fi Aware object. * <p> * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java index ac3a6bba052c..4e060d5ca3f0 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java @@ -33,7 +33,7 @@ import java.lang.ref.WeakReference; * This class represents a Wi-Fi Aware session - an attachment to the Wi-Fi Aware service through * which the app can execute discovery operations. */ -public class WifiAwareSession { +public class WifiAwareSession implements AutoCloseable { private static final String TAG = "WifiAwareSession"; private static final boolean DBG = false; private static final boolean VDBG = false; // STOPSHIP if true @@ -67,7 +67,7 @@ public class WifiAwareSession { * An application may re-attach after a destroy using * {@link WifiAwareManager#attach(AttachCallback, Handler)} . */ - public void destroy() { + public void close() { WifiAwareManager mgr = mMgr.get(); if (mgr == null) { Log.w(TAG, "destroy: called post GC on WifiAwareManager"); @@ -85,7 +85,7 @@ public class WifiAwareSession { try { if (!mTerminated) { mCloseGuard.warnIfOpen(); - destroy(); + close(); } } finally { super.finalize(); @@ -110,7 +110,7 @@ public class WifiAwareSession { * on the {@code callback} object. The resulting publish session can be modified using * {@link PublishDiscoverySession#updatePublish(PublishConfig)}. * <p> - * An application must use the {@link DiscoverySession#destroy()} to + * An application must use the {@link DiscoverySession#close()} to * terminate the publish discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} @@ -156,7 +156,7 @@ public class WifiAwareSession { * on the {@code callback} object. The resulting subscribe session can be modified using * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. * <p> - * An application must use the {@link DiscoverySession#destroy()} to + * An application must use the {@link DiscoverySession#close()} to * terminate the subscribe discovery session once it isn't needed. This will free * resources as well terminate any on-air transmissions. * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 72a6a7a7b46b..694b911a51e5 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -150,7 +150,7 @@ public class WifiAwareManagerTest { inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig), any()); // (3) disconnect - session.destroy(); + session.close(); inOrder.verify(mockAwareService).disconnect(eq(clientId), eq(binder.getValue())); // (4) try publishing again - fails silently @@ -329,7 +329,7 @@ public class WifiAwareManagerTest { inOrder.verify(mockSessionCallback).onSessionConfigFailed(); // (5) terminate - publishSession.getValue().destroy(); + publishSession.getValue().close(); mMockLooper.dispatchAll(); inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); @@ -466,7 +466,7 @@ public class WifiAwareManagerTest { inOrder.verify(mockSessionCallback).onSessionConfigFailed(); // (5) terminate - subscribeSession.getValue().destroy(); + subscribeSession.getValue().close(); mMockLooper.dispatchAll(); inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); @@ -687,8 +687,6 @@ public class WifiAwareManagerTest { collector.checkThat("mSubscribeType", subscribeConfig.mSubscribeType, equalTo(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)); collector.checkThat("mTtlSec", subscribeConfig.mTtlSec, equalTo(0)); - collector.checkThat("mMatchStyle", subscribeConfig.mMatchStyle, - equalTo(SubscribeConfig.MATCH_STYLE_ALL)); collector.checkThat("mEnableTerminateNotification", subscribeConfig.mEnableTerminateNotification, equalTo(true)); } @@ -701,14 +699,13 @@ public class WifiAwareManagerTest { final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE; final int subscribeCount = 10; final int subscribeTtl = 15; - final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY; final boolean enableTerminateNotification = false; SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter( new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList()) .setSubscribeType(subscribeType) - .setTtlSec(subscribeTtl).setMatchStyle(matchStyle) + .setTtlSec(subscribeTtl) .setTerminateNotificationEnabled(enableTerminateNotification).build(); collector.checkThat("mServiceName", serviceName.getBytes(), @@ -719,7 +716,6 @@ public class WifiAwareManagerTest { collector.checkThat("mSubscribeType", subscribeType, equalTo(subscribeConfig.mSubscribeType)); collector.checkThat("mTtlSec", subscribeTtl, equalTo(subscribeConfig.mTtlSec)); - collector.checkThat("mMatchStyle", matchStyle, equalTo(subscribeConfig.mMatchStyle)); collector.checkThat("mEnableTerminateNotification", enableTerminateNotification, equalTo(subscribeConfig.mEnableTerminateNotification)); } @@ -730,16 +726,14 @@ public class WifiAwareManagerTest { final String serviceSpecificInfo = "long arbitrary string with some info"; final byte[] matchFilter = { 1, 16, 1, 22 }; final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE; - final int subscribeCount = 10; final int subscribeTtl = 15; - final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY; final boolean enableTerminateNotification = true; SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter( new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList()) .setSubscribeType(subscribeType) - .setTtlSec(subscribeTtl).setMatchStyle(matchStyle) + .setTtlSec(subscribeTtl) .setTerminateNotificationEnabled(enableTerminateNotification).build(); Parcel parcelW = Parcel.obtain(); @@ -765,14 +759,6 @@ public class WifiAwareManagerTest { new SubscribeConfig.Builder().setTtlSec(-100); } - /** - * Validate that a bad match style configuration throws an exception. - */ - @Test(expected = IllegalArgumentException.class) - public void testSubscribeConfigBuilderBadMatchStyle() { - new SubscribeConfig.Builder().setMatchStyle(10); - } - /* * PublishConfig Tests */ |