Merge "Add param javadoc to DevicePolicyManager.setBackupServiceEnabled" into oc-dev
diff --git a/Android.mk b/Android.mk
index 991d185..9072e3b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -908,7 +908,6 @@
ext \
icu4j \
framework \
- telephony-common \
voip-common
framework_docs_LOCAL_JAVA_LIBRARIES := \
diff --git a/api/current.txt b/api/current.txt
index b1ff0dd..93caec3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3635,7 +3635,6 @@
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 @@
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);
@@ -6660,8 +6658,8 @@
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();
@@ -26740,10 +26738,10 @@
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 +26793,6 @@
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 +26801,6 @@
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 +26822,10 @@
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 +34940,7 @@
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 +37032,12 @@
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);
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 +37111,6 @@
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 +40232,12 @@
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 +40311,6 @@
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 +40328,6 @@
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";
}
@@ -46593,8 +46584,9 @@
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 {
@@ -47838,6 +47830,8 @@
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 +47846,6 @@
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 {
diff --git a/api/system-current.txt b/api/system-current.txt
index 8a4b335..bbced6c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -174,6 +174,7 @@
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 @@
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 @@
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);
@@ -6905,8 +6904,8 @@
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();
@@ -29483,11 +29482,11 @@
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 +29538,6 @@
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 +29546,6 @@
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 +29567,11 @@
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 +38033,7 @@
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";
@@ -40151,15 +40148,12 @@
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);
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 +40227,6 @@
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 +40762,7 @@
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 +43762,7 @@
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 +43772,7 @@
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 +43857,6 @@
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";
}
@@ -50171,8 +50166,9 @@
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 {
@@ -51419,6 +51415,8 @@
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 +51431,6 @@
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 {
diff --git a/api/test-current.txt b/api/test-current.txt
index e784e72..b5cfa24 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3637,7 +3637,6 @@
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 @@
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);
@@ -6690,8 +6688,8 @@
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();
@@ -26848,10 +26846,10 @@
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 +26901,6 @@
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 +26909,6 @@
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 +26930,10 @@
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 +35077,7 @@
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 +37186,12 @@
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);
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 +37265,6 @@
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 +40427,12 @@
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 +40506,6 @@
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 +40523,6 @@
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";
}
@@ -46968,8 +46959,9 @@
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 {
@@ -48217,6 +48209,8 @@
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 +48225,6 @@
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 {
diff --git a/cmds/vr/src/com/android/commands/vr/Vr.java b/cmds/vr/src/com/android/commands/vr/Vr.java
index 3fb40fb..bf97bba 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 @@
(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 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 @@
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 @@
}
}
+ 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/annotation/BroadcastBehavior.java b/core/java/android/annotation/BroadcastBehavior.java
index 9b2ca31..70d82cb 100644
--- a/core/java/android/annotation/BroadcastBehavior.java
+++ b/core/java/android/annotation/BroadcastBehavior.java
@@ -53,4 +53,9 @@
* @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/app/Activity.java b/core/java/android/app/Activity.java
index 1b972f7..cdfb52b1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -696,9 +696,6 @@
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 @@
* @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 @@
* @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 @@
* 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 62f2144..1ab45b5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2350,6 +2350,14 @@
}
}
+ /** @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 @@
*
* @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) {
@@ -3637,13 +3643,10 @@
* 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,
@@ -4015,13 +4018,13 @@
* 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);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5022d7d..46ce94f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3004,7 +3004,7 @@
// - 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 @@
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 @@
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 c561a19..3221c5d 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 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 @@
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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* 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 @@
/** @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 @@
*
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* <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 @@
* @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 @@
* 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 @@
* @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/app/CompatibilityDisplayProperties.aidl b/core/java/android/app/CompatibilityDisplayProperties.aidl
new file mode 100644
index 0000000..626a63e
--- /dev/null
+++ b/core/java/android/app/CompatibilityDisplayProperties.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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;
+
+/** @hide */
+parcelable CompatibilityDisplayProperties;
diff --git a/core/java/android/app/CompatibilityDisplayProperties.java b/core/java/android/app/CompatibilityDisplayProperties.java
new file mode 100644
index 0000000..9a9bc2c
--- /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 88399e5..c5dc86c 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -91,6 +91,9 @@
@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 @@
@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 @@
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 @@
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/Notification.java b/core/java/android/app/Notification.java
index 602cccb..2b4fb19 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -676,7 +676,16 @@
* 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.
@@ -3545,12 +3554,9 @@
/**
* 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 9059daa..2dd3301 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -162,10 +162,9 @@
* 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 4dd578e..878c8c3 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -45,6 +45,26 @@
}
/**
+ * 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 b840d84..a939eb0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2972,9 +2972,9 @@
* 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 @@
*
* @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());
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index ca74d54..d757f3e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -6,6 +6,7 @@
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;
@@ -599,7 +600,7 @@
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.AUTOFILL_TYPE_NONE;
@@ -638,7 +639,7 @@
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...
@@ -666,7 +667,7 @@
ViewNodeText mText;
int mInputType;
- String mUrl;
+ String mWebDomain;
Bundle mExtras;
LocaleList mLocaleList;
@@ -743,7 +744,7 @@
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);
@@ -805,7 +806,7 @@
if (mInputType != 0) {
flags |= FLAGS_HAS_INPUT_TYPE;
}
- if (mUrl != null) {
+ if (mWebDomain != null) {
flags |= FLAGS_HAS_URL;
}
if (mLocaleList != null) {
@@ -900,7 +901,7 @@
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);
@@ -1042,8 +1043,6 @@
*/
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();
}
@@ -1237,17 +1236,20 @@
}
/**
- * Returns the URL represented by this view.
+ * Returns the domain of the HTML document represented by this view.
*
* <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}.
*/
- @Nullable public String getUrl() {
- return mUrl;
+ @Nullable public String getWebDomain() {
+ return mWebDomain;
}
/**
@@ -1724,7 +1726,18 @@
@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
@@ -1946,9 +1959,9 @@
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) {
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 3538256..007ea88 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -18,8 +18,10 @@
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.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 @@
*/
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 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 @@
/**
* 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 @@
}
/**
- * 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 @@
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 @@
/**
* 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 @@
/**
* Return the flags supplied for the trigger.
*/
- public int getFlags() {
+ public @Flags int getFlags() {
return mFlags;
}
@@ -886,7 +908,7 @@
* 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 @@
* 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 @@
}
/**
- * 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 23f9eea..1768828 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.os.Bundle;
import android.os.PersistableBundle;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -51,6 +54,14 @@
* 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 @@
* @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 @@
* {@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 @@
* 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/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 8d2c3ec..5246513 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -73,7 +73,7 @@
/**
* 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";
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e50b2a9..fac9e13 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -118,6 +118,9 @@
* 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 @@
}
/**
+ * <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 @@
* 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 @@
* 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 @@
*
* 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/ComponentName.java b/core/java/android/content/ComponentName.java
index 8aeb22d..ea6b769 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 @@
* 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 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
/**
* 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 @@
*
* @see #unflattenFromString(String)
*/
- public String flattenToString() {
+ public @NonNull String flattenToString() {
return mPackage + "/" + mClass;
}
@@ -215,7 +217,7 @@
*
* @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 @@
*
* @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 1585d21..42ef871 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -85,6 +85,37 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
* </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 @@
* @see #deleteDatabase
*/
public abstract SQLiteDatabase openOrCreateDatabase(String name,
- int mode, CursorFactory factory,
+ @DatabaseMode int mode, CursorFactory factory,
@Nullable DatabaseErrorHandler errorHandler);
/**
@@ -1777,9 +1795,9 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* <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 @@
* @see #sendStickyBroadcast
*/
@Deprecated
+ @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY)
public abstract void removeStickyBroadcast(@RequiresPermission Intent intent);
/**
@@ -3048,7 +3061,7 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @see #checkCallingUriPermission
*/
@CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)")
+ @PackageManager.PermissionResult
public abstract int checkCallingOrSelfUriPermission(Uri uri,
@Intent.AccessUriMode int modeFlags);
@@ -4250,6 +4267,7 @@
* {@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 @@
@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 @@
* {@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 @@
* @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 @@
* @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 b6f9ac9..9c87ff2 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -19,6 +19,8 @@
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 @@
| 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 @@
// ---------------------------------------------------------------------
// 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 @@
* 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 @@
* 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 @@
*
* @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 @@
*
* @see #setAction
*/
- public String getAction() {
+ public @Nullable String getAction() {
return mAction;
}
@@ -6583,7 +6683,7 @@
* @see #getScheme
* @see #setData
*/
- public Uri getData() {
+ public @Nullable Uri getData() {
return mData;
}
@@ -6591,7 +6691,7 @@
* 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 @@
*
* @see #getData
*/
- public String getScheme() {
+ public @Nullable String getScheme() {
return mData != null ? mData.getScheme() : null;
}
@@ -6621,7 +6721,7 @@
* @see #resolveType(ContentResolver)
* @see #setType
*/
- public String getType() {
+ public @Nullable String getType() {
return mType;
}
@@ -6636,7 +6736,7 @@
* @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 @@
* @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 @@
* @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 @@
*
* @see #setSelector
*/
- public Intent getSelector() {
+ public @Nullable Intent getSelector() {
return mSelector;
}
@@ -6728,7 +6828,7 @@
*
* @see #setClipData
*/
- public ClipData getClipData() {
+ public @Nullable ClipData getClipData() {
return mClipData;
}
@@ -6754,7 +6854,7 @@
* @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 @@
* @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 @@
* 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 @@
* @see #resolveActivity
* @see #setPackage
*/
- public String getPackage() {
+ public @Nullable String getPackage() {
return mPackage;
}
@@ -7335,7 +7436,7 @@
* @see #resolveActivity
* @see #setComponent
*/
- public ComponentName getComponent() {
+ public @Nullable ComponentName getComponent() {
return mComponent;
}
@@ -7344,7 +7445,7 @@
* 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 @@
* @see #getComponent
* @see #resolveActivityInfo
*/
- public ComponentName resolveActivity(PackageManager pm) {
+ public ComponentName resolveActivity(@NonNull PackageManager pm) {
if (mComponent != null) {
return mComponent;
}
@@ -7427,7 +7528,8 @@
*
* @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 @@
* 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 @@
*
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @see #setData
* @see #normalizeMimeType
*/
- public Intent setTypeAndNormalize(String type) {
+ public @NonNull Intent setTypeAndNormalize(@Nullable String type) {
return setType(normalizeMimeType(type));
}
@@ -7633,7 +7736,7 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* @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
+ * @see #setFlags
+ * @see #getFlags
+ * @see #removeFlags
*/
- public Intent addFlags(int flags) {
+ public @NonNull Intent addFlags(@Flags int flags) {
mFlags |= flags;
return this;
}
@@ -8638,36 +8690,11 @@
* 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
+ * @see #setFlags
+ * @see #getFlags
+ * @see #addFlags
*/
- public void removeFlags(int flags) {
+ public void removeFlags(@Flags int flags) {
mFlags &= ~flags;
}
@@ -8687,7 +8714,7 @@
* @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 @@
* @see #getComponent
* @see #resolveActivity
*/
- public Intent setComponent(ComponentName component) {
+ public @NonNull Intent setComponent(@Nullable ComponentName component) {
mComponent = component;
return this;
}
@@ -8739,7 +8766,8 @@
* @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 @@
* @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 @@
*
* @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 @@
* 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 @@
* 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 @@
* <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 @@
* @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 @@
* @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 78c057d..b78c71d 100644
--- a/core/java/android/content/pm/ChangedPackages.java
+++ b/core/java/android/content/pm/ChangedPackages.java
@@ -35,7 +35,6 @@
/** 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/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 47d79cf..ecaf7eb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -522,6 +522,18 @@
*/
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 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 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 @@
* 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 @@
* 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 @@
* @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 @@
* @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 @@
* #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 @@
* #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
@@ -3881,8 +3908,8 @@
* 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.
@@ -5136,18 +5163,11 @@
* 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,
@@ -5157,14 +5177,10 @@
* 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
@@ -5174,18 +5190,11 @@
* {@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
@@ -5195,15 +5204,10 @@
* 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 1f78bff..8609351 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -145,7 +145,12 @@
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/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 1cf8f03..279d73d 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1662,9 +1662,13 @@
* <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 419e3e2..aedfc4b 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2167,9 +2167,13 @@
* <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 768beea..b854cbf 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -19,6 +19,7 @@
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 @@
/**
* 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 @@
* the networks to describe their precedence.
*/
@Deprecated
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public int getNetworkPreference() {
return TYPE_NONE;
}
@@ -763,12 +763,11 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
*
* {@hide}
*/
+ @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
return getActiveNetworkInfoForUid(uid, false);
}
@@ -896,8 +892,6 @@
/**
* 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 @@
* {@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 @@
/**
* 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 @@
* 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 @@
/**
* 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 @@
* {@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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
*
* {@hide}
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public LinkProperties getActiveLinkProperties() {
try {
return mService.getActiveLinkProperties();
@@ -1036,8 +1025,6 @@
/**
* 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 @@
* {@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 @@
/**
* 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 @@
/**
* 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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
/**
* 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 @@
*
* {@hide}
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public int getLastTetherError(String iface) {
try {
return mService.getLastTetherError(iface);
@@ -2362,13 +2338,12 @@
* 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 @@
* 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 @@
* 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 @@
/**
* 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 @@
* 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 @@
* 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 @@
* <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 @@
* 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 @@
* 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 @@
* {@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 @@
* {@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 @@
* 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/os/Parcelable.java b/core/java/android/os/Parcelable.java
index c10abec..6632ca5 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 @@
* }</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 @@
* 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 @@
*
* @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 @@
* @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 c6bbf48..1e55c78 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 @@
/**
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
}
}
+ @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 @@
* 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 7496cb2..2179bd4 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.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 @@
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/Settings.java b/core/java/android/provider/Settings.java
index 0884480..dcb35d6 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1398,6 +1398,26 @@
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
/**
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 813c54f..c229d1d 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -36,9 +36,6 @@
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 @@
/**
* 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 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) {
@@ -170,8 +148,7 @@
@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);
@@ -229,6 +206,8 @@
* 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,
@@ -267,6 +246,8 @@
* 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 +261,9 @@
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 aa6db4d..49f348c 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -39,8 +39,6 @@
* @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 @@
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 @@
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 68ce0b5..2afb1f4 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -242,7 +242,7 @@
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 @@
}
/**
- * 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 @@
/**
* @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 0506747..7523347 100644
--- a/core/java/android/service/resolver/ResolverRankerService.java
+++ b/core/java/android/service/resolver/ResolverRankerService.java
@@ -65,6 +65,12 @@
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 6eea07d..8b2d0c6 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 @@
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/transition/ChangeClipBounds.java b/core/java/android/transition/ChangeClipBounds.java
index 8d0943c..a6398d3 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 @@
}
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 @@
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 bcf0b90..d42c6db 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7381,17 +7381,20 @@
* 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 @@
* @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 @@
}
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 @@
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 @@
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 @@
*
* @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/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 435610e..387a9ce 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -362,11 +362,19 @@
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/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index d678015..268f7f3 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -30,7 +30,6 @@
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 981be21..caf188d 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -51,12 +51,10 @@
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 @@
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 @@
}
}
+ /**
+ * 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 @@
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 @@
@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 e2dd7fe..b1a9d90 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -252,7 +252,6 @@
*
* <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 aa94de0..2b25ae7 100644
--- a/core/java/android/view/autofill/Helper.java
+++ b/core/java/android/view/autofill/Helper.java
@@ -25,7 +25,8 @@
/** @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 df777c4..9417bd0 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -44,4 +44,6 @@
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/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index f80c9e6..816c949 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -491,8 +491,6 @@
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 c7ba7b5..0762b15 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -574,8 +574,6 @@
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 463ff58..0dce079 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -764,8 +764,6 @@
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 08e6575..5c4d4d2 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -417,8 +417,6 @@
}
}
- // 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/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 57e2ece..9190117 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -320,9 +320,6 @@
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 f42d6c8..399cfac 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10170,8 +10170,6 @@
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 fb00c4392..df99fb4 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -519,8 +519,6 @@
}
}
- // 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 73b62a5..54b9cd8 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -438,6 +438,14 @@
+ " 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 2c8e4e0..73886a7 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -169,6 +169,13 @@
}
/**
+ * 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 96285cd..ceb3cc8 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -234,6 +234,7 @@
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 ed0ab60..4b31c91 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 @@
&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 b95258b..6000fb5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -685,11 +685,14 @@
// 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 1777f24..3131302 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/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 7f07f03..efed165 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -356,4 +356,8 @@
<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/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml
index 350a791..7de0035 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 469c1fb..c4372eb 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 f3d8983..f54b6fb 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
similarity index 99%
rename from core/java/com/android/internal/app/LRResolverRankerService.java
rename to packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java
index 1cad7c7..9d7a568 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/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index af247bd..a0eadd0 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 @@
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.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 @@
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 @@
@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 @@
((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/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
index 752b5b0..003f905 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.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/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 143d934..7bc591f 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 @@
// 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 164138e..53a9eae 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 @@
* 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 void onConfigurationChanged() {
- Resources res = mContext.getResources();
reloadResources();
- mDummyStackView.reloadOnConfigurationChange();
+ synchronized (mDummyStackView) {
+ mDummyStackView.reloadOnConfigurationChange();
+ }
}
/**
@@ -393,7 +397,6 @@
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 @@
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 @@
*/
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 @@
* 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 @@
} 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 @@
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 @@
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 2f12282..cd747cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -149,6 +149,10 @@
* 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 +191,20 @@
* 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 +325,7 @@
* 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 +1149,15 @@
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 +1260,76 @@
@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: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskStackChanged();
+ }
+ 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: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
+ (TaskSnapshot) msg.obj);
+ }
+ 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 78c71a1..4b53cd1 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 @@
/**
* 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 @@
* 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 @@
/**
* 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 5e78b61..6dde117 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.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 @@
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 @@
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 @@
* 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 @@
/**
* 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,7 +624,7 @@
}
}
- public void dump(String prefix, PrintWriter writer) {
+ public synchronized void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.print(prefix); writer.println(TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index f3c7b84..4dec6c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -329,12 +329,14 @@
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);
}
}
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 66385a1..907928f 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 @@
}
@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
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 7eefb7e..debb157 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -238,6 +238,9 @@
// 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 @@
// 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 7a702e8..a36873e 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -59,6 +59,9 @@
* @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 @@
* 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 @@
* @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 1b5b2c6..88adbf4 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.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Entry point service for autofill management.
@@ -81,7 +82,6 @@
* {@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 @@
@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 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 @@
}
@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 85fc580..238cdd5 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 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.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 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 @@
* <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 @@
@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 @@
}
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 @@
}
}
+ 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 @@
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 70e97c4..5964172 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 @@
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 @@
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 4d0f380..432a092 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 @@
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 4bc3872..a00a397 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 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.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 @@
* 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 @@
private final MetricsLogger mMetricsLogger = new MetricsLogger();
+ private static AtomicInteger sIdCounter = new AtomicInteger();
+
/** Id of the session */
public final int id;
@@ -127,8 +134,7 @@
@GuardedBy("mLock")
private IAutoFillManagerClient mClient;
- @GuardedBy("mLock")
- RemoteFillService mRemoteFillService;
+ private final RemoteFillService mRemoteFillService;
@GuardedBy("mLock")
private SparseArray<FillResponse> mResponses;
@@ -167,7 +173,124 @@
/**
* 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 @@
}
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 @@
// FillServiceCallbacks
@Override
public void onServiceDied(RemoteFillService service) {
- // TODO(b/33197203): implement
+ // TODO(b/337565347): implement
}
// AutoFillUiCallback
@@ -437,10 +560,6 @@
mHasCallback = hasIt;
}
- public void setStructureLocked(AssistStructure structure) {
- mStructure = structure;
- }
-
/**
* Shows the save UI, when session can be saved.
*
@@ -579,7 +698,7 @@
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 @@
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 @@
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 @@
mCurrentViewId = viewState.id;
viewState.update(value, virtualBounds);
viewState.setState(ViewState.STATE_STARTED_SESSION);
+ requestNewFillResponseLocked();
return;
}
@@ -668,6 +825,19 @@
}
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 @@
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 @@
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 @@
}
// ...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 @@
}
}
- 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 @@
}
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 @@
}
}
- 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 ea5f113..3967f59 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 @@
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 @@
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 b68e3b1..bb47e5b 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 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/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 41b70a1..9bb0f86 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.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 @@
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 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 @@
throws RemoteException {
checkNotNull(deviceMacAddress);
checkCallerIsSystemOr(callingPackage);
+ checkUsesFeature(callingPackage, getCallingUserId());
updateAssociations(associations -> CollectionUtils.remove(associations,
new Association(getCallingUserId(), deviceMacAddress, callingPackage)));
}
@@ -282,12 +287,25 @@
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 @@
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/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index dd4d906..4ce76f4 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1531,6 +1531,9 @@
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/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 494aaa7..08ff7de 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 @@
* 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 6e84ed6..eeedab8 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 @@
}
void setVisibility(boolean visible) {
- mWindowContainerController.setVisibility(visible);
+ mWindowContainerController.setVisibility(visible, false /* deferHidingClient */);
+ }
+
+ void setVisible(boolean newVisible) {
+ setVisible(newVisible, false /* deferHidingClient */);
}
// TODO: Look into merging with #setVisibility()
- void setVisible(boolean newVisible) {
+ 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 824ec68..1e8a587 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.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 @@
return mStackId == HOME_STACK_ID;
}
+ final boolean isRecentsStack() {
+ return mStackId == RECENTS_STACK_ID;
+ }
+
final boolean isHomeOrRecentsStack() {
return StackId.isHomeOrRecentsStack(mStackId);
}
@@ -1402,7 +1407,9 @@
} 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 @@
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 @@
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 @@
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 6010bef..fb8c161 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 @@
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 @@
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/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index dc636e5..056fec5 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 @@
/** 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/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 9eda929..aea4cb5 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -46,12 +46,12 @@
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 */,
@@ -62,16 +62,12 @@
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 @@
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 @@
}
/**
- * 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 @@
/**
* 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/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 64ab848..0db1b5d 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 @@
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 9f693df..02b93a2 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 @@
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
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 221b2bb..32de316 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 @@
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 a8bb809..46be232 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.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 @@
// 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 @@
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 21d78ee..9d08004 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.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 @@
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 @@
/** 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 @@
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 @@
}
};
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.");
+ throw new TimeoutException("[" + token + "] Didn't bind to resolver in time!");
}
- try {
- mLock.wait(remainingMillis);
- } catch (InterruptedException ie) {
- /* ignore */
- }
+ 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 @@
@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 @@
@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 @@
@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 @@
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 6f593b0..b56db04 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 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 @@
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 @@
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) {
- if (DEBUG_EPHEMERAL) {
- Log.d(TAG, "Resolving phase 2");
- }
final long startTime = System.currentTimeMillis();
+ final String token = requestObj.responseObj.token;
+ if (DEBUG_EPHEMERAL) {
+ Log.d(TAG, "[" + token + "] Resolving phase 2");
+ }
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 @@
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 d0a28f9..faa9934 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7683,6 +7683,7 @@
}
// instant application; filter out non-exposed provider
if (instantAppPkgName != null
+ && !isInstantApp
&& (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) {
return null;
}
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
index ee615fd..d7cdf08 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 @@
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 @@
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 @@
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 @@
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 @@
// TODO: STOPSHIP Remove createVirtualDisplay conditional before launching.
if (createVirtualDisplay) {
startVirtualDisplay();
- startImageReader();
}
} else {
// Stop virtual display to test exit condition
@@ -165,6 +190,47 @@
}
/**
+ * 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 @@
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 @@
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 @@
}
}
- if (DEBUG) {
- Log.d(TAG, "VD created: " + mVirtualDisplay);
- }
+ Log.i(TAG, "VD created: " + mVirtualDisplay);
}
/**
@@ -241,6 +308,7 @@
mVirtualDisplay.release();
mVirtualDisplay = null;
}
+ stopImageReader();
}
}
}
@@ -279,11 +347,23 @@
*/
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 358861d..63c6195 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 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 cc08918..860b241 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.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 @@
}
@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 @@
}
@Override
+ public void setCompatibilityDisplayProperties(
+ CompatibilityDisplayProperties compatDisplayProp) {
+ VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
+ }
+
+ @Override
public int getCompatibilityDisplayId() {
return VrManagerService.this.getCompatibilityDisplayId();
}
@@ -642,16 +656,12 @@
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 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 292734d..c625cbe 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 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 @@
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 @@
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 936739b..3c2dfa5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -129,7 +129,11 @@
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;
@@ -178,6 +182,8 @@
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,
@@ -310,16 +316,25 @@
}
}
+ 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
@@ -743,19 +758,21 @@
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) {
@@ -1161,10 +1178,7 @@
hidden = false;
hiddenRequested = false;
}
- if (clientHidden != fromToken.clientHidden) {
- clientHidden = fromToken.clientHidden;
- sendAppVisibilityToClients();
- }
+ setClientHidden(fromToken.mClientHidden);
fromToken.mAppAnimator.transferCurrentAnimation(
mAppAnimator, tStartingWindow.mWinAnimator);
@@ -1529,10 +1543,9 @@
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);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1823610..e2f313a 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 @@
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 4262d12..bc749e1 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 @@
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 @@
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 1feb743..da7a9f0 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 @@
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 5fbc43f..9d6e033 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 @@
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 @@
}
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 @@
if (callback != null) {
callback.run();
}
+ break;
}
case NEW_ANIMATOR_SCALE: {
float scale = getCurrentAnimatorScale();
@@ -5087,6 +5088,7 @@
}
}
}
+ break;
case UPDATE_DOCKED_STACK_DIVIDER: {
synchronized (mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -5104,6 +5106,7 @@
mWindowReplacementTimeouts.clear();
}
}
+ break;
case NOTIFY_APP_TRANSITION_STARTING: {
mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b9776a3..9bdcc36 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 @@
* @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 @@
* 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 @@
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 d383aea..1106006 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,8 @@
*/
package com.android.server.notification;
+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;
@@ -198,7 +200,7 @@
boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
boolean defaultSound, boolean defaultLights) {
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)
@@ -680,6 +682,23 @@
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 303054e..bc5c29d 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 @@
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 @@
@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/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8ee6454..1ef9e49 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -45,6 +45,7 @@
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 @@
/**
* 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 @@
}
/**
+ * 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 @@
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 @@
}
/**
- * 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 e211f76..fe30eb7 100644
--- a/telephony/java/android/telephony/VisualVoicemailService.java
+++ b/telephony/java/android/telephony/VisualVoicemailService.java
@@ -18,6 +18,7 @@
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 @@
/**
* 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 @@
*
* @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 @@
*
* @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 56a8c62..8ed96a3 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -38,7 +38,7 @@
* <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/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 578a8fb..423e790 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -582,6 +582,11 @@
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;
}
diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
index fdc89b2..1a6f348 100644
--- a/tools/aapt2/cmd/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -31,6 +31,11 @@
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 1bbfb28..57c4574 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -144,6 +144,11 @@
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 b86188f..258516d 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -65,16 +65,7 @@
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 @@
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 @@
private:
DISALLOW_COPY_AND_ASSIGN(LinkContext);
+ PackageType package_type_ = PackageType::kApp;
StdErrDiagnostics diagnostics_;
NameMangler name_mangler_;
std::string compilation_package_;
@@ -627,7 +627,7 @@
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 @@
*/
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 @@
return false;
}
- if (options_.package_type == PackageType::kStaticLib) {
+ if (context_->GetPackageType() == PackageType::kStaticLib) {
if (!FlattenTableToPb(table, writer)) {
return false;
}
@@ -1374,7 +1374,7 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
}
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 @@
}
}
- 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 @@
".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 e99ee8a..78ed49b 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -59,6 +59,14 @@
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 @@
}
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 3098458..d44b3e0 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -230,15 +230,18 @@
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 4196187..8dff3a2 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -411,4 +411,40 @@
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/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h
index 4526a79..30dad802 100644
--- a/tools/aapt2/process/IResourceTableConsumer.h
+++ b/tools/aapt2/process/IResourceTableConsumer.h
@@ -32,9 +32,17 @@
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 557cd1b..29d1838 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -35,9 +35,17 @@
public:
Context() : name_mangler_({}), symbols_(&name_mangler_), min_sdk_version_(0) {}
- SymbolTable* GetExternalSymbols() override { return &symbols_; }
+ PackageType GetPackageType() override {
+ return package_type_;
+ }
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+ SymbolTable* GetExternalSymbols() override {
+ return &symbols_;
+ }
+
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
const std::string& GetCompilationPackage() override {
CHECK(bool(compilation_package_)) << "package name not set";
@@ -49,17 +57,24 @@
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 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 @@
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 @@
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 @@
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 20a4531..42786b5 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 @@
using namespace android;
+using android::base::StringPrintf;
+
namespace {
/*
@@ -87,26 +90,35 @@
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 (!ParseTable(parser.chunk())) {
- error = true;
- }
- }
-
- if (parser.event() == ResChunkPullParser::Event::kBadDocument) {
- context_->GetDiagnostics()->Error(
- DiagMessage(source_) << "corrupt resource table: " << parser.error());
+ if (!ResChunkPullParser::IsGoodEvent(parser.Next())) {
+ context_->GetDiagnostics()->Error(DiagMessage(source_)
+ << "corrupt resources.arsc: " << parser.error());
return false;
}
- return !error;
+
+ 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 (!ParseTable(parser.chunk())) {
+ return false;
+ }
+
+ 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 5d71ff3..8d92bd9 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 @@
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 3fedea2..53501f9 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -259,14 +259,19 @@
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 @@
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 @@
"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 @@
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_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 @@
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 @@
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 @@
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/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index bf5c42b..c7e1fc7 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -38,10 +38,10 @@
* {@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 @@
* 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 @@
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 334205b..d8667e6 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -84,7 +84,7 @@
/**
* 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 1ce12f3..0f1e992 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -314,7 +314,7 @@
* {@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 97a6a3f..31e7e8e 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -61,27 +61,6 @@
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 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 @@
(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 @@
dest.writeByteArray(mMatchFilter);
dest.writeInt(mSubscribeType);
dest.writeInt(mTtlSec);
- dest.writeInt(mMatchStyle);
dest.writeInt(mEnableTerminateNotification ? 1 : 0);
}
@@ -155,11 +129,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* {@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 @@
}
/**
- * 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 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 3fcbd4b..d3ed792 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -82,7 +82,7 @@
* 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 @@
* 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 @@
* 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 @@
* 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 ac3a6bb..4e060d5 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -33,7 +33,7 @@
* 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 @@
* 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 @@
try {
if (!mTerminated) {
mCloseGuard.warnIfOpen();
- destroy();
+ close();
}
} finally {
super.finalize();
@@ -110,7 +110,7 @@
* 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 @@
* 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 72a6a7a..694b911 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 @@
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 @@
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
// (5) terminate
- publishSession.getValue().destroy();
+ publishSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
@@ -466,7 +466,7 @@
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
// (5) terminate
- subscribeSession.getValue().destroy();
+ subscribeSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
@@ -687,8 +687,6 @@
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 @@
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 @@
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 @@
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 @@
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
*/