diff options
44 files changed, 1152 insertions, 545 deletions
diff --git a/api/current.txt b/api/current.txt index eac065329734..eca3c27d56b6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -203,7 +203,6 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.app { 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 @@ package android.app { 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 @@ package android.content.pm { 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 { diff --git a/api/system-current.txt b/api/system-current.txt index 3b2ad3fd44a1..55b32f6c3b93 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -315,7 +315,6 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.app { 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 @@ package android.app { 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 @@ package android.content.pm { 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 { diff --git a/api/test-current.txt b/api/test-current.txt index bfb0d14455ef..bc7a0015485b 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -203,7 +203,6 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.accounts { 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 @@ package android.app { 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 @@ package android.app { 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 @@ package android.content.pm { 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 { diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index def0ff987899..02636819781a 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -338,21 +338,24 @@ public class AccountManager { "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 @@ public class AccountManager { } /** - * 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 @@ public class AccountManager { * * <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 @@ public class AccountManager { * 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 @@ public class AccountManager { } /** - * 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 @@ public class AccountManager { * @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 @@ public class AccountManager { } /** - * 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 @@ public class AccountManager { } /** - * 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 @@ public class AccountManager { * 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 95fdfef7a5c3..35011b5f3ec3 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -437,7 +437,7 @@ public class ChooseTypeAndAccountActivity extends Activity } 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 63a0919aec5d..e0fdac146f68 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -108,15 +108,12 @@ interface IAccountManager { 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/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 3cc6282d6ab3..99ae96df01eb 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -145,6 +145,7 @@ interface IActivityManager { 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 b1bdea1cb502..4db29fb5a72a 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -186,11 +186,25 @@ public class Instrumentation { } } } - + + /** + * 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 @@ public class Instrumentation { } /** + * 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/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 92cb7099eb5d..9a8eff098c1e 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -397,14 +397,6 @@ public class ActivityInfo extends ComponentInfo 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 a135d8f11acd..59c530730170 100644 --- a/core/java/android/content/pm/InstrumentationInfo.java +++ b/core/java/android/content/pm/InstrumentationInfo.java @@ -34,6 +34,13 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { 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 class InstrumentationInfo extends PackageItemInfo implements Parcelable { 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 class InstrumentationInfo extends PackageItemInfo implements Parcelable { 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 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable { 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 ff928a0dd81d..7cef781607af 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 @@ public class PackageParser { 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 @@ public class PackageParser { 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 @@ public class PackageParser { 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/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java index 9e4dd8748f39..9dcf4f44a559 100644 --- a/core/java/android/net/NetworkScorerAppManager.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -18,6 +18,7 @@ package android.net; 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 com.android.internal.R; 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 @@ public class NetworkScorerAppManager { * 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 @@ public class NetworkScorerAppManager { 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/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 6d0fdb6033ec..76f4a7654af7 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/public.xml b/core/res/res/values/public.xml index d795d80f52da..1b48469b100e 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/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java index 5bfff26b0813..ce5d3ef665bb 100644 --- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java +++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java @@ -19,6 +19,7 @@ package android.net; 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.content.res.Resources; 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 class NetworkScorerAppManagerTest extends InstrumentationTestCase { 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 class NetworkScorerAppManagerTest extends InstrumentationTestCase { } 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 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase { .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 @@ public class NetworkScorerAppManagerTest extends InstrumentationTestCase { 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/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 5c9f2709daa7..cd38b506aab9 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -27,6 +27,7 @@ import java.util.Collection; 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 @@ public class AudioTrack extends PlayerBase 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 @@ public class AudioTrack extends PlayerBase .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 @@ public class AudioTrack extends PlayerBase 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 8ea0d8a738f5..b0df0e47eda1 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -18,6 +18,7 @@ package android.media.tv; 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.provider.BaseColumns; 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 @@ public final class TvContract { /** 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 final class TvContract { */ 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 @@ public final class TvContract { /** 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 @@ public final class TvContract { /** 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 @@ public final class TvContract { * @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); } @@ -1100,6 +1170,24 @@ public final class TvContract { /** 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. * @@ -1184,6 +1272,15 @@ public final class TvContract { */ 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. * @@ -1205,6 +1302,16 @@ public final class TvContract { */ 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. * @@ -1237,6 +1344,15 @@ public final class TvContract { */ 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". * @@ -1260,6 +1376,19 @@ public final class TvContract { */ 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". * @@ -1309,6 +1438,15 @@ public final class TvContract { */ 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. * @@ -1994,6 +2132,29 @@ public final class TvContract { /** 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"; @@ -2081,7 +2242,7 @@ public final class TvContract { * @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; @@ -2120,7 +2281,7 @@ public final class TvContract { * {@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/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 399b0d293ac2..6283148c84f8 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 @@ public class StatusBarIconView extends AnimatedImageView { 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/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java index 4535992ed5b8..7c4588983b4e 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.graphics.Rect; 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 class LightBarController implements BatteryController.BatteryStateChangeC 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 0f9f0563b7fe..07f37ab01f5c 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.animation.ValueAnimator; 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 @@ public class LightBarTransitionsController { 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 9ac6f6580ba3..638c12f3213e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3416,6 +3416,9 @@ public class StatusBar extends SystemUI implements DemoMode, } else { pw.println(" mGroupManager: null"); } + + mLightBarController.dump(fd, pw, args); + if (KeyguardUpdateMonitor.getInstance(mContext) != null) { KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args); } 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 7d9e0736fdad..68f9cb05ecaf 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 @@ public class StatusBarIconViewTest extends SysuiTestCase { 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/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 25016f6b9cf5..22dbf443a631 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -183,11 +183,12 @@ public class NetworkScoreService extends INetworkScoreService.Stub { // 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { // 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } - 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @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 class NetworkScoreService extends INetworkScoreService.Stub { public String getActiveScorerPackage() { synchronized (mServiceConnectionLock) { if (mServiceConnection != null) { - return mServiceConnection.mComponentName.getPackageName(); + return mServiceConnection.getPackageName(); } } return null; @@ -695,7 +695,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 class NetworkScoreService extends INetworkScoreService.Stub { } 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 bfa3f04edc68..fdd7cb139204 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 @@ public class AccountManagerService * 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 @@ public class AccountManagerService @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 @@ public class AccountManagerService 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 @@ public class AccountManagerService if (accountsOfType != null) { for (Account account : accountsOfType) { result.put(account, - resolveAccountVisibility(account, uid, packageName, accounts)); + resolveAccountVisibility(account, packageName, accounts)); } } } @@ -514,7 +515,7 @@ public class AccountManagerService } @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 @@ public class AccountManagerService 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 @@ public class AccountManagerService } @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 @@ public class AccountManagerService 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 @@ public class AccountManagerService * 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService // 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 @@ public class AccountManagerService /** * 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 @@ public class AccountManagerService } @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 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService } 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService } } + 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 @@ public class AccountManagerService } 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 @@ public class AccountManagerService } } - 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 class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService // 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 @@ public class AccountManagerService @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 @@ public class AccountManagerService } /** - * Returns accounts for all running users. + * Returns accounts for all running users, ignores visibility values. * * @hide */ @@ -3906,7 +3953,11 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService @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 class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService // 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 @@ public class AccountManagerService // 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 @@ public class AccountManagerService */ 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 85e4b5ffbdc3..22543cb9e022 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { 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 @@ class AccountsDb implements AutoCloseable { } /** - * 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 @@ class AccountsDb implements AutoCloseable { 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 000000000000..84e4ea9d0ee8 --- /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 ee1f28f4cb43..5ed82901ab65 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub || (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 @@ public class ActivityManagerService extends IActivityManager.Stub .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 @@ public class ActivityManagerService extends IActivityManager.Stub .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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } } + 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 10d108b6a677..ba2512020ad3 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 class ActivityStack extends ConfigurationContainer implements StackWindowL 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 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL // 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 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL 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 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL 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 f5874af74657..d1606b4dc13b 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 @@ class ActivityStarter { 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); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 384f2f8662b8..36a913fb9c53 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 @@ class AppErrors { * 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/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 49fe79c7d01e..356781fc7956 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 @@ final class ProcessRecord { 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 @@ final class ProcessRecord { 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 9e09cbbfb0c7..e237e41a3d52 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.PINNED_STACK_ID; 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta 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 class TaskRecord extends ConfigurationContainer implements TaskWindowConta 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta * @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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta && (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/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 5a2ee9a848a6..0a92a8198a52 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 @@ public class DockedStackDividerController implements DimLayerUser { 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/Task.java b/services/core/java/com/android/server/wm/Task.java index d96e1eff2363..ab9a378e7a5b 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 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU 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 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU 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 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU || 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 538f0d9f8552..a1c9c294bc05 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye 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 11667c0b6ac7..efc2e117b02d 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 class TaskWindowContainerController 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 @@ public class TaskWindowContainerController } 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 @@ public class TaskWindowContainerController @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/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java index e0c3d60142e2..d56110c67c4b 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 @@ class WindowLayersController { 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 @@ class WindowLayersController { mPinnedWindows.clear(); mInputMethodWindows.clear(); mDockedWindows.clear(); - mOnTopLauncherWindows.clear(); mReplacingWindows.clear(); mDockDivider = null; @@ -182,9 +180,6 @@ class WindowLayersController { if (task == null) { return; } - if (task.isOnTopLauncher()) { - mOnTopLauncherWindows.add(w); - } final TaskStack stack = task.mStack; if (stack == null) { return; @@ -206,10 +201,6 @@ class WindowLayersController { 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/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index 152b9c9ba031..fa9e9a804e61 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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { // "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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { 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 213fb27b8a7b..e433b60e1c94 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { @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 @@ public class AccountManagerServiceTest extends AndroidTestCase { // 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { // 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { @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 2e045ff43341..2cb8af4e97e7 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 @@ public class AccountsDbTest { @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 e30bd5d96672..e5640c7e08c1 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 @@ public class PackageParserTest { // 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/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index 4cad4e8e40f1..98ff0e254a19 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -78,8 +78,7 @@ public class WindowFrameTests { 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 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 7dec52df9109..bc850170d4b2 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java @@ -201,8 +201,8 @@ class WindowTestsBase { /** 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; } @@ -283,12 +283,10 @@ class WindowTestsBase { 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() { @@ -339,17 +337,16 @@ class WindowTestsBase { } }, 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); } } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 891b8a1adb73..5ee7e23eabca 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -417,7 +417,7 @@ cat include/telephony/ril.h | \ 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; |