Merge "Revert "Pass token to AutoFillUI.""
diff --git a/api/current.txt b/api/current.txt
index b47397b..eca3c27 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -203,7 +203,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int __removed0 = 16844097; // 0x1010541
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
@@ -1270,6 +1269,7 @@
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
+ field public static final int targetProcess = 16844097; // 0x1010541
field public static final int targetSandboxVersion = 16844110; // 0x101054e
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
@@ -2909,7 +2909,7 @@
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
- method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
+ method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -2918,7 +2918,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
- method public int getAccountVisibility(android.accounts.Account, int);
+ method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2929,9 +2929,9 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
+ method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
- method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -2945,7 +2945,7 @@
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
- method public boolean setAccountVisibility(android.accounts.Account, int, int);
+ method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2985,8 +2985,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
- field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
@@ -4804,6 +4804,7 @@
method public void addMonitor(android.app.Instrumentation.ActivityMonitor);
method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+ method public void addResults(android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
method public void callActivityOnDestroy(android.app.Activity);
@@ -4828,6 +4829,7 @@
method public android.os.Bundle getBinderCounts();
method public android.content.ComponentName getComponentName();
method public android.content.Context getContext();
+ method public java.lang.String getProcessName();
method public android.content.Context getTargetContext();
method public android.app.UiAutomation getUiAutomation();
method public android.app.UiAutomation getUiAutomation(int);
@@ -9903,6 +9905,7 @@
field public java.lang.String[] splitPublicSourceDirs;
field public java.lang.String[] splitSourceDirs;
field public java.lang.String targetPackage;
+ field public java.lang.String targetProcess;
}
public class LabeledIntent extends android.content.Intent {
@@ -23943,6 +23946,7 @@
field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
@@ -23950,6 +23954,7 @@
field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -23963,17 +23968,14 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
- field public static final java.lang.String COLUMN_LOGO = "logo";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
- field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
- field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
- field public static final java.lang.String COLUMN_PREVIEW_LAST_PLAYBACK_POSITION = "preview_last_playback_position";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
- field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
@@ -23993,6 +23995,7 @@
field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+ field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -25738,6 +25741,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
+ method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -25750,6 +25754,7 @@
method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
+ method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -25765,6 +25770,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
+ method public boolean removePasspointConfiguration(java.lang.String);
method public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -25979,6 +25985,241 @@
}
+package android.net.wifi.hotspot2 {
+
+ public final class ConfigParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parsePasspointConfig(java.lang.String, byte[]);
+ }
+
+ public final class PasspointConfiguration implements android.os.Parcelable {
+ ctor public PasspointConfiguration();
+ ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.hotspot2.pps.Credential getCredential();
+ method public int getCredentialPriority();
+ method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
+ method public android.net.wifi.hotspot2.pps.Policy getPolicy();
+ method public long getSubscriptionCreationTimeInMs();
+ method public long getSubscriptionExpirationTimeInMs();
+ method public java.lang.String getSubscriptionType();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
+ method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
+ method public int getUpdateIdentififer();
+ method public long getUsageLimitDataLimit();
+ method public long getUsageLimitStartTimeInMs();
+ method public long getUsageLimitTimeLimitInMinutes();
+ method public long getUsageLimitUsageTimePeriodInMinutes();
+ method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
+ method public void setCredentialPriority(int);
+ method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
+ method public void setSubscriptionCreationTimeInMs(long);
+ method public void setSubscriptionExpirationTimeInMs(long);
+ method public void setSubscriptionType(java.lang.String);
+ method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
+ method public void setUpdateIdentifier(int);
+ method public void setUsageLimitDataLimit(long);
+ method public void setUsageLimitStartTimeInMs(long);
+ method public void setUsageLimitTimeLimitInMinutes(long);
+ method public void setUsageLimitUsageTimePeriodInMinutes(long);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
+ }
+
+}
+
+package android.net.wifi.hotspot2.omadm {
+
+ public final class PpsMoParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parseMoText(java.lang.String);
+ }
+
+}
+
+package android.net.wifi.hotspot2.pps {
+
+ public final class Credential implements android.os.Parcelable {
+ ctor public Credential();
+ ctor public Credential(android.net.wifi.hotspot2.pps.Credential);
+ method public int describeContents();
+ method public java.security.cert.X509Certificate getCaCertificate();
+ method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
+ method public boolean getCheckAaaServerStatus();
+ method public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method public java.security.PrivateKey getClientPrivateKey();
+ method public long getCreationTimeInMs();
+ method public long getExpirationTimeInMs();
+ method public java.lang.String getRealm();
+ method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
+ method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
+ method public void setCaCertificate(java.security.cert.X509Certificate);
+ method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public void setCheckAaaServerCertStatus(boolean);
+ method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
+ method public void setClientPrivateKey(java.security.PrivateKey);
+ method public void setCreationTimeInMs(long);
+ method public void setExpirationTimeInMs(long);
+ method public void setRealm(java.lang.String);
+ method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
+ }
+
+ public static final class Credential.CertificateCredential implements android.os.Parcelable {
+ ctor public Credential.CertificateCredential();
+ ctor public Credential.CertificateCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public int describeContents();
+ method public byte[] getCertSha256Fingerprint();
+ method public java.lang.String getCertType();
+ method public void setCertSha256Fingerprint(byte[]);
+ method public void setCertType(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
+ }
+
+ public static final class Credential.SimCredential implements android.os.Parcelable {
+ ctor public Credential.SimCredential();
+ ctor public Credential.SimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public int describeContents();
+ method public int getEapType();
+ method public java.lang.String getImsi();
+ method public void setEapType(int);
+ method public void setImsi(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
+ }
+
+ public static final class Credential.UserCredential implements android.os.Parcelable {
+ ctor public Credential.UserCredential();
+ ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public int describeContents();
+ method public boolean getAbleToShare();
+ method public int getEapType();
+ method public boolean getMachineManaged();
+ method public java.lang.String getNonEapInnerMethod();
+ method public java.lang.String getPassword();
+ method public java.lang.String getSoftTokenApp();
+ method public java.lang.String getUsername();
+ method public void setAbleToShare(boolean);
+ method public void setEapType(int);
+ method public void setMachineManaged(boolean);
+ method public void setNonEapInnerMethod(java.lang.String);
+ method public void setPassword(java.lang.String);
+ method public void setSoftTokenApp(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
+ }
+
+ public final class HomeSp implements android.os.Parcelable {
+ ctor public HomeSp();
+ ctor public HomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public int describeContents();
+ method public java.lang.String getFqdn();
+ method public java.lang.String getFriendlyName();
+ method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
+ method public java.lang.String getIconUrl();
+ method public long[] getMatchAllOis();
+ method public long[] getMatchAnysOis();
+ method public java.lang.String[] getOtherHomePartners();
+ method public long[] getRoamingConsortiumOis();
+ method public void setFqdn(java.lang.String);
+ method public void setFriendlyName(java.lang.String);
+ method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
+ method public void setIconUrl(java.lang.String);
+ method public void setMatchAllOis(long[]);
+ method public void setMatchAnyOis(long[]);
+ method public void setOtherHomePartners(java.lang.String[]);
+ method public void setRoamingConsortiumOis(long[]);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
+ }
+
+ public final class Policy implements android.os.Parcelable {
+ ctor public Policy();
+ ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
+ method public int describeContents();
+ method public java.lang.String[] getExcludedSsidList();
+ method public int getMaximumBssLoadValue();
+ method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeUplinkBandwidth();
+ method public long getMinRoamingDownlinkBandwidth();
+ method public long getMinRoamingUplinkBandwidth();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
+ method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
+ method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
+ method public void setExcludedSsidList(java.lang.String[]);
+ method public void setMaximumBssLoadValue(int);
+ method public void setMinHomeDownlinkBandwidth(long);
+ method public void setMinHomeUplinkBandwidth(long);
+ method public void setMinRoamingDownlinkBandwidth(long);
+ method public void setMinRoamingUplinkBandwidth(long);
+ method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
+ method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
+ }
+
+ public static final class Policy.RoamingPartner implements android.os.Parcelable {
+ ctor public Policy.RoamingPartner();
+ ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
+ method public int describeContents();
+ method public java.lang.String getCountries();
+ method public java.lang.String getFqdn();
+ method public boolean getFqdnExactMatch();
+ method public int getPriority();
+ method public void setCountries(java.lang.String);
+ method public void setFqdn(java.lang.String);
+ method public void setFqdnExactMatch(boolean);
+ method public void setPriority(int);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
+ }
+
+ public final class UpdateParameter implements android.os.Parcelable {
+ ctor public UpdateParameter();
+ ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public int describeContents();
+ method public java.lang.String getBase64EncodedPassword();
+ method public java.lang.String getRestriction();
+ method public java.lang.String getServerUri();
+ method public byte[] getTrustRootCertSha256Fingerprint();
+ method public java.lang.String getTrustRootCertUrl();
+ method public long getUpdateIntervalInMinutes();
+ method public java.lang.String getUpdateMethod();
+ method public java.lang.String getUsername();
+ method public void setBase64EncodedPassword(java.lang.String);
+ method public void setRestriction(java.lang.String);
+ method public void setServerUri(java.lang.String);
+ method public void setTrustRootCertSha256Fingerprint(byte[]);
+ method public void setTrustRootCertUrl(java.lang.String);
+ method public void setUpdateIntervalInMinutes(long);
+ method public void setUpdateMethod(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
+ field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
+ field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
+ field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
+ field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
+ field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
+ field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -45685,6 +45926,7 @@
field public static final int TYPE_APPLICATION = 2; // 0x2
field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
+ field public static final int TYPE_APPLICATION_OVERLAY = 2038; // 0x7f6
field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
field public static final int TYPE_APPLICATION_STARTING = 3; // 0x3
field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea
@@ -45694,17 +45936,17 @@
field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db
field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc
field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9
- field public static final int TYPE_PHONE = 2002; // 0x7d2
- field public static final int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
+ field public static final deprecated int TYPE_PHONE = 2002; // 0x7d2
+ field public static final deprecated int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
field public static final int TYPE_PRIVATE_PRESENTATION = 2030; // 0x7ee
field public static final int TYPE_SEARCH_BAR = 2001; // 0x7d1
field public static final int TYPE_STATUS_BAR = 2000; // 0x7d0
field public static final int TYPE_STATUS_BAR_PANEL = 2014; // 0x7de
- field public static final int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
+ field public static final deprecated int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
field public static final int TYPE_SYSTEM_DIALOG = 2008; // 0x7d8
- field public static final int TYPE_SYSTEM_ERROR = 2010; // 0x7da
- field public static final int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
- field public static final int TYPE_TOAST = 2005; // 0x7d5
+ field public static final deprecated int TYPE_SYSTEM_ERROR = 2010; // 0x7da
+ field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
+ field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
field public float alpha;
field public float buttonBrightness;
diff --git a/api/system-current.txt b/api/system-current.txt
index 397de8f..55b32f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -315,7 +315,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int __removed0 = 16844097; // 0x1010541
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
@@ -1386,6 +1385,7 @@
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
+ field public static final int targetProcess = 16844097; // 0x1010541
field public static final int targetSandboxVersion = 16844110; // 0x101054e
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
@@ -3028,7 +3028,7 @@
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
- method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
+ method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -3038,7 +3038,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSessionAsUser(android.os.Bundle, android.app.Activity, android.os.UserHandle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
- method public int getAccountVisibility(android.accounts.Account, int);
+ method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -3049,9 +3049,9 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
+ method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
- method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -3065,7 +3065,7 @@
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
- method public boolean setAccountVisibility(android.accounts.Account, int, int);
+ method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -3105,8 +3105,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
- field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
@@ -4964,6 +4964,7 @@
method public void addMonitor(android.app.Instrumentation.ActivityMonitor);
method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+ method public void addResults(android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
method public void callActivityOnDestroy(android.app.Activity);
@@ -4988,6 +4989,7 @@
method public android.os.Bundle getBinderCounts();
method public android.content.ComponentName getComponentName();
method public android.content.Context getContext();
+ method public java.lang.String getProcessName();
method public android.content.Context getTargetContext();
method public android.app.UiAutomation getUiAutomation();
method public android.app.UiAutomation getUiAutomation(int);
@@ -10358,6 +10360,7 @@
field public java.lang.String[] splitPublicSourceDirs;
field public java.lang.String[] splitSourceDirs;
field public java.lang.String targetPackage;
+ field public java.lang.String targetProcess;
}
public final class IntentFilterVerificationInfo implements android.os.Parcelable {
@@ -25628,6 +25631,7 @@
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
+ field public static final java.lang.String COLUMN_SYSTEM_APPROVED = "system_approved";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
field public static final java.lang.String COLUMN_TYPE = "type";
@@ -25694,6 +25698,7 @@
field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
@@ -25701,6 +25706,7 @@
field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -25714,17 +25720,14 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
- field public static final java.lang.String COLUMN_LOGO = "logo";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
- field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
- field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
- field public static final java.lang.String COLUMN_PREVIEW_LAST_PLAYBACK_POSITION = "preview_last_playback_position";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
- field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
@@ -25745,6 +25748,7 @@
field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+ field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -28253,6 +28257,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
+ method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -28268,6 +28273,7 @@
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.wifi.WifiConnectionStatistics getConnectionStatistics();
method public android.net.DhcpInfo getDhcpInfo();
+ method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
@@ -28291,6 +28297,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
+ method public boolean removePasspointConfiguration(java.lang.String);
method public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -28674,6 +28681,241 @@
}
+package android.net.wifi.hotspot2 {
+
+ public final class ConfigParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parsePasspointConfig(java.lang.String, byte[]);
+ }
+
+ public final class PasspointConfiguration implements android.os.Parcelable {
+ ctor public PasspointConfiguration();
+ ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.hotspot2.pps.Credential getCredential();
+ method public int getCredentialPriority();
+ method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
+ method public android.net.wifi.hotspot2.pps.Policy getPolicy();
+ method public long getSubscriptionCreationTimeInMs();
+ method public long getSubscriptionExpirationTimeInMs();
+ method public java.lang.String getSubscriptionType();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
+ method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
+ method public int getUpdateIdentififer();
+ method public long getUsageLimitDataLimit();
+ method public long getUsageLimitStartTimeInMs();
+ method public long getUsageLimitTimeLimitInMinutes();
+ method public long getUsageLimitUsageTimePeriodInMinutes();
+ method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
+ method public void setCredentialPriority(int);
+ method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
+ method public void setSubscriptionCreationTimeInMs(long);
+ method public void setSubscriptionExpirationTimeInMs(long);
+ method public void setSubscriptionType(java.lang.String);
+ method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
+ method public void setUpdateIdentifier(int);
+ method public void setUsageLimitDataLimit(long);
+ method public void setUsageLimitStartTimeInMs(long);
+ method public void setUsageLimitTimeLimitInMinutes(long);
+ method public void setUsageLimitUsageTimePeriodInMinutes(long);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
+ }
+
+}
+
+package android.net.wifi.hotspot2.omadm {
+
+ public final class PpsMoParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parseMoText(java.lang.String);
+ }
+
+}
+
+package android.net.wifi.hotspot2.pps {
+
+ public final class Credential implements android.os.Parcelable {
+ ctor public Credential();
+ ctor public Credential(android.net.wifi.hotspot2.pps.Credential);
+ method public int describeContents();
+ method public java.security.cert.X509Certificate getCaCertificate();
+ method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
+ method public boolean getCheckAaaServerStatus();
+ method public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method public java.security.PrivateKey getClientPrivateKey();
+ method public long getCreationTimeInMs();
+ method public long getExpirationTimeInMs();
+ method public java.lang.String getRealm();
+ method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
+ method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
+ method public void setCaCertificate(java.security.cert.X509Certificate);
+ method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public void setCheckAaaServerCertStatus(boolean);
+ method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
+ method public void setClientPrivateKey(java.security.PrivateKey);
+ method public void setCreationTimeInMs(long);
+ method public void setExpirationTimeInMs(long);
+ method public void setRealm(java.lang.String);
+ method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
+ }
+
+ public static final class Credential.CertificateCredential implements android.os.Parcelable {
+ ctor public Credential.CertificateCredential();
+ ctor public Credential.CertificateCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public int describeContents();
+ method public byte[] getCertSha256Fingerprint();
+ method public java.lang.String getCertType();
+ method public void setCertSha256Fingerprint(byte[]);
+ method public void setCertType(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
+ }
+
+ public static final class Credential.SimCredential implements android.os.Parcelable {
+ ctor public Credential.SimCredential();
+ ctor public Credential.SimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public int describeContents();
+ method public int getEapType();
+ method public java.lang.String getImsi();
+ method public void setEapType(int);
+ method public void setImsi(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
+ }
+
+ public static final class Credential.UserCredential implements android.os.Parcelable {
+ ctor public Credential.UserCredential();
+ ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public int describeContents();
+ method public boolean getAbleToShare();
+ method public int getEapType();
+ method public boolean getMachineManaged();
+ method public java.lang.String getNonEapInnerMethod();
+ method public java.lang.String getPassword();
+ method public java.lang.String getSoftTokenApp();
+ method public java.lang.String getUsername();
+ method public void setAbleToShare(boolean);
+ method public void setEapType(int);
+ method public void setMachineManaged(boolean);
+ method public void setNonEapInnerMethod(java.lang.String);
+ method public void setPassword(java.lang.String);
+ method public void setSoftTokenApp(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
+ }
+
+ public final class HomeSp implements android.os.Parcelable {
+ ctor public HomeSp();
+ ctor public HomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public int describeContents();
+ method public java.lang.String getFqdn();
+ method public java.lang.String getFriendlyName();
+ method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
+ method public java.lang.String getIconUrl();
+ method public long[] getMatchAllOis();
+ method public long[] getMatchAnysOis();
+ method public java.lang.String[] getOtherHomePartners();
+ method public long[] getRoamingConsortiumOis();
+ method public void setFqdn(java.lang.String);
+ method public void setFriendlyName(java.lang.String);
+ method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
+ method public void setIconUrl(java.lang.String);
+ method public void setMatchAllOis(long[]);
+ method public void setMatchAnyOis(long[]);
+ method public void setOtherHomePartners(java.lang.String[]);
+ method public void setRoamingConsortiumOis(long[]);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
+ }
+
+ public final class Policy implements android.os.Parcelable {
+ ctor public Policy();
+ ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
+ method public int describeContents();
+ method public java.lang.String[] getExcludedSsidList();
+ method public int getMaximumBssLoadValue();
+ method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeUplinkBandwidth();
+ method public long getMinRoamingDownlinkBandwidth();
+ method public long getMinRoamingUplinkBandwidth();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
+ method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
+ method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
+ method public void setExcludedSsidList(java.lang.String[]);
+ method public void setMaximumBssLoadValue(int);
+ method public void setMinHomeDownlinkBandwidth(long);
+ method public void setMinHomeUplinkBandwidth(long);
+ method public void setMinRoamingDownlinkBandwidth(long);
+ method public void setMinRoamingUplinkBandwidth(long);
+ method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
+ method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
+ }
+
+ public static final class Policy.RoamingPartner implements android.os.Parcelable {
+ ctor public Policy.RoamingPartner();
+ ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
+ method public int describeContents();
+ method public java.lang.String getCountries();
+ method public java.lang.String getFqdn();
+ method public boolean getFqdnExactMatch();
+ method public int getPriority();
+ method public void setCountries(java.lang.String);
+ method public void setFqdn(java.lang.String);
+ method public void setFqdnExactMatch(boolean);
+ method public void setPriority(int);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
+ }
+
+ public final class UpdateParameter implements android.os.Parcelable {
+ ctor public UpdateParameter();
+ ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public int describeContents();
+ method public java.lang.String getBase64EncodedPassword();
+ method public java.lang.String getRestriction();
+ method public java.lang.String getServerUri();
+ method public byte[] getTrustRootCertSha256Fingerprint();
+ method public java.lang.String getTrustRootCertUrl();
+ method public long getUpdateIntervalInMinutes();
+ method public java.lang.String getUpdateMethod();
+ method public java.lang.String getUsername();
+ method public void setBase64EncodedPassword(java.lang.String);
+ method public void setRestriction(java.lang.String);
+ method public void setServerUri(java.lang.String);
+ method public void setTrustRootCertSha256Fingerprint(byte[]);
+ method public void setTrustRootCertUrl(java.lang.String);
+ method public void setUpdateIntervalInMinutes(long);
+ method public void setUpdateMethod(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
+ field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
+ field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
+ field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
+ field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
+ field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
+ field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -42379,11 +42621,6 @@
field public static final int PHONE_TYPE_GSM = 1; // 0x1
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
- field public static final int SIM_ACTIVATION_RESULT_CANCELED = 4; // 0x4
- field public static final int SIM_ACTIVATION_RESULT_COMPLETE = 0; // 0x0
- field public static final int SIM_ACTIVATION_RESULT_FAILED = 3; // 0x3
- field public static final int SIM_ACTIVATION_RESULT_IN_PROGRESS = 2; // 0x2
- field public static final int SIM_ACTIVATION_RESULT_NOT_SUPPORTED = 1; // 0x1
field public static final int SIM_STATE_ABSENT = 1; // 0x1
field public static final int SIM_STATE_CARD_IO_ERROR = 8; // 0x8
field public static final int SIM_STATE_CARD_RESTRICTED = 9; // 0x9
@@ -49094,6 +49331,7 @@
field public static final int TYPE_APPLICATION = 2; // 0x2
field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
+ field public static final int TYPE_APPLICATION_OVERLAY = 2038; // 0x7f6
field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
field public static final int TYPE_APPLICATION_STARTING = 3; // 0x3
field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea
@@ -49103,17 +49341,17 @@
field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db
field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc
field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9
- field public static final int TYPE_PHONE = 2002; // 0x7d2
- field public static final int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
+ field public static final deprecated int TYPE_PHONE = 2002; // 0x7d2
+ field public static final deprecated int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
field public static final int TYPE_PRIVATE_PRESENTATION = 2030; // 0x7ee
field public static final int TYPE_SEARCH_BAR = 2001; // 0x7d1
field public static final int TYPE_STATUS_BAR = 2000; // 0x7d0
field public static final int TYPE_STATUS_BAR_PANEL = 2014; // 0x7de
- field public static final int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
+ field public static final deprecated int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
field public static final int TYPE_SYSTEM_DIALOG = 2008; // 0x7d8
- field public static final int TYPE_SYSTEM_ERROR = 2010; // 0x7da
- field public static final int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
- field public static final int TYPE_TOAST = 2005; // 0x7d5
+ field public static final deprecated int TYPE_SYSTEM_ERROR = 2010; // 0x7da
+ field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
+ field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
field public float alpha;
field public float buttonBrightness;
diff --git a/api/test-current.txt b/api/test-current.txt
index ceac110..bc7a001 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -203,7 +203,6 @@
public static final class R.attr {
ctor public R.attr();
- field public static final int __removed0 = 16844097; // 0x1010541
field public static final int __removed1 = 16844099; // 0x1010543
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
@@ -1270,6 +1269,7 @@
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
+ field public static final int targetProcess = 16844097; // 0x1010541
field public static final int targetSandboxVersion = 16844110; // 0x101054e
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
@@ -2909,7 +2909,7 @@
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
- method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
+ method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -2918,7 +2918,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
- method public int getAccountVisibility(android.accounts.Account, int);
+ method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2929,9 +2929,9 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
+ method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
- method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -2945,7 +2945,7 @@
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
- method public boolean setAccountVisibility(android.accounts.Account, int, int);
+ method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2985,8 +2985,8 @@
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
- field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
- field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
+ field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
@@ -4814,6 +4814,7 @@
method public void addMonitor(android.app.Instrumentation.ActivityMonitor);
method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+ method public void addResults(android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
method public void callActivityOnDestroy(android.app.Activity);
@@ -4838,6 +4839,7 @@
method public android.os.Bundle getBinderCounts();
method public android.content.ComponentName getComponentName();
method public android.content.Context getContext();
+ method public java.lang.String getProcessName();
method public android.content.Context getTargetContext();
method public android.app.UiAutomation getUiAutomation();
method public android.app.UiAutomation getUiAutomation(int);
@@ -9931,6 +9933,7 @@
field public java.lang.String[] splitPublicSourceDirs;
field public java.lang.String[] splitSourceDirs;
field public java.lang.String targetPackage;
+ field public java.lang.String targetProcess;
}
public class LabeledIntent extends android.content.Intent {
@@ -24035,6 +24038,7 @@
field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_AUTHOR = "author";
field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
@@ -24042,6 +24046,7 @@
field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+ field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -24055,17 +24060,14 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+ field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
field public static final java.lang.String COLUMN_LIVE = "live";
- field public static final java.lang.String COLUMN_LOGO = "logo";
+ field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
- field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
- field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
- field public static final java.lang.String COLUMN_PREVIEW_LAST_PLAYBACK_POSITION = "preview_last_playback_position";
field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
- field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
@@ -24085,6 +24087,7 @@
field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+ field public static final java.lang.String COLUMN_WEIGHT = "weight";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
@@ -25830,6 +25833,7 @@
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
+ method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
@@ -25842,6 +25846,7 @@
method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
+ method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -25857,6 +25862,7 @@
method public boolean reassociate();
method public boolean reconnect();
method public boolean removeNetwork(int);
+ method public boolean removePasspointConfiguration(java.lang.String);
method public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -26071,6 +26077,241 @@
}
+package android.net.wifi.hotspot2 {
+
+ public final class ConfigParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parsePasspointConfig(java.lang.String, byte[]);
+ }
+
+ public final class PasspointConfiguration implements android.os.Parcelable {
+ ctor public PasspointConfiguration();
+ ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.hotspot2.pps.Credential getCredential();
+ method public int getCredentialPriority();
+ method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
+ method public android.net.wifi.hotspot2.pps.Policy getPolicy();
+ method public long getSubscriptionCreationTimeInMs();
+ method public long getSubscriptionExpirationTimeInMs();
+ method public java.lang.String getSubscriptionType();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getSubscriptionUpdate();
+ method public java.util.Map<java.lang.String, byte[]> getTrustRootCertList();
+ method public int getUpdateIdentififer();
+ method public long getUsageLimitDataLimit();
+ method public long getUsageLimitStartTimeInMs();
+ method public long getUsageLimitTimeLimitInMinutes();
+ method public long getUsageLimitUsageTimePeriodInMinutes();
+ method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
+ method public void setCredentialPriority(int);
+ method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public void setPolicy(android.net.wifi.hotspot2.pps.Policy);
+ method public void setSubscriptionCreationTimeInMs(long);
+ method public void setSubscriptionExpirationTimeInMs(long);
+ method public void setSubscriptionType(java.lang.String);
+ method public void setSubscriptionUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setTrustRootCertList(java.util.Map<java.lang.String, byte[]>);
+ method public void setUpdateIdentifier(int);
+ method public void setUsageLimitDataLimit(long);
+ method public void setUsageLimitStartTimeInMs(long);
+ method public void setUsageLimitTimeLimitInMinutes(long);
+ method public void setUsageLimitUsageTimePeriodInMinutes(long);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
+ }
+
+}
+
+package android.net.wifi.hotspot2.omadm {
+
+ public final class PpsMoParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parseMoText(java.lang.String);
+ }
+
+}
+
+package android.net.wifi.hotspot2.pps {
+
+ public final class Credential implements android.os.Parcelable {
+ ctor public Credential();
+ ctor public Credential(android.net.wifi.hotspot2.pps.Credential);
+ method public int describeContents();
+ method public java.security.cert.X509Certificate getCaCertificate();
+ method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
+ method public boolean getCheckAaaServerStatus();
+ method public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method public java.security.PrivateKey getClientPrivateKey();
+ method public long getCreationTimeInMs();
+ method public long getExpirationTimeInMs();
+ method public java.lang.String getRealm();
+ method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
+ method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
+ method public void setCaCertificate(java.security.cert.X509Certificate);
+ method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public void setCheckAaaServerCertStatus(boolean);
+ method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
+ method public void setClientPrivateKey(java.security.PrivateKey);
+ method public void setCreationTimeInMs(long);
+ method public void setExpirationTimeInMs(long);
+ method public void setRealm(java.lang.String);
+ method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
+ }
+
+ public static final class Credential.CertificateCredential implements android.os.Parcelable {
+ ctor public Credential.CertificateCredential();
+ ctor public Credential.CertificateCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public int describeContents();
+ method public byte[] getCertSha256Fingerprint();
+ method public java.lang.String getCertType();
+ method public void setCertSha256Fingerprint(byte[]);
+ method public void setCertType(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
+ }
+
+ public static final class Credential.SimCredential implements android.os.Parcelable {
+ ctor public Credential.SimCredential();
+ ctor public Credential.SimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public int describeContents();
+ method public int getEapType();
+ method public java.lang.String getImsi();
+ method public void setEapType(int);
+ method public void setImsi(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
+ }
+
+ public static final class Credential.UserCredential implements android.os.Parcelable {
+ ctor public Credential.UserCredential();
+ ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public int describeContents();
+ method public boolean getAbleToShare();
+ method public int getEapType();
+ method public boolean getMachineManaged();
+ method public java.lang.String getNonEapInnerMethod();
+ method public java.lang.String getPassword();
+ method public java.lang.String getSoftTokenApp();
+ method public java.lang.String getUsername();
+ method public void setAbleToShare(boolean);
+ method public void setEapType(int);
+ method public void setMachineManaged(boolean);
+ method public void setNonEapInnerMethod(java.lang.String);
+ method public void setPassword(java.lang.String);
+ method public void setSoftTokenApp(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
+ }
+
+ public final class HomeSp implements android.os.Parcelable {
+ ctor public HomeSp();
+ ctor public HomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public int describeContents();
+ method public java.lang.String getFqdn();
+ method public java.lang.String getFriendlyName();
+ method public java.util.Map<java.lang.String, java.lang.Long> getHomeNetworkIds();
+ method public java.lang.String getIconUrl();
+ method public long[] getMatchAllOis();
+ method public long[] getMatchAnysOis();
+ method public java.lang.String[] getOtherHomePartners();
+ method public long[] getRoamingConsortiumOis();
+ method public void setFqdn(java.lang.String);
+ method public void setFriendlyName(java.lang.String);
+ method public void setHomeNetworkIds(java.util.Map<java.lang.String, java.lang.Long>);
+ method public void setIconUrl(java.lang.String);
+ method public void setMatchAllOis(long[]);
+ method public void setMatchAnyOis(long[]);
+ method public void setOtherHomePartners(java.lang.String[]);
+ method public void setRoamingConsortiumOis(long[]);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
+ }
+
+ public final class Policy implements android.os.Parcelable {
+ ctor public Policy();
+ ctor public Policy(android.net.wifi.hotspot2.pps.Policy);
+ method public int describeContents();
+ method public java.lang.String[] getExcludedSsidList();
+ method public int getMaximumBssLoadValue();
+ method public long getMinHomeDownlinkBandWidht();
+ method public long getMinHomeUplinkBandwidth();
+ method public long getMinRoamingDownlinkBandwidth();
+ method public long getMinRoamingUplinkBandwidth();
+ method public android.net.wifi.hotspot2.pps.UpdateParameter getPolicyUpdate();
+ method public java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> getPreferredRoamingPartnerList();
+ method public java.util.Map<java.lang.Integer, java.lang.String> getRequiredProtoPortMap();
+ method public void setExcludedSsidList(java.lang.String[]);
+ method public void setMaximumBssLoadValue(int);
+ method public void setMinHomeDownlinkBandwidth(long);
+ method public void setMinHomeUplinkBandwidth(long);
+ method public void setMinRoamingDownlinkBandwidth(long);
+ method public void setMinRoamingUplinkBandwidth(long);
+ method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
+ method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
+ }
+
+ public static final class Policy.RoamingPartner implements android.os.Parcelable {
+ ctor public Policy.RoamingPartner();
+ ctor public Policy.RoamingPartner(android.net.wifi.hotspot2.pps.Policy.RoamingPartner);
+ method public int describeContents();
+ method public java.lang.String getCountries();
+ method public java.lang.String getFqdn();
+ method public boolean getFqdnExactMatch();
+ method public int getPriority();
+ method public void setCountries(java.lang.String);
+ method public void setFqdn(java.lang.String);
+ method public void setFqdnExactMatch(boolean);
+ method public void setPriority(int);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
+ }
+
+ public final class UpdateParameter implements android.os.Parcelable {
+ ctor public UpdateParameter();
+ ctor public UpdateParameter(android.net.wifi.hotspot2.pps.UpdateParameter);
+ method public int describeContents();
+ method public java.lang.String getBase64EncodedPassword();
+ method public java.lang.String getRestriction();
+ method public java.lang.String getServerUri();
+ method public byte[] getTrustRootCertSha256Fingerprint();
+ method public java.lang.String getTrustRootCertUrl();
+ method public long getUpdateIntervalInMinutes();
+ method public java.lang.String getUpdateMethod();
+ method public java.lang.String getUsername();
+ method public void setBase64EncodedPassword(java.lang.String);
+ method public void setRestriction(java.lang.String);
+ method public void setServerUri(java.lang.String);
+ method public void setTrustRootCertSha256Fingerprint(byte[]);
+ method public void setTrustRootCertUrl(java.lang.String);
+ method public void setUpdateIntervalInMinutes(long);
+ method public void setUpdateMethod(java.lang.String);
+ method public void setUsername(java.lang.String);
+ method public boolean validate();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
+ field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
+ field public static final java.lang.String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
+ field public static final java.lang.String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
+ field public static final java.lang.String UPDATE_RESTRICTION_HOMESP = "HomeSP";
+ field public static final java.lang.String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
+ field public static final java.lang.String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -45996,6 +46237,7 @@
field public static final int TYPE_APPLICATION = 2; // 0x2
field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
+ field public static final int TYPE_APPLICATION_OVERLAY = 2038; // 0x7f6
field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
field public static final int TYPE_APPLICATION_STARTING = 3; // 0x3
field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea
@@ -46005,17 +46247,17 @@
field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db
field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc
field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9
- field public static final int TYPE_PHONE = 2002; // 0x7d2
- field public static final int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
+ field public static final deprecated int TYPE_PHONE = 2002; // 0x7d2
+ field public static final deprecated int TYPE_PRIORITY_PHONE = 2007; // 0x7d7
field public static final int TYPE_PRIVATE_PRESENTATION = 2030; // 0x7ee
field public static final int TYPE_SEARCH_BAR = 2001; // 0x7d1
field public static final int TYPE_STATUS_BAR = 2000; // 0x7d0
field public static final int TYPE_STATUS_BAR_PANEL = 2014; // 0x7de
- field public static final int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
+ field public static final deprecated int TYPE_SYSTEM_ALERT = 2003; // 0x7d3
field public static final int TYPE_SYSTEM_DIALOG = 2008; // 0x7d8
- field public static final int TYPE_SYSTEM_ERROR = 2010; // 0x7da
- field public static final int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
- field public static final int TYPE_TOAST = 2005; // 0x7d5
+ field public static final deprecated int TYPE_SYSTEM_ERROR = 2010; // 0x7da
+ field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
+ field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
field public float alpha;
field public float buttonBrightness;
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index c773275..7901737 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "BootAnimation"
#include <stdint.h>
+#include <inttypes.h>
#include <sys/inotify.h>
#include <sys/poll.h>
#include <sys/stat.h>
@@ -35,6 +36,7 @@
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Log.h>
+#include <utils/SystemClock.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
@@ -350,6 +352,7 @@
bool BootAnimation::android()
{
+ ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
@@ -854,8 +857,8 @@
mTimeCheckThread = nullptr;
}
+ // We should have joined mInitAudioThread thread in playAnimation
if (mInitAudioThread != nullptr) {
- mInitAudioThread->requestExit();
mInitAudioThread = nullptr;
}
@@ -875,6 +878,7 @@
const int animationX = (mWidth - animation.width) / 2;
const int animationY = (mHeight - animation.height) / 2;
+ ALOGD("BootAnimationShownTiming: BootAnimation start time: %" PRId64 "ms", elapsedRealtime());
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index def0ff9..0263681 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -338,21 +338,24 @@
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
/**
- * Uid key to set default visibility for applications targeting API level
+ * Key to set default visibility for applications targeting API level
* {@link android.os.Build.VERSION_CODES#O} or above and don't have the same signature as
* authenticator See {@link #getAccountVisibility}. If the value was not set by authenticator
- * USER_MANAGED_NOT_VISIBLE is used.
+ * {@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE} is used.
*/
- public static final int UID_KEY_DEFAULT_VISIBILITY = -2;
+ public static final String PACKAGE_NAME_KEY_LEGACY_VISIBLE =
+ "android.accounts.key_legacy_visible";
/**
- * Uid key to set visibility for applications targeting API level below
- * {@link android.os.Build.VERSION_CODES#O} with GET_ACCOUNS permission, or applications with
- * any targeting API level with the same signature as authenticator. See
- * {@link #getAccountVisibility}. If the value was not set by authenticator USER_MANAGED_VISIBLE
- * is used.
+ * Key to set visibility for applications targeting API level below
+ * {@link android.os.Build.VERSION_CODES#O} with
+ * {@link android.Manifest.permission#GET_ACCOUNTS} permission, or applications with any
+ * targeting API level with the same signature as authenticator. See
+ * {@link #getAccountVisibility}. If the value was not set by authenticator
+ * {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
*/
- public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3;
+ public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
+ "android.accounts.key_legacy_not_visible";
/**
* @hide
@@ -565,12 +568,14 @@
}
/**
- * Returns the accounts visible to the specified package, in an environment where some apps
- * are not authorized to view all accounts. This method can only be called by system apps.
+ * Returns the accounts visible to the specified package, in an environment where some apps are
+ * not authorized to view all accounts. This method can only be called by system apps and
+ * authenticators managing the type
+ *
* @param type The type of accounts to return, null to retrieve all accounts
* @param packageName The package name of the app for which the accounts are to be returned
- * @return An array of {@link Account}, one per matching account. Empty
- * (never null) if no accounts of the specified type have been added.
+ * @return An array of {@link Account}, one per matching account. Empty (never null) if no
+ * accounts of the specified type have been added.
*/
@NonNull
public Account[] getAccountsByTypeForPackage(String type, String packageName) {
@@ -609,7 +614,8 @@
*
* <p>
* <b>NOTE:</b> If targeting your app to work on API level
- * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, GET_ACCOUNTS permission is
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
+ * {@link android.Manifest.permission#GET_ACCOUNTS} permission is
* needed for those platforms, irrespective of uid or signature match. See docs for this
* function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
*
@@ -750,7 +756,8 @@
* accounts managed by AbstractAccountAuthenticators whose signature matches the client.
* <p>
* <b>NOTE:</b> If targeting your app to work on API level
- * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, GET_ACCOUNTS permission is
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
+ * {@link android.Manifest.permission#GET_ACCOUNTS} permission is
* needed for those platforms, irrespective of uid or signature match. See docs for this
* function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
*
@@ -822,9 +829,8 @@
}
/**
- * Adds an account directly to the AccountManager. Additionally this makes the Account visible
- * to desired UIDs of applications on the device, and sends directed broadcasts to these
- * individual applications.
+ * Adds an account directly to the AccountManager. Additionally it specifies Account visiblity
+ * for given list of packages.
* <p>
* Normally used by sign-up wizards associated with authenticators, not directly by
* applications.
@@ -841,14 +847,14 @@
* @param account The {@link Account} to add
* @param password The password to associate with the account, null for none
* @param extras String values to use for the account's userdata, null for none
- * @param visibility Map from uid to visibility values which will be set before account is
- * added. See getAccountVisibility for possilbe values.
+ * @param visibility Map from packageName to visibility values which will be set before account
+ * is added. See {@link #getAccountVisibility} for possible values.
*
* @return True if the account was successfully added, false if the account already exists, the
* account is null, or another error occurs.
*/
public boolean addAccountExplicitly(Account account, String password, Bundle extras,
- Map<Integer, Integer> visibility) {
+ Map<String, Integer> visibility) {
if (account == null)
throw new IllegalArgumentException("account is null");
try {
@@ -860,20 +866,22 @@
}
/**
- * Returns UIDs of applications for which visibility of given account was explicitly set.
+ * Returns package names and visibility which were explicitly set for given account.
* <p>
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
* @param account The account for which visibility data should be returned.
*
- * @return Map from uid to visibility for given account.
+ * @return Map from package names to visibility for given account.
*/
- public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
+ public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
try {
+ if (account == null)
+ throw new IllegalArgumentException("account is null");
@SuppressWarnings("unchecked")
- Map<Integer, Integer> result = (Map<Integer, Integer>) mService
- .getUidsAndVisibilityForAccount(account);
+ Map<String, Integer> result = (Map<String, Integer>) mService
+ .getPackagesAndVisibilityForAccount(account);
return result;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
@@ -907,30 +915,34 @@
}
/**
- * Set visibility value of given account to certain UID.
+ * Set visibility value of given account to certain packageName.
+ * Package name must match installed application, or be equal to
+ * {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE} or {@link #PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE}.
* <p>
* See {@link #getAccountVisibility} for possible values.
* <p>
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
- * @param account Account to make visible.
- * @param uid The UID of the application to modify account visibility.
+ * @param account Account to update visibility
+ * @param packageName Package name of the application to modify account visibility.
* @param visibility - new visibility value.
*
* @return True if visibility value was succesfully updated.
*/
- public boolean setAccountVisibility(Account account, int uid,
+ public boolean setAccountVisibility(Account account, String packageName,
@AccountVisibility int visibility) {
+ if (account == null)
+ throw new IllegalArgumentException("account is null");
try {
- return mService.setAccountVisibility(account, uid, visibility);
+ return mService.setAccountVisibility(account, packageName, visibility);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
- * Gets visibility of certain account for given UID. Possible returned values are:
+ * Get visibility of certain account for given application. Possible returned values are:
* <ul>
* <li>{@link #VISIBILITY_UNDEFINED}</li>
* <li>{@link #VISIBILITY_VISIBLE}</li>
@@ -944,13 +956,15 @@
* the specified account.
*
* @param account Account to get visibility.
- * @param uid The UID of the application to get account visibility.
+ * @param packageName Package name of the application to get account visibility
*
- * @return int Visibility for given account and uid.
+ * @return int Visibility for given account and package.
*/
- public @AccountVisibility int getAccountVisibility(Account account, int uid) {
+ public @AccountVisibility int getAccountVisibility(Account account, String packageName) {
+ if (account == null)
+ throw new IllegalArgumentException("account is null");
try {
- return mService.getAccountVisibility(account, uid);
+ return mService.getAccountVisibility(account, packageName);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 95fdfef..35011b5 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -437,7 +437,7 @@
}
if (oldVisibility != null
&& oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) {
- AccountManager.get(this).setAccountVisibility(account, mCallingUid,
+ AccountManager.get(this).setAccountVisibility(account, mCallingPackage,
AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
}
Bundle bundle = new Bundle();
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 63a0919..e0fdac1 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -108,15 +108,12 @@
void isCredentialsUpdateSuggested(in IAccountManagerResponse response, in Account account,
String statusToken);
- /* Returns Map<Integer, Integer> from UID to visibility with all values stored for given account*/
- Map getUidsAndVisibilityForAccount(in Account account);
-
+ /* Returns Map<String, Integer> from package name to visibility with all values stored for given account */
+ Map getPackagesAndVisibilityForAccount(in Account account);
boolean addAccountExplicitlyWithVisibility(in Account account, String password, in Bundle extras,
in Map visibility);
-
- boolean setAccountVisibility(in Account a, int uid, int newVisibility);
- int getAccountVisibility(in Account a, int uid);
-
+ boolean setAccountVisibility(in Account a, in String packageName, int newVisibility);
+ int getAccountVisibility(in Account a, in String packageName);
/* Type may be null returns Map <Account, Integer>*/
Map getAccountsAndVisibilityForPackage(in String packageName, in String accountType);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 55ac1f4..558fdc6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -637,13 +637,16 @@
public void setCurrentFraction(float fraction) {
initAnimation();
fraction = clampFraction(fraction);
- long seekTime = (long) (getScaledDuration() * fraction);
- long currentTime = AnimationUtils.currentAnimationTimeMillis();
- mStartTime = currentTime - seekTime;
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
- if (!isPulsingInternal()) {
- // If the animation loop hasn't started, the startTime will be adjusted in the first
- // frame based on seek fraction.
+ if (isPulsingInternal()) {
+ long seekTime = (long) (getScaledDuration() * fraction);
+ long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ // Only modify the start time when the animation is running. Seek fraction will ensure
+ // non-running animations skip to the correct start time.
+ mStartTime = currentTime - seekTime;
+ } else {
+ // If the animation loop hasn't started, or during start delay, the startTime will be
+ // adjusted once the delay has passed based on seek fraction.
mSeekFraction = fraction;
}
mOverallFraction = fraction;
@@ -1028,7 +1031,7 @@
// started-but-not-yet-reached-the-first-frame phase.
mLastFrameTime = -1;
mFirstFrameTime = -1;
- addAnimationCallback((long) (mStartDelay * sDurationScale));
+ addAnimationCallback(0);
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
// If there's no start delay, init the animation and notify start listeners right away
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3cc6282..99ae96d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -145,6 +145,7 @@
int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
in IUiAutomationConnection connection, int userId,
in String abiOverride);
+ void addInstrumentationResults(in IApplicationThread target, in Bundle results);
void finishInstrumentation(in IApplicationThread target, int resultCode,
in Bundle results);
/**
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index b1bdea1..4db29fb 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -186,11 +186,25 @@
}
}
}
-
+
+ /**
+ * Report some results in the middle of instrumentation execution. Later results (including
+ * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
+ */
+ public void addResults(Bundle results) {
+ IActivityManager am = ActivityManager.getService();
+ try {
+ am.addInstrumentationResults(mThread.getApplicationThread(), results);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
/**
* Terminate instrumentation of the application. This will cause the
* application process to exit, removing this instrumentation from the next
- * time the application is started.
+ * time the application is started. If multiple processes are currently running
+ * for this instrumentation, all of those processes will be killed.
*
* @param resultCode Overall success/failure of instrumentation.
* @param results Any results to send back to the code that started the
@@ -278,6 +292,18 @@
}
/**
+ * Return the name of the process this instrumentation is running in. Note this should
+ * only be used for testing and debugging. If you are thinking about using this to,
+ * for example, conditionalize what is initialized in an Application class, it is strongly
+ * recommended to instead use lazy initialization (such as a getter for the state that
+ * only creates it when requested). This can greatly reduce the work your process does
+ * when created for secondary things, such as to receive a broadcast.
+ */
+ public String getProcessName() {
+ return mThread.getProcessName();
+ }
+
+ /**
* Check whether this instrumentation was started with profiling enabled.
*
* @return Returns true if profiling was enabled when starting, else false.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b7eda25..2c1cdd6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -48,6 +48,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -3903,10 +3904,24 @@
* 3. Standard template view
*/
public RemoteViews createContentView() {
+ return createContentView(false /* increasedheight */ );
+ }
+
+ /**
+ * Construct a RemoteViews for the smaller content view.
+ *
+ * @param increasedHeight true if this layout be created with an increased height. Some
+ * styles may support showing more then just that basic 1U size
+ * and the system may decide to render important notifications
+ * slightly bigger even when collapsed.
+ *
+ * @hide
+ */
+ public RemoteViews createContentView(boolean increasedHeight) {
if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.contentView;
} else if (mStyle != null) {
- final RemoteViews styleView = mStyle.makeContentView();
+ final RemoteViews styleView = mStyle.makeContentView(increasedHeight);
if (styleView != null) {
return styleView;
}
@@ -4536,6 +4551,19 @@
}
/**
+ * @return the style class of this notification
+ * @hide
+ */
+ public Class<? extends Notification.Style> getNotificationStyle() {
+ String templateClass = extras.getString(Notification.EXTRA_TEMPLATE);
+
+ if (!TextUtils.isEmpty(templateClass)) {
+ return Notification.getNotificationStyleClass(templateClass);
+ }
+ return null;
+ }
+
+ /**
* @return true if this notification is colorized. This also factors in wheather the
* notification is ongoing.
*
@@ -4656,11 +4684,13 @@
}
/**
- * Construct a Style-specific RemoteViews for the final 1U notification layout.
+ * Construct a Style-specific RemoteViews for the collapsed notification layout.
* The default implementation has nothing additional to add.
+ *
+ * @param increasedHeight true if this layout be created with an increased height.
* @hide
*/
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return null;
}
@@ -5006,6 +5036,23 @@
}
/**
+ * @param increasedHeight true if this layout be created with an increased height.
+ *
+ * @hide
+ */
+ @Override
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ if (increasedHeight) {
+ ArrayList<Action> actions = mBuilder.mActions;
+ mBuilder.mActions = new ArrayList<>();
+ RemoteViews remoteViews = makeBigContentView();
+ mBuilder.mActions = actions;
+ return remoteViews;
+ }
+ return super.makeContentView(increasedHeight);
+ }
+
+ /**
* @hide
*/
public RemoteViews makeBigContentView() {
@@ -5269,17 +5316,25 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
- Message m = findLatestIncomingMessage();
- CharSequence title = mConversationTitle != null
- ? mConversationTitle
- : (m == null) ? null : m.mSender;
- CharSequence text = (m == null)
- ? null
- : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ if (!increasedHeight) {
+ Message m = findLatestIncomingMessage();
+ CharSequence title = mConversationTitle != null
+ ? mConversationTitle
+ : (m == null) ? null : m.mSender;
+ CharSequence text = (m == null)
+ ? null
+ : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
- return mBuilder.applyStandardTemplateWithActions(mBuilder.getBaseLayoutResource(),
- mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
+ return mBuilder.applyStandardTemplate(mBuilder.getBaseLayoutResource(),
+ mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
+ } else {
+ ArrayList<Action> actions = mBuilder.mActions;
+ mBuilder.mActions = new ArrayList<>();
+ RemoteViews remoteViews = makeBigContentView();
+ mBuilder.mActions = actions;
+ return remoteViews;
+ }
}
private Message findLatestIncomingMessage() {
@@ -5844,7 +5899,7 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return makeMediaContentView();
}
@@ -6020,7 +6075,7 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
+ public RemoteViews makeContentView(boolean increasedHeight) {
return makeStandardTemplateWithCustomContent(mBuilder.mN.contentView);
}
@@ -6134,8 +6189,8 @@
* @hide
*/
@Override
- public RemoteViews makeContentView() {
- RemoteViews remoteViews = super.makeContentView();
+ public RemoteViews makeContentView(boolean increasedHeight) {
+ RemoteViews remoteViews = super.makeContentView(false /* increasedHeight */);
return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
mBuilder.mN.contentView);
}
@@ -6157,7 +6212,7 @@
return buildIntoRemoteView(remoteViews, R.id.notification_main_column,
customRemoteView);
} else if (customRemoteView != mBuilder.mN.contentView){
- remoteViews = super.makeContentView();
+ remoteViews = super.makeContentView(false /* increasedHeight */);
return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
customRemoteView);
} else {
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 92cb709..9a8eff0 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -397,14 +397,6 @@
public static final int FLAG_ALWAYS_FOCUSABLE = 0x40000;
/**
- * Bit in {@link #flags} indicating if the activity is a launcher activity which should always
- * show up on the top of others.
- * See android.R.attr#onTopLauncher.
- * @hide
- */
- public static final int FLAG_ON_TOP_LAUNCHER = 0x80000;
-
- /**
* Bit in {@link #flags} indicating if the activity is visible to ephemeral applications.
* @hide
*/
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index a135d8f..59c5307 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -34,6 +34,13 @@
public String targetPackage;
/**
+ * Names of the process(es) this instrumentation will run in. If not specified, only
+ * runs in the main process of the targetPackage. Can either be a comma-separated list
+ * of process names or '*' for any process that launches to run targetPackage code.
+ */
+ public String targetProcess;
+
+ /**
* Full path to the base APK for this application.
*/
public String sourceDir;
@@ -113,6 +120,7 @@
public InstrumentationInfo(InstrumentationInfo orig) {
super(orig);
targetPackage = orig.targetPackage;
+ targetProcess = orig.targetProcess;
sourceDir = orig.sourceDir;
publicSourceDir = orig.publicSourceDir;
splitNames = orig.splitNames;
@@ -141,6 +149,7 @@
public void writeToParcel(Parcel dest, int parcelableFlags) {
super.writeToParcel(dest, parcelableFlags);
dest.writeString(targetPackage);
+ dest.writeString(targetProcess);
dest.writeString(sourceDir);
dest.writeString(publicSourceDir);
dest.writeStringArray(splitNames);
@@ -170,6 +179,7 @@
private InstrumentationInfo(Parcel source) {
super(source);
targetPackage = source.readString();
+ targetProcess = source.readString();
sourceDir = source.readString();
publicSourceDir = source.readString();
splitNames = source.readStringArray();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ff928a0..7cef781 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -17,7 +17,6 @@
package android.content.pm;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
@@ -1623,6 +1622,7 @@
return parseApkLite(apkPath, parser, attrs, flags, signatures, certificates);
} catch (XmlPullParserException | IOException | RuntimeException e) {
+ Slog.w(TAG, "Failed to parse " + apkPath, e);
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to parse " + apkPath, e);
} finally {
@@ -3160,6 +3160,10 @@
com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
a.info.targetPackage = str != null ? str.intern() : null;
+ str = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcess);
+ a.info.targetProcess = str != null ? str.intern() : null;
+
a.info.handleProfiling = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
false);
@@ -4105,10 +4109,6 @@
a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
}
- if (sa.getBoolean(R.styleable.AndroidManifestActivity_onTopLauncher, false)) {
- a.info.flags |= FLAG_ON_TOP_LAUNCHER;
- }
-
a.info.lockTaskLaunchMode =
sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
diff --git a/core/java/android/content/res/FontResourcesParser.java b/core/java/android/content/res/FontResourcesParser.java
index 15f3a09..7ea62db 100644
--- a/core/java/android/content/res/FontResourcesParser.java
+++ b/core/java/android/content/res/FontResourcesParser.java
@@ -33,7 +33,7 @@
*/
public class FontResourcesParser {
private static final int NORMAL_WEIGHT = 400;
- private static final String ITALIC = "italic";
+ private static final int ITALIC = 1;
public static FontConfig parse(XmlPullParser parser, Resources resources)
throws XmlPullParserException, IOException {
@@ -82,9 +82,12 @@
AttributeSet attrs = Xml.asAttributeSet(parser);
TypedArray array = resources.obtainAttributes(attrs, R.styleable.FontFamilyFont);
int weight = array.getInt(R.styleable.FontFamilyFont_fontWeight, NORMAL_WEIGHT);
- boolean isItalic = ITALIC.equals(array.getString(R.styleable.FontFamilyFont_fontStyle));
+ boolean isItalic = ITALIC == array.getInt(R.styleable.FontFamilyFont_fontStyle, 0);
String filename = array.getString(R.styleable.FontFamilyFont_font);
array.recycle();
+ while (parser.next() != XmlPullParser.END_TAG) {
+ skip(parser);
+ }
return new FontConfig.Font(filename, 0, null, weight, isItalic);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 222953e..dc5750d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -46,6 +46,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
@@ -1240,36 +1241,27 @@
private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
if (networkType == TYPE_MOBILE) {
- int cap = -1;
- if ("enableMMS".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_MMS;
- } else if ("enableSUPL".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_SUPL;
- } else if ("enableDUN".equals(feature) || "enableDUNAlways".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_DUN;
- } else if ("enableHIPRI".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_INTERNET;
- } else if ("enableFOTA".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_FOTA;
- } else if ("enableIMS".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_IMS;
- } else if ("enableCBS".equals(feature)) {
- cap = NetworkCapabilities.NET_CAPABILITY_CBS;
- } else {
- return null;
+ switch (feature) {
+ case "enableCBS":
+ return networkCapabilitiesForType(TYPE_MOBILE_CBS);
+ case "enableDUN":
+ case "enableDUNAlways":
+ return networkCapabilitiesForType(TYPE_MOBILE_DUN);
+ case "enableFOTA":
+ return networkCapabilitiesForType(TYPE_MOBILE_FOTA);
+ case "enableHIPRI":
+ return networkCapabilitiesForType(TYPE_MOBILE_HIPRI);
+ case "enableIMS":
+ return networkCapabilitiesForType(TYPE_MOBILE_IMS);
+ case "enableMMS":
+ return networkCapabilitiesForType(TYPE_MOBILE_MMS);
+ case "enableSUPL":
+ return networkCapabilitiesForType(TYPE_MOBILE_SUPL);
+ default:
+ return null;
}
- NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addCapability(cap);
- netCap.maybeMarkCapabilitiesRestricted();
- return netCap;
- } else if (networkType == TYPE_WIFI) {
- if ("p2p".equals(feature)) {
- NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
- netCap.maybeMarkCapabilitiesRestricted();
- return netCap;
- }
+ } else if (networkType == TYPE_WIFI && "p2p".equals(feature)) {
+ return networkCapabilitiesForType(TYPE_WIFI_P2P);
}
return null;
}
@@ -1477,6 +1469,59 @@
return true;
}
+ private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray();
+ static {
+ sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_CBS, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_FOTA, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_IMS, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_MMS, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_SUPL, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI);
+ sLegacyTypeToTransport.put(TYPE_WIFI_P2P, NetworkCapabilities.TRANSPORT_WIFI);
+ sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH);
+ sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET);
+ }
+
+ private static final SparseIntArray sLegacyTypeToCapability = new SparseIntArray();
+ static {
+ sLegacyTypeToCapability.put(TYPE_MOBILE_CBS, NetworkCapabilities.NET_CAPABILITY_CBS);
+ sLegacyTypeToCapability.put(TYPE_MOBILE_DUN, NetworkCapabilities.NET_CAPABILITY_DUN);
+ sLegacyTypeToCapability.put(TYPE_MOBILE_FOTA, NetworkCapabilities.NET_CAPABILITY_FOTA);
+ sLegacyTypeToCapability.put(TYPE_MOBILE_IMS, NetworkCapabilities.NET_CAPABILITY_IMS);
+ sLegacyTypeToCapability.put(TYPE_MOBILE_MMS, NetworkCapabilities.NET_CAPABILITY_MMS);
+ sLegacyTypeToCapability.put(TYPE_MOBILE_SUPL, NetworkCapabilities.NET_CAPABILITY_SUPL);
+ sLegacyTypeToCapability.put(TYPE_WIFI_P2P, NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
+ }
+
+ /**
+ * Given a legacy type (TYPE_WIFI, ...) returns a NetworkCapabilities
+ * instance suitable for registering a request or callback. Throws an
+ * IllegalArgumentException if no mapping from the legacy type to
+ * NetworkCapabilities is known.
+ *
+ * @hide
+ */
+ public static NetworkCapabilities networkCapabilitiesForType(int type) {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+
+ // Map from type to transports.
+ final int NOT_FOUND = -1;
+ final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND);
+ if (transport == NOT_FOUND) {
+ throw new IllegalArgumentException("unknown legacy type: " + type);
+ }
+ nc.addTransportType(transport);
+
+ // Map from type to capabilities.
+ nc.addCapability(sLegacyTypeToCapability.get(
+ type, NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ nc.maybeMarkCapabilitiesRestricted();
+ return nc;
+ }
+
/** @hide */
public static class PacketKeepaliveCallback {
/** The requested keepalive was successfully started. */
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index ae72470..cb78009 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -178,6 +178,20 @@
}
/**
+ * Set the {@code NetworkCapabilities} for this builder instance,
+ * overriding any capabilities that had been previously set.
+ *
+ * @param nc The superseding {@code NetworkCapabilities} instance.
+ * @return The builder to facilitate chaining.
+ * @hide
+ */
+ public Builder setCapabilities(NetworkCapabilities nc) {
+ mNetworkCapabilities.clearAll();
+ mNetworkCapabilities.combineCapabilities(nc);
+ return this;
+ }
+
+ /**
* Completely clears all the {@code NetworkCapabilities} from this builder instance,
* removing even the capabilities that are set by default when the object is constructed.
*
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 9e4dd87..9dcf4f4 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -18,6 +18,7 @@
import android.Manifest.permission;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -33,6 +34,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Internal class for discovering and managing the network scorer/recommendation application.
@@ -53,33 +55,43 @@
* Holds metadata about a discovered network scorer/recommendation application.
*/
public static class NetworkScorerAppData {
- /** Package name of this scorer app. */
- public final String packageName;
-
/** UID of the scorer app. */
public final int packageUid;
+ private final ComponentName mRecommendationService;
- /**
- * Name of the recommendation service we can bind to.
- */
- public final String recommendationServiceClassName;
-
- public NetworkScorerAppData(String packageName, int packageUid,
- String recommendationServiceClassName) {
- this.packageName = packageName;
+ public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp) {
this.packageUid = packageUid;
- this.recommendationServiceClassName = recommendationServiceClassName;
+ this.mRecommendationService = recommendationServiceComp;
+ }
+
+ public String getRecommendationServicePackageName() {
+ return mRecommendationService.getPackageName();
+ }
+
+ public ComponentName getRecommendationServiceComponent() {
+ return mRecommendationService;
}
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder("NetworkScorerAppData{");
- sb.append("mPackageName='").append(packageName).append('\'');
- sb.append(", packageUid=").append(packageUid);
- sb.append(", recommendationServiceClassName='")
- .append(recommendationServiceClassName).append('\'');
- sb.append('}');
- return sb.toString();
+ return "NetworkScorerAppData{" +
+ "packageUid=" + packageUid +
+ ", mRecommendationService=" + mRecommendationService +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkScorerAppData that = (NetworkScorerAppData) o;
+ return packageUid == that.packageUid &&
+ Objects.equals(mRecommendationService, that.mRecommendationService);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageUid, mRecommendationService);
}
}
@@ -110,16 +122,16 @@
return null;
}
- final PackageManager pm = mContext.getPackageManager();
for (int i = 0; i < potentialPkgs.size(); i++) {
final String potentialPkg = potentialPkgs.get(i);
// Look for the recommendation service class and required receiver.
final ResolveInfo resolveServiceInfo = findRecommendationService(potentialPkg);
if (resolveServiceInfo != null) {
- return new NetworkScorerAppData(potentialPkg,
- resolveServiceInfo.serviceInfo.applicationInfo.uid,
- resolveServiceInfo.serviceInfo.name);
+ final ComponentName componentName =
+ new ComponentName(potentialPkg, resolveServiceInfo.serviceInfo.name);
+ return new NetworkScorerAppData(resolveServiceInfo.serviceInfo.applicationInfo.uid,
+ componentName);
} else {
if (DEBUG) {
Log.d(TAG, potentialPkg + " does not have the required components, skipping.");
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl b/core/java/android/os/Seccomp.java
similarity index 69%
copy from wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
copy to core/java/android/os/Seccomp.java
index 62d5603..f14e93f 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
+++ b/core/java/android/os/Seccomp.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
+/*
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,6 +14,11 @@
* limitations under the License.
*/
-package android.net.wifi.hotspot2.pps;
+package android.os;
-parcelable HomeSP;
+/**
+ * @hide
+ */
+public final class Seccomp {
+ public static final native void setPolicy();
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 388054d..dfcab3d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -516,6 +516,7 @@
* <li>{@link LayoutParams#TYPE_SYSTEM_ALERT}</li>
* <li>{@link LayoutParams#TYPE_SYSTEM_ERROR}</li>
* <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
+ * <li>{@link LayoutParams#TYPE_APPLICATION_OVERLAY}</li>
*
* <p>This can only be set by device owners and profile owners on the primary user.
* The default value is <code>false</code>.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index bf840e5..5a640fa 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -335,7 +335,9 @@
@ViewDebug.IntToString(from = TYPE_QS_DIALOG,
to = "TYPE_QS_DIALOG"),
@ViewDebug.IntToString(from = TYPE_SCREENSHOT,
- to = "TYPE_SCREENSHOT")
+ to = "TYPE_SCREENSHOT"),
+ @ViewDebug.IntToString(from = TYPE_APPLICATION_OVERLAY,
+ to = "TYPE_APPLICATION_OVERLAY")
})
public int type;
@@ -462,14 +464,18 @@
* These windows are normally placed above all applications, but behind
* the status bar.
* In multiuser systems shows on all users' windows.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
/**
* Window type: system window, such as low power alert. These windows
* are always on top of application windows.
* In multiuser systems shows only on the owning user's window.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
/**
@@ -482,7 +488,9 @@
/**
* Window type: transient notifications.
* In multiuser systems shows only on the owning user's window.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;
/**
@@ -490,7 +498,9 @@
* on top of everything else. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows only on the owning user's window.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;
/**
@@ -498,7 +508,9 @@
* the keyguard is active. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows on all users' windows.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;
/**
@@ -517,7 +529,9 @@
* Window type: internal system error windows, appear on top of
* everything they can.
* In multiuser systems shows only on the owning user's window.
+ * @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
+ @Deprecated
public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10;
/**
@@ -703,10 +717,44 @@
public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37;
/**
+ * Window type: Application overlay windows are displayed above all activity windows
+ * (types between {@link #FIRST_APPLICATION_WINDOW} and {@link #LAST_APPLICATION_WINDOW})
+ * but below critical system windows like the status bar or IME.
+ * <p>
+ * The system may change the position, size, or visibility of these windows at anytime
+ * to reduce visual clutter to the user and also manage resources.
+ * <p>
+ * Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission.
+ * <p>
+ * In mult-iuser systems shows only on the owning user's screen.
+ */
+ public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
+ /**
+ * Return true if the window type is an alert window.
+ *
+ * @param type The window type.
+ * @return If the window type is an alert window.
+ * @hide
+ */
+ public static boolean isSystemAlertWindowType(int type) {
+ switch (type) {
+ case TYPE_PHONE:
+ case TYPE_PRIORITY_PHONE:
+ case TYPE_SYSTEM_ALERT:
+ case TYPE_SYSTEM_ERROR:
+ case TYPE_SYSTEM_OVERLAY:
+ case TYPE_APPLICATION_OVERLAY:
+ return true;
+ }
+ return false;
+ }
+
/** @deprecated this is ignored, this value is set automatically when needed. */
@Deprecated
public static final int MEMORY_TYPE_NORMAL = 0;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bc4ae6d..8e597dc 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -16,6 +16,51 @@
package android.view;
+import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
+import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
+import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -30,6 +75,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.util.Slog;
import android.view.animation.Animation;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -423,6 +469,14 @@
public boolean isInputMethodWindow();
public int getDisplayId();
+
+ /**
+ * Returns true if the window owner can add internal system windows.
+ * That is, they have {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}.
+ */
+ default boolean canAddInternalSystemWindow() {
+ return false;
+ }
}
/**
@@ -659,27 +713,181 @@
int navigationPresence);
/**
- * Assign a window type to a layer. Allows you to control how different
+ * Returns the layer assignment for the window state. Allows you to control how different
+ * kinds of windows are ordered on-screen.
+ *
+ * @param win The window state
+ * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
+ */
+ default int getWindowLayerLw(WindowState win) {
+ return getWindowLayerFromTypeLw(win.getBaseType(), win.canAddInternalSystemWindow());
+ }
+
+ /**
+ * Returns the layer assignment for the window type. Allows you to control how different
* kinds of windows are ordered on-screen.
*
* @param type The type of window being assigned.
- *
- * @return int An arbitrary integer used to order windows, with lower
- * numbers below higher ones.
+ * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
*/
- public int windowTypeToLayerLw(int type);
+ default int getWindowLayerFromTypeLw(int type) {
+ if (isSystemAlertWindowType(type)) {
+ throw new IllegalArgumentException("Use getWindowLayerFromTypeLw() or"
+ + " getWindowLayerLw() for alert window types");
+ }
+ return getWindowLayerFromTypeLw(type, false /* canAddInternalSystemWindow */);
+ }
/**
- * Return how to Z-order sub-windows in relation to the window they are
- * attached to. Return positive to have them ordered in front, negative for
- * behind.
+ * Returns the layer assignment for the window type. Allows you to control how different
+ * kinds of windows are ordered on-screen.
+ *
+ * @param type The type of window being assigned.
+ * @param canAddInternalSystemWindow If the owner window associated with the type we are
+ * evaluating can add internal system windows. I.e they have
+ * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window
+ * types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}
+ * can be assigned layers greater than the layer for
+ * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their
+ * layers would be lesser.
+ * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
+ */
+ default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
+ if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
+ return APPLICATION_LAYER;
+ }
+
+ switch (type) {
+ case TYPE_WALLPAPER:
+ // wallpaper is at the bottom, though the window manager may move it.
+ return 1;
+ case TYPE_PRESENTATION:
+ case TYPE_PRIVATE_PRESENTATION:
+ return APPLICATION_LAYER;
+ case TYPE_DOCK_DIVIDER:
+ return APPLICATION_LAYER;
+ case TYPE_QS_DIALOG:
+ return APPLICATION_LAYER;
+ case TYPE_PHONE:
+ return 3;
+ case TYPE_SEARCH_BAR:
+ case TYPE_VOICE_INTERACTION_STARTING:
+ return 4;
+ case TYPE_VOICE_INTERACTION:
+ // voice interaction layer is almost immediately above apps.
+ return 5;
+ case TYPE_INPUT_CONSUMER:
+ return 6;
+ case TYPE_SYSTEM_DIALOG:
+ return 7;
+ case TYPE_TOAST:
+ // toasts and the plugged-in battery thing
+ return 8;
+ case TYPE_PRIORITY_PHONE:
+ // SIM errors and unlock. Not sure if this really should be in a high layer.
+ return 9;
+ case TYPE_DREAM:
+ // used for Dreams (screensavers with TYPE_DREAM windows)
+ return 10;
+ case TYPE_SYSTEM_ALERT:
+ // like the ANR / app crashed dialogs
+ return canAddInternalSystemWindow ? 11 : 10;
+ case TYPE_APPLICATION_OVERLAY:
+ return 13;
+ case TYPE_INPUT_METHOD:
+ // on-screen keyboards and other such input method user interfaces go here.
+ return 14;
+ case TYPE_INPUT_METHOD_DIALOG:
+ // on-screen keyboards and other such input method user interfaces go here.
+ return 15;
+ case TYPE_STATUS_BAR_SUB_PANEL:
+ return 17;
+ case TYPE_STATUS_BAR:
+ return 18;
+ case TYPE_STATUS_BAR_PANEL:
+ return 19;
+ case TYPE_KEYGUARD_DIALOG:
+ return 20;
+ case TYPE_VOLUME_OVERLAY:
+ // the on-screen volume indicator and controller shown when the user
+ // changes the device volume
+ return 21;
+ case TYPE_SYSTEM_OVERLAY:
+ // the on-screen volume indicator and controller shown when the user
+ // changes the device volume
+ return canAddInternalSystemWindow ? 22 : 11;
+ case TYPE_NAVIGATION_BAR:
+ // the navigation bar, if available, shows atop most things
+ return 23;
+ case TYPE_NAVIGATION_BAR_PANEL:
+ // some panels (e.g. search) need to show on top of the navigation bar
+ return 24;
+ case TYPE_SCREENSHOT:
+ // screenshot selection layer shouldn't go above system error, but it should cover
+ // navigation bars at the very least.
+ return 25;
+ case TYPE_SYSTEM_ERROR:
+ // system-level error dialogs
+ return canAddInternalSystemWindow ? 26 : 10;
+ case TYPE_MAGNIFICATION_OVERLAY:
+ // used to highlight the magnified portion of a display
+ return 27;
+ case TYPE_DISPLAY_OVERLAY:
+ // used to simulate secondary display devices
+ return 28;
+ case TYPE_DRAG:
+ // the drag layer: input for drag-and-drop is associated with this window,
+ // which sits above all other focusable windows
+ return 29;
+ case TYPE_ACCESSIBILITY_OVERLAY:
+ // overlay put by accessibility services to intercept user interaction
+ return 30;
+ case TYPE_SECURE_SYSTEM_OVERLAY:
+ return 31;
+ case TYPE_BOOT_PROGRESS:
+ return 32;
+ case TYPE_POINTER:
+ // the (mouse) pointer layer
+ return 33;
+ default:
+ Slog.e("WindowManager", "Unknown window type: " + type);
+ return APPLICATION_LAYER;
+ }
+ }
+
+ int APPLICATION_LAYER = 2;
+ int APPLICATION_MEDIA_SUBLAYER = -2;
+ int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
+ int APPLICATION_PANEL_SUBLAYER = 1;
+ int APPLICATION_SUB_PANEL_SUBLAYER = 2;
+ int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
+
+ /**
+ * Return how to Z-order sub-windows in relation to the window they are attached to.
+ * Return positive to have them ordered in front, negative for behind.
*
* @param type The sub-window type code.
*
* @return int Layer in relation to the attached window, where positive is
* above and negative is below.
*/
- public int subWindowTypeToLayerLw(int type);
+ default int getSubWindowLayerFromTypeLw(int type) {
+ switch (type) {
+ case TYPE_APPLICATION_PANEL:
+ case TYPE_APPLICATION_ATTACHED_DIALOG:
+ return APPLICATION_PANEL_SUBLAYER;
+ case TYPE_APPLICATION_MEDIA:
+ return APPLICATION_MEDIA_SUBLAYER;
+ case TYPE_APPLICATION_MEDIA_OVERLAY:
+ return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
+ case TYPE_APPLICATION_SUB_PANEL:
+ return APPLICATION_SUB_PANEL_SUBLAYER;
+ case TYPE_APPLICATION_ABOVE_SUB_PANEL:
+ return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
+ }
+ Slog.e("WindowManager", "Unknown sub-window type: " + type);
+ return 0;
+ }
/**
* Get the highest layer (actually one more than) that the wallpaper is
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index b6da1d8..71809bd 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -42,7 +43,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* This class is used to specify meta information of an input method.
@@ -110,6 +110,19 @@
private final boolean mSupportsDismissingWindow;
/**
+ * @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
+ * @return a unique ID to be returned by {@link #getId()}. We have used
+ * {@link ComponentName#flattenToShortString()} for this purpose (and it is already
+ * unrealistic to switch to a different scheme as it is already implicitly assumed in
+ * many places).
+ * @hide
+ */
+ public static String computeId(@NonNull ResolveInfo service) {
+ final ServiceInfo si = service.serviceInfo;
+ return new ComponentName(si.packageName, si.name).flattenToShortString();
+ }
+
+ /**
* Constructor.
*
* @param context The Context in which we are parsing the input method.
@@ -127,15 +140,15 @@
* @param context The Context in which we are parsing the input method.
* @param service The ResolveInfo returned from the package manager about
* this input method's component.
- * @param additionalSubtypesMap additional subtypes being added to this InputMethodInfo
+ * @param additionalSubtypes additional subtypes being added to this InputMethodInfo
* @hide
*/
public InputMethodInfo(Context context, ResolveInfo service,
- Map<String, List<InputMethodSubtype>> additionalSubtypesMap)
+ List<InputMethodSubtype> additionalSubtypes)
throws XmlPullParserException, IOException {
mService = service;
ServiceInfo si = service.serviceInfo;
- mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+ mId = computeId(service);
boolean isAuxIme = true;
boolean supportsSwitchingToNextInputMethod = false; // false as default
boolean supportsDismissingWindow = false; // false as default
@@ -233,8 +246,7 @@
isAuxIme = false;
}
- if (additionalSubtypesMap != null && additionalSubtypesMap.containsKey(mId)) {
- final List<InputMethodSubtype> additionalSubtypes = additionalSubtypesMap.get(mId);
+ if (additionalSubtypes != null) {
final int N = additionalSubtypes.size();
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = additionalSubtypes.get(i);
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 0657067..7838918 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -157,18 +158,29 @@
.setEntityType(type, 1.0f /* confidence */)
.setIntent(intent)
.setOnClickListener(TextClassificationResult.createStartActivityOnClick(
- mContext, intent))
- .setLabel(IntentFactory.getLabel(mContext, type));
+ mContext, intent));
final PackageManager pm = mContext.getPackageManager();
final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
- // TODO: If the resolveInfo is the "chooser", do not set the package name and use a default
- // icon for this classification type.
- intent.setPackage(resolveInfo.activityInfo.packageName);
- Drawable icon = resolveInfo.activityInfo.loadIcon(pm);
- if (icon == null) {
- icon = resolveInfo.loadIcon(pm);
+ if (resolveInfo != null && resolveInfo.activityInfo != null) {
+ final String packageName = resolveInfo.activityInfo.packageName;
+ if ("android".equals(packageName)) {
+ // Requires the chooser to find an activity to handle the intent.
+ builder.setLabel(IntentFactory.getLabel(mContext, type));
+ } else {
+ // A default activity will handle the intent.
+ intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
+ Drawable icon = resolveInfo.activityInfo.loadIcon(pm);
+ if (icon == null) {
+ icon = resolveInfo.loadIcon(pm);
+ }
+ builder.setIcon(icon);
+ CharSequence label = resolveInfo.activityInfo.loadLabel(pm);
+ if (label == null) {
+ label = resolveInfo.loadLabel(pm);
+ }
+ builder.setLabel(label != null ? label.toString() : null);
+ }
}
- builder.setIcon(icon);
return builder.build();
}
@@ -211,9 +223,12 @@
final String type =
smartSelection.classifyText(text, selectionStart, selectionEnd);
if (matches(type, linkMask)) {
- final ClickableSpan span = createSpan(
- context, type, text.substring(selectionStart, selectionEnd));
- spans.add(new SpanSpec(selectionStart, selectionEnd, span));
+ final Intent intent = IntentFactory.create(
+ type, text.substring(selectionStart, selectionEnd));
+ if (hasActivityHandler(context, intent)) {
+ final ClickableSpan span = createSpan(context, intent);
+ spans.add(new SpanSpec(selectionStart, selectionEnd, span));
+ }
}
}
start = end;
@@ -279,17 +294,24 @@
return result;
}
- private static ClickableSpan createSpan(
- final Context context, final String type, final String text) {
+ private static ClickableSpan createSpan(final Context context, final Intent intent) {
return new ClickableSpan() {
// TODO: Style this span.
@Override
public void onClick(View widget) {
- context.startActivity(IntentFactory.create(type, text));
+ context.startActivity(intent);
}
};
}
+ private static boolean hasActivityHandler(Context context, @Nullable Intent intent) {
+ if (intent == null) {
+ return false;
+ }
+ final ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 0);
+ return resolveInfo != null && resolveInfo.activityInfo != null;
+ }
+
/**
* Implementation of LinksInfo that adds ClickableSpans to the specified text.
*/
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c1834f1..a2cb491 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3917,12 +3917,18 @@
private void updateAssistMenuItem(
Menu menu, TextClassificationResult textClassificationResult) {
menu.removeItem(TextView.ID_ASSIST);
- if (textClassificationResult != null
- && textClassificationResult.getIcon() != null
- && textClassificationResult.getOnClickListener() != null) {
- menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, null)
- .setIcon(textClassificationResult.getIcon())
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ if (textClassificationResult != null) {
+ final Drawable icon = textClassificationResult.getIcon();
+ final CharSequence label = textClassificationResult.getLabel();
+ final OnClickListener onClickListener =
+ textClassificationResult.getOnClickListener();
+ final Intent intent = textClassificationResult.getIntent();
+ if ((icon != null || !TextUtils.isEmpty(label))
+ && (onClickListener != null || intent != null)) {
+ menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
+ .setIcon(icon)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
}
}
@@ -3935,9 +3941,22 @@
if (customCallback != null && customCallback.onActionItemClicked(mode, item)) {
return true;
}
- if (TextView.ID_ASSIST == item.getItemId() && mTextClassificationResult != null) {
- mTextClassificationResult.getOnClickListener().onClick(mTextView);
+ final TextClassificationResult textClassificationResult = mTextClassificationResult;
+ if (TextView.ID_ASSIST == item.getItemId() && textClassificationResult != null) {
+ final OnClickListener onClickListener =
+ textClassificationResult.getOnClickListener();
+ if (onClickListener != null) {
+ onClickListener.onClick(mTextView);
+ } else {
+ final Intent intent = textClassificationResult.getIntent();
+ if (intent != null) {
+ TextClassificationResult.createStartActivityOnClick(
+ mTextView.getContext(), intent)
+ .onClick(mTextView);
+ }
+ }
stopTextActionMode();
+ return true;
}
return mTextView.onTextContextMenuItem(item.getItemId());
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f3f34a8..63622f1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -377,6 +377,8 @@
int mScreenBrightnessBin = -1;
final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
+ boolean mPretendScreenOff;
+
boolean mInteractive;
StopwatchTimer mInteractiveTimer;
@@ -3395,6 +3397,11 @@
mNoAutoReset = enabled;
}
+ public void setPretendScreenOff(boolean pretendScreenOff) {
+ mPretendScreenOff = pretendScreenOff;
+ noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON);
+ }
+
private String mInitialAcquireWakeName;
private int mInitialAcquireWakeUid = -1;
@@ -3698,6 +3705,7 @@
}
public void noteScreenStateLocked(int state) {
+ state = mPretendScreenOff ? Display.STATE_OFF : state;
if (mScreenState != state) {
recordDailyStatsIfNeededLocked(true);
final int oldState = mScreenState;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index a3b066a..5049738 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -28,6 +28,7 @@
import android.os.IInstalld;
import android.os.Process;
import android.os.RemoteException;
+import android.os.Seccomp;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
@@ -712,6 +713,9 @@
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
+ // Set seccomp policy
+ Seccomp.setPolicy();
+
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java
new file mode 100644
index 0000000..518cf41
--- /dev/null
+++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.util;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.util.Objects;
+
+/**
+ * A util to look up messaging related functions for notifications. This is used for both the
+ * ranking and the actual layout.
+ */
+public class NotificationMessagingUtil {
+
+ private static final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
+ private final Context mContext;
+ private ArrayMap<Integer, String> mDefaultSmsApp = new ArrayMap<>();
+
+ public NotificationMessagingUtil(Context context) {
+ mContext = context;
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
+ }
+
+ @SuppressWarnings("deprecation")
+ private boolean isDefaultMessagingApp(StatusBarNotification sbn) {
+ final int userId = sbn.getUserId();
+ if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
+ if (mDefaultSmsApp.get(userId) == null) {
+ cacheDefaultSmsApp(userId);
+ }
+ return Objects.equals(mDefaultSmsApp.get(userId), sbn.getPackageName());
+ }
+
+ private void cacheDefaultSmsApp(int userId) {
+ mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
+ }
+
+ private final ContentObserver mSmsContentObserver = new ContentObserver(
+ new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING).equals(uri)) {
+ cacheDefaultSmsApp(userId);
+ }
+ }
+ };
+
+ public boolean isImportantMessaging(StatusBarNotification sbn, int importance) {
+ if (importance < NotificationManager.IMPORTANCE_LOW) {
+ return false;
+ }
+
+ Class<? extends Notification.Style> style = sbn.getNotification().getNotificationStyle();
+ if (Notification.MessagingStyle.class.equals(style)) {
+ return true;
+ }
+
+ if (Notification.CATEGORY_MESSAGE.equals(sbn.getNotification().category)
+ && isDefaultMessagingApp(sbn)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index cf9441b..db3ea8c 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -91,6 +91,7 @@
android_os_MessageQueue.cpp \
android_os_Parcel.cpp \
android_os_SELinux.cpp \
+ android_os_seccomp.cpp \
android_os_SystemClock.cpp \
android_os_SystemProperties.cpp \
android_os_Trace.cpp \
@@ -230,6 +231,7 @@
LOCAL_STATIC_LIBRARIES := \
libgif \
+ libseccomp_policy \
LOCAL_SHARED_LIBRARIES := \
libmemtrack \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 340f2ee..407e69c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -159,6 +159,7 @@
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
+extern int register_android_os_seccomp(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
extern int register_android_os_Trace(JNIEnv* env);
@@ -1360,6 +1361,7 @@
REG_JNI(register_android_os_GraphicsEnvironment),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_SELinux),
+ REG_JNI(register_android_os_seccomp),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
REG_JNI(register_android_net_LocalSocketImpl),
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
new file mode 100644
index 0000000..2fe5d39
--- /dev/null
+++ b/core/jni/android_os_seccomp.cpp
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+#include "JNIHelp.h"
+#include "core_jni_helpers.h"
+#include "JniConstants.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+#if defined __arm__ || defined __aarch64__
+
+#include <vector>
+
+#include <sys/prctl.h>
+
+#include <linux/unistd.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#include "seccomp_policy.h"
+
+#define syscall_nr (offsetof(struct seccomp_data, nr))
+#define arch_nr (offsetof(struct seccomp_data, arch))
+
+typedef std::vector<sock_filter> filter;
+
+// We want to keep the below inline functions for debugging and future
+// development even though they are not all sed currently.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+
+static inline void Kill(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL));
+}
+
+static inline void Trap(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
+}
+
+static inline void Error(filter& f, __u16 retcode) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO + retcode));
+}
+
+inline static void Trace(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE));
+}
+
+inline static void Allow(filter& f) {
+ f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
+}
+
+#pragma clang diagnostic pop
+
+inline static void AllowSyscall(filter& f, __u32 num) {
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, num, 0, 1));
+ Allow(f);
+}
+
+inline static void ExamineSyscall(filter& f) {
+ f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
+}
+
+inline static int SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
+ size_t jump_length = f.size() - offset - 1;
+ auto u8_jump_length = (__u8) jump_length;
+ if (u8_jump_length != jump_length) {
+ ALOGE("Can't set jump greater than 255 - actual jump is %zu",
+ jump_length);
+ return -1;
+ }
+ f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, u8_jump_length, 0);
+ return 0;
+}
+
+inline static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) {
+ f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr));
+
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_AARCH64, 2, 0));
+ f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, 1, 0));
+ Trap(f);
+ return f.size() - 2;
+}
+
+static bool install_filter(filter const& f) {
+ struct sock_fprog prog = {
+ (unsigned short) f.size(),
+ (struct sock_filter*) &f[0],
+ };
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
+ ALOGE("SECCOMP: Could not set seccomp filter of size %zu: %s", f.size(), strerror(errno));
+ return false;
+ }
+
+ ALOGI("SECCOMP: Global filter of size %zu installed", f.size());
+ return true;
+}
+
+bool set_seccomp_filter() {
+ filter f;
+
+ // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
+ // jump that must be changed to point to the start of the 32-bit policy
+ // 32 bit syscalls will not hit the policy between here and the call to SetJump
+ auto offset_to_32bit_filter =
+ ValidateArchitectureAndJumpIfNeeded(f);
+
+ // 64-bit filter
+ ExamineSyscall(f);
+
+ // arm64-only filter - autogenerated from bionic syscall usage
+ for (size_t i = 0; i < arm64_filter_size; ++i)
+ f.push_back(arm64_filter[i]);
+
+ // Syscalls needed to boot Android
+ AllowSyscall(f, 41); // __NR_pivot_root
+ AllowSyscall(f, 31); // __NR_ioprio_get
+ AllowSyscall(f, 30); // __NR_ioprio_set
+ AllowSyscall(f, 178); // __NR_gettid
+ AllowSyscall(f, 98); // __NR_futex
+ AllowSyscall(f, 220); // __NR_clone
+ AllowSyscall(f, 139); // __NR_rt_sigreturn
+ AllowSyscall(f, 240); // __NR_rt_tgsigqueueinfo
+ AllowSyscall(f, 128); // __NR_restart_syscall
+ AllowSyscall(f, 278); // __NR_getrandom
+
+ // Needed for performance tools
+ AllowSyscall(f, 241); // __NR_perf_event_open
+
+ // Needed for strace
+ AllowSyscall(f, 130); // __NR_tkill
+
+ // Needed for kernel to restart syscalls
+ AllowSyscall(f, 128); // __NR_restart_syscall
+
+ Trap(f);
+
+ if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
+ return -1;
+
+ // 32-bit filter
+ ExamineSyscall(f);
+
+ // arm32 filter - autogenerated from bionic syscall usage
+ for (size_t i = 0; i < arm_filter_size; ++i)
+ f.push_back(arm_filter[i]);
+
+ // Syscalls needed to boot android
+ AllowSyscall(f, 120); // __NR_clone
+ AllowSyscall(f, 240); // __NR_futex
+ AllowSyscall(f, 119); // __NR_sigreturn
+ AllowSyscall(f, 173); // __NR_rt_sigreturn
+ AllowSyscall(f, 363); // __NR_rt_tgsigqueueinfo
+ AllowSyscall(f, 224); // __NR_gettid
+
+ // Syscalls needed to run Chrome
+ AllowSyscall(f, 383); // __NR_seccomp - needed to start Chrome
+ AllowSyscall(f, 384); // __NR_getrandom - needed to start Chrome
+
+ // Syscalls needed to run GFXBenchmark
+ AllowSyscall(f, 190); // __NR_vfork
+
+ // Needed for strace
+ AllowSyscall(f, 238); // __NR_tkill
+
+ // Needed for kernel to restart syscalls
+ AllowSyscall(f, 0); // __NR_restart_syscall
+
+ // Needed for debugging 32-bit Chrome
+ AllowSyscall(f, 42); // __NR_pipe
+
+ // b/34732712
+ AllowSyscall(f, 364); // __NR_perf_event_open
+
+ // b/34651972
+ AllowSyscall(f, 33); // __NR_access
+ AllowSyscall(f, 195); // __NR_stat64
+
+ // b/34813887
+ AllowSyscall(f, 5); // __NR_open
+ AllowSyscall(f, 141); // __NR_getdents
+ AllowSyscall(f, 217); // __NR_getdents64
+
+ // b/34719286
+ AllowSyscall(f, 351); // __NR_eventfd
+
+ // b/34817266
+ AllowSyscall(f, 252); // __NR_epoll_wait
+
+ // Needed by sanitizers (b/34606909)
+ // 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
+ // already allowed.
+ AllowSyscall(f, 85); // __NR_readlink
+
+ // b/34908783
+ AllowSyscall(f, 250); // __NR_epoll_create
+
+ Trap(f);
+
+ return install_filter(f);
+}
+
+static void Seccomp_setPolicy(JNIEnv* /*env*/) {
+ if (!set_seccomp_filter()) {
+ ALOGE("Failed to set seccomp policy - killing");
+ exit(1);
+ }
+}
+
+#else // #if defined __arm__ || defined __aarch64__
+
+static void Seccomp_setPolicy(JNIEnv* /*env*/) {
+}
+
+#endif
+
+static const JNINativeMethod method_table[] = {
+ NATIVE_METHOD(Seccomp, setPolicy, "()V"),
+};
+
+namespace android {
+
+int register_android_os_seccomp(JNIEnv* env) {
+ return android::RegisterMethodsOrDie(env, "android/os/Seccomp",
+ method_table, NELEM(method_table));
+}
+
+}
diff --git a/core/proto/android/service/battery.proto b/core/proto/android/service/battery.proto
new file mode 100644
index 0000000..33ad682b
--- /dev/null
+++ b/core/proto/android/service/battery.proto
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service.battery;
+
+option java_multiple_files = true;
+option java_outer_classname = "BatteryServiceProto";
+
+message BatteryServiceDumpProto {
+ enum BatteryPlugged {
+ BATTERY_PLUGGED_NONE = 0;
+ BATTERY_PLUGGED_AC = 1;
+ BATTERY_PLUGGED_USB = 2;
+ BATTERY_PLUGGED_WIRELESS = 4;
+ }
+ enum BatteryStatus {
+ BATTERY_STATUS_INVALID = 0;
+ BATTERY_STATUS_UNKNOWN = 1;
+ BATTERY_STATUS_CHARGING = 2;
+ BATTERY_STATUS_DISCHARGING = 3;
+ BATTERY_STATUS_NOT_CHARGING = 4;
+ BATTERY_STATUS_FULL = 5;
+ }
+ enum BatteryHealth {
+ BATTERY_HEALTH_INVALID = 0;
+ BATTERY_HEALTH_UNKNOWN = 1;
+ BATTERY_HEALTH_GOOD = 2;
+ BATTERY_HEALTH_OVERHEAT = 3;
+ BATTERY_HEALTH_DEAD = 4;
+ BATTERY_HEALTH_OVER_VOLTAGE = 5;
+ BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
+ BATTERY_HEALTH_COLD = 7;
+ }
+
+ // If true: UPDATES STOPPED -- use 'reset' to restart
+ bool are_updates_stopped = 1;
+ // Plugged status of power sources
+ BatteryPlugged plugged = 2;
+ // Max current in microamperes
+ int32 max_charging_current = 3;
+ // Max voltage
+ int32 max_charging_voltage = 4;
+ // Battery capacity in microampere-hours
+ int32 charge_counter = 5;
+ // Charging status
+ BatteryStatus status = 6;
+ // Battery health
+ BatteryHealth health = 7;
+ // True if the battery is present
+ bool is_present = 8;
+ // Charge level, from 0 through "scale" inclusive
+ int32 level = 9;
+ // The maximum value for the charge level
+ int32 scale = 10;
+ // Battery voltage in millivolts
+ int32 voltage = 11;
+ // Battery temperature in tenths of a degree Centigrade
+ int32 temperature = 12;
+ // The type of battery installed, e.g. "Li-ion"
+ string technology = 13;
+}
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
index 5cca6ab..5a577b1 100644
--- a/core/proto/android/service/netstats.proto
+++ b/core/proto/android/service/netstats.proto
@@ -27,12 +27,16 @@
repeated NetworkInterfaceProto active_uid_interfaces = 2;
+ // Device level network stats, which may include non-IP layer traffic.
NetworkStatsRecorderProto dev_stats = 3;
+ // IP-layer traffic stats.
NetworkStatsRecorderProto xt_stats = 4;
+ // Per-UID network stats.
NetworkStatsRecorderProto uid_stats = 5;
+ // Per-UID, per-tag network stats, excluding the default tag (i.e. tag=0).
NetworkStatsRecorderProto uid_tag_stats = 6;
}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 6d0fdb6..76f4a76 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -885,6 +885,12 @@
will run against. -->
<attr name="targetPackage" format="string" />
+ <!-- The name of an application's processes that an Instrumentation object
+ will run against. If not specified, only runs in the main process of the targetPackage.
+ Can either be a comma-separated list of process names or '*' for any process that
+ launches to run targetPackage code. -->
+ <attr name="targetProcess" format="string" />
+
<!-- Flag indicating that an Instrumentation class wants to take care
of starting/stopping profiling itself, rather than relying on
the default behavior of profiling the complete time it is running.
@@ -2050,9 +2056,6 @@
in a task/stack that isn't focusable. This flag allows them to be focusable.-->
<attr name="alwaysFocusable" format="boolean" />
<attr name="enableVrMode" />
- <!-- @hide This activity is a launcher which should always show up on the top of others.
- This attribute is ignored if the activity isn't a launcher. -->
- <attr name="onTopLauncher" format="boolean" />
<attr name="rotationAnimation" />
<attr name="visibleToInstantApps" />
<!-- The code for this component is located in the given split. -->
@@ -2297,6 +2300,7 @@
is a period then it is appended to your package name. -->
<attr name="name" />
<attr name="targetPackage" />
+ <attr name="targetProcess" />
<attr name="label" />
<attr name="icon" />
<attr name="roundIcon" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 927988f..c2cd895 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -520,6 +520,7 @@
<dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
<!-- The elevation of AutoFill fill window-->
- <dimen name="autofill_fill_elevation">2dp</dimen>
+ <dimen name="autofill_fill_elevation">4dp</dimen>
<dimen name="autofill_fill_item_height">64dp</dimen>
+ <dimen name="autofill_fill_min_margin">16dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d795d80..1b48469 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2777,7 +2777,7 @@
<public name="paddingVertical" />
<public name="visibleToInstantApps" />
<public name="keyboardNavigationCluster" />
- <public name="__removed0" />
+ <public name="targetProcess" />
<public name="nextClusterForward" />
<public name="__removed1" />
<public name="textColorError" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8b9b3b2..e00874f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3064,6 +3064,7 @@
<string name="adb_active_notification_title">USB debugging connected</string>
<!-- Message of notification shown when ADB is actively connected to the phone. -->
<string name="adb_active_notification_message">Tap to disable USB debugging.</string>
+ <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string>
<!-- Title of notification shown to indicate that bug report is being collected. -->
<string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string>
@@ -4468,4 +4469,6 @@
<!-- Channel name for DeviceStorageMonitor notifications -->
<string name="device_storage_monitor_notification_channel">Device storage</string>
+ <!-- Channel name for UsbDeviceManager adb debugging notifications -->
+ <string name="adb_debugging_notification_channel_tv">USB debugging</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 571aa17..24f22cd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1914,6 +1914,7 @@
<java-symbol type="string" name="smv_process" />
<java-symbol type="string" name="tethered_notification_message" />
<java-symbol type="string" name="tethered_notification_title" />
+ <java-symbol type="string" name="adb_debugging_notification_channel_tv" />
<java-symbol type="string" name="usb_accessory_notification_title" />
<java-symbol type="string" name="usb_mtp_notification_title" />
<java-symbol type="string" name="usb_charging_notification_title" />
@@ -2833,6 +2834,7 @@
<!-- com.android.server.autofill -->
<java-symbol type="dimen" name="autofill_fill_elevation" />
<java-symbol type="dimen" name="autofill_fill_item_height" />
+ <java-symbol type="dimen" name="autofill_fill_min_margin" />
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_no" />
diff --git a/core/tests/coretests/res/font/samplefont.ttf b/core/tests/coretests/res/font/samplefont.ttf
new file mode 100644
index 0000000..2852302
--- /dev/null
+++ b/core/tests/coretests/res/font/samplefont.ttf
Binary files differ
diff --git a/core/tests/coretests/res/font/samplefont2.ttf b/core/tests/coretests/res/font/samplefont2.ttf
new file mode 100644
index 0000000..2852302
--- /dev/null
+++ b/core/tests/coretests/res/font/samplefont2.ttf
Binary files differ
diff --git a/core/tests/coretests/res/font/samplefont3.ttf b/core/tests/coretests/res/font/samplefont3.ttf
new file mode 100644
index 0000000..2852302
--- /dev/null
+++ b/core/tests/coretests/res/font/samplefont3.ttf
Binary files differ
diff --git a/core/tests/coretests/res/font/samplefont4.ttf b/core/tests/coretests/res/font/samplefont4.ttf
new file mode 100644
index 0000000..2852302
--- /dev/null
+++ b/core/tests/coretests/res/font/samplefont4.ttf
Binary files differ
diff --git a/core/tests/coretests/res/font/samplexmlfont.xml b/core/tests/coretests/res/font/samplexmlfont.xml
new file mode 100644
index 0000000..bb813e1
--- /dev/null
+++ b/core/tests/coretests/res/font/samplexmlfont.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+ <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+ <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/samplefont2" />
+ <font android:fontStyle="normal" android:fontWeight="800" android:font="@font/samplefont3" />
+ <font android:fontStyle="italic" android:fontWeight="800" android:font="@font/samplefont4" />
+</font-family>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
new file mode 100644
index 0000000..380a28774
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.content.res;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.app.Instrumentation;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.FontConfig;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Tests for {@link FontResourcesParser}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class FontResourcesParserTest {
+
+ private Instrumentation mInstrumentation;
+ private Resources mResources;
+
+ @Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mResources = mInstrumentation.getContext().getResources();
+ }
+
+ @Test
+ public void testParse() throws XmlPullParserException, IOException {
+ XmlResourceParser parser = mResources.getXml(R.font.samplexmlfont);
+
+ FontConfig result = FontResourcesParser.parse(parser, mResources);
+
+ assertNotNull(result);
+ List<FontConfig.Family> families = result.getFamilies();
+ assertEquals(1, families.size());
+ List<FontConfig.Font> fonts = families.get(0).getFonts();
+ assertEquals(4, fonts.size());
+ FontConfig.Font font1 = fonts.get(0);
+ assertEquals(400, font1.getWeight());
+ assertEquals(false, font1.isItalic());
+ assertEquals("res/font/samplefont.ttf", font1.getFontName());
+ FontConfig.Font font2 = fonts.get(1);
+ assertEquals(400, font2.getWeight());
+ assertEquals(true, font2.isItalic());
+ assertEquals("res/font/samplefont2.ttf", font2.getFontName());
+ FontConfig.Font font3 = fonts.get(2);
+ assertEquals(800, font3.getWeight());
+ assertEquals(false, font3.isItalic());
+ assertEquals("res/font/samplefont3.ttf", font3.getFontName());
+ FontConfig.Font font4 = fonts.get(3);
+ assertEquals(800, font4.getWeight());
+ assertEquals(true, font4.isItalic());
+ assertEquals("res/font/samplefont4.ttf", font4.getFontName());
+ }
+}
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 5bfff26..ce5d3ef 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -19,6 +19,7 @@
import static org.mockito.Mockito.when;
import android.Manifest.permission;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -30,13 +31,16 @@
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.provider.Settings;
import android.test.InstrumentationTestCase;
+
import com.android.internal.R;
-import java.util.List;
+
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
@Mock private Context mMockContext;
@Mock private PackageManager mMockPm;
@@ -114,39 +118,40 @@
public void testGetNetworkRecommendationProviderData_scoreNetworksNotGranted()
throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksDenied("package1");
- mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ mockScoreNetworksDenied(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
}
public void testGetNetworkRecommendationProviderData_available() throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
- mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
NetworkScorerAppData appData =
mNetworkScorerAppManager.getNetworkRecommendationProviderData();
assertNotNull(appData);
- assertEquals("package1", appData.packageName);
+ assertEquals(recoComponent, appData.getRecommendationServiceComponent());
assertEquals(924, appData.packageUid);
- assertEquals(".RecommendationService", appData.recommendationServiceClassName);
}
public void testGetActiveScorer_providerAvailable() throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
- mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
ContentResolver cr = mTargetContext.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
assertNotNull(activeScorer);
- assertEquals("package1", activeScorer.packageName);
+ assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
assertEquals(924, activeScorer.packageUid);
- assertEquals(".RecommendationService", activeScorer.recommendationServiceClassName);
}
public void testGetActiveScorer_providerNotAvailable()
@@ -159,9 +164,10 @@
}
public void testGetActiveScorer_recommendationsDisabled() throws Exception {
- setNetworkRecommendationPackageNames("package1");
- mockScoreNetworksGranted("package1");
- mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+ final ComponentName recoComponent = new ComponentName("package1", "class1");
+ setNetworkRecommendationPackageNames(recoComponent.getPackageName());
+ mockScoreNetworksGranted(recoComponent.getPackageName());
+ mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
ContentResolver cr = mTargetContext.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
@@ -187,11 +193,11 @@
.thenReturn(PackageManager.PERMISSION_DENIED);
}
- private void mockRecommendationServiceAvailable(final String packageName, int packageUid) {
+ private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid) {
final ResolveInfo serviceInfo = new ResolveInfo();
serviceInfo.serviceInfo = new ServiceInfo();
- serviceInfo.serviceInfo.name = ".RecommendationService";
- serviceInfo.serviceInfo.packageName = packageName;
+ serviceInfo.serviceInfo.name = compName.getClassName();
+ serviceInfo.serviceInfo.packageName = compName.getPackageName();
serviceInfo.serviceInfo.applicationInfo = new ApplicationInfo();
serviceInfo.serviceInfo.applicationInfo.uid = packageUid;
@@ -203,7 +209,7 @@
Intent intent = (Intent) object;
return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
.equals(intent.getAction())
- && packageName.equals(intent.getPackage());
+ && compName.getPackageName().equals(intent.getPackage());
}
}), Mockito.eq(flags))).thenReturn(serviceInfo);
}
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index 7a2cbd0..03df5de 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -29,6 +29,8 @@
*/
public abstract class GateKeeper {
+ public static final long INVALID_SECURE_USER_ID = 0;
+
private GateKeeper() {}
public static IGateKeeperService getService() {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index b234d0f..9701b0e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -17,6 +17,7 @@
package android.security.keystore;
import android.security.Credentials;
+import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
@@ -235,7 +236,8 @@
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment());
+ spec.isInvalidatedByBiometricEnrollment(),
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -275,7 +277,8 @@
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment());
+ spec.isInvalidatedByBiometricEnrollment(),
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 1818f52..dba3949 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.security.Credentials;
+import android.security.GateKeeper;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
import android.security.keymaster.KeyCharacteristics;
@@ -346,7 +347,8 @@
mSpec.isUserAuthenticationRequired(),
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment());
+ mSpec.isInvalidatedByBiometricEnrollment(),
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -533,7 +535,8 @@
mSpec.isUserAuthenticationRequired(),
mSpec.getUserAuthenticationValidityDurationSeconds(),
mSpec.isUserAuthenticationValidWhileOnBody(),
- mSpec.isInvalidatedByBiometricEnrollment());
+ mSpec.isInvalidatedByBiometricEnrollment(),
+ GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index fcbb553..64b10ab 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -500,7 +500,8 @@
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
spec.isUserAuthenticationValidWhileOnBody(),
- spec.isInvalidatedByBiometricEnrollment());
+ spec.isInvalidatedByBiometricEnrollment(),
+ spec.getBoundToSpecificSecureUserId());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -696,7 +697,8 @@
params.isUserAuthenticationRequired(),
params.getUserAuthenticationValidityDurationSeconds(),
params.isUserAuthenticationValidWhileOnBody(),
- params.isInvalidatedByBiometricEnrollment());
+ params.isInvalidatedByBiometricEnrollment(),
+ params.getBoundToSpecificSecureUserId());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index e70d33a..2592a97 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.security.GateKeeper;
import java.security.Key;
import java.security.Signature;
@@ -225,6 +226,7 @@
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
+ private final long mBoundToSecureUserId;
private KeyProtection(
Date keyValidityStart,
@@ -239,7 +241,8 @@
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationValidWhileOnBody,
- boolean invalidatedByBiometricEnrollment) {
+ boolean invalidatedByBiometricEnrollment,
+ long boundToSecureUserId) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -255,6 +258,7 @@
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
+ mBoundToSecureUserId = boundToSecureUserId;
}
/**
@@ -436,6 +440,24 @@
}
/**
+ * Return the secure user id that this key should be bound to.
+ *
+ * Normally an authentication-bound key is tied to the secure user id of the current user
+ * (either the root SID from GateKeeper for auth-bound keys with a timeout, or the authenticator
+ * id of the current fingerprint set for keys requiring explicit fingerprint authorization).
+ * If this parameter is set (this method returning non-zero value), the key should be tied to
+ * the specified secure user id, overriding the logic above.
+ *
+ * This is only applicable when {@link #isUserAuthenticationRequired} is {@code true}
+ *
+ * @see KeymasterUtils#addUserAuthArgs
+ * @hide
+ */
+ public long getBoundToSpecificSecureUserId() {
+ return mBoundToSecureUserId;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -454,6 +476,7 @@
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
+ private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
/**
* Creates a new instance of the {@code Builder}.
*
@@ -774,6 +797,26 @@
}
/**
+ * Set the secure user id that this key should be bound to.
+ *
+ * Normally an authentication-bound key is tied to the secure user id of the current user
+ * (either the root SID from GateKeeper for auth-bound keys with a timeout, or the
+ * authenticator id of the current fingerprint set for keys requiring explicit fingerprint
+ * authorization). If this parameter is set (this method returning non-zero value), the key
+ * should be tied to the specified secure user id, overriding the logic above.
+ *
+ * This is only applicable when {@link #setUserAuthenticationRequired} is set to
+ * {@code true}
+ *
+ * @see KeyProtection#getBoundToSpecificSecureUserId()
+ * @hide
+ */
+ public Builder setBoundToSpecificSecureUserId(long secureUserId) {
+ mBoundToSecureUserId = secureUserId;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -793,7 +836,8 @@
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds,
mUserAuthenticationValidWhileOnBody,
- mInvalidatedByBiometricEnrollment);
+ mInvalidatedByBiometricEnrollment,
+ mBoundToSecureUserId);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index f5272aa..34c8d1f 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -89,7 +89,10 @@
* @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user
* authentication is valid as authorization for using the key or {@code -1} if every
* use of the key needs authorization.
- *
+ * @param boundToSpecificSecureUserId if non-zero, specify which SID the key will be bound to,
+ * overriding the default logic in this method where the key is bound to either the root
+ * SID of the current user, or the fingerprint SID if explicit fingerprint authorization
+ * is requested.
* @throws IllegalStateException if user authentication is required but the system is in a wrong
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
@@ -98,7 +101,8 @@
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationValidWhileOnBody,
- boolean invalidatedByBiometricEnrollment) {
+ boolean invalidatedByBiometricEnrollment,
+ long boundToSpecificSecureUserId) {
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
@@ -120,7 +124,9 @@
}
long sid;
- if (invalidatedByBiometricEnrollment) {
+ if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = boundToSpecificSecureUserId;
+ } else if (invalidatedByBiometricEnrollment) {
// The fingerprint-only SID will change on fingerprint enrollment or removal of all,
// enrolled fingerprints, invalidating the key.
sid = fingerprintOnlySid;
@@ -138,11 +144,16 @@
+ "supported for keys requiring fingerprint authentication");
}
} else {
- // The key is authorized for use for the specified amount of time after the user has
- // authenticated. Whatever unlocks the secure lock screen should authorize this key.
- long rootSid = getRootSid();
+ long sid;
+ if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) {
+ sid = boundToSpecificSecureUserId;
+ } else {
+ // The key is authorized for use for the specified amount of time after the user has
+ // authenticated. Whatever unlocks the secure lock screen should authorize this key.
+ sid = getRootSid();
+ }
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
- KeymasterArguments.toUint64(rootSid));
+ KeymasterArguments.toUint64(sid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 9a08f63..fe68ec0 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -27,16 +27,17 @@
namespace android {
-std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path) {
- return ApkAssets::LoadImpl(path, false /*load_as_shared_library*/);
+std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system) {
+ return ApkAssets::LoadImpl(path, system, false /*load_as_shared_library*/);
}
-std::unique_ptr<ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path) {
- return ApkAssets::LoadImpl(path, true /*load_as_shared_library*/);
+std::unique_ptr<const ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path,
+ bool system) {
+ return ApkAssets::LoadImpl(path, system, true /*load_as_shared_library*/);
}
-std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(const std::string& path,
- bool load_as_shared_library) {
+std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bool system,
+ bool load_as_shared_library) {
ATRACE_CALL();
::ZipArchiveHandle unmanaged_handle;
int32_t result = ::OpenArchive(path.c_str(), &unmanaged_handle);
@@ -70,11 +71,13 @@
loaded_apk->path_ = path;
loaded_apk->loaded_arsc_ =
LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/),
- loaded_apk->resources_asset_->getLength(), load_as_shared_library);
+ loaded_apk->resources_asset_->getLength(), system, load_as_shared_library);
if (loaded_apk->loaded_arsc_ == nullptr) {
return {};
}
- return loaded_apk;
+
+ // Need to force a move for mingw32.
+ return std::move(loaded_apk);
}
std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode /*mode*/) const {
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index d2eff65..542a125 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -18,6 +18,8 @@
#include "androidfw/AssetManager2.h"
+#include <set>
+
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "utils/ByteOrder.h"
@@ -143,6 +145,36 @@
}
}
+std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
+ bool exclude_mipmap) {
+ ATRACE_CALL();
+ std::set<ResTable_config> configurations;
+ for (const PackageGroup& package_group : package_groups_) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (exclude_system && package->IsSystem()) {
+ continue;
+ }
+ package->CollectConfigurations(exclude_mipmap, &configurations);
+ }
+ }
+ return configurations;
+}
+
+std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
+ bool merge_equivalent_languages) {
+ ATRACE_CALL();
+ std::set<std::string> locales;
+ for (const PackageGroup& package_group : package_groups_) {
+ for (const LoadedPackage* package : package_group.packages_) {
+ if (exclude_system && package->IsSystem()) {
+ continue;
+ }
+ package->CollectLocales(merge_equivalent_languages, &locales);
+ }
+ }
+ return locales;
+}
+
std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
const std::string new_path = "assets/" + filename;
return OpenNonAsset(new_path, mode);
@@ -325,8 +357,15 @@
if (dtohl(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) {
if (!may_be_bag) {
LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
+ return kInvalidCookie;
}
- return kInvalidCookie;
+
+ // Create a reference since we can't represent this complex type as a Res_value.
+ out_value->dataType = Res_value::TYPE_REFERENCE;
+ out_value->data = resid;
+ *out_selected_config = config;
+ *out_flags = flags;
+ return cookie;
}
const Res_value* device_value = reinterpret_cast<const Res_value*>(
@@ -341,6 +380,37 @@
return cookie;
}
+ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
+ ResTable_config* in_out_selected_config,
+ uint32_t* in_out_flags,
+ ResTable_ref* out_last_reference) {
+ ATRACE_CALL();
+ constexpr const int kMaxIterations = 20;
+
+ out_last_reference->ident = 0u;
+ for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
+ in_out_value->data != 0u && iteration < kMaxIterations;
+ iteration++) {
+ if (out_last_reference != nullptr) {
+ out_last_reference->ident = in_out_value->data;
+ }
+ uint32_t new_flags = 0u;
+ cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
+ in_out_value, in_out_selected_config, &new_flags);
+ if (cookie == kInvalidCookie) {
+ return kInvalidCookie;
+ }
+ if (in_out_flags != nullptr) {
+ *in_out_flags |= new_flags;
+ }
+ if (out_last_reference->ident == in_out_value->data) {
+ // This reference can't be resolved, so exit now and let the caller deal with it.
+ return cookie;
+ }
+ }
+ return cookie;
+}
+
const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
ATRACE_CALL();
@@ -501,6 +571,15 @@
return result;
}
+uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
+ const std::string& fallback_type,
+ const std::string& fallback_package) {
+ (void)resource_name;
+ (void)fallback_type;
+ (void)fallback_package;
+ return 0u;
+}
+
void AssetManager2::InvalidateCaches(uint32_t diff) {
if (diff == 0xffffffffu) {
// Everything must go.
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c7d0fa5..cb589ec 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -321,6 +321,57 @@
return true;
}
+void LoadedPackage::CollectConfigurations(bool exclude_mipmap,
+ std::set<ResTable_config>* out_configs) const {
+ const static std::u16string kMipMap = u"mipmap";
+ const size_t type_count = type_specs_.size();
+ for (size_t i = 0; i < type_count; i++) {
+ const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
+ if (type_spec != nullptr) {
+ if (exclude_mipmap) {
+ const int type_idx = type_spec->type_spec->id - 1;
+ size_t type_name_len;
+ const char16_t* type_name16 = type_string_pool_.stringAt(type_idx, &type_name_len);
+ if (type_name16 != nullptr) {
+ if (kMipMap.compare(0, std::u16string::npos, type_name16, type_name_len) == 0) {
+ // This is a mipmap type, skip collection.
+ continue;
+ }
+ }
+ const char* type_name = type_string_pool_.string8At(type_idx, &type_name_len);
+ if (type_name != nullptr) {
+ if (strncmp(type_name, "mipmap", type_name_len) == 0) {
+ // This is a mipmap type, skip collection.
+ continue;
+ }
+ }
+ }
+
+ for (size_t j = 0; j < type_spec->type_count; j++) {
+ out_configs->insert(type_spec->types[j].configuration);
+ }
+ }
+ }
+}
+
+void LoadedPackage::CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const {
+ char temp_locale[RESTABLE_MAX_LOCALE_LEN];
+ const size_t type_count = type_specs_.size();
+ for (size_t i = 0; i < type_count; i++) {
+ const util::unique_cptr<TypeSpec>& type_spec = type_specs_[i];
+ if (type_spec != nullptr) {
+ for (size_t j = 0; j < type_spec->type_count; j++) {
+ const ResTable_config& configuration = type_spec->types[j].configuration;
+ if (configuration.locale != 0) {
+ configuration.getBcp47Locale(temp_locale, canonicalize);
+ std::string locale(temp_locale);
+ out_locales->insert(std::move(locale));
+ }
+ }
+ }
+ }
+}
+
std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
ATRACE_CALL();
std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()};
@@ -574,6 +625,7 @@
if (loaded_package->package_id_ == kAppPackageId) {
loaded_package->dynamic_ = load_as_shared_library;
}
+ loaded_package->system_ = system_;
packages_.push_back(std::move(loaded_package));
} break;
@@ -590,12 +642,13 @@
return true;
}
-std::unique_ptr<LoadedArsc> LoadedArsc::Load(const void* data, size_t len,
- bool load_as_shared_library) {
+std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const void* data, size_t len, bool system,
+ bool load_as_shared_library) {
ATRACE_CALL();
// Not using make_unique because the constructor is private.
std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());
+ loaded_arsc->system_ = system;
ChunkIterator iter(data, len);
while (iter.HasNext()) {
@@ -617,7 +670,9 @@
LOG(ERROR) << iter.GetLastError();
return {};
}
- return loaded_arsc;
+
+ // Need to force a move for mingw32.
+ return std::move(loaded_arsc);
}
} // namespace android
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 9d4fd29..6d1578c 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -31,8 +31,9 @@
// Holds an APK.
class ApkAssets {
public:
- static std::unique_ptr<ApkAssets> Load(const std::string& path);
- static std::unique_ptr<ApkAssets> LoadAsSharedLibrary(const std::string& path);
+ static std::unique_ptr<const ApkAssets> Load(const std::string& path, bool system = false);
+ static std::unique_ptr<const ApkAssets> LoadAsSharedLibrary(const std::string& path,
+ bool system = false);
std::unique_ptr<Asset> Open(const std::string& path,
Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
@@ -44,7 +45,8 @@
private:
DISALLOW_COPY_AND_ASSIGN(ApkAssets);
- static std::unique_ptr<ApkAssets> LoadImpl(const std::string& path, bool load_as_shared_library);
+ static std::unique_ptr<const ApkAssets> LoadImpl(const std::string& path, bool system,
+ bool load_as_shared_library);
ApkAssets() = default;
@@ -57,7 +59,7 @@
ZipArchivePtr zip_handle_;
std::string path_;
std::unique_ptr<Asset> resources_asset_;
- std::unique_ptr<LoadedArsc> loaded_arsc_;
+ std::unique_ptr<const LoadedArsc> loaded_arsc_;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 8655339..81cdc46 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -21,6 +21,7 @@
#include <array>
#include <limits>
+#include <set>
#include <unordered_map>
#include "androidfw/ApkAssets.h"
@@ -112,6 +113,24 @@
inline const ResTable_config& GetConfiguration() const { return configuration_; }
+ // Returns all configurations for which there are resources defined. This includes resource
+ // configurations in all the ApkAssets set for this AssetManager.
+ // If `exclude_system` is set to true, resource configurations from system APKs
+ // ('android' package, other libraries) will be excluded from the list.
+ // If `exclude_mipmap` is set to true, resource configurations defined for resource type 'mipmap'
+ // will be excluded from the list.
+ std::set<ResTable_config> GetResourceConfigurations(bool exclude_system = false,
+ bool exclude_mipmap = false);
+
+ // Returns all the locales for which there are resources defined. This includes resource
+ // locales in all the ApkAssets set for this AssetManager.
+ // If `exclude_system` is set to true, resource locales from system APKs
+ // ('android' package, other libraries) will be excluded from the list.
+ // If `merge_equivalent_languages` is set to true, resource locales will be canonicalized
+ // and de-duped in the resulting list.
+ std::set<std::string> GetResourceLocales(bool exclude_system = false,
+ bool merge_equivalent_languages = false);
+
// Searches the set of APKs loaded by this AssetManager and opens the first one found located
// in the assets/ directory.
// `mode` controls how the file is opened.
@@ -149,6 +168,14 @@
// Returns false if the resource was not found.
bool GetResourceFlags(uint32_t resid, uint32_t* out_flags);
+ // Finds the resource ID assigned to `resource_name`.
+ // `resource_name` must be of the form '[package:][type/]entry'.
+ // If no package is specified in `resource_name`, then `fallback_package` is used as the package.
+ // If no type is specified in `resource_name`, then `fallback_type` is used as the type.
+ // Returns 0x0 if no resource by that name was found.
+ uint32_t GetResourceId(const std::string& resource_name, const std::string& fallback_type = {},
+ const std::string& fallback_package = {});
+
// Retrieves the best matching resource with ID `resid`. The resource value is filled into
// `out_value` and the configuration for the selected value is populated in `out_selected_config`.
// `out_flags` holds the same flags as retrieved with GetResourceFlags().
@@ -162,6 +189,22 @@
Res_value* out_value, ResTable_config* out_selected_config,
uint32_t* out_flags);
+ // Resolves the resource reference in `in_out_value` if the data type is
+ // Res_value::TYPE_REFERENCE.
+ // `cookie` is the ApkAssetsCookie of the reference in `in_out_value`.
+ // `in_out_value` is the reference to resolve. The result is placed back into this object.
+ // `in_out_flags` is the type spec flags returned from calls to GetResource() or
+ // GetResourceFlags(). Configuration flags of the values pointed to by the reference
+ // are OR'd together with `in_out_flags`.
+ // `in_out_config` is populated with the configuration for which the resolved value was defined.
+ // `out_last_reference` is populated with the last reference ID before resolving to an actual
+ // value.
+ // Returns the cookie of the APK the resolved resource was defined in, or kInvalidCookie if
+ // it was not found.
+ ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
+ ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
+ ResTable_ref* out_last_reference);
+
// Retrieves the best matching bag/map resource with ID `resid`.
// This method will resolve all parent references for this bag and merge keys with the child.
// To iterate over the keys, use the following idiom:
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index e8cb164..91a7cb7 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -18,6 +18,7 @@
#define LOADEDARSC_H_
#include <memory>
+#include <set>
#include <vector>
#include "android-base/macros.h"
@@ -68,20 +69,38 @@
LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
uint32_t* out_flags) const;
+ // Returns the string pool where type names are stored.
inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
+ // Returns the string pool where the names of resource entries are stored.
inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
inline const std::string& GetPackageName() const { return package_name_; }
inline int GetPackageId() const { return package_id_; }
+ // Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
inline bool IsDynamic() const { return dynamic_; }
+ // Returns true if this package originates from a system provided resource.
+ inline bool IsSystem() const { return system_; }
+
+ // Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
+ // package could have been assigned a different package ID than what this LoadedPackage was
+ // compiled with. AssetManager rewrites the package IDs so that they are compatible at runtime.
inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
return dynamic_package_map_;
}
+ // Populates a set of ResTable_config structs, possibly excluding configurations defined for
+ // the mipmap type.
+ void CollectConfigurations(bool exclude_mipmap, std::set<ResTable_config>* out_configs) const;
+
+ // Populates a set of strings representing locales.
+ // If `canonicalize` is set to true, each locale is transformed into its canonical format
+ // before being inserted into the set. This may cause some equivalent locales to de-dupe.
+ void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
@@ -93,8 +112,9 @@
ResStringPool key_string_pool_;
std::string package_name_;
int package_id_ = -1;
- bool dynamic_ = false;
int type_id_offset_ = 0;
+ bool dynamic_ = false;
+ bool system_ = false;
ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
@@ -104,10 +124,14 @@
// when loading, including offsets and lengths.
class LoadedArsc {
public:
- // Load the resource table from memory. The data's lifetime must out-live the
- // object returned from this method.
- static std::unique_ptr<LoadedArsc> Load(const void* data, size_t len,
- bool load_as_shared_library = false);
+ // Load a resource table from memory pointed to by `data` of size `len`.
+ // The lifetime of `data` must out-live the LoadedArsc returned from this method.
+ // If `system` is set to true, the LoadedArsc is considered as a system provided resource.
+ // If `load_as_shared_library` is set to true, the application package (0x7f) is treated
+ // as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
+ // ID.
+ static std::unique_ptr<const LoadedArsc> Load(const void* data, size_t len, bool system = false,
+ bool load_as_shared_library = false);
~LoadedArsc();
@@ -125,6 +149,10 @@
// Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
const LoadedPackage* GetPackageForId(uint32_t resid) const;
+ // Returns true if this is a system provided resource.
+ inline bool IsSystem() const { return system_; }
+
+ // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
return packages_;
}
@@ -137,6 +165,7 @@
ResStringPool global_string_pool_;
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
+ bool system_ = false;
};
} // namespace android
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 56c22e6..04a5d95 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1188,6 +1188,8 @@
int compare(const ResTable_config& o) const;
int compareLogical(const ResTable_config& o) const;
+ inline bool operator<(const ResTable_config& o) const { return compare(o) < 0; }
+
// Flags indicating a set of config values. These flag constants must
// match the corresponding ones in android.content.pm.ActivityInfo and
// attrs_manifest.xml.
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index fd96730..96b42bf 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -94,8 +94,12 @@
inline bool operator==(const unique_cptr& o) const { return ptr_ == o.ptr_; }
+ inline bool operator!=(const unique_cptr& o) const { return ptr_ != o.ptr_; }
+
inline bool operator==(std::nullptr_t) const { return ptr_ == nullptr; }
+ inline bool operator!=(std::nullptr_t) const { return ptr_ != nullptr; }
+
private:
DISALLOW_COPY_AND_ASSIGN(unique_cptr);
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 0203712..6b4a719 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -24,7 +24,8 @@
namespace android {
TEST(ApkAssetsTest, LoadApk) {
- std::unique_ptr<ApkAssets> loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ std::unique_ptr<const ApkAssets> loaded_apk =
+ ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
ASSERT_NE(nullptr, loaded_apk);
EXPECT_NE(nullptr, loaded_apk->GetLoadedArsc());
@@ -33,7 +34,7 @@
}
TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
- std::unique_ptr<ApkAssets> loaded_apk =
+ std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
ASSERT_NE(nullptr, loaded_apk);
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index b3c2dc3..273290a 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -38,7 +38,7 @@
static void BM_AssetManagerLoadAssets(benchmark::State& state) {
std::string path = GetTestDataPath() + "/basic/basic.apk";
while (state.KeepRunning()) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(path);
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
AssetManager2 assets;
assets.SetApkAssets({apk.get()});
}
@@ -61,7 +61,7 @@
static void BM_AssetManagerLoadFrameworkAssets(benchmark::State& state) {
std::string path = kFrameworkPath;
while (state.KeepRunning()) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(path);
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
AssetManager2 assets;
assets.SetApkAssets({apk.get()});
}
@@ -84,10 +84,10 @@
static void GetResourceBenchmark(const std::vector<std::string>& paths,
const ResTable_config* config, uint32_t resid,
benchmark::State& state) {
- std::vector<std::unique_ptr<ApkAssets>> apk_assets;
+ std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
std::vector<const ApkAssets*> apk_assets_ptrs;
for (const std::string& path : paths) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(path);
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path);
if (apk == nullptr) {
state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
return;
@@ -187,7 +187,7 @@
BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
static void BM_AssetManagerGetBag(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
if (apk == nullptr) {
state.SkipWithError("Failed to load assets");
return;
@@ -234,4 +234,40 @@
}
BENCHMARK(BM_AssetManagerGetBagOld);
+static void BM_AssetManagerGetResourceLocales(benchmark::State& state) {
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+ if (apk == nullptr) {
+ state.SkipWithError("Failed to load assets");
+ return;
+ }
+
+ AssetManager2 assets;
+ assets.SetApkAssets({apk.get()});
+
+ while (state.KeepRunning()) {
+ std::set<std::string> locales =
+ assets.GetResourceLocales(false /*exclude_system*/, true /*merge_equivalent_languages*/);
+ benchmark::DoNotOptimize(locales);
+ }
+}
+BENCHMARK(BM_AssetManagerGetResourceLocales);
+
+static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
+ AssetManager assets;
+ if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
+ false /*isSystemAssets*/)) {
+ state.SkipWithError("Failed to load assets");
+ return;
+ }
+
+ const ResTable& table = assets.getResources(true);
+
+ while (state.KeepRunning()) {
+ Vector<String8> locales;
+ table.getLocales(&locales, true /*includeSystemLocales*/, true /*mergeEquivalentLangs*/);
+ benchmark::DoNotOptimize(locales);
+ }
+}
+BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
+
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 543456a..557d8d4 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -26,6 +26,7 @@
#include "data/lib_two/R.h"
#include "data/libclient/R.h"
#include "data/styles/R.h"
+#include "data/system/R.h"
namespace app = com::android::app;
namespace appaslib = com::android::appaslib::app;
@@ -59,16 +60,20 @@
appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
ASSERT_NE(nullptr, appaslib_assets_);
+
+ system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/);
+ ASSERT_NE(nullptr, system_assets_);
}
protected:
- std::unique_ptr<ApkAssets> basic_assets_;
- std::unique_ptr<ApkAssets> basic_de_fr_assets_;
- std::unique_ptr<ApkAssets> style_assets_;
- std::unique_ptr<ApkAssets> lib_one_assets_;
- std::unique_ptr<ApkAssets> lib_two_assets_;
- std::unique_ptr<ApkAssets> libclient_assets_;
- std::unique_ptr<ApkAssets> appaslib_assets_;
+ std::unique_ptr<const ApkAssets> basic_assets_;
+ std::unique_ptr<const ApkAssets> basic_de_fr_assets_;
+ std::unique_ptr<const ApkAssets> style_assets_;
+ std::unique_ptr<const ApkAssets> lib_one_assets_;
+ std::unique_ptr<const ApkAssets> lib_two_assets_;
+ std::unique_ptr<const ApkAssets> libclient_assets_;
+ std::unique_ptr<const ApkAssets> appaslib_assets_;
+ std::unique_ptr<const ApkAssets> system_assets_;
};
TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -291,6 +296,131 @@
EXPECT_EQ(0, bag_two->entries[4].cookie);
}
+TEST_F(AssetManager2Test, ResolveReferenceToResource) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_assets_.get()});
+
+ Res_value value;
+ ResTable_config selected_config;
+ uint32_t flags;
+ ApkAssetsCookie cookie =
+ assetmanager.GetResource(basic::R::integer::ref1, false /*may_be_bag*/,
+ 0u /*density_override*/, &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(basic::R::integer::ref2, value.data);
+
+ ResTable_ref last_ref;
+ cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
+ EXPECT_EQ(12000u, value.data);
+ EXPECT_EQ(basic::R::integer::ref2, last_ref.ident);
+}
+
+TEST_F(AssetManager2Test, ResolveReferenceToBag) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_assets_.get()});
+
+ Res_value value;
+ ResTable_config selected_config;
+ uint32_t flags;
+ ApkAssetsCookie cookie =
+ assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/,
+ 0u /*density_override*/, &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(basic::R::array::integerArray1, value.data);
+
+ ResTable_ref last_ref;
+ cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(basic::R::array::integerArray1, value.data);
+ EXPECT_EQ(basic::R::array::integerArray1, last_ref.ident);
+}
+
+static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
+ const ResTable_config& configuration) {
+ return configurations.count(configuration) > 0;
+}
+
+TEST_F(AssetManager2Test, GetResourceConfigurations) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
+
+ std::set<ResTable_config> configurations = assetmanager.GetResourceConfigurations();
+
+ // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
+ // And one extra for the default configuration.
+ EXPECT_EQ(4u, configurations.size());
+
+ ResTable_config expected_config;
+ memset(&expected_config, 0, sizeof(expected_config));
+ expected_config.language[0] = 's';
+ expected_config.language[1] = 'v';
+ EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
+
+ expected_config.language[0] = 'd';
+ expected_config.language[1] = 'e';
+ EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
+
+ expected_config.language[0] = 'f';
+ expected_config.language[1] = 'r';
+ EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
+
+ // Take out the system assets.
+ configurations = assetmanager.GetResourceConfigurations(true /* exclude_system */);
+
+ // We expect de and fr from basic_de_fr assets.
+ EXPECT_EQ(2u, configurations.size());
+
+ expected_config.language[0] = 's';
+ expected_config.language[1] = 'v';
+ EXPECT_FALSE(IsConfigurationPresent(configurations, expected_config));
+
+ expected_config.language[0] = 'd';
+ expected_config.language[1] = 'e';
+ EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
+
+ expected_config.language[0] = 'f';
+ expected_config.language[1] = 'r';
+ EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
+}
+
+TEST_F(AssetManager2Test, GetResourceLocales) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
+
+ std::set<std::string> locales = assetmanager.GetResourceLocales();
+
+ // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
+ EXPECT_EQ(3u, locales.size());
+ EXPECT_GT(locales.count("sv"), 0u);
+ EXPECT_GT(locales.count("de"), 0u);
+ EXPECT_GT(locales.count("fr"), 0u);
+
+ locales = assetmanager.GetResourceLocales(true /*exclude_system*/);
+ // We expect the de and fr locales from basic_de_fr assets.
+ EXPECT_EQ(2u, locales.size());
+ EXPECT_GT(locales.count("de"), 0u);
+ EXPECT_GT(locales.count("fr"), 0u);
+}
+
+TEST_F(AssetManager2Test, GetResourceId) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_assets_.get()});
+
+ EXPECT_EQ(basic::R::layout::main,
+ assetmanager.GetResourceId("com.android.basic:layout/main", "", ""));
+ EXPECT_EQ(basic::R::layout::main,
+ assetmanager.GetResourceId("layout/main", "", "com.android.basic"));
+ EXPECT_EQ(basic::R::layout::main,
+ assetmanager.GetResourceId("main", "layout", "com.android.basic"));
+}
+
TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index f8aa61a..756869f 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -32,7 +32,8 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk", "resources.arsc",
&contents));
- std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size());
ASSERT_NE(nullptr, loaded_arsc);
const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
@@ -58,7 +59,8 @@
ASSERT_TRUE(
ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
- std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size());
ASSERT_NE(nullptr, loaded_arsc);
ResTable_config desired_config;
@@ -80,7 +82,8 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
&contents));
- std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size());
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -101,7 +104,8 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/libclient/libclient.apk",
"resources.arsc", &contents));
- std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size());
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -128,8 +132,8 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
"resources.arsc", &contents));
- std::unique_ptr<LoadedArsc> loaded_arsc =
- LoadedArsc::Load(contents.data(), contents.size(), true /*load_as_shared_library*/);
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(
+ contents.data(), contents.size(), false /*system*/, true /*load_as_shared_library*/);
ASSERT_NE(nullptr, loaded_arsc);
const auto& packages = loaded_arsc->GetPackages();
@@ -143,7 +147,8 @@
std::string contents;
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
&contents));
- std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ std::unique_ptr<const LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size());
ASSERT_NE(nullptr, loaded_arsc);
ResTable_config desired_config;
diff --git a/libs/androidfw/tests/Theme_bench.cpp b/libs/androidfw/tests/Theme_bench.cpp
index c471be6..594c39e 100644
--- a/libs/androidfw/tests/Theme_bench.cpp
+++ b/libs/androidfw/tests/Theme_bench.cpp
@@ -28,7 +28,7 @@
constexpr const static uint32_t kAttrId = 0x01010030u; // android:attr/colorForeground
static void BM_ThemeApplyStyleFramework(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
if (apk == nullptr) {
state.SkipWithError("Failed to load assets");
return;
@@ -62,7 +62,7 @@
BENCHMARK(BM_ThemeApplyStyleFrameworkOld);
static void BM_ThemeGetAttribute(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
+ std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
AssetManager2 assets;
assets.SetApkAssets({apk.get()});
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index 59cb18a..daed28b 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -46,10 +46,10 @@
}
protected:
- std::unique_ptr<ApkAssets> style_assets_;
- std::unique_ptr<ApkAssets> libclient_assets_;
- std::unique_ptr<ApkAssets> lib_one_assets_;
- std::unique_ptr<ApkAssets> lib_two_assets_;
+ std::unique_ptr<const ApkAssets> style_assets_;
+ std::unique_ptr<const ApkAssets> libclient_assets_;
+ std::unique_ptr<const ApkAssets> lib_one_assets_;
+ std::unique_ptr<const ApkAssets> lib_two_assets_;
};
TEST_F(ThemeTest, EmptyTheme) {
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 9352b5c..8e9741e 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -53,6 +53,8 @@
enum : uint32_t {
number1 = 0x7f040000,
number2 = 0x7f040001,
+ ref1 = 0x7f040002,
+ ref2 = 0x7f040003,
// From feature
number3 = 0x7f090000,
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 2c9771b..7ee6734 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_de_fr.apk b/libs/androidfw/tests/data/basic/basic_de_fr.apk
index 0481444..e45258c 100644
--- a/libs/androidfw/tests/data/basic/basic_de_fr.apk
+++ b/libs/androidfw/tests/data/basic/basic_de_fr.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
index a8d06e7..4ae1a7c 100644
--- a/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
+++ b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
index d1dfb14..a240d4c 100644
--- a/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
+++ b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
index dca6f2f..fd3d9b2 100644
--- a/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
+++ b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index 11f6b8a..638c983 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -37,6 +37,12 @@
<public type="integer" name="number2" id="0x7f040001" />
<integer name="number2">@array/integerArray1</integer>
+ <public type="integer" name="ref1" id="0x7f040002" />
+ <integer name="ref1">@integer/ref2</integer>
+
+ <public type="integer" name="ref2" id="0x7f040003" />
+ <integer name="ref2">12000</integer>
+
<public type="style" name="Theme1" id="0x7f050000" />
<style name="Theme1">
<item name="com.android.basic:attr1">100</item>
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index ee77643..415e850 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -169,13 +169,15 @@
void DeferredLayerUpdater::detachSurfaceTexture() {
if (mSurfaceTexture.get()) {
- if (mLayer->getApi() == Layer::Api::OpenGL) {
+ if (mLayerApi == Layer::Api::OpenGL) {
status_t err = mSurfaceTexture->detachFromContext();
if (err != 0) {
// TODO: Elevate to fatal exception
ALOGE("Failed to detach SurfaceTexture from context %d", err);
}
- static_cast<GlLayer*>(mLayer)->clearTexture();
+ if (mLayer) {
+ static_cast<GlLayer*>(mLayer)->clearTexture();
+ }
}
mSurfaceTexture = nullptr;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 5c9f270..cd38b50 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -27,6 +27,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
import android.os.Handler;
@@ -538,6 +539,15 @@
throw new IllegalArgumentException("Illegal null AudioFormat");
}
+ // Check if we should enable deep buffer mode
+ if (shouldEnablePowerSaving(mAttributes, format, bufferSizeInBytes, mode)) {
+ mAttributes = new AudioAttributes.Builder(mAttributes)
+ .replaceFlags((mAttributes.getAllFlags()
+ | AudioAttributes.FLAG_DEEP_BUFFER)
+ & ~AudioAttributes.FLAG_LOW_LATENCY)
+ .build();
+ }
+
// remember which looper is associated with the AudioTrack instantiation
Looper looper;
if ((looper = Looper.myLooper()) == null) {
@@ -861,7 +871,10 @@
.build();
break;
case PERFORMANCE_MODE_NONE:
- break;
+ if (!shouldEnablePowerSaving(mAttributes, mFormat, mBufferSizeInBytes, mMode)) {
+ break; // do not enable deep buffer mode.
+ }
+ // permitted to fall through to enable deep buffer
case PERFORMANCE_MODE_POWER_SAVING:
mAttributes = new AudioAttributes.Builder(mAttributes)
.replaceFlags((mAttributes.getAllFlags()
@@ -912,6 +925,56 @@
AudioFormat.CHANNEL_OUT_SIDE_LEFT |
AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
+ // Returns a boolean whether the attributes, format, bufferSizeInBytes, mode allow
+ // power saving to be automatically enabled for an AudioTrack. Returns false if
+ // power saving is already enabled in the attributes parameter.
+ private static boolean shouldEnablePowerSaving(
+ @Nullable AudioAttributes attributes, @Nullable AudioFormat format,
+ int bufferSizeInBytes, int mode) {
+ // If no attributes, OK
+ // otherwise check attributes for USAGE_MEDIA and CONTENT_UNKNOWN, MUSIC, or MOVIE.
+ if (attributes != null &&
+ (attributes.getAllFlags() != 0 // cannot have any special flags
+ || attributes.getUsage() != AudioAttributes.USAGE_MEDIA
+ || (attributes.getContentType() != AudioAttributes.CONTENT_TYPE_UNKNOWN
+ && attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MUSIC
+ && attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MOVIE))) {
+ return false;
+ }
+
+ // Format must be fully specified and be linear pcm
+ if (format == null
+ || format.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED
+ || !AudioFormat.isEncodingLinearPcm(format.getEncoding())
+ || !AudioFormat.isValidEncoding(format.getEncoding())
+ || format.getChannelCount() < 1) {
+ return false;
+ }
+
+ // Mode must be streaming
+ if (mode != MODE_STREAM) {
+ return false;
+ }
+
+ // A buffer size of 0 is always compatible with deep buffer (when called from the Builder)
+ // but for app compatibility we only use deep buffer power saving for large buffer sizes.
+ if (bufferSizeInBytes != 0) {
+ final long BUFFER_TARGET_MODE_STREAM_MS = 100;
+ final int MILLIS_PER_SECOND = 1000;
+ final long bufferTargetSize =
+ BUFFER_TARGET_MODE_STREAM_MS
+ * format.getChannelCount()
+ * format.getBytesPerSample(format.getEncoding())
+ * format.getSampleRate()
+ / MILLIS_PER_SECOND;
+ if (bufferSizeInBytes < bufferTargetSize) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
// Convenience method for the constructor's parameter checks.
// This is where constructor IllegalArgumentException-s are thrown
// postconditions:
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 9a08fbe..b0df0e4 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -29,6 +30,8 @@
import android.text.TextUtils;
import android.util.ArraySet;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -372,6 +375,37 @@
/** The MIME type of a single TV channel. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
+ /** @hide */
+ @StringDef({
+ TYPE_OTHER,
+ TYPE_NTSC,
+ TYPE_PAL,
+ TYPE_SECAM,
+ TYPE_DVB_T,
+ TYPE_DVB_T2,
+ TYPE_DVB_S,
+ TYPE_DVB_S2,
+ TYPE_DVB_C,
+ TYPE_DVB_C2,
+ TYPE_DVB_H,
+ TYPE_DVB_SH,
+ TYPE_ATSC_T,
+ TYPE_ATSC_C,
+ TYPE_ATSC_M_H,
+ TYPE_ISDB_T,
+ TYPE_ISDB_TB,
+ TYPE_ISDB_S,
+ TYPE_ISDB_C,
+ TYPE_1SEG,
+ TYPE_DTMB,
+ TYPE_CMMB,
+ TYPE_T_DMB,
+ TYPE_S_DMB,
+ TYPE_PREVIEW,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
/**
* A generic channel type.
*
@@ -554,6 +588,15 @@
*/
public static final String TYPE_PREVIEW = "TYPE_PREVIEW";
+ /** @hide */
+ @StringDef({
+ SERVICE_TYPE_OTHER,
+ SERVICE_TYPE_AUDIO_VIDEO,
+ SERVICE_TYPE_AUDIO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ServiceType {}
+
/** A generic service type. */
public static final String SERVICE_TYPE_OTHER = "SERVICE_TYPE_OTHER";
@@ -563,6 +606,22 @@
/** The service type for radio channels that have audio only. */
public static final String SERVICE_TYPE_AUDIO = "SERVICE_TYPE_AUDIO";
+ /** @hide */
+ @StringDef({
+ VIDEO_FORMAT_240P,
+ VIDEO_FORMAT_360P,
+ VIDEO_FORMAT_480I,
+ VIDEO_FORMAT_576I,
+ VIDEO_FORMAT_576P,
+ VIDEO_FORMAT_720P,
+ VIDEO_FORMAT_1080I,
+ VIDEO_FORMAT_1080P,
+ VIDEO_FORMAT_2160P,
+ VIDEO_FORMAT_4320P,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VideoFormat {}
+
/** The video format for 240p. */
public static final String VIDEO_FORMAT_240P = "VIDEO_FORMAT_240P";
@@ -596,6 +655,17 @@
/** The video format for 4320p. */
public static final String VIDEO_FORMAT_4320P = "VIDEO_FORMAT_4320P";
+ /** @hide */
+ @StringDef({
+ VIDEO_RESOLUTION_SD,
+ VIDEO_RESOLUTION_ED,
+ VIDEO_RESOLUTION_HD,
+ VIDEO_RESOLUTION_FHD,
+ VIDEO_RESOLUTION_UHD,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VideoResolution {}
+
/** The video resolution for standard-definition. */
public static final String VIDEO_RESOLUTION_SD = "VIDEO_RESOLUTION_SD";
@@ -634,7 +704,7 @@
* @see #COLUMN_VIDEO_FORMAT
*/
@Nullable
- public static final String getVideoResolution(String videoFormat) {
+ public static final String getVideoResolution(@VideoFormat String videoFormat) {
return VIDEO_FORMAT_TO_RESOLUTION_MAP.get(videoFormat);
}
@@ -1026,6 +1096,19 @@
@SystemApi
public static final String COLUMN_TRANSIENT = "transient";
+ /**
+ * The flag indicating whether this TV channel is approved to be shown by the system.
+ *
+ * <p>A value of 1 indicates that the channel is approved to be shown by the system, and a
+ * value of 0 indicates that the channel is blocked by system. If not specified, this value
+ * is set to 0 (not approved) by default.
+ *
+ * <p>Type: INTEGER (boolean)
+ * @hide
+ */
+ @SystemApi
+ public static final String COLUMN_SYSTEM_APPROVED = "system_approved";
+
private Channels() {}
/**
@@ -1087,6 +1170,24 @@
/** The MIME type of a single TV program. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
+ /** @hide */
+ @StringDef({
+ TYPE_MOVIE,
+ TYPE_TV_SERIES,
+ TYPE_TV_SEASON,
+ TYPE_TV_EPISODE,
+ TYPE_CLIP,
+ TYPE_EVENT,
+ TYPE_CHANNEL,
+ TYPE_TRACK,
+ TYPE_ALBUM,
+ TYPE_ARTIST,
+ TYPE_PLAYLIST,
+ TYPE_STATION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
/**
* The program type for movie.
*
@@ -1171,6 +1272,15 @@
*/
public static final String TYPE_STATION = "TYPE_STATION";
+ /** @hide */
+ @StringDef({
+ WATCH_NEXT_TYPE_CONTINUE,
+ WATCH_NEXT_TYPE_NEXT,
+ WATCH_NEXT_TYPE_NEW,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WatchNextType {}
+
/**
* The watch next type for CONTINUE.
*
@@ -1192,6 +1302,16 @@
*/
public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+ /** @hide */
+ @StringDef({
+ ASPECT_RATIO_16_9,
+ ASPECT_RATIO_3_2,
+ ASPECT_RATIO_1_1,
+ ASPECT_RATIO_2_3,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AspectRatio {}
+
/**
* The aspect ratio for 16:9.
*
@@ -1224,6 +1344,15 @@
*/
public static final String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+ /** @hide */
+ @StringDef({
+ AVAILABILITY_AVAILABLE,
+ AVAILABILITY_FREE_WITH_SUBSCRIPTION,
+ AVAILABILITY_PAID_CONTENT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Availability {}
+
/**
* The availability for "available to this user".
*
@@ -1247,6 +1376,19 @@
*/
public static final String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+ /** @hide */
+ @StringDef({
+ INTERACTION_TYPE_LISTENS,
+ INTERACTION_TYPE_FOLLOWERS,
+ INTERACTION_TYPE_FANS,
+ INTERACTION_TYPE_LIKES,
+ INTERACTION_TYPE_THUMBS,
+ INTERACTION_TYPE_VIEWS,
+ INTERACTION_TYPE_VIEWERS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InteractionType {}
+
/**
* The interaction type for "listens".
*
@@ -1296,6 +1438,15 @@
*/
public static final String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+ /** @hide */
+ @StringDef({
+ REVIEW_RATING_STYLE_STARS,
+ REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
+ REVIEW_RATING_STYLE_PERCENTAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ReviewRatingStyle {}
+
/**
* The review rating style for five star rating.
*
@@ -1665,7 +1816,7 @@
*
* <p>Type: TEXT
*/
- public static final String COLUMN_LOGO = "logo";
+ public static final String COLUMN_LOGO_URI = "logo_uri";
/**
* The availability of this TV program.
@@ -1860,8 +2011,8 @@
*
* <p>Type: INTEGER
*/
- public static final String COLUMN_PREVIEW_LAST_PLAYBACK_POSITION =
- "preview_last_playback_position";
+ public static final String COLUMN_LAST_PLAYBACK_POSITION_MILLIS =
+ "last_playback_position_millis";
/**
* The duration (in milliseconds) of the preview video.
@@ -1872,7 +2023,7 @@
*
* <p>Type: INTEGER
*/
- public static final String COLUMN_PREVIEW_DURATION = "preview_duration";
+ public static final String COLUMN_DURATION_MILLIS = "duration_millis";
/**
* The intent URI which is launched when the preview video is selected.
@@ -1885,8 +2036,8 @@
*
* <p>Type: TEXT
*/
- public static final String COLUMN_PREVIEW_INTENT_URI =
- "preview_intent_uri";
+ public static final String COLUMN_APP_LINK_INTENT_URI =
+ "app_link_intent_uri";
/**
* The weight of the preview program within the channel.
@@ -1900,7 +2051,7 @@
*
* <p>Type: INTEGER
*/
- public static final String COLUMN_PREVIEW_WEIGHT = "preview_weight";
+ public static final String COLUMN_WEIGHT = "weight";
/**
* The flag indicating whether this program is transient or not.
@@ -1981,6 +2132,29 @@
/** Canonical genres for TV programs. */
public static final class Genres {
+ /** @hide */
+ @StringDef({
+ FAMILY_KIDS,
+ SPORTS,
+ SHOPPING,
+ MOVIES,
+ COMEDY,
+ TRAVEL,
+ DRAMA,
+ EDUCATION,
+ ANIMAL_WILDLIFE,
+ NEWS,
+ GAMING,
+ ARTS,
+ ENTERTAINMENT,
+ LIFE_STYLE,
+ MUSIC,
+ PREMIER,
+ TECH_SCIENCE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Genre {}
+
/** The genre for Family/Kids. */
public static final String FAMILY_KIDS = "FAMILY_KIDS";
@@ -2068,7 +2242,7 @@
* @return an encoded genre string that can be inserted into the
* {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
*/
- public static String encode(@NonNull String... genres) {
+ public static String encode(@NonNull @Genre String... genres) {
if (genres == null) {
// MNC and before will throw a NPE.
return null;
@@ -2107,7 +2281,7 @@
* {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
* @return genre strings.
*/
- public static String[] decode(@NonNull String genres) {
+ public static @Genre String[] decode(@NonNull String genres) {
if (TextUtils.isEmpty(genres)) {
// MNC and before will throw a NPE for {@code null} genres.
return EMPTY_STRING_ARRAY;
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 355f52e..f510b48 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -1,6 +1,8 @@
BASE_PATH := $(call my-dir)
LOCAL_PATH:= $(call my-dir)
+common_cflags := -Wall -Werror -Wunused -Wunreachable-code
+
include $(CLEAR_VARS)
# our source files
@@ -43,6 +45,23 @@
LOCAL_MODULE := libandroid
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_CFLAGS += $(common_cflags)
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Network library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libandroid_net
+LOCAL_CFLAGS := $(common_cflags)
+LOCAL_SRC_FILES:= \
+ net.c \
+
+LOCAL_SHARED_LIBRARIES := \
+ libnetd_client \
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/native/include \
+ bionic/libc/dns/include \
+ system/netd/include \
include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index d71b6bd..dd1614b 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -51,9 +51,6 @@
private static final String TAG = "PluginInstanceManager";
private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
- // must be one of the channels created in NotificationChannels.java
- private static final String NOTIFICATION_CHANNEL_ID = "ALR";
-
private final Context mContext;
private final PluginListener<T> mListener;
private final String mAction;
@@ -310,14 +307,14 @@
mContext.getPackageName());
final int color = Resources.getSystem().getIdentifier(
"system_notification_accent_color", "color", "android");
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setStyle(new Notification.BigTextStyle())
- .setSmallIcon(icon)
- .setWhen(0)
- .setShowWhen(false)
- .setChannel(NOTIFICATION_CHANNEL_ID)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(color));
+ final Notification.Builder nb = new Notification.Builder(mContext,
+ PluginManager.NOTIFICATION_CHANNEL_ID)
+ .setStyle(new Notification.BigTextStyle())
+ .setSmallIcon(icon)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(color));
String label = cls;
try {
label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
index f4adc93..cef485e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
@@ -55,6 +55,9 @@
static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN";
+ // must be one of the channels created in NotificationChannels.java
+ static final String NOTIFICATION_CHANNEL_ID = "ALR";
+
private static PluginManager sInstance;
private final HandlerThread mBackgroundThread;
@@ -191,15 +194,16 @@
} catch (NameNotFoundException e) {
}
// Localization not required as this will never ever appear in a user build.
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setSmallIcon(icon)
- .setWhen(0)
- .setShowWhen(false)
- .setPriority(Notification.PRIORITY_MAX)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(color))
- .setContentTitle("Plugin \"" + label + "\" has updated")
- .setContentText("Restart SysUI for changes to take effect.");
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(icon)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(color))
+ .setContentTitle("Plugin \"" + label + "\" has updated")
+ .setContentText("Restart SysUI for changes to take effect.");
Intent i = new Intent("com.android.systemui.action.RESTART").setData(
Uri.parse("package://" + pkg));
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
diff --git a/packages/SystemUI/res/drawable/pip_dismiss_background.xml b/packages/SystemUI/res/drawable/pip_dismiss_background.xml
index 3a75296..8f50231 100644
--- a/packages/SystemUI/res/drawable/pip_dismiss_background.xml
+++ b/packages/SystemUI/res/drawable/pip_dismiss_background.xml
@@ -1,22 +1,22 @@
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2017 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <corners
- android:radius="100dp" />
- <solid
- android:color="#66000000" />
+ android:shape="rectangle">
+ <gradient
+ android:startColor="#B3000000"
+ android:endColor="#00000000"
+ android:angle="90"/>
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml
index 141e610..f02a56c 100644
--- a/packages/SystemUI/res/layout/pip_dismiss_view.xml
+++ b/packages/SystemUI/res/layout/pip_dismiss_view.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!--
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,12 +14,44 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pip_dismiss_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/pip_dismiss_background"
- android:foreground="@drawable/pip_dismiss"
- android:alpha="0"
- android:forceHasOverlappingRendering="false" />
+ android:alpha="0">
+
+ <!-- The height of the below view needs to be animated from a window
+ so it needs to be in a container to resize smoothly -->
+ <View
+ android:id="@+id/gradient_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="bottom"
+ android:background="@drawable/pip_dismiss_background" />
+
+ <LinearLayout
+ android:id="@+id/pip_dismiss_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:orientation="horizontal"
+ android:paddingBottom="32dp" >
+
+ <ImageView
+ android:id="@+id/pip_dismiss_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:padding="2dp"
+ android:src="@drawable/pip_dismiss"
+ android:tint="#FFFFFFFF" />
+
+ <TextView
+ android:id="@+id/pip_dismiss_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/pip_phone_close"
+ android:textColor="#FFFFFFFF"
+ android:textSize="16sp" />
+ </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index cf65f4a..0f5ca9b 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -27,7 +27,7 @@
android:layout_height="48dp"
android:layout_gravity="top|end"
android:padding="10dp"
- android:contentDescription="@string/pip_phone_dismiss"
+ android:contentDescription="@string/pip_phone_close"
android:src="@drawable/ic_close_white"
android:background="?android:selectableItemBackgroundBorderless" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 919f292..b768f90 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -69,6 +69,9 @@
<!-- Height of a small notification in the status bar-->
<dimen name="notification_min_height">92dp</dimen>
+ <!-- Height of a small notification in the status bar if it is a large (like messaging)-->
+ <dimen name="notification_min_height_large">132dp</dimen>
+
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d3e965a..363b3e2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1746,8 +1746,8 @@
<!-- Label for PIP action to Minimize the PIP [CHAR LIMIT=25] -->
<string name="pip_phone_minimize">Minimize</string>
- <!-- Label for PIP action to Dismiss the PIP -->
- <string name="pip_phone_dismiss">Dismiss</string>
+ <!-- Label for PIP the drag to close zone [CHAR LIMIT=NONE]-->
+ <string name="pip_phone_close">Close</string>
<!-- PIP section of the tuner. Non-translatable since it should
not appear on production builds ever. -->
@@ -1802,10 +1802,8 @@
<string name="notification_channel_alerts">Alerts</string>
<!-- Title for the notification channel dedicated to screenshot progress. [CHAR LIMIT=NONE] -->
<string name="notification_channel_screenshot">Screenshots</string>
- <!-- Title for the notification channel for urgent security issues. [CHAR LIMIT=NONE] -->
- <string name="notification_channel_security">Security</string>
- <!-- Title for the notification channel containing multi-user status information. [CHAR LIMIT=NONE] -->
- <string name="notification_channel_user_status">User status</string>
+ <!-- Title for the notification channel for miscellaneous notices. [CHAR LIMIT=NONE] -->
+ <string name="notification_channel_general">General Messages</string>
<!-- Title for the notification channel for problems with storage (i.e. low disk). [CHAR LIMIT=NONE] -->
<string name="notification_channel_storage">Storage</string>
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 94b2fdb..9b74cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -21,11 +21,10 @@
import android.view.View;
public interface RecentsComponent {
- void showRecents(boolean triggeredFromAltTab, boolean fromHome);
- void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+ void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
+ void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecents(Display display);
void preloadRecents();
- void cancelPreloadingRecents();
void showNextAffiliatedTask();
void showPrevAffiliatedTask();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index a7ac719..e182176 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -17,13 +17,19 @@
package com.android.systemui.pip.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.TouchDelegate;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.FrameLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -35,12 +41,22 @@
private static final int SHOW_TARGET_DELAY = 100;
private static final int SHOW_TARGET_DURATION = 200;
+ private static final float DISMISS_TEXT_MAX_SCALE = 2f;
+ private static final float DISMISS_GRADIENT_MIN_HEIGHT_PERCENT = 0.33f;
+ private static final float DISMISS_GRADIENT_MAX_HEIGHT_PERCENT = 0.5f;
+ private static final float DISMISS_THRESHOLD = 0.55f;
+
private Context mContext;
private WindowManager mWindowManager;
private View mDismissView;
private Rect mDismissTargetScreenBounds = new Rect();
+ private View mDismissContainer;
+ private View mGradientView;
+ private float mMinHeight;
+ private float mMaxHeight;
+
public PipDismissViewController(Context context) {
mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -51,25 +67,37 @@
*/
public void createDismissTarget() {
if (mDismissView == null) {
+ // Determine sizes for the gradient
+ Point windowSize = new Point();
+ mWindowManager.getDefaultDisplay().getSize(windowSize);
+ mMinHeight = windowSize.y * DISMISS_GRADIENT_MIN_HEIGHT_PERCENT;
+ mMaxHeight = windowSize.y * DISMISS_GRADIENT_MAX_HEIGHT_PERCENT;
+
// Create a new view for the dismiss target
- int dismissTargetSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.pip_dismiss_target_size);
LayoutInflater inflater = LayoutInflater.from(mContext);
mDismissView = inflater.inflate(R.layout.pip_dismiss_view, null);
- mDismissView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ mGradientView = mDismissView.findViewById(R.id.gradient_view);
+ FrameLayout.LayoutParams glp = (android.widget.FrameLayout.LayoutParams) mGradientView
+ .getLayoutParams();
+ glp.height = (int) mMaxHeight;
+ mGradientView.setLayoutParams(glp);
+ mGradientView.setPivotY(windowSize.y);
+ mGradientView.setScaleY(mMaxHeight / mMinHeight); // Set to min height via scaling
+ mDismissContainer = mDismissView.findViewById(R.id.pip_dismiss_container);
+ mDismissContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
- if (mDismissView != null) {
- mDismissView.getBoundsOnScreen(mDismissTargetScreenBounds);
+ if (mDismissContainer != null) {
+ mDismissContainer.getBoundsOnScreen(mDismissTargetScreenBounds);
}
}
});
// Add the target to the window
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- dismissTargetSize,
- dismissTargetSize,
+ windowSize.x,
+ (int) mMaxHeight,
WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
@@ -84,7 +112,8 @@
/**
* Shows the dismiss target.
*/
- public void showDismissTarget() {
+ public void showDismissTarget(Rect pinnedStack) {
+ updateDismissTarget(pinnedStack);
mDismissView.animate()
.alpha(1f)
.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
@@ -115,10 +144,46 @@
}
/**
+ * Updates the appearance of the dismiss target based on how close the PIP is.
+ */
+ public void updateDismissTarget(Rect pinnedStack) {
+ // As PIP moves over / away from delete target it grows / shrinks
+ final float scalePercent = calculateDistancePercent(pinnedStack);
+ final float newScale = 1 + (DISMISS_TEXT_MAX_SCALE - 1) * scalePercent;
+ final float minGradientScale = mMinHeight / mMaxHeight;
+ final float newHeight = Math.max(minGradientScale, scalePercent);
+ mGradientView.setScaleY(newHeight);
+ mDismissContainer.setScaleX(newScale);
+ mDismissContainer.setScaleY(newScale);
+ }
+
+ /**
+ * @return the percentage of distance the PIP is away from the dismiss target point.
+ */
+ private float calculateDistancePercent(Rect pinnedStack) {
+ final int distance = mDismissTargetScreenBounds.height();
+ final int textX = mDismissTargetScreenBounds.centerX();
+ final int textY = mDismissTargetScreenBounds.bottom;
+ final float pipCurrX = pinnedStack.centerX();
+ final float pipCurrY = pinnedStack.bottom;
+ final float currentDistance = PointF.length(pipCurrX - textX, pipCurrY - textY);
+ if (currentDistance <= distance) {
+ return 1 - (currentDistance / distance);
+ }
+ return 0;
+ }
+
+ /**
* @return the dismiss target screen bounds.
*/
public Rect getDismissBounds() {
return mDismissTargetScreenBounds;
}
+ /**
+ * @return whether the PIP is positioned on the dismiss target enough to be dismissed.
+ */
+ public boolean shouldDismiss(Rect pinnedStack) {
+ return calculateDistancePercent(pinnedStack) >= DISMISS_THRESHOLD;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c7b15ef..10393c6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -33,6 +33,7 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
@@ -72,6 +73,7 @@
private static final int DISMISS_STACK_DURATION = 375;
private static final int EXPAND_STACK_DURATION = 225;
private static final int MINIMIZE_STACK_MAX_DURATION = 200;
+ private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
// The fraction of the stack width that the user has to drag offscreen to minimize the PIP
private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
@@ -106,6 +108,16 @@
}
};
+ private Handler mHandler = new Handler();
+ private Runnable mShowDismissAffordance = new Runnable() {
+ @Override
+ public void run() {
+ if (mEnableDragToDismiss) {
+ mDismissViewController.showDismissTarget(mPinnedStackBounds);
+ }
+ }
+ };
+
// Behaviour states
private boolean mIsTappingThrough;
private boolean mIsMinimized;
@@ -194,7 +206,7 @@
mTouchState = new PipTouchState(mViewConfig);
mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
mGestures = new PipTouchGesture[] {
- mDragToDismissGesture, mDefaultMovementGesture
+ mDefaultMovementGesture
};
mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
registerInputConsumer();
@@ -522,6 +534,9 @@
private void movePinnedStack(Rect bounds) {
if (!bounds.equals(mPinnedStackBounds)) {
mPinnedStackBounds.set(bounds);
+ if (mEnableDragToDismiss) {
+ mDismissViewController.updateDismissTarget(bounds);
+ }
mMotionHelper.resizeToBounds(mPinnedStackBounds);
}
}
@@ -564,57 +579,25 @@
}
/**
- * Gesture controlling dragging over a target to dismiss the PIP.
- */
- private PipTouchGesture mDragToDismissGesture = new PipTouchGesture() {
- @Override
- public void onDown(PipTouchState touchState) {
- if (mEnableDragToDismiss) {
- // TODO: Consider setting a timer such at after X time, we show the dismiss
- // target if the user hasn't already dragged some distance
- mDismissViewController.createDismissTarget();
- }
- }
-
- @Override
- boolean onMove(PipTouchState touchState) {
- if (mEnableDragToDismiss && touchState.startedDragging()) {
- mDismissViewController.showDismissTarget();
- }
- return false;
- }
-
- @Override
- public boolean onUp(PipTouchState touchState) {
- if (mEnableDragToDismiss) {
- try {
- if (touchState.isDragging()) {
- Rect dismissBounds = mDismissViewController.getDismissBounds();
- PointF lastTouch = touchState.getLastTouchPosition();
- if (dismissBounds.contains((int) lastTouch.x, (int) lastTouch.y)) {
- animateDismissPinnedStack(dismissBounds);
- MetricsLogger.action(mContext,
- MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
- METRIC_VALUE_DISMISSED_BY_DRAG);
- return true;
- }
- }
- } finally {
- mDismissViewController.destroyDismissTarget();
- }
- }
- return false;
- }
- };
-
- /**** Gestures ****/
-
- /**
* Gesture controlling normal movement of the PIP.
*/
private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
+
+ @Override
+ public void onDown(PipTouchState touchState) {
+ if (mEnableDragToDismiss) {
+ mDismissViewController.createDismissTarget();
+ mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
+ }
+ }
+
@Override
boolean onMove(PipTouchState touchState) {
+ if (touchState.startedDragging() && mEnableDragToDismiss) {
+ mHandler.removeCallbacks(mShowDismissAffordance);
+ mDismissViewController.showDismissTarget(mPinnedStackBounds);
+ }
+
if (touchState.isDragging()) {
// Move the pinned stack freely
PointF lastDelta = touchState.getLastTouchDelta();
@@ -636,6 +619,23 @@
@Override
public boolean onUp(PipTouchState touchState) {
+ try {
+ if (mEnableDragToDismiss) {
+ mHandler.removeCallbacks(mShowDismissAffordance);
+ PointF vel = mTouchState.getVelocity();
+ final float velocity = PointF.length(vel.x, vel.y);
+ if (touchState.isDragging()
+ && velocity < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ if (mDismissViewController.shouldDismiss(mPinnedStackBounds)) {
+ Rect dismissBounds = mDismissViewController.getDismissBounds();
+ animateDismissPinnedStack(dismissBounds);
+ return true;
+ }
+ }
+ }
+ } finally {
+ mDismissViewController.destroyDismissTarget();
+ }
if (touchState.isDragging()) {
PointF vel = mTouchState.getVelocity();
if (!mIsMinimized && (shouldMinimizedPinnedStack()
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 82ec69d..09ce2ad 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -145,16 +145,16 @@
}
private void showInvalidChargerNotification() {
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_power_low)
- .setWhen(0)
- .setShowWhen(false)
- .setOngoing(true)
- .setContentTitle(mContext.getString(R.string.invalid_charger_title))
- .setContentText(mContext.getString(R.string.invalid_charger_text))
- .setChannel(NotificationChannels.ALERTS)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color));
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NotificationChannels.ALERTS)
+ .setSmallIcon(R.drawable.ic_power_low)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setOngoing(true)
+ .setContentTitle(mContext.getString(R.string.invalid_charger_title))
+ .setContentText(mContext.getString(R.string.invalid_charger_text))
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
@@ -164,19 +164,19 @@
private void showWarningNotification() {
final int textRes = R.string.battery_low_percent_format;
final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0);
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_power_low)
- // Bump the notification when the bucket dropped.
- .setWhen(mBucketDroppedNegativeTimeMs)
- .setShowWhen(false)
- .setContentTitle(mContext.getString(R.string.battery_low_title))
- .setContentText(mContext.getString(textRes, percentage))
- .setOnlyAlertOnce(true)
- .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
- .setChannel(NotificationChannels.ALERTS)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NotificationChannels.ALERTS)
+ .setSmallIcon(R.drawable.ic_power_low)
+ // Bump the notification when the bucket dropped.
+ .setWhen(mBucketDroppedNegativeTimeMs)
+ .setShowWhen(false)
+ .setContentTitle(mContext.getString(R.string.battery_low_title))
+ .setContentText(mContext.getString(textRes, percentage))
+ .setOnlyAlertOnce(true)
+ .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.battery_saver_mode_color));
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
}
@@ -235,18 +235,18 @@
return;
}
mTempWarning = true;
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_device_thermostat_24)
- .setWhen(0)
- .setShowWhen(false)
- .setContentTitle(mContext.getString(R.string.high_temp_title))
- .setContentText(mContext.getString(R.string.high_temp_notif_message))
- .setChannel(NotificationChannels.ALERTS)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
- .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NotificationChannels.ALERTS)
+ .setSmallIcon(R.drawable.ic_device_thermostat_24)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setContentTitle(mContext.getString(R.string.high_temp_title))
+ .setContentText(mContext.getString(R.string.high_temp_notif_message))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
+ .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.battery_saver_mode_color));
SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 8d18a75..9157e33 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents;
+import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
+
import android.app.ActivityManager;
import android.app.UiModeManager;
import android.content.ComponentName;
@@ -38,6 +40,7 @@
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
+import android.view.WindowManager;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
@@ -59,6 +62,7 @@
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.tv.RecentsTvImpl;
import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import java.util.ArrayList;
import java.util.HashSet;
@@ -70,7 +74,7 @@
* users.
*/
public class Recents extends SystemUI
- implements RecentsComponent {
+ implements RecentsComponent, CommandQueue.Callbacks {
private final static String TAG = "Recents";
private final static boolean DEBUG = false;
@@ -201,6 +205,7 @@
sTaskLoader = new RecentsTaskLoader(mContext);
sConfiguration = new RecentsConfiguration(mContext);
mHandler = new Handler();
+ getComponent(CommandQueue.class).addCallbacks(this);
UiModeManager uiModeManager = (UiModeManager) mContext.
getSystemService(Context.UI_MODE_SERVICE);
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
@@ -247,7 +252,7 @@
* Shows the Recents.
*/
@Override
- public void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
+ public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
@@ -257,6 +262,10 @@
if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
return;
}
+ try {
+ ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_RECENT_APPS);
+ } catch (RemoteException e) {
+ }
int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
@@ -287,7 +296,7 @@
* Hides the Recents.
*/
@Override
- public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+ public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
@@ -318,6 +327,11 @@
}
}
+ @Override
+ public void toggleRecentApps() {
+ toggleRecents(mContext.getSystemService(WindowManager.class).getDefaultDisplay());
+ }
+
/**
* Toggles the Recents activity.
*/
@@ -387,7 +401,7 @@
}
@Override
- public void cancelPreloadingRecents() {
+ public void cancelPreloadRecentApps() {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 9a8b267..609e3fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -53,6 +53,7 @@
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
@@ -311,15 +312,23 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
- // If the user taps quickly
- if (!debugFlags.isPagingEnabled() ||
- (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
- elapsedTime < ViewConfiguration.getDoubleTapTimeout())) {
- // Launch the next focused task
- EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
+ // Has the user tapped quickly?
+ boolean isQuickTap = ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
+ elapsedTime < ViewConfiguration.getDoubleTapTimeout();
+ if (Recents.getConfiguration().isGridEnabled) {
+ if (isQuickTap) {
+ EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
+ } else {
+ EventBus.getDefault().post(new LaunchMostRecentTaskRequestEvent());
+ }
} else {
- // Notify recents to move onto the next task
- EventBus.getDefault().post(new IterateRecentsEvent());
+ if (!debugFlags.isPagingEnabled() || isQuickTap) {
+ // Launch the next focused task
+ EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
+ } else {
+ // Notify recents to move onto the next task
+ EventBus.getDefault().post(new IterateRecentsEvent());
+ }
}
} else {
// If the user has toggled it too quickly, then just eat up the event here (it's
@@ -743,11 +752,7 @@
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask,
windowOverrideRect);
- // When using a grid layout, the header is already visible on screen at the target
- // location, making it unnecessary to draw it in the transition thumbnail.
- Bitmap thumbnail = stackView.useGridLayout()
- ? mThumbTransitionBitmapCache.createAshmemBitmap()
- : drawThumbnailTransitionBitmap(toTask, toTransform,
+ Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
mThumbTransitionBitmapCache);
if (thumbnail != null) {
RectF toTaskRect = toTransform.rect;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
new file mode 100644
index 0000000..24913a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This event is sent to request that the most recent task is launched.
+ */
+public class LaunchMostRecentTaskRequestEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index a2ee4c5..f1314aba 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -619,7 +619,7 @@
postAnimationTrigger.addLastDecrementRunnable(() -> {
mStackView.getTouchHandler().onChildDismissed(deleteTaskView);
});
- deleteTaskView.animate().setDuration(300).scaleX(0).scaleY(0).alpha(0).setListener(
+ deleteTaskView.animate().setDuration(300).scaleX(0.9f).scaleY(0.9f).alpha(0).setListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 8ae7a83..fb94c7e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -64,6 +64,7 @@
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
@@ -1733,6 +1734,13 @@
mUIDozeTrigger.stopDozing();
}
+ public final void onBusEvent(LaunchMostRecentTaskRequestEvent event) {
+ if (mStack.getTaskCount() > 0) {
+ Task mostRecentTask = mStack.getStackFrontMostTask(true /* includeFreefromTasks */);
+ launchTask(mostRecentTask);
+ }
+ }
+
public final void onBusEvent(LaunchNextTaskRequestEvent event) {
if (mAwaitingFirstLayout) {
mLaunchNextAfterFirstMeasure = true;
@@ -1741,29 +1749,7 @@
final Task launchTask = mStack.getNextLaunchTarget();
if (launchTask != null) {
- // Stop all animations
- cancelAllTaskViewAnimations();
-
- float curScroll = mStackScroller.getStackScroll();
- float targetScroll = mLayoutAlgorithm.getStackScrollForTaskAtInitialOffset(launchTask);
- float absScrollDiff = Math.abs(targetScroll - curScroll);
- if (getChildViewForTask(launchTask) == null || absScrollDiff > 0.35f) {
- int duration = (int) (LAUNCH_NEXT_SCROLL_BASE_DURATION +
- absScrollDiff * LAUNCH_NEXT_SCROLL_INCR_DURATION);
- mStackScroller.animateScroll(targetScroll,
- duration, new Runnable() {
- @Override
- public void run() {
- EventBus.getDefault().send(new LaunchTaskEvent(
- getChildViewForTask(launchTask), launchTask, null,
- INVALID_STACK_ID, false /* screenPinningRequested */));
- }
- });
- } else {
- EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
- launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
- }
-
+ launchTask(launchTask);
MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
launchTask.key.getComponent().toString());
} else if (mStack.getTaskCount() == 0) {
@@ -2215,6 +2201,31 @@
return -1;
}
+ private void launchTask(Task task) {
+ // Stop all animations
+ cancelAllTaskViewAnimations();
+
+ float curScroll = mStackScroller.getStackScroll();
+ float targetScroll = mLayoutAlgorithm.getStackScrollForTaskAtInitialOffset(task);
+ float absScrollDiff = Math.abs(targetScroll - curScroll);
+ if (getChildViewForTask(task) == null || absScrollDiff > 0.35f) {
+ int duration = (int) (LAUNCH_NEXT_SCROLL_BASE_DURATION +
+ absScrollDiff * LAUNCH_NEXT_SCROLL_INCR_DURATION);
+ mStackScroller.animateScroll(targetScroll,
+ duration, new Runnable() {
+ @Override
+ public void run() {
+ EventBus.getDefault().send(new LaunchTaskEvent(
+ getChildViewForTask(task), task, null,
+ INVALID_STACK_ID, false /* screenPinningRequested */));
+ }
+ });
+ } else {
+ EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task),
+ task, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+ }
+ }
+
/**
* Check whether we should use the grid layout.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 7135caf..9a4b45a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -178,20 +178,19 @@
.bigPicture(picture.createAshmemBitmap());
// The public notification will show similar info but with the actual screenshot omitted
- mPublicNotificationBuilder = new Notification.Builder(context)
- .setChannel(NotificationChannels.SCREENSHOTS)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setContentText(r.getString(R.string.screenshot_saving_text))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
+ mPublicNotificationBuilder =
+ new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setContentText(r.getString(R.string.screenshot_saving_text))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
- mNotificationBuilder = new Notification.Builder(context)
- .setChannel(NotificationChannels.SCREENSHOTS)
+ mNotificationBuilder = new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
.setTicker(r.getString(R.string.screenshot_saving_ticker)
+ (mTickerAddSpace ? " " : ""))
.setContentTitle(r.getString(R.string.screenshot_saving_title))
@@ -335,7 +334,6 @@
// Update the text and the icon for the existing notification
mPublicNotificationBuilder
- .setChannel(NotificationChannels.SCREENSHOTS)
.setContentTitle(r.getString(R.string.screenshot_saved_title))
.setContentText(r.getString(R.string.screenshot_saved_text))
.setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
@@ -344,7 +342,6 @@
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
mNotificationBuilder
- .setChannel(NotificationChannels.SCREENSHOTS)
.setContentTitle(r.getString(R.string.screenshot_saved_title))
.setContentText(r.getString(R.string.screenshot_saved_text))
.setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
@@ -858,7 +855,7 @@
String errorMsg = r.getString(msgResId);
// Repurpose the existing notification to notify the user of the error
- Notification.Builder b = new Notification.Builder(context)
+ Notification.Builder b = new Notification.Builder(context, NotificationChannels.ALERTS)
.setTicker(r.getString(R.string.screenshot_failed_title))
.setContentTitle(r.getString(R.string.screenshot_failed_title))
.setContentText(errorMsg)
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 19eefec..7699bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -107,7 +107,7 @@
List<ActivityManager.RecentTaskInfo> taskList =
SystemServicesProxy.getInstance(mContext).getRecentTasks(1,
UserHandle.USER_CURRENT, false, new ArraySet<>());
- recents.showRecents(
+ recents.showRecentApps(
false /* triggeredFromAltTab */,
false /* fromHome */);
if (!taskList.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index b9ed725..4b1baa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -38,7 +38,6 @@
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -140,8 +139,6 @@
private ValueAnimator mBackgroundColorAnimator;
private float mAppearAnimationFraction = -1.0f;
private float mAppearAnimationTranslation;
- private boolean mShowingLegacyBackground;
- private final int mLegacyColor;
private final int mNormalColor;
private final int mLowPriorityColor;
private boolean mIsBelowSpeedBump;
@@ -192,7 +189,6 @@
mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
setClipChildren(false);
setClipToPadding(false);
- mLegacyColor = context.getColor(R.color.notification_legacy_background_color);
mNormalColor = context.getColor(R.color.notification_material_background_color);
mLowPriorityColor = context.getColor(
R.color.notification_material_background_low_priority_color);
@@ -489,11 +485,6 @@
updateOutlineAlpha();
}
- public void setShowingLegacyBackground(boolean showing) {
- mShowingLegacyBackground = showing;
- updateBackgroundTint();
- }
-
@Override
public void setBelowSpeedBump(boolean below) {
super.setBelowSpeedBump(below);
@@ -950,8 +941,6 @@
}
if (withTint && mBgTint != NO_COLOR) {
return mBgTint;
- } else if (mShowingLegacyBackground) {
- return mLegacyColor;
} else if (mIsBelowSpeedBump) {
return mLowPriorityColor;
} else {
@@ -962,8 +951,6 @@
protected int getRippleColor() {
if (mBgTint != 0) {
return mTintedRippleColor;
- } else if (mShowingLegacyBackground) {
- return mTintedRippleColor;
} else if (mIsBelowSpeedBump) {
return mLowPriorityRippleColor;
} else {
@@ -1009,7 +996,6 @@
public void reset() {
setTintColor(0);
resetBackgroundAlpha();
- setShowingLegacyBackground(false);
setBelowSpeedBump(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index d1245b1..85e2bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -77,6 +77,7 @@
private int mMaxHeadsUpHeightLegacy;
private int mMaxHeadsUpHeight;
private int mNotificationMinHeight;
+ private int mNotificationMinHeightLarge;
private int mNotificationMaxHeight;
private int mNotificationAmbientHeight;
private int mIncreasedPaddingBetweenElements;
@@ -207,6 +208,7 @@
private Runnable mOnDismissRunnable;
private boolean mIsLowPriority;
private boolean mIsColorized;
+ private boolean mUseIncreasedCollapsedHeight;
@Override
public boolean isGroupExpansionChanging() {
@@ -341,8 +343,14 @@
boolean customView = layout.getContractedChild().getId()
!= com.android.internal.R.id.status_bar_latest_event_content;
boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
- int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
- mNotificationMinHeightLegacy : mNotificationMinHeight;
+ int minHeight;
+ if (customView && beforeN && !mIsSummaryWithChildren) {
+ minHeight = mNotificationMinHeightLegacy;
+ } else if (mUseIncreasedCollapsedHeight && layout == mPrivateLayout) {
+ minHeight = mNotificationMinHeightLarge;
+ } else {
+ minHeight = mNotificationMinHeight;
+ }
boolean headsUpCustom = layout.getHeadsUpChild() != null &&
layout.getHeadsUpChild().getId()
!= com.android.internal.R.id.status_bar_latest_event_content;
@@ -979,6 +987,10 @@
}
}
+ public void setUseIncreasedCollapsedHeight(boolean use) {
+ mUseIncreasedCollapsedHeight = use;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -992,6 +1004,8 @@
private void initDimens() {
mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
+ mNotificationMinHeightLarge = getFontScaledHeight(
+ R.dimen.notification_min_height_large);
mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
mNotificationAmbientHeight = getFontScaledHeight(R.dimen.notification_ambient_height);
mMaxHeadsUpHeightLegacy = getFontScaledHeight(
@@ -1782,9 +1796,7 @@
return mShowingPublic ? mPublicLayout : mPrivateLayout;
}
- @Override
public void setShowingLegacyBackground(boolean showing) {
- super.setShowingLegacyBackground(showing);
for (NotificationContentView l : mLayouts) {
l.setShowingLegacyBackground(showing);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index e0ddf13..57d2e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -505,7 +505,8 @@
isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED)
- && (mIsHeadsUp || mHeadsUpAnimatingAway);
+ && (mIsHeadsUp || mHeadsUpAnimatingAway)
+ && !mContainingNotification.isOnKeyguard();
if (transitioningBetweenHunAndExpanded || pinned) {
return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight());
}
@@ -611,7 +612,7 @@
public int getMaxHeight() {
if (mExpandedChild != null) {
return mExpandedChild.getHeight();
- } else if (mIsHeadsUp && mHeadsUpChild != null) {
+ } else if (mIsHeadsUp && mHeadsUpChild != null && !mContainingNotification.isOnKeyguard()) {
return mHeadsUpChild.getHeight();
}
return mContractedChild.getHeight();
@@ -921,7 +922,8 @@
return VISIBLE_TYPE_SINGLELINE;
}
- if ((mIsHeadsUp || mHeadsUpAnimatingAway) && mHeadsUpChild != null) {
+ if ((mIsHeadsUp || mHeadsUpAnimatingAway) && mHeadsUpChild != null
+ && !mContainingNotification.isOnKeyguard()) {
if (viewHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
return VISIBLE_TYPE_HEADSUP;
} else {
@@ -1174,7 +1176,7 @@
mExpandable = expandable;
// if the expanded child has the same height as the collapsed one we hide it.
if (mExpandedChild != null && mExpandedChild.getHeight() != 0) {
- if ((!mIsHeadsUp || mHeadsUpChild == null)) {
+ if (!mIsHeadsUp || mHeadsUpChild == null || mContainingNotification.isOnKeyguard()) {
if (mExpandedChild.getHeight() == mContractedChild.getHeight()) {
expandable = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b49ba0c..f73a5ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -126,13 +126,13 @@
}
public boolean cacheContentViews(Context ctx, Notification updatedNotification,
- boolean isLowPriority) {
+ boolean isLowPriority, boolean useIncreasedCollapsedView) {
boolean applyInPlace = false;
if (updatedNotification != null) {
final Notification.Builder updatedNotificationBuilder
= Notification.Builder.recoverBuilder(ctx, updatedNotification);
final RemoteViews newContentView = createContentView(updatedNotificationBuilder,
- isLowPriority);
+ isLowPriority, useIncreasedCollapsedView);
final RemoteViews newBigContentView = createBigContentView(
updatedNotificationBuilder, isLowPriority);
final RemoteViews newHeadsUpContentView =
@@ -162,7 +162,8 @@
final Notification.Builder builder
= Notification.Builder.recoverBuilder(ctx, notification.getNotification());
- cachedContentView = createContentView(builder, isLowPriority);
+ cachedContentView = createContentView(builder, isLowPriority,
+ useIncreasedCollapsedView);
cachedBigContentView = createBigContentView(builder, isLowPriority);
cachedHeadsUpContentView = builder.createHeadsUpContentView();
cachedPublicContentView = builder.makePublicContentView();
@@ -188,11 +189,11 @@
}
private RemoteViews createContentView(Notification.Builder builder,
- boolean isAmbient) {
- if (isAmbient) {
+ boolean isLowPriority, boolean useLarge) {
+ if (isLowPriority) {
return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
}
- return builder.createContentView();
+ return builder.createContentView(useLarge);
}
// Returns true if the RemoteViews are the same.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 399b0d2..6283148 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -256,9 +256,16 @@
if (mIcon == null) {
return false;
}
- Drawable drawable = getIcon(mIcon);
+ Drawable drawable;
+ try {
+ drawable = getIcon(mIcon);
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "OOM while inflating " + mIcon.icon + " for slot " + mSlot);
+ return false;
+ }
+
if (drawable == null) {
- Log.w(TAG, "No icon for slot " + mSlot);
+ Log.w(TAG, "No icon for slot " + mSlot + "; " + mIcon.icon);
return false;
}
if (withClear) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 3b18886..03c7325 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -41,10 +41,12 @@
private final ViewInvertHelper mInvertHelper;
private final Paint mGreyPaint = new Paint();
private boolean mShowingLegacyBackground;
+ private int mLegacyColor;
protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
super(view, row);
mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
+ mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
}
@Override
@@ -103,6 +105,15 @@
}
@Override
+ public int getCustomBackgroundColor() {
+ int customBackgroundColor = super.getCustomBackgroundColor();
+ if (customBackgroundColor == 0 && mShowingLegacyBackground) {
+ return mLegacyColor;
+ }
+ return customBackgroundColor;
+ }
+
+ @Override
public void setShowingLegacyBackground(boolean showing) {
super.setShowingLegacyBackground(showing);
mShowingLegacyBackground = showing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 4535992..7c458898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -20,15 +20,19 @@
import android.view.View;
import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.policy.BatteryController;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
/**
* Controls how light status bar flag applies to the icons.
*/
-public class LightBarController implements BatteryController.BatteryStateChangeCallback {
+public class LightBarController implements BatteryController.BatteryStateChangeCallback, Dumpable {
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
@@ -203,4 +207,37 @@
public void onPowerSaveChanged(boolean isPowerSave) {
reevaluate();
}
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("LightBarController: ");
+ pw.print(" mSystemUiVisibility=0x"); pw.print(
+ Integer.toHexString(mSystemUiVisibility));
+ pw.print(" mFullscreenStackVisibility=0x"); pw.print(
+ Integer.toHexString(mFullscreenStackVisibility));
+ pw.print(" mDockedStackVisibility=0x"); pw.println(
+ Integer.toHexString(mDockedStackVisibility));
+
+ pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
+ pw.print(" mDockedLight="); pw.println(mDockedLight);
+
+ pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
+ pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
+
+ pw.print(" mNavigationLight="); pw.print(mNavigationLight);
+ pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
+
+ pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
+ pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
+
+ pw.print(" mScrimAlpha="); pw.print(mScrimAlpha);
+ pw.print(" mScrimAlphaBelowThreshold="); pw.println(mScrimAlphaBelowThreshold);
+ pw.println();
+ pw.println(" StatusBarTransitionsController:");
+ mStatusBarIconController.getTransitionsController().dump(fd, pw, args);
+ pw.println();
+ pw.println(" NavigationBarTransitionsController:");
+ mNavigationBarController.dump(fd, pw, args);
+ pw.println();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 0f9f056..07f37ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -20,13 +20,18 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
+import android.util.TimeUtils;
+import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* Class to control all aspects about light bar changes.
*/
-public class LightBarTransitionsController {
+public class LightBarTransitionsController implements Dumpable {
public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
@@ -147,6 +152,26 @@
mApplier.applyDarkIntensity(darkIntensity);
}
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print(" mTransitionDeferring="); pw.print(mTransitionDeferring);
+ if (mTransitionDeferring) {
+ pw.println();
+ pw.print(" mTransitionDeferringStartTime=");
+ pw.println(TimeUtils.formatUptime(mTransitionDeferringStartTime));
+
+ pw.print(" mTransitionDeferringDuration=");
+ TimeUtils.formatDuration(mTransitionDeferringDuration, pw);
+ pw.println();
+ }
+ pw.print(" mTransitionPending="); pw.print(mTransitionPending);
+ pw.print(" mTintChangePending="); pw.println(mTintChangePending);
+
+ pw.print(" mPendingDarkIntensity="); pw.print(mPendingDarkIntensity);
+ pw.print(" mDarkIntensity="); pw.print(mDarkIntensity);
+ pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
+ }
+
/**
* Interface to apply a specific dark intensity.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 78d2c87..638c12f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1,3 +1,5 @@
+
+
/*
* Copyright (C) 2010 The Android Open Source Project
*
@@ -113,6 +115,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationMessagingUtil;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -270,8 +273,6 @@
protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
- protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
- protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
@@ -281,8 +282,8 @@
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
// Should match the values in PhoneWindowManager
- public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
+ public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
private static final String BANNER_ACTION_CANCEL =
"com.android.systemui.statusbar.banner_action_cancel";
@@ -702,6 +703,7 @@
}
};
+ private NotificationMessagingUtil mMessagingUtil;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private UserSwitcherController mUserSwitcherController;
private NetworkController mNetworkController;
@@ -766,6 +768,7 @@
Context.DEVICE_POLICY_SERVICE);
mNotificationData = new NotificationData(this);
+ mMessagingUtil = new NotificationMessagingUtil(mContext);
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -2760,28 +2763,6 @@
@Override
public void handleMessage(Message m) {
switch (m.what) {
- // start old BaseStatusBar.H handling.
- case MSG_SHOW_RECENT_APPS:
- showRecents(m.arg1 > 0, m.arg2 != 0);
- break;
- case MSG_HIDE_RECENT_APPS:
- hideRecents(m.arg1 > 0, m.arg2 > 0);
- break;
- case MSG_TOGGLE_RECENTS_APPS:
- toggleRecents();
- break;
- case MSG_PRELOAD_RECENT_APPS:
- preloadRecents();
- break;
- case MSG_CANCEL_PRELOAD_RECENT_APPS:
- cancelPreloadingRecents();
- break;
- case MSG_SHOW_NEXT_AFFILIATED_TASK:
- showRecentsNextAffiliatedTask();
- break;
- case MSG_SHOW_PREV_AFFILIATED_TASK:
- showRecentsPreviousAffiliatedTask();
- break;
case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
toggleKeyboardShortcuts(m.arg1);
break;
@@ -3435,6 +3416,9 @@
} else {
pw.println(" mGroupManager: null");
}
+
+ mLightBarController.dump(fd, pw, args);
+
if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
}
@@ -5794,20 +5778,21 @@
PendingIntent.FLAG_CANCEL_CURRENT);
final int colorRes = com.android.internal.R.color.system_notification_accent_color;
- Notification.Builder note = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_android)
- .setContentTitle(mContext.getString(R.string.hidden_notifications_title))
- .setContentText(mContext.getString(R.string.hidden_notifications_text))
- .setChannel(NotificationChannels.SECURITY)
- .setOngoing(true)
- .setColor(mContext.getColor(colorRes))
- .setContentIntent(setupIntent)
- .addAction(R.drawable.ic_close,
- mContext.getString(R.string.hidden_notifications_cancel),
- cancelIntent)
- .addAction(R.drawable.ic_settings,
- mContext.getString(R.string.hidden_notifications_setup),
- setupIntent);
+ Notification.Builder note =
+ new Notification.Builder(mContext, NotificationChannels.GENERAL)
+ .setSmallIcon(R.drawable.ic_android)
+ .setContentTitle(mContext.getString(
+ R.string.hidden_notifications_title))
+ .setContentText(mContext.getString(R.string.hidden_notifications_text))
+ .setOngoing(true)
+ .setColor(mContext.getColor(colorRes))
+ .setContentIntent(setupIntent)
+ .addAction(R.drawable.ic_close,
+ mContext.getString(R.string.hidden_notifications_cancel),
+ cancelIntent)
+ .addAction(R.drawable.ic_settings,
+ mContext.getString(R.string.hidden_notifications_setup),
+ setupIntent);
overrideNotificationAppName(mContext, note);
NotificationManager noMan =
@@ -6087,26 +6072,6 @@
}
@Override
- public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
- int msg = MSG_SHOW_RECENT_APPS;
- mHandler.removeMessages(msg);
- mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0).sendToTarget();
- }
-
- @Override
- public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- int msg = MSG_HIDE_RECENT_APPS;
- mHandler.removeMessages(msg);
- mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0,
- triggeredFromHomeKey ? 1 : 0).sendToTarget();
- }
-
- @Override
- public void toggleRecentApps() {
- toggleRecents();
- }
-
- @Override
public void toggleSplitScreen() {
toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
}
@@ -6139,20 +6104,6 @@
mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
}
- /** Jumps to the next affiliated task in the group. */
- public void showNextAffiliatedTask() {
- int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
-
- /** Jumps to the previous affiliated task in the group. */
- public void showPreviousAffiliatedTask() {
- int msg = MSG_SHOW_PREV_AFFILIATED_TASK;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
-
protected void sendCloseSystemWindows(String reason) {
try {
ActivityManager.getService().closeSystemDialogs(reason);
@@ -6160,33 +6111,6 @@
}
}
- /** Proxy for RecentsComponent */
-
- protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
- if (mRecents != null) {
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
- mRecents.showRecents(triggeredFromAltTab, fromHome);
- }
- }
-
- protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- if (mRecents != null) {
- mRecents.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
- }
- }
-
- protected void toggleRecents() {
- if (mRecents != null) {
- mRecents.toggleRecents(mDisplay);
- }
- }
-
- protected void preloadRecents() {
- if (mRecents != null) {
- mRecents.preloadRecents();
- }
- }
-
protected void toggleKeyboardShortcuts(int deviceId) {
KeyboardShortcuts.toggle(mContext, deviceId);
}
@@ -6195,24 +6119,6 @@
KeyboardShortcuts.dismiss();
}
- protected void cancelPreloadingRecents() {
- if (mRecents != null) {
- mRecents.cancelPreloadingRecents();
- }
- }
-
- protected void showRecentsNextAffiliatedTask() {
- if (mRecents != null) {
- mRecents.showNextAffiliatedTask();
- }
- }
-
- protected void showRecentsPreviousAffiliatedTask() {
- if (mRecents != null) {
- mRecents.showPrevAffiliatedTask();
- }
- }
-
/**
* Save the current "public" (locked and secure) state of the lockscreen.
*/
@@ -6336,8 +6242,10 @@
final StatusBarNotification sbn = entry.notification;
boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
+ boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
+ mNotificationData.getImportance(sbn.getKey()));
try {
- entry.cacheContentViews(mContext, null, isLowPriority);
+ entry.cacheContentViews(mContext, null, isLowPriority, useIncreasedCollapsedHeight);
} catch (RuntimeException e) {
Log.e(TAG, "Unable to get notification remote views", e);
return false;
@@ -6507,6 +6415,7 @@
row.setUserExpanded(userExpanded);
}
row.setUserLocked(userLocked);
+ row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
row.onNotificationUpdated(entry);
return true;
}
@@ -6996,10 +6905,13 @@
Notification n = notification.getNotification();
mNotificationData.updateRanking(ranking);
+ boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(notification,
+ mNotificationData.getImportance(notification.getKey()));
+ entry.row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
boolean applyInPlace;
try {
applyInPlace = entry.cacheContentViews(mContext, notification.getNotification(),
- mNotificationData.isAmbient(key));
+ mNotificationData.isAmbient(key), useIncreasedCollapsedHeight);
} catch (RuntimeException e) {
Log.e(TAG, "Unable to get notification remote views", e);
applyInPlace = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index fd71f43..7a32bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -560,18 +560,20 @@
private void showLogoutNotification(int userId) {
PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
- Notification.Builder builder = new Notification.Builder(mContext)
- .setVisibility(Notification.VISIBILITY_SECRET)
- .setChannel(NotificationChannels.USER)
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
- .setContentText(mContext.getString(R.string.user_logout_notification_text))
- .setContentIntent(logoutPI)
- .setOngoing(true)
- .setShowWhen(false)
- .addAction(R.drawable.ic_delete,
- mContext.getString(R.string.user_logout_notification_action),
- logoutPI);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.GENERAL)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle(mContext.getString(
+ R.string.user_logout_notification_title))
+ .setContentText(mContext.getString(
+ R.string.user_logout_notification_text))
+ .setContentIntent(logoutPI)
+ .setOngoing(true)
+ .setShowWhen(false)
+ .addAction(R.drawable.ic_delete,
+ mContext.getString(R.string.user_logout_notification_action),
+ logoutPI);
SystemUI.overrideNotificationAppName(mContext, builder);
NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER,
SystemMessage.NOTE_LOGOUT_USER, builder.build(), new UserHandle(userId));
@@ -584,17 +586,17 @@
PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
- Notification.Builder builder = new Notification.Builder(mContext)
- .setVisibility(Notification.VISIBILITY_SECRET)
- .setChannel(NotificationChannels.USER)
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle(mContext.getString(R.string.guest_notification_title))
- .setContentText(mContext.getString(R.string.guest_notification_text))
- .setContentIntent(removeGuestPI)
- .setShowWhen(false)
- .addAction(R.drawable.ic_delete,
- mContext.getString(R.string.guest_notification_remove_action),
- removeGuestPI);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.GENERAL)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle(mContext.getString(R.string.guest_notification_title))
+ .setContentText(mContext.getString(R.string.guest_notification_text))
+ .setContentIntent(removeGuestPI)
+ .setShowWhen(false)
+ .addAction(R.drawable.ic_delete,
+ mContext.getString(R.string.guest_notification_remove_action),
+ removeGuestPI);
SystemUI.overrideNotificationAppName(mContext, builder);
NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST,
SystemMessage.NOTE_REMOVE_GUEST, builder.build(), new UserHandle(guestUserId));
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 9a16d6d..43727e0 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -198,18 +198,19 @@
rec.getNickname());
final CharSequence text = mContext.getString(R.string.ext_media_missing_message);
- Notification.Builder builder = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_sd_card_48dp)
- .setColor(mContext.getColor(R.color.system_notification_accent_color))
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(buildForgetPendingIntent(rec))
- .setStyle(new Notification.BigTextStyle().bigText(text))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true)
- .setChannel(NotificationChannels.STORAGE)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setDeleteIntent(buildSnoozeIntent(fsUuid));
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.STORAGE)
+ .setSmallIcon(R.drawable.ic_sd_card_48dp)
+ .setColor(mContext.getColor(
+ R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setContentIntent(buildForgetPendingIntent(rec))
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setDeleteIntent(buildSnoozeIntent(fsUuid));
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
@@ -226,17 +227,17 @@
final CharSequence text = mContext.getString(
R.string.ext_media_unsupported_notification_message, disk.getDescription());
- Notification.Builder builder = new Notification.Builder(mContext)
- .setChannel(NotificationChannels.STORAGE)
- .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
- .setColor(mContext.getColor(R.color.system_notification_accent_color))
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(buildInitPendingIntent(disk))
- .setStyle(new Notification.BigTextStyle().bigText(text))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true)
- .setCategory(Notification.CATEGORY_ERROR);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.STORAGE)
+ .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
+ .setColor(mContext.getColor(R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setContentIntent(buildInitPendingIntent(disk))
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true)
+ .setCategory(Notification.CATEGORY_ERROR);
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
@@ -475,19 +476,19 @@
intent = buildWizardMigratePendingIntent(move);
}
- Notification.Builder builder = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_sd_card_48dp)
- .setColor(mContext.getColor(R.color.system_notification_accent_color))
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(intent)
- .setStyle(new Notification.BigTextStyle().bigText(text))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true)
- .setChannel(NotificationChannels.STORAGE)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setProgress(100, status, false)
- .setOngoing(true);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.STORAGE)
+ .setSmallIcon(R.drawable.ic_sd_card_48dp)
+ .setColor(mContext.getColor(R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setContentIntent(intent)
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setProgress(100, status, false)
+ .setOngoing(true);
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
@@ -526,18 +527,18 @@
intent = null;
}
- Notification.Builder builder = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_sd_card_48dp)
- .setColor(mContext.getColor(R.color.system_notification_accent_color))
- .setContentTitle(title)
- .setContentText(text)
- .setContentIntent(intent)
- .setStyle(new Notification.BigTextStyle().bigText(text))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setChannel(NotificationChannels.STORAGE)
- .setAutoCancel(true);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.STORAGE)
+ .setSmallIcon(R.drawable.ic_sd_card_48dp)
+ .setColor(mContext.getColor(R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setContentIntent(intent)
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setAutoCancel(true);
SystemUI.overrideNotificationAppName(mContext, builder);
mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
@@ -562,15 +563,15 @@
private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
CharSequence text) {
- Notification.Builder builder = new Notification.Builder(mContext)
- .setChannel(NotificationChannels.STORAGE)
- .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
- .setColor(mContext.getColor(R.color.system_notification_accent_color))
- .setContentTitle(title)
- .setContentText(text)
- .setStyle(new Notification.BigTextStyle().bigText(text))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setLocalOnly(true);
+ Notification.Builder builder =
+ new Notification.Builder(mContext, NotificationChannels.STORAGE)
+ .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
+ .setColor(mContext.getColor(R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(text)
+ .setStyle(new Notification.BigTextStyle().bigText(text))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true);
overrideNotificationAppName(mContext, builder);
return builder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 6bb8aea..15ad0ce 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -27,8 +27,7 @@
public class NotificationChannels extends SystemUI {
public static String ALERTS = "ALR";
public static String SCREENSHOTS = "SCN";
- public static String SECURITY = "SEC";
- public static String USER = "USR";
+ public static String GENERAL = "GEN";
public static String STORAGE = "DSK";
@VisibleForTesting
@@ -42,14 +41,10 @@
new NotificationChannel(
SCREENSHOTS,
context.getString(R.string.notification_channel_screenshot),
- NotificationManager.IMPORTANCE_DEFAULT),
+ NotificationManager.IMPORTANCE_LOW),
new NotificationChannel(
- SECURITY,
- context.getString(R.string.notification_channel_security),
- NotificationManager.IMPORTANCE_HIGH),
- new NotificationChannel(
- USER,
- context.getString(R.string.notification_channel_user_status),
+ GENERAL,
+ context.getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_MIN),
new NotificationChannel(
STORAGE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
index 3bb9f5f..77f96b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
@@ -31,6 +28,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class NotificationContentViewTest {
@@ -39,13 +41,16 @@
Context mContext;
@Before
+ @UiThreadTest
public void setup() {
- ExpandableNotificationRow rowMock = mock(ExpandableNotificationRow.class);
- when(rowMock.getIntrinsicHeight()).thenReturn(10);
-
mContext = InstrumentationRegistry.getTargetContext();
mView = new NotificationContentView(mContext, null);
- mView.setContainingNotification(rowMock);
+ ExpandableNotificationRow row = new ExpandableNotificationRow(mContext, null);
+ ExpandableNotificationRow mockRow = spy(row);
+ doNothing().when(mockRow).updateBackgroundAlpha(anyFloat());
+ doReturn(10).when(mockRow).getIntrinsicHeight();
+
+ mView.setContainingNotification(mockRow);
mView.setHeights(10, 20, 30, 40);
mView.setContractedChild(createViewWithHeight(10));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index 7d9e073..68f9cb05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -16,36 +16,74 @@
package com.android.systemui.statusbar;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
-import android.os.Debug;
import android.os.UserHandle;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
-
-import static junit.framework.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import org.mockito.ArgumentMatcher;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class StatusBarIconViewTest extends SysuiTestCase {
+ @Rule
+ public ExpectedException mThrown = ExpectedException.none();
+
private StatusBarIconView mIconView;
private StatusBarIcon mStatusBarIcon = mock(StatusBarIcon.class);
+ private PackageManager mPackageManagerSpy;
+ private Context mContext;
+ private Resources mMockResources;
+
@Before
- public void setUp() {
- mIconView = new StatusBarIconView(getContext(), "slot", null);
- mStatusBarIcon = new StatusBarIcon(UserHandle.ALL, getContext().getPackageName(),
- Icon.createWithResource(getContext(), R.drawable.ic_android), 0, 0, "");
+ public void setUp() throws Exception {
+ // Set up context such that asking for "mockPackage" resources returns mMockResources.
+ mMockResources = mock(Resources.class);
+ mPackageManagerSpy = spy(getContext().getPackageManager());
+ doReturn(mMockResources).when(mPackageManagerSpy)
+ .getResourcesForApplicationAsUser(eq("mockPackage"), anyInt());
+ doReturn(mMockResources).when(mPackageManagerSpy)
+ .getResourcesForApplication(eq("mockPackage"));
+ doReturn(mMockResources).when(mPackageManagerSpy).getResourcesForApplication(argThat(
+ (ArgumentMatcher<ApplicationInfo>) o -> "mockPackage".equals(o.packageName)));
+ mContext = new ContextWrapper(getContext()) {
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManagerSpy;
+ }
+ };
+
+ mIconView = new StatusBarIconView(mContext, "test_slot", null);
+ mStatusBarIcon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+ Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "");
}
@Test
@@ -55,4 +93,11 @@
assertNull(mIconView.getTag(R.id.icon_is_grayscale));
}
+ @Test
+ public void testSettingOomingIconDoesNotThrowOom() {
+ when(mMockResources.getDrawable(anyInt(), any())).thenThrow(new OutOfMemoryError("mocked"));
+ mStatusBarIcon.icon = Icon.createWithResource("mockPackage", R.drawable.ic_android);
+
+ assertFalse(mIconView.set(mStatusBarIcon));
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
index 8949598..f67296d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
@@ -55,9 +55,8 @@
Set<String> ALL_CHANNELS = new ArraySet<>(Arrays.asList(
NotificationChannels.ALERTS,
NotificationChannels.SCREENSHOTS,
- NotificationChannels.SECURITY,
- NotificationChannels.USER,
- NotificationChannels.STORAGE
+ NotificationChannels.STORAGE,
+ NotificationChannels.GENERAL
));
NotificationChannels.createAll(mContext);
ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
index 01996ca..202c4cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
@@ -29,7 +29,7 @@
public static void attachView(View view) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_SYSTEM_ALERT,
+ LayoutParams.TYPE_APPLICATION_OVERLAY,
0, PixelFormat.TRANSLUCENT);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> InstrumentationRegistry.getContext()
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3ba8915..a861522 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3899,6 +3899,7 @@
case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
return AccessibilityWindowInfo.TYPE_SYSTEM;
}
diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
index c68ac60..e53165d 100644
--- a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
+++ b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
@@ -17,134 +17,277 @@
import static com.android.server.autofill.Helper.DEBUG;
+import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.os.IBinder;
import android.util.Slog;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.View.MeasureSpec;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
-import java.io.PrintWriter;
/**
* A window above the application that is smartly anchored to a rectangular region.
*/
-final class AnchoredWindow {
+final class AnchoredWindow implements View.OnLayoutChangeListener, View.OnTouchListener {
private static final String TAG = "AutoFill";
+ private static final int NULL_HEIGHT = -1;
+
private final WindowManager mWm;
- private final View mRootView;
- private final View mView;
- private final int mWidth;
- private final int mHeight;
- private boolean mIsShowing = false;
+ private final IBinder mAppToken;
+ private final View mContentView;
+
+ private final View mWindowSizeListenerView;
+ private final int mMinMargin;
+
+ private int mLastHeight = NULL_HEIGHT;
+ @Nullable
+ private Rect mLastBounds;
+ @Nullable
+ private Rect mLastDisplayBounds;
/**
* Constructor.
*
- * @param wm window manager that draws the view on a window
- * @param view singleton view in the window
- * @param width requested width of the view
- * @param height requested height of the view
+ * @param wm window manager that draws the content on a window
+ * @param appToken token to pass to window manager
+ * @param contentView content of the window
*/
- AnchoredWindow(WindowManager wm, View view, int width, int height) {
+ AnchoredWindow(WindowManager wm, IBinder appToken, View contentView) {
mWm = wm;
- mRootView = wrapView(view, width, height);
- mView = view;
- mWidth = width;
- mHeight = height;
+ mAppToken = appToken;
+ mContentView = contentView;
+
+ mContentView.addOnLayoutChangeListener(this);
+
+ Context context = contentView.getContext();
+
+ mWindowSizeListenerView = new FrameLayout(context);
+ mWindowSizeListenerView.addOnLayoutChangeListener(this);
+
+ mMinMargin = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.autofill_fill_min_margin);
}
/**
* Shows the window.
*
- * @param bounds the rectangular region this window should be anchored to
+ * @param bounds the region the window should be anchored to
*/
void show(Rect bounds) {
- final LayoutParams params = createBaseLayoutParams();
- params.x = bounds.left;
- params.y = bounds.bottom;
+ if (DEBUG) Slog.d(TAG, "show bounds=" + bounds);
- if (!mIsShowing) {
- if (DEBUG) Slog.d(TAG, "adding view " + mView);
- mWm.addView(mRootView, params);
- } else {
- if (DEBUG) Slog.d(TAG, "updating view " + mView);
- mWm.updateViewLayout(mRootView, params);
+ if (!mWindowSizeListenerView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "adding mWindowSizeListenerView");
+ LayoutParams params = createWindowLayoutParams(
+ mAppToken,
+ LayoutParams.FLAG_NOT_TOUCHABLE); // not touchable
+ params.gravity = Gravity.LEFT | Gravity.TOP;
+ params.x = 0;
+ params.y = 0;
+ params.width = LayoutParams.MATCH_PARENT;
+ params.height = LayoutParams.MATCH_PARENT;
+ mWm.addView(mWindowSizeListenerView, params);
}
- mIsShowing = true;
+
+ updateBounds(bounds);
}
/**
* Hides the window.
*/
void hide() {
- if (DEBUG) Slog.d(TAG, "removing view " + mView);
+ if (DEBUG) Slog.d(TAG, "hide");
- if (mIsShowing) {
- mWm.removeView(mRootView);
+ mLastHeight = NULL_HEIGHT;
+ mLastBounds = null;
+ mLastDisplayBounds = null;
+
+ if (mWindowSizeListenerView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "removing mWindowSizeListenerView");
+ mWm.removeView(mWindowSizeListenerView);
}
- mIsShowing = false;
- }
- /**
- * Wraps a view with a SelfRemovingView and sets its requested width and height.
- */
- private View wrapView(View view, int width, int height) {
- final ViewGroup viewGroup = new SelfRemovingView(view.getContext());
- viewGroup.addView(view, new ViewGroup.LayoutParams(width, height));
- return viewGroup;
- }
-
- private static LayoutParams createBaseLayoutParams() {
- final LayoutParams params = new LayoutParams();
- // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL
- params.type = LayoutParams.TYPE_SYSTEM_ALERT;
- params.flags =
- LayoutParams.SOFT_INPUT_STATE_UNCHANGED
- | LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | LayoutParams.FLAG_NOT_FOCUSABLE
- | LayoutParams.FLAG_NOT_TOUCH_MODAL
- | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
- params.gravity = Gravity.TOP | Gravity.LEFT;
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- return params;
+ if (mContentView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "removing mContentView");
+ mContentView.setOnTouchListener(null);
+ mWm.removeView(mContentView);
+ }
}
@Override
- public String toString() {
- if (!DEBUG) return super.toString();
-
- return "AnchoredWindow: [width=" + mWidth + ", height=" + mHeight + ", view=" + mView + "]";
+ public void onLayoutChange(View view, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ if (view == mWindowSizeListenerView) {
+ if (DEBUG) Slog.d(TAG, "onLayoutChange() for mWindowSizeListenerView");
+ // mWindowSizeListenerView layout changed, get the size of the display bounds and update
+ // the window.
+ final Rect displayBounds = new Rect();
+ view.getBoundsOnScreen(displayBounds);
+ updateDisplayBounds(displayBounds);
+ } else if (view == mContentView) {
+ // mContentView layout changed, update the window in case its height changed.
+ if (DEBUG) Slog.d(TAG, "onLayoutChange() for mContentView");
+ updateHeight();
+ }
}
- void dump(PrintWriter pw) {
- pw.println("Anchored Window");
- final String prefix = " ";
- pw.print(prefix); pw.print("width: "); pw.println(mWidth);
- pw.print(prefix); pw.print("height: "); pw.println(mHeight);
- pw.print(prefix); pw.print("visible: "); pw.println(mIsShowing);
+ // When the window is touched outside, hide the window.
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (view == mContentView && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ hide();
+ return true;
+ }
+ return false;
}
- /** FrameLayout that listens for touch events removes itself if the touch event is outside. */
- private final class SelfRemovingView extends FrameLayout {
- public SelfRemovingView(Context context) {
- super(context);
+ private boolean updateHeight() {
+ final Rect displayBounds = mLastDisplayBounds;
+ if (displayBounds == null) {
+ return false;
}
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- hide();
- return true;
- } else {
- return super.onTouchEvent(event);
+ mContentView.measure(
+ MeasureSpec.makeMeasureSpec(displayBounds.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(displayBounds.height(), MeasureSpec.AT_MOST));
+ int height = mContentView.getMeasuredHeight();
+ if (height != mLastHeight) {
+ if (DEBUG) Slog.d(TAG, "update height=" + height);
+ mLastHeight = height;
+ update(height, mLastBounds, displayBounds);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void updateBounds(Rect bounds) {
+ if (!bounds.equals(mLastBounds)) {
+ if (DEBUG) Slog.d(TAG, "update bounds=" + bounds);
+ mLastBounds = bounds;
+
+ update(mLastHeight, bounds, mLastDisplayBounds);
+ }
+ }
+
+ private void updateDisplayBounds(Rect displayBounds) {
+ if (!displayBounds.equals(mLastDisplayBounds)) {
+ if (DEBUG) Slog.d(TAG, "update displayBounds=" + displayBounds);
+ mLastDisplayBounds = displayBounds;
+
+ if (!updateHeight()) {
+ update(mLastHeight, mLastBounds, displayBounds);
}
}
}
+
+ // Updates the window if height, bounds, and displayBounds are not null.
+ // Caller should ensure that something changed before calling.
+ private void update(int height, @Nullable Rect bounds, @Nullable Rect displayBounds) {
+ if (height == NULL_HEIGHT || bounds == null || displayBounds == null) {
+ return;
+ }
+
+ if (DEBUG) Slog.d(TAG, "update height=" + height + ", bounds=" + bounds
+ + ", displayBounds=" + displayBounds);
+
+ final LayoutParams params = createWindowLayoutParams(mAppToken,
+ LayoutParams.FLAG_NOT_TOUCH_MODAL // outside touches go to windows behind us
+ | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); // outside touches trigger MotionEvent
+ params.setTitle("AutoFill Fill"); // used for debugging
+ updatePosition(params, height, mMinMargin, bounds, displayBounds);
+ if (!mContentView.isAttachedToWindow()) {
+ if (DEBUG) Slog.d(TAG, "adding mContentView");
+ mWm.addView(mContentView, params);
+ mContentView.setOnTouchListener(this);
+ } else {
+ if (DEBUG) Slog.d(TAG, "updating mContentView");
+ mWm.updateViewLayout(mContentView, params);
+ }
+ }
+
+ /**
+ * Updates the position of the window by altering the {@link LayoutParams}.
+ *
+ * <p>The window can be anchored either above or below the bounds. Anchoring the window below
+ * the bounds is preferred, if it fits. Otherwise, anchor the window on the side with more
+ * space.
+ *
+ * @param params the params to update
+ * @param height the requested height of the window
+ * @param minMargin the minimum margin between the window and the display bounds
+ * @param bounds the region the window should be anchored to
+ * @param displayBounds the region in which the window may be displayed
+ */
+ private static void updatePosition(
+ LayoutParams params,
+ int height,
+ int minMargin,
+ Rect bounds,
+ Rect displayBounds) {
+ boolean below;
+ int verticalSpace;
+ final int verticalSpaceBelow = displayBounds.bottom - bounds.bottom - minMargin;
+ if (height <= verticalSpaceBelow) {
+ // Fits below bounds.
+ below = true;
+ verticalSpace = height;
+ } else {
+ final int verticalSpaceAbove = bounds.top - displayBounds.top - minMargin;
+ if (height <= verticalSpaceAbove) {
+ // Fits above bounds.
+ below = false;
+ verticalSpace = height;
+ } else {
+ // Pick above/below based on which has the most space.
+ if (verticalSpaceBelow >= verticalSpaceAbove) {
+ below = true;
+ verticalSpace = verticalSpaceBelow;
+ } else {
+ below = false;
+ verticalSpace = verticalSpaceAbove;
+ }
+ }
+ }
+
+ int gravity;
+ int y;
+ if (below) {
+ if (DEBUG) Slog.d(TAG, "anchorBelow");
+ gravity = Gravity.TOP | Gravity.LEFT;
+ y = bounds.bottom - displayBounds.top;
+ } else {
+ if (DEBUG) Slog.d(TAG, "anchorAbove");
+ gravity = Gravity.BOTTOM | Gravity.LEFT;
+ y = displayBounds.bottom - bounds.top;
+ }
+
+ final int x = bounds.left - displayBounds.left;
+
+ params.gravity = gravity;
+ params.x = x;
+ params.y = y;
+ params.width = bounds.width();
+ params.height = verticalSpace;
+ }
+
+ private static LayoutParams createWindowLayoutParams(IBinder appToken, int flags) {
+ final LayoutParams params = new LayoutParams();
+ params.token = appToken;
+ params.type = LayoutParams.TYPE_PHONE;
+ params.flags =
+ flags
+ | LayoutParams.FLAG_NOT_FOCUSABLE // don't receive input events
+ | LayoutParams.FLAG_ALT_FOCUSABLE_IM; // resize for soft input
+ params.format = PixelFormat.TRANSLUCENT;
+ return params;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index 76c2916..45fedd1 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -69,8 +69,6 @@
private AnchoredWindow mFillWindow;
private DatasetPicker mFillView;
private ViewState mViewState;
- private Rect mBounds;
- private String mFilterText;
/**
* Custom snackbar UI used for saving autofill or other informational messages.
@@ -114,8 +112,6 @@
}
mViewState = null;
- mBounds = null;
- mFilterText = null;
mFillView = null;
mFillWindow = null;
}
@@ -143,23 +139,14 @@
mSession.autoFillApp(dataset);
hideFillUi();
});
- mFillWindow = new AnchoredWindow(
- mWm, mFillView, 800, ViewGroup.LayoutParams.WRAP_CONTENT);
+ mFillWindow = new AnchoredWindow(mWm, mAppToken, mFillView);
- if (DEBUG) Slog.d(TAG, "show FillUi");
+ if (DEBUG) Slog.d(TAG, "showFillUi(): view changed");
}
- if (!bounds.equals(mBounds)) {
- if (DEBUG) Slog.d(TAG, "update FillUi bounds: " + mBounds);
- mBounds = bounds;
- mFillWindow.show(mBounds);
- }
-
- if (!filterText.equals(mFilterText)) {
- if (DEBUG) Slog.d(TAG, "update FillUi filter text: " + mFilterText);
- mFilterText = filterText;
- mFillView.update(mFilterText);
- }
+ if (DEBUG) Slog.d(TAG, "showFillUi(): bounds=" + bounds + ", filterText=" + filterText);
+ mFillView.update(filterText);
+ mFillWindow.show(bounds);
}, 0);
}
@@ -248,8 +235,6 @@
pw.print(prefix); pw.print("mSessionId: "); pw.println(mSession.mId);
pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState);
- pw.print(prefix); pw.print("mBounds: "); pw.println(mBounds);
- pw.print(prefix); pw.print("mFilterText: "); pw.println(mFilterText);
}
//similar to a snackbar, but can be a bit custom since it is more than just text. This will
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
index 7245aaa..db516d8 100644
--- a/services/autofill/java/com/android/server/autofill/DatasetPicker.java
+++ b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
@@ -38,8 +38,6 @@
* 3) the View is detached.
*/
final class DatasetPicker extends ListView implements OnItemClickListener {
- private static final String TAG = "DatasetPicker";
-
interface Listener {
void onDatasetPicked(Dataset dataset);
}
@@ -80,7 +78,7 @@
adapter.getFilter().filter(prefix, new FilterListener() {
@Override
public void onFilterComplete(int count) {
- DatasetPicker.this.requestLayout();
+ setVisibility(count > 0 ? View.VISIBLE : View.GONE);
}
});
}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index dd550f2..6248cab 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -49,8 +49,10 @@
import android.os.UEventObserver;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.battery.BatteryServiceDumpProto;
import android.util.EventLog;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import java.io.File;
import java.io.FileDescriptor;
@@ -801,6 +803,35 @@
}
}
+ private void dumpProto(FileDescriptor fd) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ synchronized (mLock) {
+ proto.write(BatteryServiceDumpProto.ARE_UPDATES_STOPPED, mUpdatesStopped);
+ int batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_NONE;
+ if (mBatteryProps.chargerAcOnline) {
+ batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_AC;
+ } else if (mBatteryProps.chargerUsbOnline) {
+ batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_USB;
+ } else if (mBatteryProps.chargerWirelessOnline) {
+ batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_WIRELESS;
+ }
+ proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
+ proto.write(BatteryServiceDumpProto.MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
+ proto.write(BatteryServiceDumpProto.CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
+ proto.write(BatteryServiceDumpProto.STATUS, mBatteryProps.batteryStatus);
+ proto.write(BatteryServiceDumpProto.HEALTH, mBatteryProps.batteryHealth);
+ proto.write(BatteryServiceDumpProto.IS_PRESENT, mBatteryProps.batteryPresent);
+ proto.write(BatteryServiceDumpProto.LEVEL, mBatteryProps.batteryLevel);
+ proto.write(BatteryServiceDumpProto.SCALE, BATTERY_SCALE);
+ proto.write(BatteryServiceDumpProto.VOLTAGE, mBatteryProps.batteryVoltage);
+ proto.write(BatteryServiceDumpProto.TEMPERATURE, mBatteryProps.batteryTemperature);
+ proto.write(BatteryServiceDumpProto.TECHNOLOGY, mBatteryProps.batteryTechnology);
+ }
+ proto.flush();
+ }
+
private final class Led {
private final Light mBatteryLight;
@@ -878,7 +909,11 @@
return;
}
- dumpInternal(fd, pw, args);
+ if (args.length > 0 && "--proto".equals(args[0])) {
+ dumpProto(fd);
+ } else {
+ dumpInternal(fd, pw, args);
+ }
}
@Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 3e711ec..22eca77 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3028,22 +3028,22 @@
PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
mSettings.getCurrentUserId());
- final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
+ final HashMap<String, List<InputMethodSubtype>> additionalSubtypeMap =
mFileManager.getAllAdditionalInputMethodSubtypes();
for (int i = 0; i < services.size(); ++i) {
ResolveInfo ri = services.get(i);
ServiceInfo si = ri.serviceInfo;
- ComponentName compName = new ComponentName(si.packageName, si.name);
- if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
- si.permission)) {
- Slog.w(TAG, "Skipping input method " + compName
+ final String imeId = InputMethodInfo.computeId(ri);
+ if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
+ Slog.w(TAG, "Skipping input method " + imeId
+ ": it does not require the permission "
+ android.Manifest.permission.BIND_INPUT_METHOD);
continue;
}
- if (DEBUG) Slog.d(TAG, "Checking " + compName);
+ if (DEBUG) Slog.d(TAG, "Checking " + imeId);
+ final List<InputMethodSubtype> additionalSubtypes = additionalSubtypeMap.get(imeId);
try {
InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
mMethodList.add(p);
@@ -3054,7 +3054,7 @@
Slog.d(TAG, "Found an input method " + p);
}
} catch (Exception e) {
- Slog.wtf(TAG, "Unable to load input method " + compName, e);
+ Slog.wtf(TAG, "Unable to load input method " + imeId, e);
}
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 25016f6..22dbf44 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -183,11 +183,12 @@
// connection.
if (DBG) Log.d(TAG, "No active scorers available.");
unbindFromScoringServiceIfNeeded();
- } else if (activeScorer.packageName.equals(scorerPackageName)) {
+ } else if (activeScorer.getRecommendationServicePackageName().equals(scorerPackageName))
+ {
// The active scoring service changed in some way.
if (DBG) {
Log.d(TAG, "Possible change to the active scorer: "
- + activeScorer.packageName);
+ + activeScorer.getRecommendationServicePackageName());
}
if (forceUnbind) {
unbindFromScoringServiceIfNeeded();
@@ -198,7 +199,8 @@
// bound to the correct scoring app. The logic in bindToScoringServiceIfNeeded()
// will sort that out to leave us bound to the most recent active scorer.
if (DBG) {
- Log.d(TAG, "Binding to " + activeScorer.packageName + " if needed.");
+ Log.d(TAG, "Binding to " + activeScorer.getRecommendationServiceComponent()
+ + " if needed.");
}
bindToScoringServiceIfNeeded(activeScorer);
}
@@ -334,22 +336,19 @@
bindToScoringServiceIfNeeded(scorerData);
}
- private void bindToScoringServiceIfNeeded(NetworkScorerAppData scorerData) {
- if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + scorerData + ")");
- if (scorerData != null && scorerData.recommendationServiceClassName != null) {
- ComponentName componentName = new ComponentName(scorerData.packageName,
- scorerData.recommendationServiceClassName);
+ private void bindToScoringServiceIfNeeded(NetworkScorerAppData appData) {
+ if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + appData + ")");
+ if (appData != null) {
synchronized (mServiceConnectionLock) {
// If we're connected to a different component then drop it.
if (mServiceConnection != null
- && !mServiceConnection.mComponentName.equals(componentName)) {
+ && !mServiceConnection.mAppData.equals(appData)) {
unbindFromScoringServiceIfNeeded();
}
// If we're not connected at all then create a new connection.
if (mServiceConnection == null) {
- mServiceConnection = new ScoringServiceConnection(componentName,
- scorerData.packageUid);
+ mServiceConnection = new ScoringServiceConnection(appData);
}
// Make sure the connection is connected (idempotent)
@@ -625,7 +624,7 @@
}
}
- private boolean isCallerSystemUid() {
+ private boolean callerCanRequestScores() {
// REQUEST_NETWORK_SCORES is a signature only permission.
return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) ==
PackageManager.PERMISSION_GRANTED;
@@ -634,7 +633,7 @@
@Override
public boolean clearScores() {
// Only the active scorer or the system should be allowed to flush all scores.
- if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
+ if (isCallerActiveScorer(getCallingUid()) || callerCanRequestScores()) {
final long token = Binder.clearCallingIdentity();
try {
clearInternal();
@@ -672,7 +671,8 @@
@Override
public boolean isCallerActiveScorer(int callingUid) {
synchronized (mServiceConnectionLock) {
- return mServiceConnection != null && mServiceConnection.mScoringAppUid == callingUid;
+ return mServiceConnection != null
+ && mServiceConnection.mAppData.packageUid == callingUid;
}
}
@@ -686,7 +686,7 @@
public String getActiveScorerPackage() {
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
- return mServiceConnection.mComponentName.getPackageName();
+ return mServiceConnection.getPackageName();
}
}
return null;
@@ -695,7 +695,7 @@
@Override
public void disableScoring() {
// Only the active scorer or the system should be allowed to disable scoring.
- if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
+ if (isCallerActiveScorer(getCallingUid()) || callerCanRequestScores()) {
// no-op for now but we could write to the setting if needed.
} else {
throw new SecurityException(
@@ -881,7 +881,7 @@
writer.println("Scoring is disabled.");
return;
}
- writer.println("Current scorer: " + currentScorer.packageName);
+ writer.println("Current scorer: " + currentScorer);
sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
@Override
@@ -966,21 +966,19 @@
}
private static class ScoringServiceConnection implements ServiceConnection {
- private final ComponentName mComponentName;
- private final int mScoringAppUid;
+ private final NetworkScorerAppData mAppData;
private volatile boolean mBound = false;
private volatile boolean mConnected = false;
private volatile INetworkRecommendationProvider mRecommendationProvider;
- ScoringServiceConnection(ComponentName componentName, int scoringAppUid) {
- mComponentName = componentName;
- mScoringAppUid = scoringAppUid;
+ ScoringServiceConnection(NetworkScorerAppData appData) {
+ mAppData = appData;
}
void connect(Context context) {
if (!mBound) {
Intent service = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
- service.setComponent(mComponentName);
+ service.setComponent(mAppData.getRecommendationServiceComponent());
mBound = context.bindServiceAsUser(service, this,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
UserHandle.SYSTEM);
@@ -1010,6 +1008,10 @@
return mRecommendationProvider;
}
+ String getPackageName() {
+ return mAppData.getRecommendationServiceComponent().getPackageName();
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
@@ -1027,7 +1029,9 @@
}
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound
+ writer.println("ScoringServiceConnection: "
+ + mAppData.getRecommendationServiceComponent()
+ + ", bound: " + mBound
+ ", connected: " + mConnected);
}
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index bfa3f04..fdd7cb1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -287,16 +287,17 @@
* and then rebuild the cache. All under the cache lock. But that change is too
* large at this point.
*/
+ final String removedPackageName = intent.getData().toString();
Runnable purgingRunnable = new Runnable() {
@Override
public void run() {
purgeOldGrantsAll();
// Notify authenticator about removed app?
+ removeVisibilityValuesForPackage(removedPackageName);
}
};
mHandler.post(purgingRunnable);
}
-
}
}, intentFilter);
@@ -429,7 +430,7 @@
@Override
public boolean addAccountExplicitlyWithVisibility(Account account, String password,
- Bundle extras, Map uidToVisibility) {
+ Bundle extras, Map packageToVisibility) {
Bundle.setDefusable(extras, true);
final int callingUid = Binder.getCallingUid();
@@ -455,7 +456,7 @@
try {
UserAccounts accounts = getUserAccounts(userId);
return addAccountInternal(accounts, account, password, extras, callingUid,
- (Map<Integer, Integer>) uidToVisibility);
+ (Map<String, Integer>) packageToVisibility);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -505,7 +506,7 @@
if (accountsOfType != null) {
for (Account account : accountsOfType) {
result.put(account,
- resolveAccountVisibility(account, uid, packageName, accounts));
+ resolveAccountVisibility(account, packageName, accounts));
}
}
}
@@ -514,7 +515,7 @@
}
@Override
- public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
+ public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
if (account == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getUserId(callingUid);
@@ -525,18 +526,18 @@
String.format("uid %s cannot get secrets for account %s", callingUid, account);
throw new SecurityException(msg);
}
- return getUidsAndVisibilityForAccount(account, accounts);
+ return getPackagesAndVisibilityForAccount(account, accounts);
}
/**
- * Returns all UIDs and visibility values, which were set for given account
+ * Returns all package names and visibility values, which were set for given account.
*
- * @param account account
+ * @param account Account to get visibility values.
* @param accounts UserAccount that currently hosts the account and application
*
- * @return Map from uid to visibility.
+ * @return Map from package names to visibility.
*/
- private Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account,
+ private Map<String, Integer> getPackagesAndVisibilityForAccount(Account account,
UserAccounts accounts) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
@@ -548,7 +549,7 @@
}
@Override
- public int getAccountVisibility(Account a, int uid) {
+ public int getAccountVisibility(Account a, String packageName) {
if (a == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
@@ -559,23 +560,24 @@
a.type);
throw new SecurityException(msg);
}
- return getAccountVisibility(a, uid, getUserAccounts(UserHandle.getUserId(callingUid)));
+ return getAccountVisibility(a, packageName,
+ getUserAccounts(UserHandle.getUserId(callingUid)));
}
/**
- * Method gets visibility for given account and UID from the database
+ * Method returns visibility for given account and package name.
*
- * @param account The account to check visibility of
- * @param uid UID to check visibility of
+ * @param account The account to check visibility.
+ * @param packageName Package name to check visibility.
* @param accounts UserAccount that currently hosts the account and application
*
* @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored.
*
*/
- private int getAccountVisibility(Account account, int uid, UserAccounts accounts) {
+ private int getAccountVisibility(Account account, String packageName, UserAccounts accounts) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
- Integer visibility = accounts.accountsDb.findAccountVisibility(account, uid);
+ Integer visibility = accounts.accountsDb.findAccountVisibility(account, packageName);
return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED;
} finally {
StrictMode.setThreadPolicy(oldPolicy);
@@ -586,19 +588,29 @@
* Method which handles default values for Account visibility.
*
* @param account The account to check visibility.
- * @param uid UID to check visibility.
- * @param packageName Package name to check visibility - the method assumes that it has the same
- * uid as specified in the parameter.
+ * @param packageName Package name to check visibility
* @param accounts UserAccount that currently hosts the account and application
*
* @return Visibility value, the method never returns AccountManager.VISIBILITY_UNDEFINED
*
*/
- private Integer resolveAccountVisibility(Account account, int uid, String packageName,
+ private Integer resolveAccountVisibility(Account account, @NonNull String packageName,
UserAccounts accounts) {
- if (packageName == null) {
- packageName = getPackageNameForUid(uid);
+ Preconditions.checkNotNull(packageName, "packageName cannot be null");
+
+ int uid = -1;
+ try {
+ long identityToken = clearCallingIdentity();
+ try {
+ uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ } catch (NameNotFoundException e) {
+ Log.d(TAG, "Package not found " + e.getMessage());
+ return AccountManager.VISIBILITY_NOT_VISIBLE;
}
+
// System visibility can not be restricted.
if (UserHandle.isSameApp(uid, Process.SYSTEM_UID)) {
return AccountManager.VISIBILITY_VISIBLE;
@@ -612,8 +624,13 @@
return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account
}
+ if (isSpecialPackageKey(packageName)) {
+ Log.d(TAG, "Package name is forbidden: " + packageName);
+ return AccountManager.VISIBILITY_NOT_VISIBLE;
+ }
+
// Return stored value if it was set.
- int visibility = getAccountVisibility(account, uid, accounts);
+ int visibility = getAccountVisibility(account, packageName, accounts);
if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
return visibility;
@@ -622,10 +639,9 @@
if (isPermittedForPackage(packageName, accounts.userId,
Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
return AccountManager.VISIBILITY_VISIBLE;
-
}
// Profile owner gets visibility by default.
- if(isProfileOwner(uid)) {
+ if (isProfileOwner(uid)) {
return AccountManager.VISIBILITY_VISIBLE;
}
// Apps with READ_CONTACTS permission get visibility by default even post O.
@@ -638,13 +654,13 @@
// Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
// match.
visibility = getAccountVisibility(account,
- AccountManager.UID_KEY_DEFAULT_LEGACY_VISIBILITY, accounts);
+ AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE, accounts);
if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
}
} else {
- visibility = getAccountVisibility(account, AccountManager.UID_KEY_DEFAULT_VISIBILITY,
- accounts);
+ visibility = getAccountVisibility(account,
+ AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE, accounts);
if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
}
@@ -655,7 +671,7 @@
/**
* Checks targetSdk for a package;
*
- * @param packageName Package Name
+ * @param packageName Package name
*
* @return True if package's target SDK is below {@link android.os.Build.VERSION_CODES#O}, or
* undefined
@@ -682,7 +698,7 @@
}
@Override
- public boolean setAccountVisibility(Account a, int uid, int newVisibility) {
+ public boolean setAccountVisibility(Account a, String packageName, int newVisibility) {
if (a == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
@@ -693,38 +709,42 @@
a.type);
throw new SecurityException(msg);
}
- return setAccountVisibility(a, uid, newVisibility, true /* notify */,
+ return setAccountVisibility(a, packageName, newVisibility, true /* notify */,
getUserAccounts(UserHandle.getUserId(callingUid)));
}
/**
- * Gives a certain UID, represented a application, access to an account. This method
- * is called indirectly by the Authenticator.
+ * Updates visibility for given account name and package.
*
- * @param account Account to update visibility
- * @param uid to add visibility of the Account
- * @param newVisibility new visibility
+ * @param account Account to update visibility.
+ * @param packageName Package name for which visibility is updated.
+ * @param newVisibility New visibility calue
* @param notify if the flag is set applications will get notification about visibility change
* @param accounts UserAccount that currently hosts the account and application
*
* @return True if account visibility was changed.
*/
- private boolean setAccountVisibility(Account account, int uid, int newVisibility,
+ private boolean setAccountVisibility(Account account, String packageName, int newVisibility,
boolean notify, UserAccounts accounts) {
synchronized (accounts.cacheLock) {
LinkedHashSet<String> interestedPackages;
if (notify) {
- if (uid < 0) {
+ if (isSpecialPackageKey(packageName)) {
interestedPackages = getRequestingPackageNames(account.type, accounts);
} else {
- interestedPackages = new LinkedHashSet<>();
- String[] subPackages = mPackageManager.getPackagesForUid(uid);
- if (subPackages != null) {
- Collections.addAll(interestedPackages, subPackages);
+ if (!packageExistsForUser(packageName, accounts.userId)) {
+ return false; // package is not installed.
}
+ interestedPackages = new LinkedHashSet<>();
+ interestedPackages.add(packageName);
}
} else {
// Notifications will not be send.
+ if (!isSpecialPackageKey(packageName) &&
+ !packageExistsForUser(packageName, accounts.userId)) {
+ // package is not installed and not meta value.
+ return false;
+ }
interestedPackages = new LinkedHashSet<>();
}
Integer[] interestedPackagesVisibility = new Integer[interestedPackages.size()];
@@ -734,14 +754,15 @@
return false;
}
int index = 0;
- for (String packageName : interestedPackages) {
+ for (String interestedPackage : interestedPackages) {
interestedPackagesVisibility[index++] =
- resolveAccountVisibility(account, uid, packageName, accounts);
+ resolveAccountVisibility(account, interestedPackage, accounts);
}
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
- if (!accounts.accountsDb.setAccountVisibility(accountId, uid, newVisibility)) {
+ if (!accounts.accountsDb.setAccountVisibility(accountId, packageName,
+ newVisibility)) {
return false;
}
} finally {
@@ -749,10 +770,10 @@
}
index = 0;
- for (String packageName : interestedPackages) {
- int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
+ for (String interestedPackage : interestedPackages) {
+ int visibility = resolveAccountVisibility(account, interestedPackage, accounts);
if (visibility != interestedPackagesVisibility[index++]) {
- sendNotification(packageName, account, accounts.userId);
+ sendNotification(interestedPackage, account, accounts.userId);
}
}
if (notify) {
@@ -777,23 +798,40 @@
LinkedHashSet<String> interestedPackages = getRequestingPackageNames(account.type,
accounts);
for (String packageName : interestedPackages) {
- try {
- final int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
- int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
- if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) {
- sendNotification(packageName, account, accounts.userId);
- }
- } catch (NameNotFoundException e) {
- // ignore
+ int visibility = resolveAccountVisibility(account, packageName, accounts);
+ if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) {
+ sendNotification(packageName, account, accounts.userId);
}
}
}
- LinkedHashSet<String> getRequestingPackageNames(String accountType, UserAccounts accouns) {
+ LinkedHashSet<String> getRequestingPackageNames(String accountType, UserAccounts accounts) {
// TODO return packages registered to get notifications.
return new LinkedHashSet<String>();
}
+ private boolean packageExistsForUser(String packageName, int userId) {
+ try {
+ long identityToken = clearCallingIdentity();
+ try {
+ mPackageManager.getPackageUidAsUser(packageName, userId);
+ return true; // package exist
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if packageName is one of special values.
+ */
+ private boolean isSpecialPackageKey(String packageName) {
+ return (AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE.equals(packageName)
+ || AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE.equals(packageName));
+ }
+
private void sendAccountsChangedBroadcast(int userId) {
Log.i(TAG, "the accounts changed, sending broadcast of "
+ ACCOUNTS_CHANGED_INTENT.getAction());
@@ -1075,6 +1113,20 @@
}
}
+ private void removeVisibilityValuesForPackage(String packageName) {
+ synchronized (mUsers) {
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserAccounts accounts = mUsers.valueAt(i);
+ try {
+ int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
+ } catch (NameNotFoundException e) {
+ // package does not exist - remove visibility values
+ accounts.accountsDb.deleteAccountVisibilityForPackage(packageName);
+ }
+ }
+ }
+ }
+
private void onUserRemoved(Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userId < 1) return;
@@ -1472,7 +1524,7 @@
}
private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
- Bundle extras, int callingUid, Map<Integer, Integer> uidToVisibility) {
+ Bundle extras, int callingUid, Map<String, Integer> packageToVisibility) {
Bundle.setDefusable(extras, true);
if (account == null) {
return false;
@@ -1513,9 +1565,9 @@
}
}
- if (uidToVisibility != null) {
- for (Entry<Integer, Integer> entry : uidToVisibility.entrySet()) {
- setAccountVisibility(account, entry.getKey() /* uid */,
+ if (packageToVisibility != null) {
+ for (Entry<String, Integer> entry : packageToVisibility.entrySet()) {
+ setAccountVisibility(account, entry.getKey() /* package */,
entry.getValue() /* visibility */, false /* notify */, accounts);
}
}
@@ -1569,6 +1621,7 @@
public void hasFeatures(IAccountManagerResponse response,
Account account, String[] features, String opPackageName) {
int callingUid = Binder.getCallingUid();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "hasFeatures: " + account
+ ", response " + response
@@ -1982,14 +2035,7 @@
int[] visibilityForInterestedPackages = new int[interestedPackages.size()];
int index = 0;
for (String packageName : interestedPackages) {
- int visibility = AccountManager.VISIBILITY_NOT_VISIBLE;
- try {
- final int uid = mPackageManager.getPackageUidAsUser(packageName,
- UserHandle.getUserId(callingUid));
- visibility = resolveAccountVisibility(account, uid, packageName, accounts);
- } catch (NameNotFoundException e) {
- // ignore
- }
+ int visibility = resolveAccountVisibility(account, packageName, accounts);
visibilityForInterestedPackages[index++] = visibility;
}
accounts.accountsDb.beginTransaction();
@@ -3663,7 +3709,7 @@
// In addition to the permissions required to get an auth token we also allow
// the account to be accessed by apps for which user or authenticator granted visibility.
- int visibility = resolveAccountVisibility(account, uid, packageName,
+ int visibility = resolveAccountVisibility(account, packageName,
getUserAccounts(UserHandle.getUserId(uid)));
return (visibility == AccountManager.VISIBILITY_VISIBLE
|| visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
@@ -3870,6 +3916,7 @@
@NonNull
public Account[] getAccounts(int userId, String opPackageName) {
int callingUid = Binder.getCallingUid();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
opPackageName);
if (visibleAccountTypes.isEmpty()) {
@@ -3890,7 +3937,7 @@
}
/**
- * Returns accounts for all running users.
+ * Returns accounts for all running users, ignores visibility values.
*
* @hide
*/
@@ -3906,7 +3953,11 @@
return getAccounts(runningUserIds);
}
- /** {@hide} */
+ /**
+ * Returns accounts for all users, ignores visibility values.
+ *
+ * @hide
+ */
@NonNull
public AccountAndUser[] getAllAccounts() {
final List<UserInfo> users = getUserManager().getUsers(true);
@@ -3924,10 +3975,12 @@
UserAccounts userAccounts = getUserAccounts(userId);
if (userAccounts == null) continue;
synchronized (userAccounts.cacheLock) {
- Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
+ Account[] accounts = getAccountsFromCacheLocked(
+ userAccounts,
+ null /* type */,
Binder.getCallingUid(),
- null,
- false /* incl managed not visible*/);
+ null /* packageName */,
+ false /* include managed not visible*/);
for (int a = 0; a < accounts.length; a++) {
runningAccounts.add(new AccountAndUser(accounts[a], userId));
}
@@ -3941,9 +3994,10 @@
@Override
@NonNull
public Account[] getAccountsAsUser(String type, int userId, String opPackageName) {
- // Need calling package
- return getAccountsAsUser(type, userId, null /* callingPackage */, -1, opPackageName,
- false /* includeUserManagedNotVisible */);
+ int callingUid = Binder.getCallingUid();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
+ return getAccountsAsUser(type, userId, opPackageName /* callingPackage */, -1,
+ opPackageName, false /* includeUserManagedNotVisible */);
}
@NonNull
@@ -4112,6 +4166,7 @@
public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
int callingUid = Binder.getCallingUid();
if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
+ // Don't do opPackageName check - caller is system.
throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
+ callingUid + " with uid=" + uid);
}
@@ -4125,6 +4180,7 @@
String opPackageName) {
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
int packageUid = -1;
try {
packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
@@ -4148,6 +4204,7 @@
String[] features,
String opPackageName) {
int callingUid = Binder.getCallingUid();
+ mAppOpsManager.checkPackage(callingUid, opPackageName);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAccounts: accountType " + type
+ ", response " + response
@@ -4738,7 +4795,7 @@
userAccounts.accountsDb.dumpDeAccountsTable(fout);
} else {
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
- Process.SYSTEM_UID, null, false);
+ Process.SYSTEM_UID, null /* packageName */, false);
fout.println("Accounts: " + accounts.length);
for (Account account : accounts) {
fout.println(" " + account);
@@ -4954,7 +5011,7 @@
// Method checks visibility for applications targeing API level below {@link
// android.os.Build.VERSION_CODES#O},
- // returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVELEGED permission.
+ // returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVILEGED permission.
private boolean checkGetAccountsPermission(String packageName, int userId) {
return isPermittedForPackage(packageName, userId, Manifest.permission.GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
@@ -5307,8 +5364,7 @@
// filter based on visibility.
Map<Account, Integer> firstPass = new HashMap<>();
for (Account account : unfiltered) {
- int visibility =
- resolveAccountVisibility(account, callingUid, callingPackage, accounts);
+ int visibility = resolveAccountVisibility(account, callingPackage, accounts);
if ((visibility == AccountManager.VISIBILITY_VISIBLE
|| visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE)
|| (includeManagedNotVisible
@@ -5403,6 +5459,9 @@
*/
protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
int callingUid, String callingPackage, boolean includeManagedNotVisible) {
+ if (callingPackage == null) {
+ callingPackage = getPackageNameForUid(callingUid);
+ }
if (accountType != null) {
final Account[] accounts = userAccounts.accountCache.get(accountType);
if (accounts == null) {
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 85e4b5f..22543cb 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -54,7 +54,7 @@
private static final String DATABASE_NAME = "accounts.db";
private static final int PRE_N_DATABASE_VERSION = 9;
private static final int CE_DATABASE_VERSION = 10;
- private static final int DE_DATABASE_VERSION = 2; // Added visibility support in O.
+ private static final int DE_DATABASE_VERSION = 3; // Added visibility support in O
static final String TABLE_ACCOUNTS = "accounts";
@@ -75,7 +75,7 @@
private static final String TABLE_VISIBILITY = "visibility";
private static final String VISIBILITY_ACCOUNTS_ID = "accounts_id";
- private static final String VISIBILITY_UID = "_uid";
+ private static final String VISIBILITY_PACKAGE = "_package";
private static final String VISIBILITY_VALUE = "value";
private static final String TABLE_GRANTS = "grants";
@@ -252,7 +252,7 @@
createAccountsDeletionTrigger(db);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_GRANTS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_DEBUG);
- oldVersion ++;
+ oldVersion++;
}
if (oldVersion != newVersion) {
@@ -559,9 +559,9 @@
private void createAccountsVisibilityTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_VISIBILITY + " ( "
+ VISIBILITY_ACCOUNTS_ID + " INTEGER NOT NULL, "
- + VISIBILITY_UID + " TEXT NOT NULL, "
+ + VISIBILITY_PACKAGE + " TEXT NOT NULL, "
+ VISIBILITY_VALUE + " INTEGER, "
- + "PRIMARY KEY(" + VISIBILITY_ACCOUNTS_ID + "," + VISIBILITY_UID + "))");
+ + "PRIMARY KEY(" + VISIBILITY_ACCOUNTS_ID + "," + VISIBILITY_PACKAGE + "))");
}
static void createDebugTable(SQLiteDatabase db) {
@@ -591,9 +591,18 @@
Log.i(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
if (oldVersion == 1) {
- createAccountsVisibilityTable(db);
- createAccountsDeletionVisibilityCleanupTrigger(db);
- ++oldVersion;
+ createAccountsVisibilityTable(db);
+ createAccountsDeletionVisibilityCleanupTrigger(db);
+ oldVersion = 3; // skip version 2 which had uid based table
+ }
+
+ if (oldVersion == 2) {
+ // Remove uid based table and replace it with packageName based
+ db.execSQL("DROP TRIGGER IF EXISTS " + TABLE_ACCOUNTS + "DeleteVisibility");
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_VISIBILITY);
+ createAccountsVisibilityTable(db);
+ createAccountsDeletionVisibilityCleanupTrigger(db);
+ oldVersion++;
}
if (oldVersion != newVersion) {
@@ -890,20 +899,20 @@
new String[] {Integer.toString(uid)}) > 0;
}
- boolean setAccountVisibility(long accountId, int uid, int visibility) {
+ boolean setAccountVisibility(long accountId, String packageName, int visibility) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(VISIBILITY_ACCOUNTS_ID, String.valueOf(accountId));
- values.put(VISIBILITY_UID, String.valueOf(uid));
+ values.put(VISIBILITY_PACKAGE, packageName);
values.put(VISIBILITY_VALUE, String.valueOf(visibility));
return (db.replace(TABLE_VISIBILITY, VISIBILITY_VALUE, values) != -1);
}
- Integer findAccountVisibility(Account account, int uid) {
+ Integer findAccountVisibility(Account account, String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
- SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_UID + "=? ",
- new String[] {account.name, account.type, String.valueOf(uid)}, null, null, null);
+ SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_PACKAGE + "=? ",
+ new String[] {account.name, account.type, packageName}, null, null, null);
try {
while (cursor.moveToNext()) {
return cursor.getInt(0);
@@ -914,11 +923,11 @@
return null;
}
- Integer findAccountVisibility(long accountId, int uid) {
+ Integer findAccountVisibility(long accountId, String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
- VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_UID + "=? ",
- new String[] {String.valueOf(accountId), String.valueOf(uid)}, null, null, null);
+ VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_PACKAGE + "=? ",
+ new String[] {String.valueOf(accountId), packageName}, null, null, null);
try {
while (cursor.moveToNext()) {
return cursor.getInt(0);
@@ -944,18 +953,18 @@
}
/**
- * Returns a map from uid to visibility value.
+ * Returns a map from packageNames to visibility.
*/
- Map<Integer, Integer> findAllVisibilityValuesForAccount(Account account) {
+ Map<String, Integer> findAllVisibilityValuesForAccount(Account account) {
SQLiteDatabase db = mDeDatabase.getReadableDatabase();
- Map<Integer, Integer> result = new HashMap<>();
+ Map<String, Integer> result = new HashMap<>();
final Cursor cursor =
- db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_UID, VISIBILITY_VALUE},
- SELECTION_ACCOUNTS_ID_BY_ACCOUNT,
- new String[] {account.name, account.type}, null, null, null);
+ db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_PACKAGE, VISIBILITY_VALUE},
+ SELECTION_ACCOUNTS_ID_BY_ACCOUNT, new String[] {account.name, account.type},
+ null, null, null);
try {
while (cursor.moveToNext()) {
- result.put(cursor.getInt(0), cursor.getInt(1));
+ result.put(cursor.getString(0), cursor.getInt(1));
}
} finally {
cursor.close();
@@ -963,10 +972,10 @@
return result;
}
- boolean deleteAccountVisibilityForUid(int uid) {
+ boolean deleteAccountVisibilityForPackage(String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
- return db.delete(TABLE_VISIBILITY, VISIBILITY_UID + "=? ",
- new String[] {Integer.toString(uid)}) > 0;
+ return db.delete(TABLE_VISIBILITY, VISIBILITY_PACKAGE + "=? ",
+ new String[] {packageName}) > 0;
}
long insertOrReplaceMetaAuthTypeAndUid(String authenticatorType, int uid) {
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
new file mode 100644
index 0000000..84e4ea9
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IInstrumentationWatcher;
+import android.app.IUiAutomationConnection;
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
+import android.util.PrintWriterPrinter;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class ActiveInstrumentation {
+ final ActivityManagerService mService;
+
+ // Class installed to instrument app
+ ComponentName mClass;
+
+ // All process names that should be instrumented
+ String[] mTargetProcesses;
+
+ // The application being instrumented
+ ApplicationInfo mTargetInfo;
+
+ // Where to save profiling
+ String mProfileFile;
+
+ // Who is waiting
+ IInstrumentationWatcher mWatcher;
+
+ // Connection to use the UI introspection APIs.
+ IUiAutomationConnection mUiAutomationConnection;
+
+ // As given to us
+ Bundle mArguments;
+
+ // Any intermediate results that have been collected.
+ Bundle mCurResults;
+
+ // Copy of instrumentationClass.
+ ComponentName mResultClass;
+
+ // Contains all running processes that have active instrumentation.
+ final ArrayList<ProcessRecord> mRunningProcesses = new ArrayList<>();
+
+ // Set to true when we have told the watcher the instrumentation is finished.
+ boolean mFinished;
+
+ ActiveInstrumentation(ActivityManagerService service) {
+ mService = service;
+ }
+
+ void removeProcess(ProcessRecord proc) {
+ mFinished = true;
+ mRunningProcesses.remove(proc);
+ if (mRunningProcesses.size() == 0) {
+ mService.mActiveInstrumentation.remove(this);
+ }
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ActiveInstrumentation{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(mClass.toShortString());
+ if (mFinished) {
+ sb.append(" FINISHED");
+ }
+ sb.append(" ");
+ sb.append(mRunningProcesses.size());
+ sb.append(" procs");
+ sb.append('}');
+ return sb.toString();
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mClass="); pw.print(mClass);
+ pw.print(" mFinished="); pw.println(mFinished);
+ pw.print(prefix); pw.println("mRunningProcesses:");
+ for (int i=0; i<mRunningProcesses.size(); i++) {
+ pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(mRunningProcesses.get(i));
+ }
+ pw.print(prefix); pw.print("mTargetProcesses=");
+ pw.println(Arrays.toString(mTargetProcesses));
+ pw.print(prefix); pw.print("mTargetInfo=");
+ pw.println(mTargetInfo);
+ if (mTargetInfo != null) {
+ mTargetInfo.dump(new PrintWriterPrinter(pw), prefix + " ", 0);
+ }
+ if (mProfileFile != null) {
+ pw.print(prefix); pw.print("mProfileFile="); pw.println(mProfileFile);
+ }
+ if (mWatcher != null) {
+ pw.print(prefix); pw.print("mWatcher="); pw.println(mWatcher);
+ }
+ if (mUiAutomationConnection != null) {
+ pw.print(prefix); pw.print("mUiAutomationConnection=");
+ pw.println(mUiAutomationConnection);
+ }
+ pw.print(prefix); pw.print("mArguments=");
+ pw.println(mArguments);
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ee1f28f..5ed8290 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -573,7 +573,9 @@
final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter();
- public IntentFirewall mIntentFirewall;
+ final ArrayList<ActiveInstrumentation> mActiveInstrumentation = new ArrayList<>();
+
+ public final IntentFirewall mIntentFirewall;
// Whether we should show our dialogs (ANR, crash, etc) or just perform their
// default action automatically. Important for devices without direct input
@@ -3926,7 +3928,7 @@
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
- if (app == null || app.instrumentationClass == null) {
+ if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
}
@@ -5092,9 +5094,9 @@
app.activities.clear();
- if (app.instrumentationClass != null) {
+ if (app.instr != null) {
Slog.w(TAG, "Crash of app " + app.processName
- + " running instrumentation " + app.instrumentationClass);
+ + " running instrumentation " + app.instr.mClass);
Bundle info = new Bundle();
info.putString("shortMsg", "Process crashed.");
finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
@@ -5227,7 +5229,7 @@
// Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
- boolean doLowMem = app.instrumentationClass == null;
+ boolean doLowMem = app.instr == null;
boolean doOomAdj = doLowMem;
if (!app.killedByAm) {
Slog.i(TAG, "Process " + app.processName + " (pid " + pid
@@ -6383,7 +6385,7 @@
handleAppDiedLocked(app, willRestart, allowRestart);
if (willRestart) {
removeLruProcessLocked(app);
- addAppLocked(app.info, false, null /* ABI override */);
+ addAppLocked(app.info, null, false, null /* ABI override */);
}
} else {
mRemovedProcesses.add(app);
@@ -6559,7 +6561,7 @@
mWaitForDebugger = mOrigWaitForDebugger;
}
}
- String profileFile = app.instrumentationProfileFile;
+ String profileFile = app.instr != null ? app.instr.mProfileFile : null;
ParcelFileDescriptor profileFd = null;
int samplingInterval = 0;
boolean profileAutoStop = false;
@@ -6587,14 +6589,13 @@
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
}
- if (app.instrumentationClass != null) {
- notifyPackageUse(app.instrumentationClass.getPackageName(),
+ if (app.instr != null) {
+ notifyPackageUse(app.instr.mClass.getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
+ processName + " with config " + getGlobalConfiguration());
- ApplicationInfo appInfo = app.instrumentationInfo != null
- ? app.instrumentationInfo : app.info;
+ ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
app.compat = compatibilityInfoForPackageLocked(appInfo);
if (profileFd != null) {
profileFd = profileFd.dup();
@@ -6614,16 +6615,57 @@
.getSerial();
// }
+ // Check if this is a secondary process that should be incorporated into some
+ // currently active instrumentation. (Note we do this AFTER all of the profiling
+ // stuff above because profiling can currently happen only in the primary
+ // instrumentation process.)
+ if (mActiveInstrumentation.size() > 0 && app.instr == null) {
+ for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) {
+ ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
+ if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
+ if (aInstr.mTargetProcesses.length == 0) {
+ // This is the wildcard mode, where every process brought up for
+ // the target instrumentation should be included.
+ if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
+ app.instr = aInstr;
+ aInstr.mRunningProcesses.add(app);
+ }
+ } else {
+ for (String proc : aInstr.mTargetProcesses) {
+ if (proc.equals(app.processName)) {
+ app.instr = aInstr;
+ aInstr.mRunningProcesses.add(app);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
- thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
- profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
- app.instrumentationUiAutomationConnection, testMode,
- mBinderTransactionTrackingEnabled, enableTrackAllocation,
- isRestrictedBackupMode || !normalMode, app.persistent,
- new Configuration(getGlobalConfiguration()), app.compat,
- getCommonServicesLocked(app.isolated),
- mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial);
+ if (app.instr != null) {
+ thread.bindApplication(processName, appInfo, providers,
+ app.instr.mClass,
+ profilerInfo, app.instr.mArguments,
+ app.instr.mWatcher,
+ app.instr.mUiAutomationConnection, testMode,
+ mBinderTransactionTrackingEnabled, enableTrackAllocation,
+ isRestrictedBackupMode || !normalMode, app.persistent,
+ new Configuration(getGlobalConfiguration()), app.compat,
+ getCommonServicesLocked(app.isolated),
+ mCoreSettingsObserver.getCoreSettingsLocked(),
+ buildSerial);
+ } else {
+ thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
+ null, null, null, testMode,
+ mBinderTransactionTrackingEnabled, enableTrackAllocation,
+ isRestrictedBackupMode || !normalMode, app.persistent,
+ new Configuration(getGlobalConfiguration()), app.compat,
+ getCommonServicesLocked(app.isolated),
+ mCoreSettingsObserver.getCoreSettingsLocked(),
+ buildSerial);
+ }
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
updateLruProcessLocked(app, false, null);
@@ -11595,7 +11637,7 @@
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
- addAppLocked(app, false, null /* ABI override */);
+ addAppLocked(app, null, false, null /* ABI override */);
}
}
} catch (RemoteException ex) {
@@ -11783,17 +11825,18 @@
return false;
}
- final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
+ final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
String abiOverride) {
ProcessRecord app;
if (!isolated) {
- app = getProcessRecordLocked(info.processName, info.uid, true);
+ app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
+ info.uid, true);
} else {
app = null;
}
if (app == null) {
- app = newProcessRecordLocked(info, null, isolated, 0);
+ app = newProcessRecordLocked(info, customProcess, isolated, 0);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
@@ -11814,7 +11857,8 @@
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
- startProcessLocked(app, "added application", app.processName, abiOverride,
+ startProcessLocked(app, "added application",
+ customProcess != null ? customProcess : app.processName, abiOverride,
null /* entryPoint */, null /* entryPointArgs */);
}
@@ -12269,11 +12313,11 @@
synchronized (this) {
synchronized (mPidsSelfLocked) {
final int callingPid = Binder.getCallingPid();
- ProcessRecord precessRecord = mPidsSelfLocked.get(callingPid);
- if (precessRecord == null) {
+ ProcessRecord proc = mPidsSelfLocked.get(callingPid);
+ if (proc == null) {
throw new SecurityException("Unknown process: " + callingPid);
}
- if (precessRecord.instrumentationUiAutomationConnection == null) {
+ if (proc.instr == null || proc.instr.mUiAutomationConnection == null) {
throw new SecurityException("Only an instrumentation process "
+ "with a UiAutomation can call setUserIsMonkey");
}
@@ -12330,7 +12374,7 @@
}
public static long getInputDispatchingTimeoutLocked(ProcessRecord r) {
- if (r != null && (r.instrumentationClass != null || r.usingWrapper)) {
+ if (r != null && (r.instr != null || r.usingWrapper)) {
return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
}
return KEY_DISPATCHING_TIMEOUT;
@@ -12391,7 +12435,7 @@
return false;
}
- if (proc.instrumentationClass != null) {
+ if (proc.instr != null) {
Bundle info = new Bundle();
info.putString("shortMsg", "keyDispatchingTimedOut");
info.putString("longMsg", annotation);
@@ -14901,8 +14945,31 @@
printed = true;
needSep = true;
}
- pw.println(String.format("%sIsolated #%2d: %s",
- " ", i, r.toString()));
+ pw.print(" Isolated #"); pw.print(i); pw.print(": ");
+ pw.println(r);
+ }
+ }
+
+ if (mActiveInstrumentation.size() > 0) {
+ boolean printed = false;
+ for (int i=0; i<mActiveInstrumentation.size(); i++) {
+ ActiveInstrumentation ai = mActiveInstrumentation.get(i);
+ if (dumpPackage != null && !ai.mClass.getPackageName().equals(dumpPackage)
+ && !ai.mTargetInfo.packageName.equals(dumpPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Active instrumentation:");
+ printedAnything = true;
+ printed = true;
+ needSep = true;
+ }
+ pw.print(" Instrumentation #"); pw.print(i); pw.print(": ");
+ pw.println(ai);
+ ai.dump(pw, " ");
}
}
@@ -19046,18 +19113,35 @@
throw new SecurityException(msg);
}
+ ActiveInstrumentation activeInstr = new ActiveInstrumentation(this);
+ activeInstr.mClass = className;
+ String defProcess = ai.processName;;
+ if (ii.targetProcess == null) {
+ activeInstr.mTargetProcesses = new String[]{ai.processName};
+ } else if (ii.targetProcess.equals("*")) {
+ activeInstr.mTargetProcesses = new String[0];
+ } else {
+ activeInstr.mTargetProcesses = ii.targetProcess.split(",");
+ defProcess = activeInstr.mTargetProcesses[0];
+ }
+ activeInstr.mTargetInfo = ai;
+ activeInstr.mProfileFile = profileFile;
+ activeInstr.mArguments = arguments;
+ activeInstr.mWatcher = watcher;
+ activeInstr.mUiAutomationConnection = uiAutomationConnection;
+ activeInstr.mResultClass = className;
+
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId,
"start instr");
- ProcessRecord app = addAppLocked(ai, false, abiOverride);
- app.instrumentationClass = className;
- app.instrumentationInfo = ai;
- app.instrumentationProfileFile = profileFile;
- app.instrumentationArguments = arguments;
- app.instrumentationWatcher = watcher;
- app.instrumentationUiAutomationConnection = uiAutomationConnection;
- app.instrumentationResultClass = className;
+ ProcessRecord app = addAppLocked(ai, defProcess, false, abiOverride);
+ app.instr = activeInstr;
+ activeInstr.mFinished = false;
+ activeInstr.mRunningProcesses.add(app);
+ if (!mActiveInstrumentation.contains(activeInstr)) {
+ mActiveInstrumentation.add(activeInstr);
+ }
Binder.restoreCallingIdentity(origId);
}
@@ -19084,24 +19168,70 @@
}
}
+ void addInstrumentationResultsLocked(ProcessRecord app, Bundle results) {
+ if (app.instr == null) {
+ Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
+ return;
+ }
+
+ if (!app.instr.mFinished && results != null) {
+ if (app.instr.mCurResults == null) {
+ app.instr.mCurResults = new Bundle(results);
+ } else {
+ app.instr.mCurResults.putAll(results);
+ }
+ }
+ }
+
+ public void addInstrumentationResults(IApplicationThread target, Bundle results) {
+ int userId = UserHandle.getCallingUserId();
+ // Refuse possible leaked file descriptors
+ if (results != null && results.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+
+ synchronized(this) {
+ ProcessRecord app = getRecordForAppLocked(target);
+ if (app == null) {
+ Slog.w(TAG, "addInstrumentationResults: no app for " + target);
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ addInstrumentationResultsLocked(app, results);
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
- if (app.instrumentationWatcher != null) {
- mInstrumentationReporter.reportFinished(app.instrumentationWatcher,
- app.instrumentationClass, resultCode, results);
+ if (app.instr == null) {
+ Slog.w(TAG, "finishInstrumentation called on non-instrumented: " + app);
+ return;
}
- // Can't call out of the system process with a lock held, so post a message.
- if (app.instrumentationUiAutomationConnection != null) {
- mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
- app.instrumentationUiAutomationConnection).sendToTarget();
+ if (!app.instr.mFinished) {
+ if (app.instr.mWatcher != null) {
+ Bundle finalResults = app.instr.mCurResults;
+ if (finalResults != null) {
+ if (app.instr.mCurResults != null && results != null) {
+ finalResults.putAll(results);
+ }
+ } else {
+ finalResults = results;
+ }
+ mInstrumentationReporter.reportFinished(app.instr.mWatcher,
+ app.instr.mClass, resultCode, finalResults);
+ }
+
+ // Can't call out of the system process with a lock held, so post a message.
+ if (app.instr.mUiAutomationConnection != null) {
+ mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
+ app.instr.mUiAutomationConnection).sendToTarget();
+ }
+ app.instr.mFinished = true;
}
- app.instrumentationWatcher = null;
- app.instrumentationUiAutomationConnection = null;
- app.instrumentationClass = null;
- app.instrumentationInfo = null;
- app.instrumentationProfileFile = null;
- app.instrumentationArguments = null;
+ app.instr.removeProcess(app);
+ app.instr = null;
forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false, app.userId,
"finished inst");
@@ -19884,7 +20014,7 @@
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
- } else if (app.instrumentationClass != null) {
+ } else if (app.instr != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
@@ -21973,7 +22103,7 @@
mRemovedProcesses.remove(i);
if (app.persistent) {
- addAppLocked(app.info, false, null /* ABI override */);
+ addAppLocked(app.info, null, false, null /* ABI override */);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3573b8b..58c17eb 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -30,6 +30,7 @@
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
@@ -44,7 +45,10 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
+import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -79,6 +83,7 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
@@ -2007,7 +2012,8 @@
+ ", newGlobalConfig=" + newGlobalConfig
+ ", newTaskMergedOverrideConfig=" + newTaskMergedOverrideConfig);
- if ((changes&(~info.getRealConfigChanged())) != 0 || forceNewConfig) {
+ if (shouldRelaunchLocked(changes, newGlobalConfig, newTaskMergedOverrideConfig)
+ || forceNewConfig) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
configChangeFlags |= changes;
startFreezingScreenLocked(app, globalChanges);
@@ -2058,6 +2064,27 @@
return true;
}
+ /**
+ * When assessing a configuration change, decide if the changes flags and the new configurations
+ * should cause the Activity to relaunch.
+ */
+ private boolean shouldRelaunchLocked(int changes, Configuration newGlobalConfig,
+ Configuration newTaskMergedOverrideConfig) {
+ int configChanged = info.getRealConfigChanged();
+
+ // Override for apps targeting pre-O sdks
+ // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
+ // to the config change.
+ // For O and later, apps will be required to add configChanges="uimode" to their manifest.
+ if (appInfo.targetSdkVersion < O
+ && requestedVrComponent != null
+ && (isInVrUiMode(newGlobalConfig) || isInVrUiMode(newTaskMergedOverrideConfig))) {
+ configChanged |= CONFIG_UI_MODE;
+ }
+
+ return (changes&(~configChanged)) != 0;
+ }
+
private static int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
Configuration oldTaskOverride) {
// If we went from full-screen to non-full-screen, make sure to use the correct
@@ -2294,6 +2321,10 @@
}
}
+ private static boolean isInVrUiMode(Configuration config) {
+ return (config.uiMode & Configuration.UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
+ }
+
@Override
public String toString() {
if (stringName != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 10d108b..ba25120 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1554,38 +1554,6 @@
final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
final int focusedStackId = focusedStack.mStackId;
- final TaskRecord topFocusedTask = focusedStack.topTask();
- final boolean isOnTopLauncherFocused = topFocusedTask != null &&
- topFocusedTask.isOnTopLauncher();
- if (isOnTopLauncherFocused) {
- // When an on-top launcher is focused, we should find out whether the freeform stack or
- // the fullscreen stack appears first underneath and has activities to show, and then
- // make it visible.
- boolean behindFullscreenOrFreeForm = false;
- for (int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
- stackBehindFocusedIndex >= 0; stackBehindFocusedIndex--) {
- ActivityStack stack = mStacks.get(stackBehindFocusedIndex);
- if ((stack.mStackId == FREEFORM_WORKSPACE_STACK_ID
- || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
- && stack.topRunningActivityLocked() != null) {
- if (stackIndex == stackBehindFocusedIndex) {
- return !behindFullscreenOrFreeForm ? STACK_VISIBLE : STACK_INVISIBLE;
- }
- behindFullscreenOrFreeForm = true;
- }
- }
- }
- // If an on-top launcher is on the top of the home stack but the home stack is not focused,
- // then the whole stack should be invisible.
- TaskRecord topTask = topTask();
- if (mStackId != focusedStackId && topTask != null && topTask.isOnTopLauncher()) {
- // We're here mostly because the on-top launcher didn't have a chance to move itself to
- // back. We should move it to back as soon as possible to avoid other activities
- // returning to it or other visibility issues.
- moveTaskToBackLocked(topTask.taskId);
- return STACK_INVISIBLE;
- }
-
if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
&& hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
&& !focusedStack.topActivity().fullscreen) {
@@ -1790,28 +1758,7 @@
// status of an activity in a previous task affects other.
behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
} else if (mStackId == HOME_STACK_ID) {
- if (task.isOnTopLauncher()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "On-top launcher: at " + task
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // When an on-top launcher is visible, (e.g. it's on the top of the home stack),
- // other tasks in the home stack could be visible if and only if:
- // - some app is running in the docked stack;
- // - no app is running in either the fullscreen stack or the freefrom stack.
- final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
- final ActivityStack fullscreenStack = mStackSupervisor.getStack(
- FULLSCREEN_WORKSPACE_STACK_ID);
- final ActivityStack freeformStack = mStackSupervisor.getStack(
- FREEFORM_WORKSPACE_STACK_ID);
- final boolean dockedStackEmpty = dockedStack == null ||
- dockedStack.topRunningActivityLocked() == null;
- final boolean fullscreenStackEmpty = fullscreenStack == null ||
- fullscreenStack.topRunningActivityLocked() == null;
- final boolean freeformStackEmpty = freeformStack == null ||
- freeformStack.topRunningActivityLocked() == null;
- behindFullscreenActivity = dockedStackEmpty || !fullscreenStackEmpty ||
- !freeformStackEmpty;
- } else if (task.isHomeTask()) {
+ if (task.isHomeTask()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
+ " stackInvisible=" + stackInvisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2699,14 +2646,7 @@
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHomeOrRecents = lastStack.isHomeOrRecentsStack();
final TaskRecord topTask = lastStack.topTask();
- final boolean fromOnTopLauncher = topTask != null && topTask.isOnTopLauncher();
- if (fromOnTopLauncher) {
- // Since an on-top launcher will is moved to back when tasks are launched from it,
- // those tasks should first try to return to a non-home activity.
- // This also makes sure that non-home activities are visible under a transparent
- // non-home activity.
- task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
+ if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
// If it's a last task over home - we default to keep its return to type not to
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
@@ -4404,23 +4344,6 @@
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId);
if (mStackId == HOME_STACK_ID && topTask().isHomeTask()) {
- if (topTask().isOnTopLauncher()) {
- // An on-top launcher doesn't affect the visibility of activities on other stacks
- // behind it. So if we're moving an on-top launcher to the back, we want to move the
- // focus to the next focusable stack and resume an activity there.
- // Besides, when the docked stack is visible, we should also move the home stack to
- // the back to avoid the recents pops up on top of a fullscreen or freeform
- // activity.
-
- // Move the home stack to back.
- moveToBack(topTask());
-
- // Resume an activity in the next focusable stack.
- adjustFocusToNextFocusableStackLocked("moveTaskToBack");
- mStackSupervisor.resumeFocusedStackTopActivityLocked();
- return true;
- }
-
// For the case where we are moving the home task back and there is an activity visible
// behind it on the fullscreen stack, we want to move the focus to the visible behind
// activity to maintain order with what the user is seeing.
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index c2fc9dc..d1606b4 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1498,15 +1498,7 @@
private void updateTaskReturnToType(
TaskRecord task, int launchFlags, ActivityStack focusedStack) {
- if (focusedStack != null && focusedStack.isHomeOrRecentsStack()
- && focusedStack.topTask() != null && focusedStack.topTask().isOnTopLauncher()) {
- // Since an on-top launcher will is moved to back when tasks are launched from it,
- // those tasks should first try to return to a non-home activity.
- // This also makes sure that non-home activities are visible under a transparent
- // non-home activity.
- task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- return;
- } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
+ if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity.
task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
@@ -1802,7 +1794,7 @@
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
- if (mStartActivity.task == null) {
+ if (mStartActivity.task == null || mStartActivity.task == parent) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 384f2f8..36a913f 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -357,7 +357,7 @@
* If this process was running instrumentation, finish now - it will be handled in
* {@link ActivityManagerService#handleAppDiedLocked}.
*/
- if (r != null && r.instrumentationClass != null) {
+ if (r != null && r.instr != null) {
return;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f1f8bb2..3571302 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -51,8 +51,8 @@
import android.telephony.TelephonyManager;
import android.util.IntArray;
import android.util.Slog;
-
import android.util.TimeUtils;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
@@ -1127,6 +1127,7 @@
pw.println(" full-history: include additional detailed events in battery history:");
pw.println(" wake_lock_in, alarms and proc events");
pw.println(" no-auto-reset: don't automatically reset stats when unplugged");
+ pw.println(" pretend-screen-off: pretend the screen is off, even if screen state changes");
}
private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
@@ -1144,6 +1145,10 @@
synchronized (mStats) {
mStats.setNoAutoReset(enable);
}
+ } else if ("pretend-screen-off".equals(args[i])) {
+ synchronized (mStats) {
+ mStats.setPretendScreenOff(enable);
+ }
} else {
pw.println("Unknown enable/disable option: " + args[i]);
dumpHelp(pw);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 49fe79c..356781f 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -135,13 +135,7 @@
int lruSeq; // Sequence id for identifying LRU update cycles
CompatibilityInfo compat; // last used compatibility mode
IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
- ComponentName instrumentationClass;// class installed to instrument app
- ApplicationInfo instrumentationInfo; // the application being instrumented
- String instrumentationProfileFile; // where to save profiling
- IInstrumentationWatcher instrumentationWatcher; // who is waiting
- IUiAutomationConnection instrumentationUiAutomationConnection; // Connection to use the UI introspection APIs.
- Bundle instrumentationArguments;// as given to us
- ComponentName instrumentationResultClass;// copy of instrumentationClass
+ ActiveInstrumentation instr;// Set to currently active instrumentation running in process
boolean usingWrapper; // Set to true when process was launched with a wrapper attached
final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
long lastWakeTime; // How long proc held wake lock at last check
@@ -248,19 +242,8 @@
pw.println("}");
}
pw.print(prefix); pw.print("compat="); pw.println(compat);
- if (instrumentationClass != null || instrumentationProfileFile != null
- || instrumentationArguments != null) {
- pw.print(prefix); pw.print("instrumentationClass=");
- pw.print(instrumentationClass);
- pw.print(" instrumentationProfileFile=");
- pw.println(instrumentationProfileFile);
- pw.print(prefix); pw.print("instrumentationArguments=");
- pw.println(instrumentationArguments);
- pw.print(prefix); pw.print("instrumentationInfo=");
- pw.println(instrumentationInfo);
- if (instrumentationInfo != null) {
- instrumentationInfo.dump(new PrintWriterPrinter(pw), prefix + " ");
- }
+ if (instr != null) {
+ pw.print(prefix); pw.print("instr="); pw.println(instr);
}
pw.print(prefix); pw.print("thread="); pw.println(thread);
pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9e09cbb..e237e41 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -75,7 +75,6 @@
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
-import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
@@ -191,17 +190,15 @@
int mResizeMode; // The resize mode of this task and its activities.
// Based on the {@link ActivityInfo#resizeMode} of the root activity.
- boolean mSupportsPictureInPicture; // Whether or not this task and its activities support PiP.
- // Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root
- // activity.
+ private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
+ // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
+ // of the root activity.
boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
// changes on a temporary basis.
private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
// ActivityManager.LOCK_TASK_LAUNCH_MODE_*
private boolean mPrivileged; // The root activity application of this task holds
// privileged permissions.
- private boolean mIsOnTopLauncher; // Whether this task is an on-top launcher. See
- // android.R.attr#onTopLauncher.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
@@ -424,8 +421,8 @@
final Configuration overrideConfig = getOverrideConfiguration();
mWindowContainerController = new TaskWindowContainerController(taskId, this,
getStack().getWindowContainerController(), userId, bounds, overrideConfig,
- mResizeMode, mSupportsPictureInPicture, isHomeTask(), isOnTopLauncher(),
- onTop, showForAllUsers, lastTaskDescription);
+ mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
+ lastTaskDescription);
}
void removeWindowContainer() {
@@ -688,7 +685,6 @@
}
mResizeMode = info.resizeMode;
mSupportsPictureInPicture = info.supportsPictureInPicture();
- mIsOnTopLauncher = (info.flags & FLAG_ON_TOP_LAUNCHER) != 0;
mLockTaskMode = info.lockTaskLaunchMode;
mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
setLockTaskAuth();
@@ -1335,7 +1331,7 @@
* @param bounds The bounds to be tested.
* @return True if the requested bounds are okay for a resizing request.
*/
- boolean canResizeToBounds(Rect bounds) {
+ private boolean canResizeToBounds(Rect bounds) {
if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
// Note: If not on the freeform workspace, we ignore the bounds.
return true;
@@ -1348,10 +1344,6 @@
&& (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
}
- boolean isOnTopLauncher() {
- return isHomeTask() && mIsOnTopLauncher;
- }
-
/**
* Find the activity in the history stack within the given task. Returns
* the index within the history at which it's found, or < 0 if not found.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ef792b0..1d60946 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5933,7 +5933,7 @@
final AccessibilityManager accessibilityManager =
(AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
- updateA11yVolumeAlias(accessibilityManager.isEnabled());
+ updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
accessibilityManager.addTouchExplorationStateChangeListener(this);
accessibilityManager.addAccessibilityServicesStateChangeListener(this);
}
@@ -6066,6 +6066,7 @@
pw.print(" mSafeMediaVolumeState=");
pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
+ pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
pw.print(" mMcc="); pw.println(mMcc);
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 816d5fe..4930c53 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -46,7 +46,7 @@
implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer {
public final static String TAG = "AudioService.PlaybackActivityMonitor";
- private final static boolean DEBUG = true;
+ private final static boolean DEBUG = false;
private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
// a public client is one that needs an anonymized version of the playback configurations, we
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 08a3332..017c5fb 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -66,9 +66,9 @@
public static final int EVENT_ON_LINKPROPERTIES = 3;
public static final int EVENT_ON_LOST = 4;
- private static final int LISTEN_ALL = 1;
- private static final int TRACK_DEFAULT = 2;
- private static final int MOBILE_REQUEST = 3;
+ private static final int CALLBACK_LISTEN_ALL = 1;
+ private static final int CALLBACK_TRACK_DEFAULT = 2;
+ private static final int CALLBACK_MOBILE_REQUEST = 3;
private final Context mContext;
private final StateMachine mTarget;
@@ -98,10 +98,10 @@
final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
.clearCapabilities().build();
- mListenAllCallback = new UpstreamNetworkCallback(LISTEN_ALL);
+ mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
cm().registerNetworkCallback(listenAllRequest, mListenAllCallback);
- mDefaultNetworkCallback = new UpstreamNetworkCallback(TRACK_DEFAULT);
+ mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_TRACK_DEFAULT);
cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
}
@@ -136,30 +136,25 @@
return;
}
- final NetworkRequest.Builder builder = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- if (mDunRequired) {
- builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
- } else {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
- final NetworkRequest mobileUpstreamRequest = builder.build();
+ // The following use of the legacy type system cannot be removed until
+ // after upstream selection no longer finds networks by legacy type.
+ // See also http://b/34364553 .
+ final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
+
+ final NetworkRequest mobileUpstreamRequest = new NetworkRequest.Builder()
+ .setCapabilities(ConnectivityManager.networkCapabilitiesForType(legacyType))
+ .build();
// The existing default network and DUN callbacks will be notified.
// Therefore, to avoid duplicate notifications, we only register a no-op.
- mMobileNetworkCallback = new UpstreamNetworkCallback(MOBILE_REQUEST);
+ mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST);
// TODO: Change the timeout from 0 (no onUnavailable callback) to some
// moderate callback timeout. This might be useful for updating some UI.
// Additionally, we log a message to aid in any subsequent debugging.
Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
- // The following use of the legacy type system cannot be removed until
- // after upstream selection no longer finds networks by legacy type.
- // See also b/34364553.
- final int apnType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
- cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, apnType);
+ cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType);
}
public void releaseMobileNetworkRequest() {
@@ -184,17 +179,18 @@
// Always request whatever extra information we can, in case this
// was already up when start() was called, in which case we would
// not have been notified of any information that had not changed.
- final NetworkCallback cb =
- (callbackType == TRACK_DEFAULT) ? mDefaultNetworkCallback :
- (callbackType == MOBILE_REQUEST) ? mMobileNetworkCallback : null;
- if (cb != null) {
- final ConnectivityManager cm = cm();
- cm.requestNetworkCapabilities(mDefaultNetworkCallback);
- cm.requestLinkProperties(mDefaultNetworkCallback);
- }
-
- if (callbackType == TRACK_DEFAULT) {
- mCurrentDefault = network;
+ switch (callbackType) {
+ case CALLBACK_LISTEN_ALL:
+ break;
+ case CALLBACK_TRACK_DEFAULT:
+ cm().requestNetworkCapabilities(mDefaultNetworkCallback);
+ cm().requestLinkProperties(mDefaultNetworkCallback);
+ mCurrentDefault = network;
+ break;
+ case CALLBACK_MOBILE_REQUEST:
+ cm().requestNetworkCapabilities(mMobileNetworkCallback);
+ cm().requestLinkProperties(mMobileNetworkCallback);
+ break;
}
// Requesting updates for mListenAllCallback is not currently possible
@@ -262,7 +258,7 @@
}
private void handleLost(int callbackType, Network network) {
- if (callbackType == TRACK_DEFAULT) {
+ if (callbackType == CALLBACK_TRACK_DEFAULT) {
mCurrentDefault = null;
// Receiving onLost() for a default network does not necessarily
// mean the network is gone. We wait for a separate notification
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index b089ba7..7cb223d 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -70,6 +70,8 @@
ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
/** Amount of time a job is allowed to execute for before being considered timed-out. */
private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins.
+ /** Amount of time the JobScheduler waits for the initial service launch+bind. */
+ private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000;
/** Amount of time the JobScheduler will wait for a response from an app for a message. */
private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
@@ -645,8 +647,20 @@
private void scheduleOpTimeOut() {
removeOpTimeOut();
- final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
- EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
+ final long timeoutMillis;
+ switch (mVerb) {
+ case VERB_EXECUTING:
+ timeoutMillis = EXECUTING_TIMESLICE_MILLIS;
+ break;
+
+ case VERB_BINDING:
+ timeoutMillis = OP_BIND_TIMEOUT_MILLIS;
+ break;
+
+ default:
+ timeoutMillis = OP_TIMEOUT_MILLIS;
+ break;
+ }
if (DEBUG) {
Slog.d(TAG, "Scheduling time out for '" +
mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 3bf95ef..98177fe 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -155,10 +155,10 @@
}
/**
- * Tells the system UI that volume has changed on a remote session.
+ * Tells the system UI that volume has changed on an active remote session.
*/
public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
- if (mRvc == null) {
+ if (mRvc == null || !session.isActive()) {
return;
}
try {
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 6f49df4..279bf90 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -31,6 +31,8 @@
import android.text.TextUtils;
import android.util.ArrayMap;
+import com.android.internal.util.NotificationMessagingUtil;
+
import java.util.Comparator;
import java.util.Objects;
@@ -40,18 +42,15 @@
public class NotificationComparator
implements Comparator<NotificationRecord> {
- private final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
-
private final Context mContext;
+ private final NotificationMessagingUtil mMessagingUtil;
private String mDefaultPhoneApp;
- private ArrayMap<Integer, String> mDefaultSmsApp = new ArrayMap<>();
public NotificationComparator(Context context) {
mContext = context;
mContext.registerReceiver(mPhoneAppBroadcastReceiver,
new IntentFilter(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED));
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
+ mMessagingUtil = new NotificationMessagingUtil(mContext);
}
@Override
@@ -73,9 +72,15 @@
return -1 * Boolean.compare(leftImportantOngoing, rightImportantOngoing);
}
+ boolean leftMessaging = isImportantMessaging(left);
+ boolean rightMessaging = isImportantMessaging(right);
+ if (leftMessaging != rightMessaging) {
+ return -1 * Boolean.compare(leftMessaging, rightMessaging);
+ }
+
// Next: sufficiently import person to person communication
- boolean leftPeople = isImportantMessaging(left);
- boolean rightPeople = isImportantMessaging(right);
+ boolean leftPeople = isImportantPeople(left);
+ boolean rightPeople = isImportantPeople(right);
if (leftPeople && rightPeople){
// by contact proximity, close to far. if same proximity, check further fields.
@@ -128,50 +133,31 @@
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
-
// TODO: add whitelist
return isCall(record) || isMediaNotification(record);
}
- protected boolean isImportantMessaging(NotificationRecord record) {
+ protected boolean isImportantPeople(NotificationRecord record) {
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
-
- Class<? extends Notification.Style> style = getNotificationStyle(record);
- if (Notification.MessagingStyle.class.equals(style)) {
- return true;
- }
-
if (record.getContactAffinity() > ValidateNotificationPeople.NONE) {
return true;
}
-
- if (record.getNotification().category == Notification.CATEGORY_MESSAGE
- && isDefaultMessagingApp(record)) {
- return true;
- }
-
return false;
}
+ protected boolean isImportantMessaging(NotificationRecord record) {
+ return mMessagingUtil.isImportantMessaging(record.sbn, record.getImportance());
+ }
+
private boolean isOngoing(NotificationRecord record) {
final int ongoingFlags =
Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_ONGOING_EVENT;
return (record.getNotification().flags & ongoingFlags) != 0;
}
- private Class<? extends Notification.Style> getNotificationStyle(NotificationRecord record) {
- String templateClass =
- record.getNotification().extras.getString(Notification.EXTRA_TEMPLATE);
-
- if (!TextUtils.isEmpty(templateClass)) {
- return Notification.getNotificationStyleClass(templateClass);
- }
- return null;
- }
-
private boolean isMediaNotification(NotificationRecord record) {
return record.getNotification().extras.getParcelable(
Notification.EXTRA_MEDIA_SESSION) != null;
@@ -191,18 +177,6 @@
return Objects.equals(pkg, mDefaultPhoneApp);
}
- @SuppressWarnings("deprecation")
- private boolean isDefaultMessagingApp(NotificationRecord record) {
- final int userId = record.getUserId();
- if (userId == UserHandle.USER_NULL || userId == UserHandle.USER_ALL) return false;
- if (mDefaultSmsApp.get(userId) == null) {
- mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
- }
- return Objects.equals(mDefaultSmsApp.get(userId), record.sbn.getPackageName());
- }
-
private final BroadcastReceiver mPhoneAppBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -210,17 +184,4 @@
intent.getStringExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME);
}
};
-
- private final ContentObserver mSmsContentObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING).equals(uri)) {
- mDefaultSmsApp.put(userId, Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId));
-
- }
- }
- };
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6f20f10..0e5ea6e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -712,6 +712,7 @@
// System configuration read by SystemConfig.
final int[] mGlobalGids;
final SparseArray<ArraySet<String>> mSystemPermissions;
+ @GuardedBy("mAvailableFeatures")
final ArrayMap<String, FeatureInfo> mAvailableFeatures;
// If mac_permissions.xml was found for seinfo labeling.
@@ -4215,21 +4216,22 @@
@Override
public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
- synchronized (mPackages) {
- final ArrayList<FeatureInfo> res = new ArrayList<>(mAvailableFeatures.values());
-
- final FeatureInfo fi = new FeatureInfo();
- fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
- FeatureInfo.GL_ES_VERSION_UNDEFINED);
- res.add(fi);
-
- return new ParceledListSlice<>(res);
+ ArrayList<FeatureInfo> res;
+ synchronized (mAvailableFeatures) {
+ res = new ArrayList<>(mAvailableFeatures.size() + 1);
+ res.addAll(mAvailableFeatures.values());
}
+ final FeatureInfo fi = new FeatureInfo();
+ fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
+ FeatureInfo.GL_ES_VERSION_UNDEFINED);
+ res.add(fi);
+
+ return new ParceledListSlice<>(res);
}
@Override
public boolean hasSystemFeature(String name, int version) {
- synchronized (mPackages) {
+ synchronized (mAvailableFeatures) {
final FeatureInfo feat = mAvailableFeatures.get(name);
if (feat == null) {
return false;
@@ -20379,20 +20381,22 @@
pw.println("Features:");
}
- for (FeatureInfo feat : mAvailableFeatures.values()) {
- if (checkin) {
- pw.print("feat,");
- pw.print(feat.name);
- pw.print(",");
- pw.println(feat.version);
- } else {
- pw.print(" ");
- pw.print(feat.name);
- if (feat.version > 0) {
- pw.print(" version=");
- pw.print(feat.version);
+ synchronized (mAvailableFeatures) {
+ for (FeatureInfo feat : mAvailableFeatures.values()) {
+ if (checkin) {
+ pw.print("feat,");
+ pw.print(feat.name);
+ pw.print(",");
+ pw.println(feat.version);
+ } else {
+ pw.print(" ");
+ pw.print(feat.name);
+ if (feat.version > 0) {
+ pw.print(" version=");
+ pw.print(feat.version);
+ }
+ pw.println();
}
- pw.println();
}
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 37fff68..180f6c9 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -16,17 +16,24 @@
package com.android.server.policy;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.O;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
@@ -63,21 +70,14 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -103,8 +103,11 @@
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
+import static android.view.WindowManagerGlobal.ADD_OKAY;
+import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -156,7 +159,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Debug;
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
@@ -314,12 +316,6 @@
// Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
- static final int APPLICATION_MEDIA_SUBLAYER = -2;
- static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
- static final int APPLICATION_PANEL_SUBLAYER = 1;
- static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
- static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
-
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -2315,86 +2311,82 @@
if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) {
// Window manager will make sure these are okay.
- return WindowManagerGlobal.ADD_OKAY;
+ return ADD_OKAY;
}
- String permission = null;
- switch (type) {
- case TYPE_TOAST:
- // XXX right now the app process has complete control over
- // this... should introduce a token to let the system
- // monitor/control what they are doing.
- outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW;
- break;
- case TYPE_DREAM:
- case TYPE_INPUT_METHOD:
- case TYPE_WALLPAPER:
- case TYPE_PRESENTATION:
- case TYPE_PRIVATE_PRESENTATION:
- case TYPE_VOICE_INTERACTION:
- case TYPE_ACCESSIBILITY_OVERLAY:
- case TYPE_QS_DIALOG:
- // The window manager will check these.
- break;
- case TYPE_PHONE:
- case TYPE_PRIORITY_PHONE:
- case TYPE_SYSTEM_ALERT:
- case TYPE_SYSTEM_ERROR:
- case TYPE_SYSTEM_OVERLAY:
- permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
- outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
- break;
+
+ if (!isSystemAlertWindowType(type)) {
+ switch (type) {
+ case TYPE_TOAST:
+ // Only apps that target older than O SDK can add window without a token, after
+ // that we require a token so apps cannot add toasts directly as the token is
+ // added by the notification system.
+ // Window manager does the checking for this.
+ outAppOp[0] = OP_TOAST_WINDOW;
+ return ADD_OKAY;
+ case TYPE_DREAM:
+ case TYPE_INPUT_METHOD:
+ case TYPE_WALLPAPER:
+ case TYPE_PRESENTATION:
+ case TYPE_PRIVATE_PRESENTATION:
+ case TYPE_VOICE_INTERACTION:
+ case TYPE_ACCESSIBILITY_OVERLAY:
+ case TYPE_QS_DIALOG:
+ // The window manager will check these.
+ return ADD_OKAY;
+ }
+ return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
+ == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED;
+ }
+
+ // Things get a little more interesting for alert windows...
+ outAppOp[0] = OP_SYSTEM_ALERT_WINDOW;
+
+ final int callingUid = Binder.getCallingUid();
+ // system processes will be automatically granted privilege to draw
+ if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
+ return ADD_OKAY;
+ }
+
+ ApplicationInfo appInfo;
+ try {
+ appInfo = mContext.getPackageManager().getApplicationInfo(attrs.packageName,
+ UserHandle.getUserId(callingUid));
+ } catch (PackageManager.NameNotFoundException e) {
+ appInfo = null;
+ }
+
+ if (appInfo == null || (type != TYPE_APPLICATION_OVERLAY && appInfo.targetSdkVersion >= O)) {
+ /**
+ * Apps targeting >= {@link Build.VERSION_CODES#O} are required to hold
+ * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} (system signature apps)
+ * permission to add alert windows that aren't
+ * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
+ */
+ return (mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED)
+ ? ADD_OKAY : ADD_PERMISSION_DENIED;
+ }
+
+ // check if user has enabled this operation. SecurityException will be thrown if this app
+ // has not been allowed by the user
+ final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, attrs.packageName);
+ switch (mode) {
+ case AppOpsManager.MODE_ALLOWED:
+ case AppOpsManager.MODE_IGNORED:
+ // although we return ADD_OKAY for MODE_IGNORED, the added window will
+ // actually be hidden in WindowManagerService
+ return ADD_OKAY;
+ case AppOpsManager.MODE_ERRORED:
+ // Don't crash legacy apps
+ if (appInfo.targetSdkVersion < M) {
+ return ADD_OKAY;
+ }
+ return ADD_PERMISSION_DENIED;
default:
- permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+ // in the default mode, we will make a decision here based on
+ // checkCallingPermission()
+ return (mContext.checkCallingPermission(SYSTEM_ALERT_WINDOW) == PERMISSION_GRANTED)
+ ? ADD_OKAY : ADD_PERMISSION_DENIED;
}
- if (permission != null) {
- if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
- final int callingUid = Binder.getCallingUid();
- // system processes will be automatically allowed privilege to draw
- if (callingUid == Process.SYSTEM_UID) {
- return WindowManagerGlobal.ADD_OKAY;
- }
-
- // check if user has enabled this operation. SecurityException will be thrown if
- // this app has not been allowed by the user
- final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
- attrs.packageName);
- switch (mode) {
- case AppOpsManager.MODE_ALLOWED:
- case AppOpsManager.MODE_IGNORED:
- // although we return ADD_OKAY for MODE_IGNORED, the added window will
- // actually be hidden in WindowManagerService
- return WindowManagerGlobal.ADD_OKAY;
- case AppOpsManager.MODE_ERRORED:
- try {
- ApplicationInfo appInfo = mContext.getPackageManager()
- .getApplicationInfo(attrs.packageName,
- UserHandle.getUserId(callingUid));
- // Don't crash legacy apps
- if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- return WindowManagerGlobal.ADD_OKAY;
- }
- } catch (PackageManager.NameNotFoundException e) {
- /* ignore */
- }
- return WindowManagerGlobal.ADD_PERMISSION_DENIED;
- default:
- // in the default mode, we will make a decision here based on
- // checkCallingPermission()
- if (mContext.checkCallingPermission(permission) !=
- PackageManager.PERMISSION_GRANTED) {
- return WindowManagerGlobal.ADD_PERMISSION_DENIED;
- } else {
- return WindowManagerGlobal.ADD_OKAY;
- }
- }
- }
-
- if (mContext.checkCallingOrSelfPermission(permission)
- != PackageManager.PERMISSION_GRANTED) {
- return WindowManagerGlobal.ADD_PERMISSION_DENIED;
- }
- }
- return WindowManagerGlobal.ADD_OKAY;
}
@Override
@@ -2440,9 +2432,7 @@
}
// Check if third party app has set window to system window type.
- return mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
- != PackageManager.PERMISSION_GRANTED;
+ return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED;
}
@Override
@@ -2591,130 +2581,9 @@
}
}
- /** {@inheritDoc} */
- @Override
- public int windowTypeToLayerLw(int type) {
- if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
- return 2;
- }
- switch (type) {
- case TYPE_WALLPAPER:
- // wallpaper is at the bottom, though the window manager may move it.
- return 1;
- case TYPE_PRESENTATION:
- case TYPE_PRIVATE_PRESENTATION:
- return 2;
- case TYPE_DOCK_DIVIDER:
- return 2;
- case TYPE_QS_DIALOG:
- return 2;
- case TYPE_PHONE:
- return 3;
- case TYPE_SEARCH_BAR:
- case TYPE_VOICE_INTERACTION_STARTING:
- return 4;
- case TYPE_VOICE_INTERACTION:
- // voice interaction layer is almost immediately above apps.
- return 5;
- case TYPE_INPUT_CONSUMER:
- return 6;
- case TYPE_SYSTEM_DIALOG:
- return 7;
- case TYPE_TOAST:
- // toasts and the plugged-in battery thing
- return 8;
- case TYPE_PRIORITY_PHONE:
- // SIM errors and unlock. Not sure if this really should be in a high layer.
- return 9;
- case TYPE_DREAM:
- // used for Dreams (screensavers with TYPE_DREAM windows)
- return 10;
- case TYPE_SYSTEM_ALERT:
- // like the ANR / app crashed dialogs
- return 11;
- case TYPE_INPUT_METHOD:
- // on-screen keyboards and other such input method user interfaces go here.
- return 12;
- case TYPE_INPUT_METHOD_DIALOG:
- // on-screen keyboards and other such input method user interfaces go here.
- return 13;
- case TYPE_STATUS_BAR_SUB_PANEL:
- return 15;
- case TYPE_STATUS_BAR:
- return 16;
- case TYPE_STATUS_BAR_PANEL:
- return 17;
- case TYPE_KEYGUARD_DIALOG:
- return 18;
- case TYPE_VOLUME_OVERLAY:
- // the on-screen volume indicator and controller shown when the user
- // changes the device volume
- return 19;
- case TYPE_SYSTEM_OVERLAY:
- // the on-screen volume indicator and controller shown when the user
- // changes the device volume
- return 20;
- case TYPE_NAVIGATION_BAR:
- // the navigation bar, if available, shows atop most things
- return 21;
- case TYPE_NAVIGATION_BAR_PANEL:
- // some panels (e.g. search) need to show on top of the navigation bar
- return 22;
- case TYPE_SCREENSHOT:
- // screenshot selection layer shouldn't go above system error, but it should cover
- // navigation bars at the very least.
- return 23;
- case TYPE_SYSTEM_ERROR:
- // system-level error dialogs
- return 24;
- case TYPE_MAGNIFICATION_OVERLAY:
- // used to highlight the magnified portion of a display
- return 25;
- case TYPE_DISPLAY_OVERLAY:
- // used to simulate secondary display devices
- return 26;
- case TYPE_DRAG:
- // the drag layer: input for drag-and-drop is associated with this window,
- // which sits above all other focusable windows
- return 27;
- case TYPE_ACCESSIBILITY_OVERLAY:
- // overlay put by accessibility services to intercept user interaction
- return 28;
- case TYPE_SECURE_SYSTEM_OVERLAY:
- return 29;
- case TYPE_BOOT_PROGRESS:
- return 30;
- case TYPE_POINTER:
- // the (mouse) pointer layer
- return 31;
- }
- Log.e(TAG, "Unknown window type: " + type);
- return 2;
- }
-
- /** {@inheritDoc} */
- @Override
- public int subWindowTypeToLayerLw(int type) {
- switch (type) {
- case TYPE_APPLICATION_PANEL:
- case TYPE_APPLICATION_ATTACHED_DIALOG:
- return APPLICATION_PANEL_SUBLAYER;
- case TYPE_APPLICATION_MEDIA:
- return APPLICATION_MEDIA_SUBLAYER;
- case TYPE_APPLICATION_MEDIA_OVERLAY:
- return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
- case TYPE_APPLICATION_SUB_PANEL:
- return APPLICATION_SUB_PANEL_SUBLAYER;
- case TYPE_APPLICATION_ABOVE_SUB_PANEL:
- return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;
- }
- Log.e(TAG, "Unknown sub-window type: " + type);
- return 0;
- }
-
@Override
public int getMaxWallpaperLayer() {
- return windowTypeToLayerLw(TYPE_STATUS_BAR);
+ return getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
}
private int getNavigationBarWidth(int rotation, int uiMode) {
@@ -2797,8 +2666,7 @@
return false;
default:
// Hide only windows below the keyguard host window.
- return windowTypeToLayerLw(win.getBaseType())
- < windowTypeToLayerLw(TYPE_STATUS_BAR);
+ return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_STATUS_BAR);
}
}
@@ -3043,7 +2911,7 @@
"PhoneWindowManager");
break;
}
- return WindowManagerGlobal.ADD_OKAY;
+ return ADD_OKAY;
}
/** {@inheritDoc} */
@@ -7837,8 +7705,8 @@
immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
final boolean navAllowedHidden = immersive || immersiveSticky;
- if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType())
- > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) {
+ if (hideNavBarSysui && !navAllowedHidden
+ && getWindowLayerLw(win) > getWindowLayerFromTypeLw(TYPE_INPUT_CONSUMER)) {
// We can't hide the navbar from this window otherwise the input consumer would not get
// the input events.
vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 8cc53f0..e026130 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -23,15 +23,12 @@
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.OperationApplicationException;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -84,12 +81,9 @@
import com.android.server.IoThread;
import com.android.server.SystemService;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -241,44 +235,6 @@
// the update can be handled in {@link #onSomePackagesChanged}.
return true;
}
-
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(getChangingUserId());
- if (!userState.packageSet.contains(packageName)) {
- // Not a TV input package.
- return;
- }
- }
-
- ArrayList<ContentProviderOperation> operations = new ArrayList<>();
-
- String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?";
- String[] selectionArgs = { packageName };
-
- operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI)
- .withSelection(selection, selectionArgs).build());
- operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI)
- .withSelection(selection, selectionArgs).build());
- operations.add(ContentProviderOperation
- .newDelete(TvContract.WatchedPrograms.CONTENT_URI)
- .withSelection(selection, selectionArgs).build());
-
- ContentProviderResult[] results = null;
- try {
- ContentResolver cr = getContentResolverForUser(getChangingUserId());
- results = cr.applyBatch(TvContract.AUTHORITY, operations);
- } catch (RemoteException | OperationApplicationException e) {
- Slog.e(TAG, "error in applyBatch", e);
- }
-
- if (DEBUG) {
- Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid
- + ")");
- Slog.d(TAG, "results=" + results);
- }
- }
};
monitor.register(mContext, null, UserHandle.ALL, true);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index e8385fc..8368b05 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -31,7 +31,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.hardware.display.DisplayManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -138,7 +137,6 @@
private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
/** Tracks the state of the screen and keyguard UI.*/
private int mSystemSleepFlags = FLAG_NONE;
- private CompatibilityDisplay mCompatibilityDisplay;
private static final int MSG_VR_STATE_CHANGE = 0;
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -496,11 +494,6 @@
mComponentObserver.rebuildAll();
}
-
- DisplayManager dm =
- (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
- mCompatibilityDisplay = new CompatibilityDisplay(dm, mVrManager);
- mCompatibilityDisplay.init();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
mVrModeAllowed = true;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 49ffa22..f7a9e41 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -369,6 +369,7 @@
case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
case WindowManager.LayoutParams.TYPE_TOAST:
case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
@@ -687,7 +688,7 @@
mSurfaceControl = surfaceControl;
mSurfaceControl.setLayerStack(mWindowManager.getDefaultDisplay()
.getLayerStack());
- mSurfaceControl.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
+ mSurfaceControl.setLayer(mWindowManagerService.mPolicy.getWindowLayerFromTypeLw(
WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY)
* WindowManagerService.TYPE_LAYER_MULTIPLIER);
mSurfaceControl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 3eb529b..4eb8e02 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -951,9 +951,9 @@
float scaleW = appWidth / thumbWidth;
getNextAppTransitionStartRect(taskId, mTmpRect);
final float fromX;
- final float fromY;
+ float fromY;
final float toX;
- final float toY;
+ float toY;
final float pivotX;
final float pivotY;
if (shouldScaleDownThumbnailTransition(uiMode, orientation)) {
@@ -966,6 +966,12 @@
toY = appRect.height() / 2 * (1 - 1 / scaleW) + appRect.top;
pivotX = mTmpRect.width() / 2;
pivotY = appRect.height() / 2 / scaleW;
+ if (mGridLayoutRecentsEnabled) {
+ // In the grid layout, the header is displayed above the thumbnail instead of
+ // overlapping it.
+ fromY -= thumbHeightI;
+ toY -= thumbHeightI * scaleW;
+ }
} else {
pivotX = 0;
pivotY = 0;
@@ -1014,7 +1020,10 @@
// This AnimationSet uses the Interpolators assigned above.
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
- set.addAnimation(alpha);
+ if (!mGridLayoutRecentsEnabled) {
+ // In the grid layout, the header should be shown for the whole animation.
+ set.addAnimation(alpha);
+ }
set.addAnimation(translate);
set.addAnimation(clipAnim);
a = set;
@@ -1033,7 +1042,10 @@
// This AnimationSet uses the Interpolators assigned above.
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
- set.addAnimation(alpha);
+ if (!mGridLayoutRecentsEnabled) {
+ // In the grid layout, the header should be shown for the whole animation.
+ set.addAnimation(alpha);
+ }
set.addAnimation(translate);
a = set;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index d643769..061aa83 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -192,7 +192,8 @@
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
DisplayContent dc) {
- super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc);
+ super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
+ false /* ownerCanManageAppTokens */);
appToken = token;
mVoiceInteraction = voiceInteraction;
mInputApplicationHandle = new InputApplicationHandle(this);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 679f178..c45136c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2185,7 +2185,7 @@
&& !mService.mInputMethodTarget.isInMultiWindowMode();
}
- final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
+ final int aboveAppLayer = (mService.mPolicy.getWindowLayerFromTypeLw(TYPE_APPLICATION) + 1)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay);
synchronized(mService.mWindowMap) {
@@ -2728,8 +2728,10 @@
*/
private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
// Tokens with higher base layer are z-ordered on-top.
- mService.mPolicy.windowTypeToLayerLw(token1.windowType)
- < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
+ mService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
+ token1.mOwnerCanManageAppTokens)
+ < mService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
+ token2.mOwnerCanManageAppTokens) ? -1 : 1;
private final Predicate<WindowState> mGetOrientingWindow = w -> {
if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 5a2ee9a..0a92a81 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -621,11 +621,7 @@
final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible())
|| (homeStack.hasMultipleTaskWithHomeTaskNotTop());
- // If the home task is an on-top launcher, we don't want to minimize the docked stack.
- // Instead we want everything underneath that was visible to remain visible.
- // See android.R.attr#onTopLauncher.
- final boolean isOnTopLauncher = homeStack.topTaskIsOnTopLauncher();
- setMinimizedDockedStack(homeVisible && !homeBehind && !isOnTopLauncher, animate);
+ setMinimizedDockedStack(homeVisible && !homeBehind, animate);
}
private boolean isWithinDisplay(Task task) {
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 1ae987f..3fdafc7 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -239,7 +239,7 @@
}
int getDragLayerLw() {
- return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
+ return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
+ WindowManagerService.TYPE_LAYER_OFFSET;
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index b92bfb9..36753b7 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -77,7 +77,7 @@
}
private int getLayerLw(int windowType) {
- return mService.mPolicy.windowTypeToLayerLw(windowType)
+ return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
+ WindowManagerService.TYPE_LAYER_OFFSET;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 5f53d84..37b8deb 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
@@ -237,8 +238,8 @@
// Figure out whether this window is layered above system windows.
// We need to do this here to help the activity manager know how to
// layer its ANR dialog.
- int systemAlertLayer = mService.mPolicy.windowTypeToLayerLw(
- WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
+ TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
aboveSystem = windowState.mBaseLayer > systemAlertLayer;
} else if (appWindowToken != null) {
Slog.i(TAG_WM, "Input event dispatching timed out "
@@ -471,7 +472,7 @@
/* Callback to get pointer layer. */
@Override
public int getPointerLayer() {
- return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_POINTER)
+ return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
+ WindowManagerService.TYPE_LAYER_OFFSET;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d96e1ef..ab9a378 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -91,20 +91,16 @@
private boolean mHomeTask;
- // Whether this task is an on-top launcher task, which is determined by the root activity.
- private boolean mIsOnTopLauncher;
-
private TaskDescription mTaskDescription;
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
- Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
- boolean supportsPictureInPicture, boolean homeTask, TaskDescription taskDescription,
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, TaskDescription taskDescription,
TaskWindowContainerController controller) {
mTaskId = taskId;
mStack = stack;
mUserId = userId;
mService = service;
- mIsOnTopLauncher = isOnTopLauncher;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
mHomeTask = homeTask;
@@ -117,7 +113,7 @@
return mStack != null ? mStack.getDisplayContent() : null;
}
- int getAdjustedAddPosition(int suggestedPosition) {
+ private int getAdjustedAddPosition(int suggestedPosition) {
final int size = mChildren.size();
if (suggestedPosition >= size) {
return Math.min(size, suggestedPosition);
@@ -347,10 +343,6 @@
|| mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
}
- boolean isOnTopLauncher() {
- return mIsOnTopLauncher;
- }
-
boolean cropWindowsToStackBounds() {
return isResizeable();
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 538f0d9..a1c9c29 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -160,10 +160,6 @@
return mChildren.size() > 1 && !mChildren.get(mChildren.size() - 1).isHomeTask();
}
- boolean topTaskIsOnTopLauncher() {
- return mChildren.get(mChildren.size() - 1).isOnTopLauncher();
- }
-
/**
* Set the bounds of the stack and its containing tasks.
* @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index 11667c0..efc2e11 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -51,17 +51,17 @@
public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
StackWindowController stackController, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
+ boolean homeTask, boolean toTop, boolean showForAllUsers,
TaskDescription taskDescription) {
this(taskId, listener, stackController, userId, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, isOnTopLauncher, toTop, showForAllUsers,
- taskDescription, WindowManagerService.getInstance());
+ supportsPictureInPicture, homeTask, toTop, showForAllUsers, taskDescription,
+ WindowManagerService.getInstance());
}
public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
StackWindowController stackController, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, boolean isOnTopLauncher, boolean toTop, boolean showForAllUsers,
+ boolean homeTask, boolean toTop, boolean showForAllUsers,
TaskDescription taskDescription, WindowManagerService service) {
super(listener, service);
mTaskId = taskId;
@@ -78,7 +78,7 @@
}
EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
- supportsPictureInPicture, homeTask, isOnTopLauncher, taskDescription);
+ supportsPictureInPicture, homeTask, taskDescription);
final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
stack.addTask(task, position, showForAllUsers, true /* moveParents */);
}
@@ -87,9 +87,9 @@
@VisibleForTesting
Task createTask(int taskId, TaskStack stack, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, boolean isOnTopLauncher, TaskDescription taskDescription) {
- return new Task(taskId, stack, userId, mService, bounds, overrideConfig, isOnTopLauncher,
- resizeMode, supportsPictureInPicture, homeTask, taskDescription, this);
+ boolean homeTask, TaskDescription taskDescription) {
+ return new Task(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, taskDescription, this);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 8ea1b3b..28aebbb 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -40,8 +40,8 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM;
WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
- DisplayContent dc) {
- super(service, token, TYPE_WALLPAPER, explicit, dc);
+ DisplayContent dc, boolean ownerCanManageAppTokens) {
+ super(service, token, TYPE_WALLPAPER, explicit, dc, ownerCanManageAppTokens);
dc.mWallpaperController.addWallpaperToken(this);
}
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index e0c3d60..d56110c 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -59,7 +59,6 @@
private ArrayDeque<WindowState> mPinnedWindows = new ArrayDeque<>();
private ArrayDeque<WindowState> mDockedWindows = new ArrayDeque<>();
private ArrayDeque<WindowState> mInputMethodWindows = new ArrayDeque<>();
- private ArrayDeque<WindowState> mOnTopLauncherWindows = new ArrayDeque<>();
private WindowState mDockDivider = null;
private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>();
private int mCurBaseLayer;
@@ -138,7 +137,6 @@
mPinnedWindows.clear();
mInputMethodWindows.clear();
mDockedWindows.clear();
- mOnTopLauncherWindows.clear();
mReplacingWindows.clear();
mDockDivider = null;
@@ -182,9 +180,6 @@
if (task == null) {
return;
}
- if (task.isOnTopLauncher()) {
- mOnTopLauncherWindows.add(w);
- }
final TaskStack stack = task.mStack;
if (stack == null) {
return;
@@ -206,10 +201,6 @@
layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
- while (!mOnTopLauncherWindows.isEmpty()) {
- layer = assignAndIncreaseLayerIfNeeded(mOnTopLauncherWindows.remove(), layer);
- }
-
// We know that we will be animating a relaunching window in the near future, which will
// receive a z-order increase. We want the replaced window to immediately receive the same
// treatment, e.g. to be above the dock divider.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9b96523..971794b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,13 +16,14 @@
package com.android.server.wm;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -101,7 +102,6 @@
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IActivityManager;
-import android.app.RemoteAction;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -236,7 +236,6 @@
import java.util.HashMap;
import java.util.List;
-import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
@@ -523,7 +522,7 @@
boolean mSupportsPictureInPicture = false;
int getDragLayerLocked() {
- return mPolicy.windowTypeToLayerLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
+ return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
}
class RotationWatcher {
@@ -1099,6 +1098,8 @@
long origId;
final int callingUid = Binder.getCallingUid();
final int type = attrs.type;
+ final boolean ownerCanAddInternalSystemWindow =
+ mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
synchronized(mWindowMap) {
if (!mDisplayReady) {
@@ -1200,7 +1201,8 @@
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
}
- token = new WindowToken(this, attrs.token, type, false, displayContent);
+ token = new WindowToken(this, attrs.token, type, false, displayContent,
+ ownerCanAddInternalSystemWindow);
} else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
atoken = token.asAppWindowToken();
if (atoken == null) {
@@ -1270,11 +1272,13 @@
// It is not valid to use an app token with other system types; we will
// instead make a new token for it (as if null had been passed in for the token).
attrs.token = null;
- token = new WindowToken(this, null, type, false, displayContent);
+ token = new WindowToken(this, null, type, false, displayContent,
+ ownerCanAddInternalSystemWindow);
}
- WindowState win = new WindowState(this, session, client, token, parentWindow,
- appOp[0], seq, attrs, viewVisibility, session.mUid);
+ final WindowState win = new WindowState(this, session, client, token, parentWindow,
+ appOp[0], seq, attrs, viewVisibility, session.mUid,
+ ownerCanAddInternalSystemWindow);
if (win.mDeathRecipient == null) {
// Client has apparently died, so there is no reason to
// continue.
@@ -2405,9 +2409,10 @@
return;
}
if (type == TYPE_WALLPAPER) {
- new WallpaperWindowToken(this, binder, true, dc);
+ new WallpaperWindowToken(this, binder, true, dc,
+ true /* ownerCanManageAppTokens */);
} else {
- new WindowToken(this, binder, type, true, dc);
+ new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
}
}
}
@@ -3606,7 +3611,7 @@
mCircularDisplayMask = new CircularDisplayMask(
getDefaultDisplayContentLocked().getDisplay(),
mFxSession,
- mPolicy.windowTypeToLayerLw(
+ mPolicy.getWindowLayerFromTypeLw(
WindowManager.LayoutParams.TYPE_POINTER)
* TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
}
@@ -3635,7 +3640,7 @@
mContext,
getDefaultDisplayContentLocked().getDisplay(),
mFxSession,
- mPolicy.windowTypeToLayerLw(
+ mPolicy.getWindowLayerFromTypeLw(
WindowManager.LayoutParams.TYPE_POINTER)
* TYPE_LAYER_MULTIPLIER + 10);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 050adfe..867080e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -18,7 +18,6 @@
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.isLowRamDeviceStatic;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
@@ -164,6 +163,8 @@
final int mAppOp;
// UserId and appId of the owner. Don't display windows of non-current user.
final int mOwnerUid;
+ /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
+ final boolean mOwnerCanAddInternalSystemWindow;
final IWindowId mWindowId;
WindowToken mToken;
// The same object as mToken if this is an app window and null for non-app windows.
@@ -561,7 +562,7 @@
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
- int viewVisibility, int ownerId) {
+ int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
mService = service;
mSession = s;
mClient = c;
@@ -569,6 +570,7 @@
mToken = token;
mAppToken = mToken.asAppWindowToken();
mOwnerUid = ownerId;
+ mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
mWindowId = new IWindowId.Stub() {
@Override
public void registerFocusObserver(IWindowFocusObserver observer) {
@@ -613,9 +615,9 @@
if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
- mBaseLayer = mPolicy.windowTypeToLayerLw(parentWindow.mAttrs.type)
+ mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
- mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
+ mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
mIsChildWindow = true;
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
@@ -629,7 +631,7 @@
} else {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
- mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
+ mBaseLayer = mPolicy.getWindowLayerLw(this)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = 0;
mIsChildWindow = false;
@@ -676,6 +678,11 @@
return mAttrs.packageName;
}
+ @Override
+ public boolean canAddInternalSystemWindow() {
+ return mOwnerCanAddInternalSystemWindow;
+ }
+
/**
* Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
* from {@param frame}. In other words, it applies the insets that would result if
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b163abf..d2ea64c8 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -915,10 +915,15 @@
if (attachedTransformation != null) {
tmpMatrix.postConcat(attachedTransformation.getMatrix());
}
- tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
if (appTransformation != null) {
tmpMatrix.postConcat(appTransformation.getMatrix());
}
+
+ // The translation that applies the position of the window needs to be applied at the
+ // end in case that other translations include scaling. Otherwise the scaling will
+ // affect this translation. But it needs to be set before the screen rotation animation
+ // so the pivot point is at the center of the screen for all windows.
+ tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
if (screenAnimation) {
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 4b94d15..8beb87d 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -77,6 +77,9 @@
// The display this token is on.
protected DisplayContent mDisplayContent;
+ /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
+ final boolean mOwnerCanManageAppTokens;
+
/**
* Compares two child window of this token and returns -1 if the first is lesser than the
* second in terms of z-order and 1 otherwise.
@@ -98,11 +101,12 @@
};
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
- DisplayContent dc) {
+ DisplayContent dc, boolean ownerCanManageAppTokens) {
mService = service;
token = _token;
windowType = type;
mPersistOnEmpty = persistOnEmpty;
+ mOwnerCanManageAppTokens = ownerCanManageAppTokens;
onDisplayChanged(dc);
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 152b9c9..fa9e9a8 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -117,6 +117,8 @@
private static final String SSID = "ssid";
private static final String SSID_2 = "ssid_2";
private static final String SSID_3 = "ssid_3";
+ private static final ComponentName RECOMMENDATION_SERVICE_COMP =
+ new ComponentName("newPackageName", "newScoringServiceClass");
private static final ScoredNetwork SCORED_NETWORK =
new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID), "00:00:00:00:00:00")),
null /* rssiCurve*/);
@@ -124,7 +126,7 @@
new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID_2), "00:00:00:00:00:00")),
null /* rssiCurve*/);
private static final NetworkScorerAppData NEW_SCORER =
- new NetworkScorerAppData("newPackageName", 1, "newScoringServiceClass");
+ new NetworkScorerAppData(1, RECOMMENDATION_SERVICE_COMP);
@Mock private NetworkScorerAppManager mNetworkScorerAppManager;
@Mock private Context mContext;
@@ -203,8 +205,7 @@
verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
- .setComponent(new ComponentName(NEW_SCORER.packageName,
- NEW_SCORER.recommendationServiceClassName))),
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
@@ -657,7 +658,8 @@
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mNetworkScoreService.systemRunning();
- assertEquals(NEW_SCORER.packageName, mNetworkScoreService.getActiveScorerPackage());
+ assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
+ mNetworkScoreService.getActiveScorerPackage());
}
@Test
@@ -829,8 +831,6 @@
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
- final ComponentName componentName = new ComponentName(NEW_SCORER.packageName,
- NEW_SCORER.recommendationServiceClassName);
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
@@ -840,7 +840,8 @@
when(mockBinder.queryLocalInterface(anyString()))
.thenReturn(mRecommendationProvider);
invocation.getArgumentAt(1, ServiceConnection.class)
- .onServiceConnected(componentName, mockBinder);
+ .onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
+ mockBinder);
return true;
}
});
@@ -849,8 +850,8 @@
private void bindToScorer(boolean callerIsScorer) {
final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
- NetworkScorerAppData appData = new NetworkScorerAppData(NEW_SCORER.packageName,
- callingUid, NEW_SCORER.recommendationServiceClassName);
+ NetworkScorerAppData appData =
+ new NetworkScorerAppData(callingUid, RECOMMENDATION_SERVICE_COMP);
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
isA(UserHandle.class))).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 213fb27..e433b60 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -190,6 +190,8 @@
mAms.addAccountExplicitly(a31, "p31", null);
mAms.addAccountExplicitly(a32, "p32", null);
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(6, accounts.length);
@@ -306,6 +308,8 @@
@SmallTest
public void testRemovedAccountSync() throws Exception {
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
unlockSystemUser();
Account a1 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
Account a2 = new Account("account2", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2);
@@ -347,6 +351,8 @@
// Start testing
unlockSystemUser();
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
assertEquals("1 account should be migrated", 1, accounts.length);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
@@ -1048,7 +1054,6 @@
// Assert finishSessionAsUser added calling uid and pid into the sessionBundle
assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID));
assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID));
- // Assert App bundle data overrides sessionBundle data
assertEquals(sessionBundle.getString(
AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package");
@@ -1387,6 +1392,9 @@
@SmallTest
public void testRemoveAccountAsUserRemovalAllowed() throws Exception {
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+
unlockSystemUser();
mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p1", null);
Account[] addedAccounts =
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index 2e045ff..2cb8af4 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -355,49 +355,49 @@
@Test
public void testVisibilityFindSetDelete() {
long accId = 10;
- int uid1 = 100500;
- int uid2 = 100501;
+ String packageName1 = "com.example.one";
+ String packageName2 = "com.example.two";
Account account = new Account("name", "example.com");
- assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+ assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
mAccountsDb.insertDeAccount(account, accId);
- assertNull(mAccountsDb.findAccountVisibility(account, uid1));
- assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
+ assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
+ assertNull(mAccountsDb.findAccountVisibility(accId, packageName1));
- mAccountsDb.setAccountVisibility(accId, uid1, 1);
- assertEquals(mAccountsDb.findAccountVisibility(account, uid1), Integer.valueOf(1));
- assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
+ mAccountsDb.setAccountVisibility(accId, packageName1, 1);
+ assertEquals(mAccountsDb.findAccountVisibility(account, packageName1), Integer.valueOf(1));
+ assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1));
- mAccountsDb.setAccountVisibility(accId, uid2, 2);
- assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(2));
+ mAccountsDb.setAccountVisibility(accId, packageName2, 2);
+ assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(2));
- mAccountsDb.setAccountVisibility(accId, uid2, 3);
- assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(3));
+ mAccountsDb.setAccountVisibility(accId, packageName2, 3);
+ assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(3));
- Map<Integer, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account);
+ Map<String, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account);
assertEquals(vis.size(), 2);
- assertEquals(vis.get(uid1), Integer.valueOf(1));
- assertEquals(vis.get(uid2), Integer.valueOf(3));
+ assertEquals(vis.get(packageName1), Integer.valueOf(1));
+ assertEquals(vis.get(packageName2), Integer.valueOf(3));
- assertTrue(mAccountsDb.deleteAccountVisibilityForUid(uid1));
- assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
- assertFalse(mAccountsDb.deleteAccountVisibilityForUid(uid1)); // Already deleted.
+ assertTrue(mAccountsDb.deleteAccountVisibilityForPackage(packageName1));
+ assertNull(mAccountsDb.findAccountVisibility(accId, packageName1));
+ assertFalse(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); // 2nd attempt.
}
@Test
public void testVisibilityCleanupTrigger() {
long accId = 10;
- int uid1 = 100500;
+ String packageName1 = "com.example.one";
Account account = new Account("name", "example.com");
- assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+ assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
mAccountsDb.insertDeAccount(account, accId);
- assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+ assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
- mAccountsDb.setAccountVisibility(accId, uid1, 1);
- assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
+ mAccountsDb.setAccountVisibility(accId, packageName1, 1);
+ assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1));
assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility.
- assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+ assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index e30bd5d..e5640c7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -309,6 +309,7 @@
// Sanity check for InstrumentationInfo.
assertEquals(a.info.targetPackage, b.info.targetPackage);
+ assertEquals(a.info.targetProcess, b.info.targetProcess);
assertEquals(a.info.sourceDir, b.info.sourceDir);
assertEquals(a.info.publicSourceDir, b.info.publicSourceDir);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index ec429a0..1e471e3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,49 +16,7 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
-import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
-import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
-import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
-import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.mockito.Mockito.mock;
import android.annotation.Nullable;
@@ -70,12 +28,10 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
import android.os.PowerManagerInternal;
@@ -163,127 +119,6 @@
}
@Override
- public int windowTypeToLayerLw(int type) {
- // TODO: figure-out a good way to keep this in-sync with PhoneWindowManager...sigh!
- if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
- return 2;
- }
- switch (type) {
- case TYPE_PRESENTATION:
- case TYPE_PRIVATE_PRESENTATION:
- return 2;
- case TYPE_WALLPAPER:
- // wallpaper is at the bottom, though the window manager may move it.
- return 2;
- case TYPE_DOCK_DIVIDER:
- return 2;
- case TYPE_QS_DIALOG:
- return 2;
- case TYPE_PHONE:
- return 3;
- case TYPE_SEARCH_BAR:
- case TYPE_VOICE_INTERACTION_STARTING:
- return 4;
- case TYPE_VOICE_INTERACTION:
- // voice interaction layer is almost immediately above apps.
- return 5;
- case TYPE_INPUT_CONSUMER:
- return 6;
- case TYPE_SYSTEM_DIALOG:
- return 7;
- case TYPE_TOAST:
- // toasts and the plugged-in battery thing
- return 8;
- case TYPE_PRIORITY_PHONE:
- // SIM errors and unlock. Not sure if this really should be in a high layer.
- return 9;
- case TYPE_DREAM:
- // used for Dreams (screensavers with TYPE_DREAM windows)
- return 10;
- case TYPE_SYSTEM_ALERT:
- // like the ANR / app crashed dialogs
- return 11;
- case TYPE_INPUT_METHOD:
- // on-screen keyboards and other such input method user interfaces go here.
- return 12;
- case TYPE_INPUT_METHOD_DIALOG:
- // on-screen keyboards and other such input method user interfaces go here.
- return 13;
- case TYPE_STATUS_BAR_SUB_PANEL:
- return 15;
- case TYPE_STATUS_BAR:
- return 16;
- case TYPE_STATUS_BAR_PANEL:
- return 17;
- case TYPE_KEYGUARD_DIALOG:
- return 18;
- case TYPE_VOLUME_OVERLAY:
- // the on-screen volume indicator and controller shown when the user
- // changes the device volume
- return 19;
- case TYPE_SYSTEM_OVERLAY:
- // the on-screen volume indicator and controller shown when the user
- // changes the device volume
- return 20;
- case TYPE_NAVIGATION_BAR:
- // the navigation bar, if available, shows atop most things
- return 21;
- case TYPE_NAVIGATION_BAR_PANEL:
- // some panels (e.g. search) need to show on top of the navigation bar
- return 22;
- case TYPE_SCREENSHOT:
- // screenshot selection layer shouldn't go above system error, but it should cover
- // navigation bars at the very least.
- return 23;
- case TYPE_SYSTEM_ERROR:
- // system-level error dialogs
- return 24;
- case TYPE_MAGNIFICATION_OVERLAY:
- // used to highlight the magnified portion of a display
- return 25;
- case TYPE_DISPLAY_OVERLAY:
- // used to simulate secondary display devices
- return 26;
- case TYPE_DRAG:
- // the drag layer: input for drag-and-drop is associated with this window,
- // which sits above all other focusable windows
- return 27;
- case TYPE_ACCESSIBILITY_OVERLAY:
- // overlay put by accessibility services to intercept user interaction
- return 28;
- case TYPE_SECURE_SYSTEM_OVERLAY:
- return 29;
- case TYPE_BOOT_PROGRESS:
- return 30;
- case TYPE_POINTER:
- // the (mouse) pointer layer
- return 31;
- }
- Log.e(TAG, "Unknown window type: " + type);
- return 2;
- }
-
- @Override
- public int subWindowTypeToLayerLw(int type) {
- // TODO: figure-out a good way to keep this in-sync with PhoneWindowManager...
- switch (type) {
- case TYPE_APPLICATION_PANEL:
- case TYPE_APPLICATION_ATTACHED_DIALOG:
- return 1;
- case TYPE_APPLICATION_MEDIA:
- return -2;
- case TYPE_APPLICATION_MEDIA_OVERLAY:
- return -1;
- case TYPE_APPLICATION_SUB_PANEL:
- return 2;
- case TYPE_APPLICATION_ABOVE_SUB_PANEL:
- return 3;
- }
- Log.e(TAG, "Unknown sub-window type: " + type);
- return 0;
- }
-
- @Override
public int getMaxWallpaperLayer() {
return 0;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 186884b..98ff0e2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -57,7 +57,8 @@
final Task mTask;
boolean mDockedResizingForTest = false;
WindowStateWithTask(WindowManager.LayoutParams attrs, Task t) {
- super(sWm, null, mIWindow, mWindowToken, null, 0, 0, attrs, 0, 0);
+ super(sWm, null, mIWindow, mWindowToken, null, 0, 0, attrs, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
mTask = t;
}
@@ -77,8 +78,7 @@
final Rect mInsetBounds = new Rect();
boolean mFullscreenForTest = true;
TaskWithBounds(Rect bounds) {
- super(0, mStubStack, 0, sWm, null, null, false, 0, false, false, new TaskDescription(),
- null);
+ super(0, mStubStack, 0, sWm, null, null, 0, false, false, new TaskDescription(), null);
mBounds = bounds;
}
@Override
@@ -106,7 +106,7 @@
sWm.mSystemDecorLayer = 10000;
mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
- sWm.getDefaultDisplayContentLocked());
+ sWm.getDefaultDisplayContentLocked(), false /* ownerCanManageAppTokens */);
mStubStack = new TaskStack(sWm, 0);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index c6f88ed..bc85017 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -181,7 +181,7 @@
attrs.setTitle(name);
final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
- 0, attrs, 0, 0);
+ 0, attrs, 0, 0, false /* ownerCanAddInternalSystemWindow */);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);
@@ -201,8 +201,8 @@
/** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
static Task createTaskInStack(TaskStack stack, int userId) {
- final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0,
- false, false, new TaskDescription(), null);
+ final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, 0, false,
+ false, new TaskDescription(), null);
stack.addTask(newTask, POSITION_TOP);
return newTask;
}
@@ -223,7 +223,8 @@
}
TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(sWm, mock(IBinder.class), type, persistOnEmpty, dc);
+ super(sWm, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
}
int getWindowsCount() {
@@ -282,12 +283,10 @@
private boolean mIsAnimating = false;
TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
- Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
- boolean supportsPictureInPicture, boolean homeTask,
- TaskWindowContainerController controller) {
- super(taskId, stack, userId, service, bounds, overrideConfig, isOnTopLauncher,
- resizeMode, supportsPictureInPicture, homeTask, new TaskDescription(),
- controller);
+ Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+ boolean homeTask, TaskWindowContainerController controller) {
+ super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, new TaskDescription(), controller);
}
boolean shouldDeferRemoval() {
@@ -338,17 +337,16 @@
}
}, stackController, 0 /* userId */, null /* bounds */,
EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
- false /* supportsPictureInPicture */, false /* homeTask*/,
- false /* isOnTopLauncher */, true /* toTop*/, true /* showForAllUsers */,
- new TaskDescription(), sWm);
+ false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
+ true /* showForAllUsers */, new TaskDescription(), sWm);
}
@Override
TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
- boolean homeTask, boolean isOnTopLauncher, TaskDescription taskDescription) {
- return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig,
- isOnTopLauncher, resizeMode, supportsPictureInPicture, homeTask, this);
+ boolean homeTask, TaskDescription taskDescription) {
+ return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
+ supportsPictureInPicture, homeTask, this);
}
}
@@ -403,7 +401,8 @@
boolean resizeReported;
TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
- super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0);
+ super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 4d2c3b9..07b4ca1 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -17,6 +17,7 @@
package com.android.server.usb;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -134,6 +135,8 @@
private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
+ private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
+
private UsbHandler mHandler;
private boolean mBootCompleted;
@@ -239,6 +242,16 @@
mNotificationManager = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ // Ensure that the notification channels are set up
+ if (isTv()) {
+ // TV-specific notification channel
+ mNotificationManager.createNotificationChannel(
+ new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
+ mContext.getString(
+ com.android.internal.R.string.adb_debugging_notification_channel_tv),
+ NotificationManager.IMPORTANCE_HIGH));
+ }
+
// We do not show the USB notification if the primary volume supports mass storage.
// The legacy mass storage UI will be used instead.
boolean massStorageSupported = false;
@@ -325,6 +338,10 @@
}
}
+ private boolean isTv() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
private final class UsbHandler extends Handler {
// current USB state
@@ -928,9 +945,9 @@
CharSequence message = r.getText(
com.android.internal.R.string.adb_active_notification_message);
- Intent intent = Intent.makeRestartActivityTask(
- new ComponentName("com.android.settings",
- "com.android.settings.DevelopmentSettings"));
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
intent, 0, null, UserHandle.CURRENT);
@@ -947,6 +964,8 @@
.setContentText(message)
.setContentIntent(pi)
.setVisibility(Notification.VISIBILITY_PUBLIC)
+ .extend(new Notification.TvExtender()
+ .setChannel(ADB_NOTIFICATION_CHANNEL_ID_TV))
.build();
mAdbNotificationShown = true;
mNotificationManager.notifyAsUser(null, id, notification,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6c45233..3b15f1c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1173,6 +1173,9 @@
* and {@code NEW_CODE} is the new {@code ImsReasonInfo#CODE_*} which this combination of
* original code and message shall be remapped to.
*
+ * Note: If {@code *} is specified for the original code, any ImsReasonInfo with the matching
+ * {@code MESSAGE} will be remapped to {@code NEW_CODE}.
+ *
* Example: "501|call completion elsewhere|1014"
* When the {@link ImsReasonInfo#getCode()} is {@link ImsReasonInfo#CODE_USER_TERMINATED} and
* the {@link ImsReasonInfo#getExtraMessage()} is {@code "call completion elsewhere"},
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 10cb7c9..e53e246 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -246,23 +246,18 @@
*/
public static final int IMEI_NOT_ACCEPTED = 58;
+ /**
+ * A call over WIFI was disconnected because the WIFI signal was lost or became too degraded to
+ * continue the call.
+ */
+ public static final int WIFI_LOST = 59;
+
//*********************************************************************************************
// When adding a disconnect type:
- // 1) Please assign the new type the next id value below.
- // 2) Increment the next id value below to a new value.
- // 3) Update MAXIMUM_VALID_VALUE to the new disconnect type.
- // 4) Update toString() with the newly added disconnect type.
- // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
- //
- // NextId: 59
+ // 1) Update toString() with the newly added disconnect type.
+ // 2) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//*********************************************************************************************
- /** Smallest valid value for call disconnect codes. */
- public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
-
- /** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = IMEI_NOT_ACCEPTED;
-
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
// Do nothing.
@@ -387,6 +382,8 @@
return "DIALED_CALL_FORWARDING_WHILE_ROAMING";
case IMEI_NOT_ACCEPTED:
return "IMEI_NOT_ACCEPTED";
+ case WIFI_LOST:
+ return "WIFI_LOST";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 913da82..1b3aa8a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -819,37 +819,6 @@
public static final String EVENT_DOWNGRADE_DATA_DISABLED =
"android.telephony.event.EVENT_DOWNGRADE_DATA_DISABLED";
- /**
- * Response codes for sim activation. Activation completed successfully.
- * @hide
- */
- @SystemApi
- public static final int SIM_ACTIVATION_RESULT_COMPLETE = 0;
- /**
- * Response codes for sim activation. Activation not supported (device has no SIM).
- * @hide
- */
- @SystemApi
- public static final int SIM_ACTIVATION_RESULT_NOT_SUPPORTED = 1;
- /**
- * Response codes for sim activation. Activation is in progress.
- * @hide
- */
- @SystemApi
- public static final int SIM_ACTIVATION_RESULT_IN_PROGRESS = 2;
- /**
- * Response codes for sim activation. Activation failed to complete.
- * @hide
- */
- @SystemApi
- public static final int SIM_ACTIVATION_RESULT_FAILED = 3;
- /**
- * Response codes for sim activation. Activation canceled by user.
- * @hide
- */
- @SystemApi
- public static final int SIM_ACTIVATION_RESULT_CANCELED = 4;
-
/* Visual voicemail protocols */
/**
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 56b8822..c71808c 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -308,6 +308,11 @@
public static final int CODE_DATA_DISABLED = 1406;
/**
+ * Indicates a call was disconnected due to loss of wifi signal.
+ */
+ public static final int CODE_WIFI_LOST = 1407;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 891b8a1a..5ee7e23 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -417,7 +417,7 @@
int RIL_UNSOL_RESPONSE_BASE = 1000;
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
- int RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002;
+ int RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED = 1002;
int RIL_UNSOL_RESPONSE_NEW_SMS = 1003;
int RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
int RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005;
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
new file mode 100644
index 0000000..b984bbf
--- /dev/null
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.net;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConnectivityManagerTest {
+ static NetworkCapabilities verifyNetworkCapabilities(
+ int legacyType, int transportType, int... capabilities) {
+ final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
+ assertNotNull(nc);
+ assertTrue(nc.hasTransport(transportType));
+ for (int capability : capabilities) {
+ assertTrue(nc.hasCapability(capability));
+ }
+
+ return nc;
+ }
+
+ static void verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType) {
+ verifyNetworkCapabilities(
+ legacyType,
+ transportType,
+ NET_CAPABILITY_INTERNET,
+ NET_CAPABILITY_NOT_RESTRICTED,
+ NET_CAPABILITY_NOT_VPN,
+ NET_CAPABILITY_TRUSTED);
+ }
+
+ static void verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability) {
+ final NetworkCapabilities nc = verifyNetworkCapabilities(
+ legacyType,
+ TRANSPORT_CELLULAR,
+ capability,
+ NET_CAPABILITY_NOT_VPN,
+ NET_CAPABILITY_TRUSTED);
+
+ assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobile() {
+ verifyUnrestrictedNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE, TRANSPORT_CELLULAR);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileCbs() {
+ verifyRestrictedMobileNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_CBS, NET_CAPABILITY_CBS);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileDun() {
+ verifyRestrictedMobileNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_DUN, NET_CAPABILITY_DUN);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileFota() {
+ verifyRestrictedMobileNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_FOTA, NET_CAPABILITY_FOTA);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileHipri() {
+ verifyUnrestrictedNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_HIPRI, TRANSPORT_CELLULAR);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileIms() {
+ verifyRestrictedMobileNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_IMS, NET_CAPABILITY_IMS);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileMms() {
+ final NetworkCapabilities nc = verifyNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_MMS,
+ TRANSPORT_CELLULAR,
+ NET_CAPABILITY_MMS,
+ NET_CAPABILITY_NOT_VPN,
+ NET_CAPABILITY_TRUSTED);
+
+ assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeMobileSupl() {
+ final NetworkCapabilities nc = verifyNetworkCapabilities(
+ ConnectivityManager.TYPE_MOBILE_SUPL,
+ TRANSPORT_CELLULAR,
+ NET_CAPABILITY_SUPL,
+ NET_CAPABILITY_NOT_VPN,
+ NET_CAPABILITY_TRUSTED);
+
+ assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeWifi() {
+ verifyUnrestrictedNetworkCapabilities(
+ ConnectivityManager.TYPE_WIFI, TRANSPORT_WIFI);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeWifiP2p() {
+ final NetworkCapabilities nc = verifyNetworkCapabilities(
+ ConnectivityManager.TYPE_WIFI_P2P,
+ TRANSPORT_WIFI,
+ NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_VPN,
+ NET_CAPABILITY_TRUSTED, NET_CAPABILITY_WIFI_P2P);
+
+ assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeBluetooth() {
+ verifyUnrestrictedNetworkCapabilities(
+ ConnectivityManager.TYPE_BLUETOOTH, TRANSPORT_BLUETOOTH);
+ }
+
+ @Test
+ public void testNetworkCapabilitiesForTypeEthernet() {
+ verifyUnrestrictedNetworkCapabilities(
+ ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET);
+ }
+}
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 3d466ef..3d7bd94 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -16,10 +16,15 @@
#include "LoadedApk.h"
+#include "ResourceValues.h"
+#include "ValueVisitor.h"
+#include "flatten/Archive.h"
+#include "flatten/TableFlattener.h"
+
namespace aapt {
-std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(
- IAaptContext* context, const StringPiece& path) {
+std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(IAaptContext* context,
+ const android::StringPiece& path) {
Source source(path);
std::string error;
std::unique_ptr<io::ZipFileCollection> apk =
@@ -53,4 +58,67 @@
return util::make_unique<LoadedApk>(source, std::move(apk), std::move(table));
}
+bool LoadedApk::WriteToArchive(IAaptContext* context, IArchiveWriter* writer) {
+ std::set<std::string> referenced_resources;
+ // List the files being referenced in the resource table.
+ for (auto& pkg : table_->packages) {
+ for (auto& type : pkg->types) {
+ for (auto& entry : type->entries) {
+ for (auto& config_value : entry->values) {
+ FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
+ if (file_ref) {
+ referenced_resources.insert(*file_ref->path);
+ }
+ }
+ }
+ }
+ }
+
+ std::unique_ptr<io::IFileCollectionIterator> iterator = apk_->Iterator();
+ while (iterator->HasNext()) {
+ io::IFile* file = iterator->Next();
+
+ std::string path = file->GetSource().path;
+ // The name of the path has the format "<zip-file-name>@<path-to-file>".
+ path = path.substr(path.find("@") + 1);
+
+ // Skip resources that are not referenced if requested.
+ if (path.find("res/") == 0 && referenced_resources.find(path) == referenced_resources.end()) {
+ if (context->IsVerbose()) {
+ context->GetDiagnostics()->Note(DiagMessage()
+ << "Removing resource '" << path << "' from APK.");
+ }
+ continue;
+ }
+
+ // The resource table needs to be reserialized since it might have changed.
+ if (path == "resources.arsc") {
+ BigBuffer buffer = BigBuffer(1024);
+ TableFlattener flattener(&buffer);
+ if (!flattener.Consume(context, table_.get())) {
+ return false;
+ }
+
+ if (!writer->StartEntry(path, ArchiveEntry::kAlign) || !writer->WriteEntry(buffer) ||
+ !writer->FinishEntry()) {
+ context->GetDiagnostics()->Error(DiagMessage()
+ << "Error when writing file '" << path << "' in APK.");
+ return false;
+ }
+ continue;
+ }
+
+ std::unique_ptr<io::IData> data = file->OpenAsData();
+ uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
+ if (!writer->StartEntry(path, compression_flags) ||
+ !writer->WriteEntry(data->data(), data->size()) || !writer->FinishEntry()) {
+ context->GetDiagnostics()->Error(DiagMessage()
+ << "Error when writing file '" << path << "' in APK.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace aapt
diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h
index 0cc2d22..f8878d1 100644
--- a/tools/aapt2/LoadedApk.h
+++ b/tools/aapt2/LoadedApk.h
@@ -19,12 +19,11 @@
#include "androidfw/StringPiece.h"
-#include "io/ZipArchive.h"
#include "ResourceTable.h"
+#include "flatten/Archive.h"
+#include "io/ZipArchive.h"
#include "unflatten/BinaryResourceParser.h"
-using android::StringPiece;
-
namespace aapt {
/** Info about an APK loaded in memory. */
@@ -42,8 +41,14 @@
const Source& GetSource() { return source_; }
- static std::unique_ptr<LoadedApk> LoadApkFromPath(
- IAaptContext* context, const StringPiece& path);
+ /**
+ * Writes the APK on disk at the given path, while also removing the resource
+ * files that are not referenced in the resource table.
+ */
+ bool WriteToArchive(IAaptContext* context, IArchiveWriter* writer);
+
+ static std::unique_ptr<LoadedApk> LoadApkFromPath(IAaptContext* context,
+ const android::StringPiece& path);
private:
Source source_;
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 3ed698b..227ffa3 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "5";
+static const char* sMinorVersion = "6";
int PrintVersion() {
std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index fdabce1..35971e7 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -39,6 +39,8 @@
return "bool";
case ResourceType::kColor:
return "color";
+ case ResourceType::kConfigVarying:
+ return "configVarying";
case ResourceType::kDimen:
return "dimen";
case ResourceType::kDrawable:
@@ -85,6 +87,7 @@
{"^attr-private", ResourceType::kAttrPrivate},
{"bool", ResourceType::kBool},
{"color", ResourceType::kColor},
+ {"configVarying", ResourceType::kConfigVarying},
{"dimen", ResourceType::kDimen},
{"drawable", ResourceType::kDrawable},
{"font", ResourceType::kFont},
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 1950ea3..4d915d9 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -44,6 +44,11 @@
kAttrPrivate,
kBool,
kColor,
+
+ // Not really a type, but it shows up in some CTS tests and
+ // we need to continue respecting it.
+ kConfigVarying,
+
kDimen,
kDrawable,
kFont,
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 79379fe..1c750c6 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -338,50 +338,52 @@
using BagParseFunc = std::function<bool(ResourceParser*, xml::XmlPullParser*,
ParsedResource*)>;
- static const auto elToItemMap =
- ImmutableMap<std::string, ItemTypeFormat>::CreatePreSorted({
- {"bool", {ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN}},
- {"color", {ResourceType::kColor, android::ResTable_map::TYPE_COLOR}},
- {"dimen",
- {ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT |
- android::ResTable_map::TYPE_FRACTION |
- android::ResTable_map::TYPE_DIMENSION}},
- {"drawable",
- {ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR}},
- {"fraction",
- {ResourceType::kFraction,
- android::ResTable_map::TYPE_FLOAT |
- android::ResTable_map::TYPE_FRACTION |
- android::ResTable_map::TYPE_DIMENSION}},
- {"integer",
- {ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER}},
- {"string",
- {ResourceType::kString, android::ResTable_map::TYPE_STRING}},
- });
+ static const auto elToItemMap = ImmutableMap<std::string, ItemTypeFormat>::CreatePreSorted({
+ {"bool", {ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN}},
+ {"color", {ResourceType::kColor, android::ResTable_map::TYPE_COLOR}},
+ {"configVarying", {ResourceType::kConfigVarying, android::ResTable_map::TYPE_ANY}},
+ {"dimen",
+ {ResourceType::kDimen,
+ android::ResTable_map::TYPE_FLOAT | android::ResTable_map::TYPE_FRACTION |
+ android::ResTable_map::TYPE_DIMENSION}},
+ {"drawable", {ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR}},
+ {"fraction",
+ {ResourceType::kFraction,
+ android::ResTable_map::TYPE_FLOAT | android::ResTable_map::TYPE_FRACTION |
+ android::ResTable_map::TYPE_DIMENSION}},
+ {"integer", {ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER}},
+ {"string", {ResourceType::kString, android::ResTable_map::TYPE_STRING}},
+ });
- static const auto elToBagMap =
- ImmutableMap<std::string, BagParseFunc>::CreatePreSorted({
- {"add-resource", std::mem_fn(&ResourceParser::ParseAddResource)},
- {"array", std::mem_fn(&ResourceParser::ParseArray)},
- {"attr", std::mem_fn(&ResourceParser::ParseAttr)},
- {"declare-styleable",
- std::mem_fn(&ResourceParser::ParseDeclareStyleable)},
- {"integer-array", std::mem_fn(&ResourceParser::ParseIntegerArray)},
- {"java-symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
- {"plurals", std::mem_fn(&ResourceParser::ParsePlural)},
- {"public", std::mem_fn(&ResourceParser::ParsePublic)},
- {"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)},
- {"string-array", std::mem_fn(&ResourceParser::ParseStringArray)},
- {"style", std::mem_fn(&ResourceParser::ParseStyle)},
- {"symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
- });
+ static const auto elToBagMap = ImmutableMap<std::string, BagParseFunc>::CreatePreSorted({
+ {"add-resource", std::mem_fn(&ResourceParser::ParseAddResource)},
+ {"array", std::mem_fn(&ResourceParser::ParseArray)},
+ {"attr", std::mem_fn(&ResourceParser::ParseAttr)},
+ {"configVarying",
+ std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kConfigVarying,
+ std::placeholders::_2, std::placeholders::_3)},
+ {"declare-styleable", std::mem_fn(&ResourceParser::ParseDeclareStyleable)},
+ {"integer-array", std::mem_fn(&ResourceParser::ParseIntegerArray)},
+ {"java-symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
+ {"plurals", std::mem_fn(&ResourceParser::ParsePlural)},
+ {"public", std::mem_fn(&ResourceParser::ParsePublic)},
+ {"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)},
+ {"string-array", std::mem_fn(&ResourceParser::ParseStringArray)},
+ {"style", std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kStyle,
+ std::placeholders::_2, std::placeholders::_3)},
+ {"symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
+ });
std::string resource_type = parser->element_name();
// The value format accepted for this resource.
uint32_t resource_format = 0u;
+ bool can_be_item = true;
+ bool can_be_bag = true;
if (resource_type == "item") {
+ can_be_bag = false;
+
// Items have their type encoded in the type attribute.
if (Maybe<StringPiece> maybe_type =
xml::FindNonEmptyAttribute(parser, "type")) {
@@ -406,6 +408,17 @@
return false;
}
}
+ } else if (resource_type == "bag") {
+ can_be_item = false;
+
+ // Bags have their type encoded in the type attribute.
+ if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
+ resource_type = maybe_type.value().to_string();
+ } else {
+ diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
+ << "<bag> must have a 'type' attribute");
+ return false;
+ }
}
// Get the name of the resource. This will be checked later, because not all
@@ -426,36 +439,61 @@
return true;
}
- const auto item_iter = elToItemMap.find(resource_type);
- if (item_iter != elToItemMap.end()) {
- // This is an item, record its type and format and start parsing.
+ if (can_be_item) {
+ const auto item_iter = elToItemMap.find(resource_type);
+ if (item_iter != elToItemMap.end()) {
+ // This is an item, record its type and format and start parsing.
- if (!maybe_name) {
- diag_->Error(DiagMessage(out_resource->source)
- << "<" << parser->element_name()
- << "> missing 'name' attribute");
- return false;
+ if (!maybe_name) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<" << parser->element_name() << "> missing 'name' attribute");
+ return false;
+ }
+
+ out_resource->name.type = item_iter->second.type;
+ out_resource->name.entry = maybe_name.value().to_string();
+
+ // Only use the implicit format for this type if it wasn't overridden.
+ if (!resource_format) {
+ resource_format = item_iter->second.format;
+ }
+
+ if (!ParseItem(parser, out_resource, resource_format)) {
+ return false;
+ }
+ return true;
}
-
- out_resource->name.type = item_iter->second.type;
- out_resource->name.entry = maybe_name.value().to_string();
-
- // Only use the implicit format for this type if it wasn't overridden.
- if (!resource_format) {
- resource_format = item_iter->second.format;
- }
-
- if (!ParseItem(parser, out_resource, resource_format)) {
- return false;
- }
- return true;
}
// This might be a bag or something.
- const auto bag_iter = elToBagMap.find(resource_type);
- if (bag_iter != elToBagMap.end()) {
- // Ensure we have a name (unless this is a <public-group>).
- if (resource_type != "public-group") {
+ if (can_be_bag) {
+ const auto bag_iter = elToBagMap.find(resource_type);
+ if (bag_iter != elToBagMap.end()) {
+ // Ensure we have a name (unless this is a <public-group>).
+ if (resource_type != "public-group") {
+ if (!maybe_name) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<" << parser->element_name() << "> missing 'name' attribute");
+ return false;
+ }
+
+ out_resource->name.entry = maybe_name.value().to_string();
+ }
+
+ // Call the associated parse method. The type will be filled in by the
+ // parse func.
+ if (!bag_iter->second(this, parser, out_resource)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ if (can_be_item) {
+ // Try parsing the elementName (or type) as a resource. These shall only be
+ // resources like 'layout' or 'xml' and they can only be references.
+ const ResourceType* parsed_type = ParseResourceType(resource_type);
+ if (parsed_type) {
if (!maybe_name) {
diag_->Error(DiagMessage(out_resource->source)
<< "<" << parser->element_name()
@@ -463,39 +501,16 @@
return false;
}
+ out_resource->name.type = *parsed_type;
out_resource->name.entry = maybe_name.value().to_string();
+ out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
+ if (!out_resource->value) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "invalid value for type '" << *parsed_type << "'. Expected a reference");
+ return false;
+ }
+ return true;
}
-
- // Call the associated parse method. The type will be filled in by the
- // parse func.
- if (!bag_iter->second(this, parser, out_resource)) {
- return false;
- }
- return true;
- }
-
- // Try parsing the elementName (or type) as a resource. These shall only be
- // resources like 'layout' or 'xml' and they can only be references.
- const ResourceType* parsed_type = ParseResourceType(resource_type);
- if (parsed_type) {
- if (!maybe_name) {
- diag_->Error(DiagMessage(out_resource->source)
- << "<" << parser->element_name()
- << "> missing 'name' attribute");
- return false;
- }
-
- out_resource->name.type = *parsed_type;
- out_resource->name.entry = maybe_name.value().to_string();
- out_resource->value =
- ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
- if (!out_resource->value) {
- diag_->Error(DiagMessage(out_resource->source)
- << "invalid value for type '" << *parsed_type
- << "'. Expected a reference");
- return false;
- }
- return true;
}
diag_->Warn(DiagMessage(out_resource->source)
@@ -1048,9 +1063,9 @@
return true;
}
-bool ResourceParser::ParseStyle(xml::XmlPullParser* parser,
+bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
ParsedResource* out_resource) {
- out_resource->name.type = ResourceType::kStyle;
+ out_resource->name.type = type;
std::unique_ptr<Style> style = util::make_unique<Style>();
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index c12dacf..cc0fa26 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -102,7 +102,8 @@
bool weak);
Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
const android::StringPiece& tag);
- bool ParseStyle(xml::XmlPullParser* parser, ParsedResource* out_resource);
+ bool ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
+ ParsedResource* out_resource);
bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
bool ParseDeclareStyleable(xml::XmlPullParser* parser,
ParsedResource* out_resource);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 5762fb0..cf901da 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -719,4 +719,23 @@
EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType);
}
+TEST_F(ResourceParserTest, ParseConfigVaryingItem) {
+ std::string input = R"EOF(<item name="foo" type="configVarying">Hey</item>)EOF";
+ ASSERT_TRUE(TestParse(input));
+ ASSERT_NE(nullptr, test::GetValue<String>(&table_, "configVarying/foo"));
+}
+
+TEST_F(ResourceParserTest, ParseBagElement) {
+ std::string input =
+ R"EOF(<bag name="bag" type="configVarying"><item name="test">Hello!</item></bag>)EOF";
+ ASSERT_TRUE(TestParse(input));
+
+ Style* val = test::GetValue<Style>(&table_, "configVarying/bag");
+ ASSERT_NE(nullptr, val);
+
+ ASSERT_EQ(1u, val->entries.size());
+ EXPECT_EQ(Reference(test::ParseNameOrDie("attr/test")), val->entries[0].key);
+ EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get()));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index 6acb4d3..ad4e3ce 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -49,6 +49,10 @@
ASSERT_NE(type, nullptr);
EXPECT_EQ(*type, ResourceType::kColor);
+ type = ParseResourceType("configVarying");
+ ASSERT_NE(type, nullptr);
+ EXPECT_EQ(*type, ResourceType::kConfigVarying);
+
type = ParseResourceType("dimen");
ASSERT_NE(type, nullptr);
EXPECT_EQ(*type, ResourceType::kDimen);
diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h
index 3d5b5b1..1ef9743 100644
--- a/tools/aapt2/io/File.h
+++ b/tools/aapt2/io/File.h
@@ -63,6 +63,11 @@
IFile* CreateFileSegment(size_t offset, size_t len);
+ /** Returns whether the file was compressed before it was stored in memory. */
+ virtual bool WasCompressed() {
+ return false;
+ }
+
private:
// Any segments created from this IFile need to be owned by this IFile, so
// keep them
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 62b436f..6494d2d 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -59,6 +59,10 @@
const Source& ZipFile::GetSource() const { return source_; }
+bool ZipFile::WasCompressed() {
+ return zip_entry_.method != kCompressStored;
+}
+
ZipFileCollectionIterator::ZipFileCollectionIterator(
ZipFileCollection* collection)
: current_(collection->files_.begin()), end_(collection->files_.end()) {}
@@ -66,7 +70,7 @@
bool ZipFileCollectionIterator::HasNext() { return current_ != end_; }
IFile* ZipFileCollectionIterator::Next() {
- IFile* result = current_->second.get();
+ IFile* result = current_->get();
++current_;
return result;
}
@@ -110,8 +114,10 @@
std::string(reinterpret_cast<const char*>(zip_entry_name.name),
zip_entry_name.name_length);
std::string nested_path = path.to_string() + "@" + zip_entry_path;
- collection->files_[zip_entry_path] = util::make_unique<ZipFile>(
- collection->handle_, zip_data, Source(nested_path));
+ std::unique_ptr<IFile> file =
+ util::make_unique<ZipFile>(collection->handle_, zip_data, Source(nested_path));
+ collection->files_by_name_[zip_entry_path] = file.get();
+ collection->files_.push_back(std::move(file));
}
if (result != -1) {
@@ -122,9 +128,9 @@
}
IFile* ZipFileCollection::FindFile(const StringPiece& path) {
- auto iter = files_.find(path.to_string());
- if (iter != files_.end()) {
- return iter->second.get();
+ auto iter = files_by_name_.find(path.to_string());
+ if (iter != files_by_name_.end()) {
+ return iter->second;
}
return nullptr;
}
diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h
index 634adad..56c74e3 100644
--- a/tools/aapt2/io/ZipArchive.h
+++ b/tools/aapt2/io/ZipArchive.h
@@ -40,6 +40,7 @@
std::unique_ptr<IData> OpenAsData() override;
const Source& GetSource() const override;
+ bool WasCompressed() override;
private:
ZipArchiveHandle zip_handle_;
@@ -57,7 +58,7 @@
io::IFile* Next() override;
private:
- std::map<std::string, std::unique_ptr<IFile>>::const_iterator current_, end_;
+ std::vector<std::unique_ptr<IFile>>::const_iterator current_, end_;
};
/**
@@ -78,7 +79,8 @@
ZipFileCollection();
ZipArchiveHandle handle_;
- std::map<std::string, std::unique_ptr<IFile>> files_;
+ std::vector<std::unique_ptr<IFile>> files_;
+ std::map<std::string, IFile*> files_by_name_;
};
} // namespace io
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index e5eaf2f..b4cf4f8 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -111,6 +111,36 @@
return true;
}
+// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
+static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
+ bool has_name = false;
+ if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
+ if (attr->value.empty()) {
+ diag->Error(DiagMessage(el->line_number)
+ << "android:name in <uses-feature> must not be empty");
+ return false;
+ }
+ has_name = true;
+ }
+
+ bool has_gl_es_version = false;
+ if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
+ if (has_name) {
+ diag->Error(DiagMessage(el->line_number)
+ << "cannot define both android:name and android:glEsVersion in <uses-feature>");
+ return false;
+ }
+ has_gl_es_version = true;
+ }
+
+ if (!has_name && !has_gl_es_version) {
+ diag->Error(DiagMessage(el->line_number)
+ << "<uses-feature> must have either android:name or android:glEsVersion attribute");
+ return false;
+ }
+ return true;
+}
+
bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
IDiagnostics* diag) {
// First verify some options.
@@ -134,15 +164,25 @@
}
}
- // Common intent-filter actions.
+ // Common <intent-filter> actions.
xml::XmlNodeAction intent_filter_action;
intent_filter_action["action"];
intent_filter_action["category"];
intent_filter_action["data"];
- // Common meta-data actions.
+ // Common <meta-data> actions.
xml::XmlNodeAction meta_data_action;
+ // Common <uses-feature> actions.
+ xml::XmlNodeAction uses_feature_action;
+ uses_feature_action.Action(VerifyUsesFeature);
+
+ // Common component actions.
+ xml::XmlNodeAction component_action;
+ component_action.Action(RequiredNameIsJavaClassName);
+ component_action["intent-filter"] = intent_filter_action;
+ component_action["meta-data"] = meta_data_action;
+
// Manifest actions.
xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
manifest_action.Action(VerifyManifest);
@@ -190,6 +230,7 @@
});
// Instrumentation actions.
+ manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
if (!options_.rename_instrumentation_target_package) {
return true;
@@ -201,6 +242,7 @@
}
return true;
});
+ manifest_action["instrumentation"]["meta-data"] = meta_data_action;
manifest_action["original-package"];
manifest_action["protected-broadcast"];
@@ -208,51 +250,28 @@
manifest_action["permission"];
manifest_action["permission-tree"];
manifest_action["permission-group"];
-
manifest_action["uses-configuration"];
- manifest_action["uses-feature"];
manifest_action["supports-screens"];
-
+ manifest_action["uses-feature"] = uses_feature_action;
+ manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
manifest_action["compatible-screens"];
manifest_action["compatible-screens"]["screen"];
-
manifest_action["supports-gl-texture"];
-
manifest_action["meta-data"] = meta_data_action;
// Application actions.
xml::XmlNodeAction& application_action = manifest_action["application"];
application_action.Action(OptionalNameIsJavaClassName);
- // Uses library actions.
application_action["uses-library"];
-
- // Meta-data.
application_action["meta-data"] = meta_data_action;
-
- // Activity actions.
- application_action["activity"].Action(RequiredNameIsJavaClassName);
- application_action["activity"]["intent-filter"] = intent_filter_action;
- application_action["activity"]["meta-data"] = meta_data_action;
-
- // Activity alias actions.
- application_action["activity-alias"]["intent-filter"] = intent_filter_action;
- application_action["activity-alias"]["meta-data"] = meta_data_action;
-
- // Service actions.
- application_action["service"].Action(RequiredNameIsJavaClassName);
- application_action["service"]["intent-filter"] = intent_filter_action;
- application_action["service"]["meta-data"] = meta_data_action;
-
- // Receiver actions.
- application_action["receiver"].Action(RequiredNameIsJavaClassName);
- application_action["receiver"]["intent-filter"] = intent_filter_action;
- application_action["receiver"]["meta-data"] = meta_data_action;
+ application_action["activity"] = component_action;
+ application_action["activity-alias"] = component_action;
+ application_action["service"] = component_action;
+ application_action["receiver"] = component_action;
// Provider actions.
- application_action["provider"].Action(RequiredNameIsJavaClassName);
- application_action["provider"]["intent-filter"] = intent_filter_action;
- application_action["provider"]["meta-data"] = meta_data_action;
+ application_action["provider"] = component_action;
application_action["provider"]["grant-uri-permissions"];
application_action["provider"]["path-permissions"];
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 12a304a..ce84993 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -90,7 +90,7 @@
}
TEST_F(ManifestFixerTest, AllowMetaData) {
- auto doc = Verify(R"EOF(
+ auto doc = Verify(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<meta-data />
@@ -98,12 +98,13 @@
<meta-data />
<activity android:name=".Hi"><meta-data /></activity>
<activity-alias android:name=".Ho"><meta-data /></activity-alias>
- <receiver android:name=".OffToWork"><meta-data /></receiver>
- <provider android:name=".We"><meta-data /></provider>
- <service android:name=".Go"><meta-data /></service>
+ <receiver android:name=".OffTo"><meta-data /></receiver>
+ <provider android:name=".Work"><meta-data /></provider>
+ <service android:name=".We"><meta-data /></service>
</application>
+ <instrumentation android:name=".Go"><meta-data /></instrumentation>
</manifest>)EOF");
- ASSERT_NE(nullptr, doc);
+ ASSERT_NE(nullptr, doc);
}
TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
@@ -290,7 +291,7 @@
std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
- <instrumentation android:targetPackage="android" />
+ <instrumentation android:name=".TestRunner" android:targetPackage="android" />
</manifest>)EOF",
options);
ASSERT_NE(nullptr, doc);
@@ -354,4 +355,51 @@
EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(attr->compiled_value.get()));
}
+TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
+ std::string input = R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-feature android:name="feature" />
+ <uses-feature android:glEsVersion="1" />
+ <feature-group />
+ <feature-group>
+ <uses-feature android:name="feature_in_group" />
+ <uses-feature android:glEsVersion="2" />
+ </feature-group>
+ </manifest>)EOF";
+ EXPECT_NE(nullptr, Verify(input));
+
+ input = R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-feature android:name="feature" android:glEsVersion="1" />
+ </manifest>)EOF";
+ EXPECT_EQ(nullptr, Verify(input));
+
+ input = R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-feature />
+ </manifest>)EOF";
+ EXPECT_EQ(nullptr, Verify(input));
+
+ input = R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <feature-group>
+ <uses-feature android:name="feature" android:glEsVersion="1" />
+ </feature-group>
+ </manifest>)EOF";
+ EXPECT_EQ(nullptr, Verify(input));
+
+ input = R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <feature-group>
+ <uses-feature />
+ </feature-group>
+ </manifest>)EOF";
+ EXPECT_EQ(nullptr, Verify(input));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index e2a752e..44d22c4 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,12 @@
# Android Asset Packaging Tool 2.0 (AAPT2) release notes
+## Version 2.6
+### `aapt2`
+- Support legacy `configVarying` resource type.
+- Support `<bag>` tag and treat as `<style>` regardless of type.
+- Add `<feature-group>` manifest tag verification.
+- Add `<meta-data>` tag support to `<instrumentation>`.
+
## Version 2.5
### `aapt2 link ...`
- Transition XML versioning: Adds a new flag `--no-version-transitions` to disable automatic
diff --git a/tools/aapt2/strip/Strip.cpp b/tools/aapt2/strip/Strip.cpp
index b3787ec..c34cfbf3 100644
--- a/tools/aapt2/strip/Strip.cpp
+++ b/tools/aapt2/strip/Strip.cpp
@@ -22,6 +22,7 @@
#include "Diagnostics.h"
#include "Flags.h"
#include "LoadedApk.h"
+#include "split/TableSplitter.h"
using android::StringPiece;
@@ -78,7 +79,27 @@
context_->GetDiagnostics()->Note(DiagMessage() << "Stripping APK...");
}
- // TODO(lecesne): Implement stripping here.
+ // TODO(lecesne): Add support for more than one density.
+ if (options_.target_configs.size() > 1) {
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "Multiple densities not supported at the moment");
+ return 1;
+ }
+
+ // Stripping the APK using the TableSplitter with no splits and the target
+ // density as the preferred density. The resource table is modified in
+ // place in the LoadedApk.
+ TableSplitterOptions splitter_options;
+ splitter_options.preferred_density = options_.target_configs[0].density;
+ std::vector<SplitConstraints> splits;
+ TableSplitter splitter(splits, splitter_options);
+ splitter.SplitTable(apk->GetResourceTable());
+
+ std::unique_ptr<IArchiveWriter> writer =
+ CreateZipFileArchiveWriter(context_->GetDiagnostics(), options_.output_path);
+ if (!apk->WriteToArchive(context_, writer.get())) {
+ return 1;
+ }
return 0;
}
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index aeabcff..7098fe9 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -370,8 +370,7 @@
return false;
}
- if (!table_->AddResourceAllowMangled(name, config, {},
- std::move(resource_value),
+ if (!table_->AddResourceAllowMangled(name, res_id, config, {}, std::move(resource_value),
context_->GetDiagnostics())) {
return false;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ab725e2..3fb8ef3 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -973,7 +973,6 @@
*
* @param config The Passpoint configuration to be added
* @return true on success
- * @hide
*/
public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
@@ -988,7 +987,6 @@
*
* @param fqdn The FQDN of the passpoint configuration to be removed
* @return true on success
- * @hide
*/
public boolean removePasspointConfiguration(String fqdn) {
try {
@@ -1004,7 +1002,6 @@
* An empty list will be returned when no configurations are installed.
*
* @return A list of {@link PasspointConfiguration}
- * @hide
*/
public List<PasspointConfiguration> getPasspointConfigurations() {
try {
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
similarity index 97%
rename from wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
rename to wifi/java/android/net/wifi/hotspot2/ConfigParser.java
index 78b335d..027b049a 100644
--- a/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
@@ -16,7 +16,7 @@
package android.net.wifi.hotspot2;
-import android.net.wifi.hotspot2.omadm.PPSMOParser;
+import android.net.wifi.hotspot2.omadm.PpsMoParser;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
@@ -41,11 +41,9 @@
/**
* Utility class for building PasspointConfiguration from an installation file.
- *
- * @hide
*/
-public final class ConfigBuilder {
- private static final String TAG = "ConfigBuilder";
+public final class ConfigParser {
+ private static final String TAG = "ConfigParser";
// Header names.
private static final String CONTENT_TYPE = "Content-Type";
@@ -101,6 +99,10 @@
public String encodingType = null;
}
+ /**
+ * @hide
+ */
+ public ConfigParser() {}
/**
* Parse the Hotspot 2.0 Release 1 configuration data into a {@link PasspointConfiguration}
@@ -133,7 +135,7 @@
* certificate chain (optional).
* @return {@link PasspointConfiguration}
*/
- public static PasspointConfiguration buildPasspointConfig(String mimeType, byte[] data) {
+ public static PasspointConfiguration parsePasspointConfig(String mimeType, byte[] data) {
// Verify MIME type.
if (!TextUtils.equals(mimeType, TYPE_WIFI_CONFIG)) {
Log.e(TAG, "Unexpected MIME type: " + mimeType);
@@ -169,7 +171,7 @@
throw new IOException("Missing Passpoint Profile");
}
- PasspointConfiguration config = PPSMOParser.parseMOText(new String(profileData));
+ PasspointConfiguration config = PpsMoParser.parseMoText(new String(profileData));
if (config == null) {
throw new IOException("Failed to parse Passpoint profile");
}
@@ -470,4 +472,4 @@
}
return new Pair<PrivateKey, List<X509Certificate>>(clientKey, clientCertificateChain);
}
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index c2b307d..7b73b4b 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -17,7 +17,7 @@
package android.net.wifi.hotspot2;
import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.os.Parcelable;
@@ -38,8 +38,6 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
- *
- * @hide
*/
public final class PasspointConfiguration implements Parcelable {
private static final String TAG = "PasspointConfiguration";
@@ -60,11 +58,11 @@
private static final int NULL_VALUE = -1;
/**
- * Configurations under HomeSP subtree.
+ * Configurations under HomeSp subtree.
*/
- private HomeSP mHomeSp = null;
- public void setHomeSp(HomeSP homeSp) { mHomeSp = homeSp; }
- public HomeSP getHomeSp() { return mHomeSp; }
+ private HomeSp mHomeSp = null;
+ public void setHomeSp(HomeSp homeSp) { mHomeSp = homeSp; }
+ public HomeSp getHomeSp() { return mHomeSp; }
/**
* Configurations under Credential subtree.
@@ -248,7 +246,7 @@
}
if (source.mHomeSp != null) {
- mHomeSp = new HomeSP(source.mHomeSp);
+ mHomeSp = new HomeSp(source.mHomeSp);
}
if (source.mCredential != null) {
mCredential = new Credential(source.mCredential);
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
similarity index 98%
rename from wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
rename to wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
index 24672d4..2ffe428 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
@@ -18,7 +18,7 @@
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.text.TextUtils;
@@ -109,11 +109,9 @@
* </Node>
* </Node>
* </MgmtTree>
- *
- * @hide
*/
-public final class PPSMOParser {
- private static final String TAG = "PPSMOParser";
+public final class PpsMoParser {
+ private static final String TAG = "PpsMoParser";
/**
* XML tags expected in the PPS MO (PerProviderSubscription Management Object) XML tree.
@@ -326,13 +324,18 @@
}
/**
+ * @hide
+ */
+ public PpsMoParser() {}
+
+ /**
* Convert a XML string representation of a PPS MO (PerProviderSubscription
* Management Object) tree to a {@link PasspointConfiguration} object.
*
* @param xmlString XML string representation of a PPS MO tree
* @return {@link PasspointConfiguration} or null
*/
- public static PasspointConfiguration parseMOText(String xmlString) {
+ public static PasspointConfiguration parseMoText(String xmlString) {
// Convert the XML string to a XML tree.
XMLParser xmlParser = new XMLParser();
XMLNode root = null;
@@ -640,12 +643,12 @@
* @return HomeSP
* @throws ParsingException
*/
- private static HomeSP parseHomeSP(PPSNode node) throws ParsingException {
+ private static HomeSp parseHomeSP(PPSNode node) throws ParsingException {
if (node.isLeaf()) {
throw new ParsingException("Leaf node not expected for HomeSP");
}
- HomeSP homeSp = new HomeSP();
+ HomeSp homeSp = new HomeSp();
for (PPSNode child : node.getChildren()) {
switch (child.getName()) {
case NODE_FQDN:
@@ -655,7 +658,7 @@
homeSp.setFriendlyName(getPpsNodeValue(child));
break;
case NODE_ROAMING_CONSORTIUM_OI:
- homeSp.setRoamingConsortiumOIs(
+ homeSp.setRoamingConsortiumOis(
parseRoamingConsortiumOI(getPpsNodeValue(child)));
break;
case NODE_ICON_URL:
@@ -666,8 +669,8 @@
break;
case NODE_HOME_OI_LIST:
Pair<List<Long>, List<Long>> homeOIs = parseHomeOIList(child);
- homeSp.setMatchAllOIs(convertFromLongList(homeOIs.first));
- homeSp.setMatchAnyOIs(convertFromLongList(homeOIs.second));
+ homeSp.setMatchAllOis(convertFromLongList(homeOIs.first));
+ homeSp.setMatchAnyOis(convertFromLongList(homeOIs.second));
break;
case NODE_OTHER_HOME_PARTNERS:
homeSp.setOtherHomePartners(parseOtherHomePartners(child));
@@ -909,7 +912,7 @@
credential.setRealm(getPpsNodeValue(child));
break;
case NODE_CHECK_AAA_SERVER_CERT_STATUS:
- credential.setCheckAAAServerCertStatus(
+ credential.setCheckAaaServerCertStatus(
Boolean.parseBoolean(getPpsNodeValue(child)));
break;
case NODE_SIM:
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index ff93486..025d4d3 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -42,8 +42,6 @@
*
* In addition to the fields in the Credential subtree, this will also maintain necessary
* information for the private key and certificates associated with this credential.
- *
- * @hide
*/
public final class Credential implements Parcelable {
private static final String TAG = "Credential";
@@ -98,12 +96,12 @@
* and Accounting) server's certificate during EAP (Extensible Authentication
* Protocol) authentication.
*/
- private boolean mCheckAAAServerCertStatus = false;
- public void setCheckAAAServerCertStatus(boolean checkAAAServerCertStatus) {
- mCheckAAAServerCertStatus = checkAAAServerCertStatus;
+ private boolean mCheckAaaServerCertStatus = false;
+ public void setCheckAaaServerCertStatus(boolean checkAaaServerCertStatus) {
+ mCheckAaaServerCertStatus = checkAaaServerCertStatus;
}
- public boolean getCheckAAAServerStatus() {
- return mCheckAAAServerCertStatus;
+ public boolean getCheckAaaServerStatus() {
+ return mCheckAaaServerCertStatus;
}
/**
@@ -685,7 +683,7 @@
mCreationTimeInMs = source.mCreationTimeInMs;
mExpirationTimeInMs = source.mExpirationTimeInMs;
mRealm = source.mRealm;
- mCheckAAAServerCertStatus = source.mCheckAAAServerCertStatus;
+ mCheckAaaServerCertStatus = source.mCheckAaaServerCertStatus;
if (source.mUserCredential != null) {
mUserCredential = new UserCredential(source.mUserCredential);
}
@@ -714,7 +712,7 @@
dest.writeLong(mCreationTimeInMs);
dest.writeLong(mExpirationTimeInMs);
dest.writeString(mRealm);
- dest.writeInt(mCheckAAAServerCertStatus ? 1 : 0);
+ dest.writeInt(mCheckAaaServerCertStatus ? 1 : 0);
dest.writeParcelable(mUserCredential, flags);
dest.writeParcelable(mCertCredential, flags);
dest.writeParcelable(mSimCredential, flags);
@@ -736,7 +734,7 @@
return TextUtils.equals(mRealm, that.mRealm)
&& mCreationTimeInMs == that.mCreationTimeInMs
&& mExpirationTimeInMs == that.mExpirationTimeInMs
- && mCheckAAAServerCertStatus == that.mCheckAAAServerCertStatus
+ && mCheckAaaServerCertStatus == that.mCheckAaaServerCertStatus
&& (mUserCredential == null ? that.mUserCredential == null
: mUserCredential.equals(that.mUserCredential))
&& (mCertCredential == null ? that.mCertCredential == null
@@ -751,7 +749,7 @@
@Override
public int hashCode() {
return Objects.hash(mRealm, mCreationTimeInMs, mExpirationTimeInMs,
- mCheckAAAServerCertStatus, mUserCredential, mCertCredential, mSimCredential,
+ mCheckAaaServerCertStatus, mUserCredential, mCertCredential, mSimCredential,
mCaCertificate, mClientCertificateChain, mClientPrivateKey);
}
@@ -800,7 +798,7 @@
credential.setCreationTimeInMs(in.readLong());
credential.setExpirationTimeInMs(in.readLong());
credential.setRealm(in.readString());
- credential.setCheckAAAServerCertStatus(in.readInt() != 0);
+ credential.setCheckAaaServerCertStatus(in.readInt() != 0);
credential.setUserCredential(in.readParcelable(null));
credential.setCertCredential(in.readParcelable(null));
credential.setSimCredential(in.readParcelable(null));
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.aidl
similarity index 96%
rename from wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
rename to wifi/java/android/net/wifi/hotspot2/pps/HomeSp.aidl
index 62d5603..6d343bd 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.hotspot2.pps;
-parcelable HomeSP;
+parcelable HomeSp;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
similarity index 79%
rename from wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
rename to wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 8b3b79c..7a46129 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -34,11 +34,9 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
- *
- * @hide
*/
-public final class HomeSP implements Parcelable {
- private static final String TAG = "HomeSP";
+public final class HomeSp implements Parcelable {
+ private static final String TAG = "HomeSp";
/**
* Maximum number of bytes allowed for a SSID.
@@ -108,12 +106,12 @@
* Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object
* (MO) tree for more detail.
*/
- private long[] mMatchAllOIs = null;
- public void setMatchAllOIs(long[] matchAllOIs) {
- mMatchAllOIs = matchAllOIs;
+ private long[] mMatchAllOis = null;
+ public void setMatchAllOis(long[] matchAllOis) {
+ mMatchAllOis = matchAllOis;
}
- public long[] getMatchAllOIs() {
- return mMatchAllOIs;
+ public long[] getMatchAllOis() {
+ return mMatchAllOis;
}
/**
@@ -129,12 +127,12 @@
* Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object
* (MO) tree for more detail.
*/
- private long[] mMatchAnyOIs = null;
- public void setMatchAnyOIs(long[] matchAnyOIs) {
- mMatchAnyOIs = matchAnyOIs;
+ private long[] mMatchAnyOis = null;
+ public void setMatchAnyOis(long[] matchAnyOis) {
+ mMatchAnyOis = matchAnyOis;
}
- public long[] getMatchAnysOIs() {
- return mMatchAnyOIs;
+ public long[] getMatchAnysOis() {
+ return mMatchAnyOis;
}
/**
@@ -155,25 +153,25 @@
* List of Organization Identifiers (OIs) identifying a roaming consortium of
* which this provider is a member.
*/
- private long[] mRoamingConsortiumOIs = null;
- public void setRoamingConsortiumOIs(long[] roamingConsortiumOIs) {
- mRoamingConsortiumOIs = roamingConsortiumOIs;
+ private long[] mRoamingConsortiumOis = null;
+ public void setRoamingConsortiumOis(long[] roamingConsortiumOis) {
+ mRoamingConsortiumOis = roamingConsortiumOis;
}
- public long[] getRoamingConsortiumOIs() {
- return mRoamingConsortiumOIs;
+ public long[] getRoamingConsortiumOis() {
+ return mRoamingConsortiumOis;
}
/**
- * Constructor for creating HomeSP with default values.
+ * Constructor for creating HomeSp with default values.
*/
- public HomeSP() {}
+ public HomeSp() {}
/**
* Copy constructor.
*
* @param source The source to copy from
*/
- public HomeSP(HomeSP source) {
+ public HomeSp(HomeSp source) {
if (source == null) {
return;
}
@@ -183,19 +181,19 @@
if (source.mHomeNetworkIds != null) {
mHomeNetworkIds = Collections.unmodifiableMap(source.mHomeNetworkIds);
}
- if (source.mMatchAllOIs != null) {
- mMatchAllOIs = Arrays.copyOf(source.mMatchAllOIs, source.mMatchAllOIs.length);
+ if (source.mMatchAllOis != null) {
+ mMatchAllOis = Arrays.copyOf(source.mMatchAllOis, source.mMatchAllOis.length);
}
- if (source.mMatchAnyOIs != null) {
- mMatchAnyOIs = Arrays.copyOf(source.mMatchAnyOIs, source.mMatchAnyOIs.length);
+ if (source.mMatchAnyOis != null) {
+ mMatchAnyOis = Arrays.copyOf(source.mMatchAnyOis, source.mMatchAnyOis.length);
}
if (source.mOtherHomePartners != null) {
mOtherHomePartners = Arrays.copyOf(source.mOtherHomePartners,
source.mOtherHomePartners.length);
}
- if (source.mRoamingConsortiumOIs != null) {
- mRoamingConsortiumOIs = Arrays.copyOf(source.mRoamingConsortiumOIs,
- source.mRoamingConsortiumOIs.length);
+ if (source.mRoamingConsortiumOis != null) {
+ mRoamingConsortiumOis = Arrays.copyOf(source.mRoamingConsortiumOis,
+ source.mRoamingConsortiumOis.length);
}
}
@@ -210,10 +208,10 @@
dest.writeString(mFriendlyName);
dest.writeString(mIconUrl);
writeHomeNetworkIds(dest, mHomeNetworkIds);
- dest.writeLongArray(mMatchAllOIs);
- dest.writeLongArray(mMatchAnyOIs);
+ dest.writeLongArray(mMatchAllOis);
+ dest.writeLongArray(mMatchAnyOis);
dest.writeStringArray(mOtherHomePartners);
- dest.writeLongArray(mRoamingConsortiumOIs);
+ dest.writeLongArray(mRoamingConsortiumOis);
}
@Override
@@ -221,30 +219,30 @@
if (this == thatObject) {
return true;
}
- if (!(thatObject instanceof HomeSP)) {
+ if (!(thatObject instanceof HomeSp)) {
return false;
}
- HomeSP that = (HomeSP) thatObject;
+ HomeSp that = (HomeSp) thatObject;
return TextUtils.equals(mFqdn, that.mFqdn)
&& TextUtils.equals(mFriendlyName, that.mFriendlyName)
&& TextUtils.equals(mIconUrl, that.mIconUrl)
&& (mHomeNetworkIds == null ? that.mHomeNetworkIds == null
: mHomeNetworkIds.equals(that.mHomeNetworkIds))
- && Arrays.equals(mMatchAllOIs, that.mMatchAllOIs)
- && Arrays.equals(mMatchAnyOIs, that.mMatchAnyOIs)
+ && Arrays.equals(mMatchAllOis, that.mMatchAllOis)
+ && Arrays.equals(mMatchAnyOis, that.mMatchAnyOis)
&& Arrays.equals(mOtherHomePartners, that.mOtherHomePartners)
- && Arrays.equals(mRoamingConsortiumOIs, that.mRoamingConsortiumOIs);
+ && Arrays.equals(mRoamingConsortiumOis, that.mRoamingConsortiumOis);
}
@Override
public int hashCode() {
- return Objects.hash(mFqdn, mFriendlyName, mIconUrl, mHomeNetworkIds, mMatchAllOIs,
- mMatchAnyOIs, mOtherHomePartners, mRoamingConsortiumOIs);
+ return Objects.hash(mFqdn, mFriendlyName, mIconUrl, mHomeNetworkIds, mMatchAllOis,
+ mMatchAnyOis, mOtherHomePartners, mRoamingConsortiumOis);
}
/**
- * Validate HomeSP data.
+ * Validate HomeSp data.
*
* @return true on success or false on failure
*/
@@ -270,25 +268,25 @@
return true;
}
- public static final Creator<HomeSP> CREATOR =
- new Creator<HomeSP>() {
+ public static final Creator<HomeSp> CREATOR =
+ new Creator<HomeSp>() {
@Override
- public HomeSP createFromParcel(Parcel in) {
- HomeSP homeSp = new HomeSP();
+ public HomeSp createFromParcel(Parcel in) {
+ HomeSp homeSp = new HomeSp();
homeSp.setFqdn(in.readString());
homeSp.setFriendlyName(in.readString());
homeSp.setIconUrl(in.readString());
homeSp.setHomeNetworkIds(readHomeNetworkIds(in));
- homeSp.setMatchAllOIs(in.createLongArray());
- homeSp.setMatchAnyOIs(in.createLongArray());
+ homeSp.setMatchAllOis(in.createLongArray());
+ homeSp.setMatchAnyOis(in.createLongArray());
homeSp.setOtherHomePartners(in.createStringArray());
- homeSp.setRoamingConsortiumOIs(in.createLongArray());
+ homeSp.setRoamingConsortiumOis(in.createLongArray());
return homeSp;
}
@Override
- public HomeSP[] newArray(int size) {
- return new HomeSP[size];
+ public HomeSp[] newArray(int size) {
+ return new HomeSp[size];
}
/**
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index ceaada4..caca0e4 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -40,18 +40,11 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
- *
- * @hide
*/
public final class Policy implements Parcelable {
private static final String TAG = "Policy";
/**
- * Default priority for preferred roaming partner.
- */
- public static final int PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY = 128;
-
- /**
* Maximum number of SSIDs in the exclusion list.
*/
private static final int MAX_EXCLUSION_SSIDS = 128;
@@ -189,8 +182,9 @@
/**
* Priority associated with this roaming partner policy.
+ * Using Integer.MIN_VALUE to indicate unset value.
*/
- private int mPriority = PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY;
+ private int mPriority = Integer.MIN_VALUE;
public void setPriority(int priority) {
mPriority = priority;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
index 17fbf9f..70264b0e 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -34,8 +34,6 @@
*
* For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
* Release 2 Technical Specification.
- *
- * @hide
*/
public final class UpdateParameter implements Parcelable {
private static final String TAG = "UpdateParameter";
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
similarity index 91%
rename from wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
rename to wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
index f7dbf7e..56bb437 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
@@ -21,7 +21,7 @@
import android.net.wifi.FakeKeys;
import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.BufferedReader;
@@ -33,10 +33,10 @@
import org.junit.Test;
/**
- * Unit tests for {@link android.net.wifi.hotspot2.ConfigBuilder}.
+ * Unit tests for {@link android.net.wifi.hotspot2.ConfigParser}.
*/
@SmallTest
-public class ConfigBuilderTest {
+public class ConfigParserTest {
/**
* Hotspot 2.0 Release 1 installation file that contains a Passpoint profile and a
* CA (Certificate Authority) X.509 certificate {@link FakeKeys#CA_CERT0}.
@@ -83,10 +83,10 @@
PasspointConfiguration config = new PasspointConfiguration();
// HomeSP configuration.
- HomeSP homeSp = new HomeSP();
+ HomeSp homeSp = new HomeSp();
homeSp.setFriendlyName("Century House");
homeSp.setFqdn("mi6.co.uk");
- homeSp.setRoamingConsortiumOIs(new long[] {0x112233L, 0x445566L});
+ homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L});
config.setHomeSp(homeSp);
// Credential configuration.
@@ -123,7 +123,7 @@
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT);
PasspointConfiguration expectedConfig = generateConfigurationFromProfile();
PasspointConfiguration actualConfig =
- ConfigBuilder.buildPasspointConfig(
+ ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes());
assertTrue(actualConfig.equals(expectedConfig));
}
@@ -136,7 +136,7 @@
@Test
public void parseConfigFileWithInvalidMimeType() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/wifi-config", configStr.getBytes()));
}
@@ -148,7 +148,7 @@
@Test
public void parseConfigFileWithUnencodedData() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_UNENCODED_DATA);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes()));
}
@@ -160,7 +160,7 @@
@Test
public void parseConfigFileWithInvalidPart() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_INVALID_PART);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes()));
}
@@ -172,7 +172,7 @@
@Test
public void parseConfigFileWithMissingBoundary() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_MISSING_BOUNDARY);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes()));
}
@@ -185,7 +185,7 @@
@Test
public void parseConfigFileWithInvalidContentType() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_INVALID_CONTENT_TYPE);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes()));
}
@@ -197,7 +197,7 @@
@Test
public void parseConfigFileWithoutPasspointProfile() throws Exception {
String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITHOUT_PROFILE);
- assertNull(ConfigBuilder.buildPasspointConfig(
+ assertNull(ConfigParser.parsePasspointConfig(
"application/x-wifi-config", configStr.getBytes()));
}
}
\ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 3aed918..7df4fcf 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -21,7 +21,7 @@
import android.net.wifi.EAPConstants;
import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.os.Parcel;
@@ -50,11 +50,11 @@
*
* @return {@link android.net.wifi.hotspot2.pps.HomeSP}
*/
- private static HomeSP createHomeSp() {
- HomeSP homeSp = new HomeSP();
+ private static HomeSp createHomeSp() {
+ HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName("friendly name");
- homeSp.setRoamingConsortiumOIs(new long[] {0x55, 0x66});
+ homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
return homeSp;
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
similarity index 91%
rename from wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
rename to wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
index 15de5c7..7cd72f0 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
@@ -19,10 +19,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import android.net.wifi.hotspot2.omadm.PPSMOParser;
+import android.net.wifi.hotspot2.omadm.PpsMoParser;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.test.suitebuilder.annotation.SmallTest;
@@ -43,10 +43,10 @@
import java.util.Map;
/**
- * Unit tests for {@link android.net.wifi.hotspot2.omadm.PPSMOParser}.
+ * Unit tests for {@link android.net.wifi.hotspot2.omadm.PpsMoParser}.
*/
@SmallTest
-public class PPSMOParserTest {
+public class PpsMoParserTest {
private static final String VALID_PPS_MO_XML_FILE = "assets/pps/PerProviderSubscription.xml";
private static final String PPS_MO_XML_FILE_DUPLICATE_HOMESP =
"assets/pps/PerProviderSubscription_DuplicateHomeSP.xml";
@@ -122,17 +122,17 @@
config.setUsageLimitUsageTimePeriodInMinutes(99910);
// HomeSP configuration.
- HomeSP homeSp = new HomeSP();
+ HomeSp homeSp = new HomeSp();
homeSp.setFriendlyName("Century House");
homeSp.setFqdn("mi6.co.uk");
- homeSp.setRoamingConsortiumOIs(new long[] {0x112233L, 0x445566L});
+ homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L});
homeSp.setIconUrl("icon.test.com");
Map<String, Long> homeNetworkIds = new HashMap<>();
homeNetworkIds.put("TestSSID", 0x12345678L);
homeNetworkIds.put("NullHESSID", null);
homeSp.setHomeNetworkIds(homeNetworkIds);
- homeSp.setMatchAllOIs(new long[] {0x11223344});
- homeSp.setMatchAnyOIs(new long[] {0x55667788});
+ homeSp.setMatchAllOis(new long[] {0x11223344});
+ homeSp.setMatchAnyOis(new long[] {0x55667788});
homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"});
config.setHomeSp(homeSp);
@@ -141,7 +141,7 @@
credential.setCreationTimeInMs(format.parse("2016-01-01T10:00:00Z").getTime());
credential.setExpirationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
credential.setRealm("shaken.stirred.com");
- credential.setCheckAAAServerCertStatus(true);
+ credential.setCheckAaaServerCertStatus(true);
Credential.UserCredential userCredential = new Credential.UserCredential();
userCredential.setUsername("james");
userCredential.setPassword("Ym9uZDAwNw==");
@@ -209,53 +209,53 @@
public void parseValidPPSMOTree() throws Exception {
String ppsMoTree = loadResourceFile(VALID_PPS_MO_XML_FILE);
PasspointConfiguration expectedConfig = generateConfigurationFromPPSMOTree();
- PasspointConfiguration actualConfig = PPSMOParser.parseMOText(ppsMoTree);
+ PasspointConfiguration actualConfig = PpsMoParser.parseMoText(ppsMoTree);
assertTrue(actualConfig.equals(expectedConfig));
}
@Test
public void parseNullPPSMOTree() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(null));
+ assertEquals(null, PpsMoParser.parseMoText(null));
}
@Test
public void parseEmptyPPSMOTree() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(new String()));
+ assertEquals(null, PpsMoParser.parseMoText(new String()));
}
@Test
public void parsePPSMOTreeWithDuplicateHomeSP() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_DUPLICATE_HOMESP)));
}
@Test
public void parsePPSMOTreeWithDuplicateValue() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_DUPLICATE_VALUE)));
}
@Test
public void parsePPSMOTreeWithMissingValue() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_MISSING_VALUE)));
}
@Test
public void parsePPSMOTreeWithMissingName() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_MISSING_NAME)));
}
@Test
public void parsePPSMOTreeWithInvalidNode() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_INVALID_NODE)));
}
@Test
public void parsePPSMOTreeWithInvalidName() throws Exception {
- assertEquals(null, PPSMOParser.parseMOText(
+ assertEquals(null, PpsMoParser.parseMoText(
loadResourceFile(PPS_MO_XML_FILE_INVALID_NAME)));
}
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 6f68e1c..c7ade00 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -59,7 +59,7 @@
cred.setCreationTimeInMs(123455L);
cred.setExpirationTimeInMs(2310093L);
cred.setRealm("realm");
- cred.setCheckAAAServerCertStatus(true);
+ cred.setCheckAaaServerCertStatus(true);
cred.setUserCredential(userCred);
cred.setCertCredential(certCred);
cred.setSimCredential(simCred);
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
similarity index 68%
rename from wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
rename to wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index 92e94ee..c41c11f 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -30,10 +30,10 @@
import java.util.Map;
/**
- * Unit tests for {@link android.net.wifi.hotspot2.pps.HomeSP}.
+ * Unit tests for {@link android.net.wifi.hotspot2.pps.HomeSp}.
*/
@SmallTest
-public class HomeSPTest {
+public class HomeSpTest {
/**
* Helper function for creating a map of home network IDs for testing.
@@ -48,68 +48,68 @@
}
/**
- * Helper function for creating a HomeSP for testing.
+ * Helper function for creating a HomeSp for testing.
*
- * @param homeNetworkIds The map of home network IDs associated with HomeSP
- * @return {@link HomeSP}
+ * @param homeNetworkIds The map of home network IDs associated with HomeSp
+ * @return {@link HomeSp}
*/
- private static HomeSP createHomeSp(Map<String, Long> homeNetworkIds) {
- HomeSP homeSp = new HomeSP();
+ private static HomeSp createHomeSp(Map<String, Long> homeNetworkIds) {
+ HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName("friendly name");
homeSp.setIconUrl("icon.url");
homeSp.setHomeNetworkIds(homeNetworkIds);
- homeSp.setMatchAllOIs(new long[] {0x11L, 0x22L});
- homeSp.setMatchAnyOIs(new long[] {0x33L, 0x44L});
+ homeSp.setMatchAllOis(new long[] {0x11L, 0x22L});
+ homeSp.setMatchAnyOis(new long[] {0x33L, 0x44L});
homeSp.setOtherHomePartners(new String[] {"partner1", "partner2"});
- homeSp.setRoamingConsortiumOIs(new long[] {0x55, 0x66});
+ homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
return homeSp;
}
/**
- * Helper function for creating a HomeSP with home network IDs for testing.
+ * Helper function for creating a HomeSp with home network IDs for testing.
*
- * @return {@link HomeSP}
+ * @return {@link HomeSp}
*/
- private static HomeSP createHomeSpWithHomeNetworkIds() {
+ private static HomeSp createHomeSpWithHomeNetworkIds() {
return createHomeSp(createHomeNetworkIds());
}
/**
- * Helper function for creating a HomeSP without home network IDs for testing.
+ * Helper function for creating a HomeSp without home network IDs for testing.
*
- * @return {@link HomeSP}
+ * @return {@link HomeSp}
*/
- private static HomeSP createHomeSpWithoutHomeNetworkIds() {
+ private static HomeSp createHomeSpWithoutHomeNetworkIds() {
return createHomeSp(null);
}
/**
- * Helper function for verifying HomeSP after parcel write then read.
+ * Helper function for verifying HomeSp after parcel write then read.
* @param writeHomeSp
* @throws Exception
*/
- private static void verifyParcel(HomeSP writeHomeSp) throws Exception {
+ private static void verifyParcel(HomeSp writeHomeSp) throws Exception {
Parcel parcel = Parcel.obtain();
writeHomeSp.writeToParcel(parcel, 0);
parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
- HomeSP readHomeSp = HomeSP.CREATOR.createFromParcel(parcel);
+ HomeSp readHomeSp = HomeSp.CREATOR.createFromParcel(parcel);
assertTrue(readHomeSp.equals(writeHomeSp));
}
/**
- * Verify parcel read/write for an empty HomeSP.
+ * Verify parcel read/write for an empty HomeSp.
*
* @throws Exception
*/
@Test
- public void verifyParcelWithEmptyHomeSP() throws Exception {
- verifyParcel(new HomeSP());
+ public void verifyParcelWithEmptyHomeSp() throws Exception {
+ verifyParcel(new HomeSp());
}
/**
- * Verify parcel read/write for a HomeSP containing Home Network IDs.
+ * Verify parcel read/write for a HomeSp containing Home Network IDs.
*
* @throws Exception
*/
@@ -119,7 +119,7 @@
}
/**
- * Verify parcel read/write for a HomeSP without Home Network IDs.
+ * Verify parcel read/write for a HomeSp without Home Network IDs.
*
* @throws Exception
*/
@@ -129,62 +129,62 @@
}
/**
- * Verify that a HomeSP is valid when both FQDN and Friendly Name
+ * Verify that a HomeSp is valid when both FQDN and Friendly Name
* are provided.
*
* @throws Exception
*/
@Test
- public void validateValidHomeSP() throws Exception {
- HomeSP homeSp = createHomeSpWithHomeNetworkIds();
+ public void validateValidHomeSp() throws Exception {
+ HomeSp homeSp = createHomeSpWithHomeNetworkIds();
assertTrue(homeSp.validate());
}
/**
- * Verify that a HomeSP is not valid when FQDN is not provided
+ * Verify that a HomeSp is not valid when FQDN is not provided
*
* @throws Exception
*/
@Test
public void validateHomeSpWithoutFqdn() throws Exception {
- HomeSP homeSp = createHomeSpWithHomeNetworkIds();
+ HomeSp homeSp = createHomeSpWithHomeNetworkIds();
homeSp.setFqdn(null);
assertFalse(homeSp.validate());
}
/**
- * Verify that a HomeSP is not valid when Friendly Name is not provided
+ * Verify that a HomeSp is not valid when Friendly Name is not provided
*
* @throws Exception
*/
@Test
public void validateHomeSpWithoutFriendlyName() throws Exception {
- HomeSP homeSp = createHomeSpWithHomeNetworkIds();
+ HomeSp homeSp = createHomeSpWithHomeNetworkIds();
homeSp.setFriendlyName(null);
assertFalse(homeSp.validate());
}
/**
- * Verify that a HomeSP is valid when the optional Home Network IDs are
+ * Verify that a HomeSp is valid when the optional Home Network IDs are
* not provided.
*
* @throws Exception
*/
@Test
public void validateHomeSpWithoutHomeNetworkIds() throws Exception {
- HomeSP homeSp = createHomeSpWithoutHomeNetworkIds();
+ HomeSp homeSp = createHomeSpWithoutHomeNetworkIds();
assertTrue(homeSp.validate());
}
/**
- * Verify that a HomeSP is invalid when the optional Home Network IDs
+ * Verify that a HomeSp is invalid when the optional Home Network IDs
* contained an invalid SSID (exceeding maximum number of bytes).
*
* @throws Exception
*/
@Test
public void validateHomeSpWithInvalidHomeNetworkIds() throws Exception {
- HomeSP homeSp = createHomeSpWithoutHomeNetworkIds();
+ HomeSp homeSp = createHomeSpWithoutHomeNetworkIds();
// HomeNetworkID with SSID exceeding the maximum length.
Map<String, Long> homeNetworkIds = new HashMap<>();
byte[] rawSsidBytes = new byte[33];
@@ -202,8 +202,8 @@
*/
@Test
public void validateCopyConstructorFromNullSource() throws Exception {
- HomeSP copySp = new HomeSP(null);
- HomeSP defaultSp = new HomeSP();
+ HomeSp copySp = new HomeSp(null);
+ HomeSp defaultSp = new HomeSp();
assertTrue(copySp.equals(defaultSp));
}
@@ -214,8 +214,8 @@
*/
@Test
public void validateCopyConstructorFromValidSource() throws Exception {
- HomeSP sourceSp = createHomeSpWithHomeNetworkIds();
- HomeSP copySp = new HomeSP(sourceSp);
+ HomeSp sourceSp = createHomeSpWithHomeNetworkIds();
+ HomeSp copySp = new HomeSp(sourceSp);
assertTrue(copySp.equals(sourceSp));
}
}