diff options
42 files changed, 1180 insertions, 404 deletions
diff --git a/api/current.txt b/api/current.txt index d38e75a..f31593d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2716,6 +2716,7 @@ package android.accounts { method public final android.os.IBinder getIBinder(); method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException; method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException; + field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry"; } public class Account implements android.os.Parcelable { @@ -25840,6 +25841,15 @@ package android.provider { field public static final android.net.Uri CONTENT_URI; } + public static final class ContactsContract.ProviderStatus { + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status"; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String STATUS = "status"; + field public static final int STATUS_BUSY = 1; // 0x1 + field public static final int STATUS_EMPTY = 2; // 0x2 + field public static final int STATUS_NORMAL = 0; // 0x0 + } + public static final class ContactsContract.QuickContact { ctor public ContactsContract.QuickContact(); method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]); @@ -31155,7 +31165,6 @@ package android.telephony { method public boolean setOperatorBrandOverride(java.lang.String); method public boolean setPreferredNetworkTypeToGlobal(); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); - field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE"; field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final int CALL_STATE_IDLE = 0; // 0x0 @@ -37390,7 +37399,6 @@ package android.view { field public static final int TITLE_CHANGED = 64; // 0x40 field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0 field public static final int TYPE_APPLICATION = 2; // 0x2 - field public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = 1005; // 0x3ed field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9 field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8 diff --git a/api/system-current.txt b/api/system-current.txt index 44d8c8e..cf6d0f6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -71,6 +71,7 @@ package android { field public static final java.lang.String CAPTURE_VIDEO_OUTPUT = "android.permission.CAPTURE_VIDEO_OUTPUT"; field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE"; field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION"; + field public static final java.lang.String CHANGE_DEVICE_IDLE_TEMP_WHITELIST = "android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"; field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE"; field public static final java.lang.String CHANGE_WIFI_MULTICAST_STATE = "android.permission.CHANGE_WIFI_MULTICAST_STATE"; field public static final java.lang.String CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE"; @@ -2797,6 +2798,7 @@ package android.accounts { method public final android.os.IBinder getIBinder(); method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException; method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException; + field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry"; } public class Account implements android.os.Parcelable { @@ -6331,6 +6333,7 @@ package android.app.usage { method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long); method public android.app.usage.UsageEvents queryEvents(long, long); method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long); + method public void whitelistAppTemporarily(java.lang.String, long, android.os.UserHandle); field public static final int INTERVAL_BEST = 4; // 0x4 field public static final int INTERVAL_DAILY = 0; // 0x0 field public static final int INTERVAL_MONTHLY = 2; // 0x2 @@ -6486,7 +6489,9 @@ package android.bluetooth { method public static boolean checkBluetoothAddress(java.lang.String); method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile); method public boolean disable(); + method public boolean disableBLE(); method public boolean enable(); + method public boolean enableBLE(); method public java.lang.String getAddress(); method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser(); method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner(); @@ -6502,6 +6507,7 @@ package android.bluetooth { method public boolean isBleScanAlwaysAvailable(); method public boolean isDiscovering(); method public boolean isEnabled(); + method public boolean isLeEnabled(); method public boolean isMultipleAdvertisementSupported(); method public boolean isOffloadedFilteringSupported(); method public boolean isOffloadedScanBatchingSupported(); @@ -6512,6 +6518,7 @@ package android.bluetooth { method public deprecated boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); method public deprecated boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback); method public deprecated void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback); + field public static final java.lang.String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED"; field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED"; @@ -27763,6 +27770,15 @@ package android.provider { field public static final android.net.Uri CONTENT_URI; } + public static final class ContactsContract.ProviderStatus { + field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status"; + field public static final android.net.Uri CONTENT_URI; + field public static final java.lang.String STATUS = "status"; + field public static final int STATUS_BUSY = 1; // 0x1 + field public static final int STATUS_EMPTY = 2; // 0x2 + field public static final int STATUS_NORMAL = 0; // 0x0 + } + public static final class ContactsContract.QuickContact { ctor public ContactsContract.QuickContact(); method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]); @@ -33403,7 +33419,6 @@ package android.telephony { method public int[] supplyPukReportResult(java.lang.String, java.lang.String); method public void toggleRadioOnOff(); method public void updateServiceLocation(); - field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE"; field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final int CALL_STATE_IDLE = 0; // 0x0 @@ -39651,7 +39666,6 @@ package android.view { field public static final int TITLE_CHANGED = 64; // 0x40 field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0 field public static final int TYPE_APPLICATION = 2; // 0x2 - field public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = 1005; // 0x3ed field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9 field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8 diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index dbc9051..3e4a66d 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -108,6 +108,14 @@ import java.util.Arrays; public abstract class AbstractAccountAuthenticator { private static final String TAG = "AccountAuthenticator"; + /** + * Bundle key used for the {@code long} expiration time (in millis from the unix epoch) of the + * associated auth token. + * + * @see #getAuthToken + */ + public static final String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry"; + private final Context mContext; public AbstractAccountAuthenticator(Context context) { @@ -115,6 +123,7 @@ public abstract class AbstractAccountAuthenticator { } private class Transport extends IAccountAuthenticator.Stub { + @Override public void addAccount(IAccountAuthenticatorResponse response, String accountType, String authTokenType, String[] features, Bundle options) throws RemoteException { @@ -140,6 +149,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void confirmCredentials(IAccountAuthenticatorResponse response, Account account, Bundle options) throws RemoteException { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -162,6 +172,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void getAuthTokenLabel(IAccountAuthenticatorResponse response, String authTokenType) throws RemoteException { @@ -184,6 +195,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void getAuthToken(IAccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws RemoteException { @@ -209,6 +221,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void updateCredentials(IAccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws RemoteException { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -234,6 +247,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void editProperties(IAccountAuthenticatorResponse response, String accountType) throws RemoteException { checkBinderPermission(); @@ -248,6 +262,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void hasFeatures(IAccountAuthenticatorResponse response, Account account, String[] features) throws RemoteException { checkBinderPermission(); @@ -262,6 +277,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void getAccountRemovalAllowed(IAccountAuthenticatorResponse response, Account account) throws RemoteException { checkBinderPermission(); @@ -276,6 +292,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void getAccountCredentialsForCloning(IAccountAuthenticatorResponse response, Account account) throws RemoteException { checkBinderPermission(); @@ -291,6 +308,7 @@ public abstract class AbstractAccountAuthenticator { } } + @Override public void addAccountFromCredentials(IAccountAuthenticatorResponse response, Account account, Bundle accountCredentials) throws RemoteException { @@ -410,21 +428,42 @@ public abstract class AbstractAccountAuthenticator { public abstract Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException; + /** - * Gets the authtoken for an account. + * Gets an authtoken for an account. + * + * If not {@code null}, the resultant {@link Bundle} will contain different sets of keys + * depending on whether a token was successfully issued and, if not, whether one + * could be issued via some {@link android.app.Activity}. + * <p> + * If a token cannot be provided without some additional activity, the Bundle should contain + * {@link AccountManager#KEY_INTENT} with an associated {@link Intent}. On the other hand, if + * there is no such activity, then a Bundle containing + * {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} should be + * returned. + * <p> + * If a token can be successfully issued, the implementation should return the + * {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of the + * account associated with the token as well as the {@link AccountManager#KEY_AUTHTOKEN}. In + * addition {@link AbstractAccountAuthenticator} implementations that declare themselves + * {@code android:customTokens=true} may also provide a non-negative {@link + * #KEY_CUSTOM_TOKEN_EXPIRY} long value containing the expiration timestamp of the expiration + * time (in millis since the unix epoch). + * <p> + * Implementers should assume that tokens will be cached on the basis of account and + * authTokenType. The system may ignore the contents of the supplied options Bundle when + * determining to re-use a cached token. Furthermore, implementers should assume a supplied + * expiration time will be treated as non-binding advice. + * <p> + * Finally, note that for android:customTokens=false authenticators, tokens are cached + * indefinitely until some client calls {@link + * AccountManager#invalidateAuthToken(String,String)}. + * * @param response to send the result back to the AccountManager, will never be null * @param account the account whose credentials are to be retrieved, will never be null * @param authTokenType the type of auth token to retrieve, will never be null * @param options a Bundle of authenticator-specific options, may be null - * @return a Bundle result or null if the result is to be returned via the response. The result - * will contain either: - * <ul> - * <li> {@link AccountManager#KEY_INTENT}, or - * <li> {@link AccountManager#KEY_ACCOUNT_NAME}, {@link AccountManager#KEY_ACCOUNT_TYPE}, - * and {@link AccountManager#KEY_AUTHTOKEN}, or - * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to - * indicate an error - * </ul> + * @return a Bundle result or null if the result is to be returned via the response. * @throws NetworkErrorException if the authenticator could not honor the request due to a * network error */ @@ -518,6 +557,7 @@ public abstract class AbstractAccountAuthenticator { public Bundle getAccountCredentialsForCloning(final AccountAuthenticatorResponse response, final Account account) throws NetworkErrorException { new Thread(new Runnable() { + @Override public void run() { Bundle result = new Bundle(); result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false); @@ -543,6 +583,7 @@ public abstract class AbstractAccountAuthenticator { Account account, Bundle accountCredentials) throws NetworkErrorException { new Thread(new Runnable() { + @Override public void run() { Bundle result = new Bundle(); result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 978b4bc..a0b95b6 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -16,6 +16,8 @@ package android.app.admin; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; @@ -76,7 +78,7 @@ import java.util.List; * <h3>Developer Guides</h3> * <p>For more information about managing policies for device administration, read the * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> - * developer guide.</p> + * developer guide. * </div> */ public class DevicePolicyManager { @@ -122,9 +124,6 @@ public class DevicePolicyManager { * * <p> If provisioning fails, the managedProfile is removed so the device returns to its * previous state. - * - * <p>Input: Nothing.</p> - * <p>Output: Nothing</p> */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_PROVISION_MANAGED_PROFILE @@ -155,7 +154,7 @@ public class DevicePolicyManager { * message containing an NFC record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}. * * <p> When this extra is set, the application must have exactly one device admin receiver. - * This receiver will be set as the profile or device owner and active admin.</p> + * This receiver will be set as the profile or device owner and active admin. * @see DeviceAdminReceiver * @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still @@ -212,7 +211,7 @@ public class DevicePolicyManager { /** * A Boolean extra that can be used by the mobile device management application to skip the - * disabling of system apps during provisioning when set to <code>true</code>. + * disabling of system apps during provisioning when set to {@code true}. * * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner * provisioning via an NFC bump. @@ -644,9 +643,6 @@ public class DevicePolicyManager { * * <p> * If provisioning fails, the device is factory reset. - * - * <p>Input: Nothing.</p> - * <p>Output: Nothing</p> */ public static final String MIME_TYPE_PROVISIONING_NFC_V2 = "application/com.android.managedprovisioning.v2"; @@ -847,18 +843,18 @@ public class DevicePolicyManager { * Return true if the given administrator component is currently * active (enabled) in the system. */ - public boolean isAdminActive(ComponentName who) { - return isAdminActiveAsUser(who, UserHandle.myUserId()); + public boolean isAdminActive(@NonNull ComponentName admin) { + return isAdminActiveAsUser(admin, UserHandle.myUserId()); } /** * @see #isAdminActive(ComponentName) * @hide */ - public boolean isAdminActiveAsUser(ComponentName who, int userId) { + public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) { if (mService != null) { try { - return mService.isAdminActive(who, userId); + return mService.isAdminActive(admin, userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -870,10 +866,10 @@ public class DevicePolicyManager { * for the user. * @hide */ - public boolean isRemovingAdmin(ComponentName who, int userId) { + public boolean isRemovingAdmin(@NonNull ComponentName admin, int userId) { if (mService != null) { try { - return mService.isRemovingAdmin(who, userId); + return mService.isRemovingAdmin(admin, userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -883,8 +879,8 @@ public class DevicePolicyManager { /** - * Return a list of all currently active device administrator's component - * names. Note that if there are no administrators than null may be + * Return a list of all currently active device administrators' component + * names. If there are no administrators {@code null} may be * returned. */ public List<ComponentName> getActiveAdmins() { @@ -928,10 +924,10 @@ public class DevicePolicyManager { * try to remove someone else's component, a security exception will be * thrown. */ - public void removeActiveAdmin(ComponentName who) { + public void removeActiveAdmin(@NonNull ComponentName admin) { if (mService != null) { try { - mService.removeActiveAdmin(who, UserHandle.myUserId()); + mService.removeActiveAdmin(admin, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -940,14 +936,14 @@ public class DevicePolicyManager { /** * Returns true if an administrator has been granted a particular device policy. This can - * be used to check if the administrator was activated under an earlier set of policies, + * be used to check whether the administrator was activated under an earlier set of policies, * but requires additional policies after an upgrade. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be * an active administrator, or an exception will be thrown. * @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}. */ - public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) { + public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) { if (mService != null) { try { return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId()); @@ -1048,7 +1044,7 @@ public class DevicePolicyManager { * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC} * or {@link #PASSWORD_QUALITY_COMPLEX}. */ - public void setPasswordQuality(ComponentName admin, int quality) { + public void setPasswordQuality(@NonNull ComponentName admin, int quality) { if (mService != null) { try { mService.setPasswordQuality(admin, quality); @@ -1061,15 +1057,15 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password quality for all admins of this user * and its profiles or a particular one. - * @param admin The name of the admin component to check, or null to aggregate + * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. */ - public int getPasswordQuality(ComponentName admin) { + public int getPasswordQuality(@Nullable ComponentName admin) { return getPasswordQuality(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordQuality(ComponentName admin, int userHandle) { + public int getPasswordQuality(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordQuality(admin, userHandle); @@ -1101,7 +1097,7 @@ public class DevicePolicyManager { * @param length The new desired minimum password length. A value of 0 * means there is no restriction. */ - public void setPasswordMinimumLength(ComponentName admin, int length) { + public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumLength(admin, length); @@ -1114,15 +1110,15 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password length for all admins of this * user and its profiles or a particular one. - * @param admin The name of the admin component to check, or null to aggregate + * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. */ - public int getPasswordMinimumLength(ComponentName admin) { + public int getPasswordMinimumLength(@Nullable ComponentName admin) { return getPasswordMinimumLength(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumLength(ComponentName admin, int userHandle) { + public int getPasswordMinimumLength(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumLength(admin, userHandle); @@ -1155,7 +1151,7 @@ public class DevicePolicyManager { * required in the password. A value of 0 means there is no * restriction. */ - public void setPasswordMinimumUpperCase(ComponentName admin, int length) { + public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumUpperCase(admin, length); @@ -1173,17 +1169,17 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of upper case letters required in the * password. */ - public int getPasswordMinimumUpperCase(ComponentName admin) { + public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) { return getPasswordMinimumUpperCase(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumUpperCase(ComponentName admin, int userHandle) { + public int getPasswordMinimumUpperCase(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumUpperCase(admin, userHandle); @@ -1216,7 +1212,7 @@ public class DevicePolicyManager { * required in the password. A value of 0 means there is no * restriction. */ - public void setPasswordMinimumLowerCase(ComponentName admin, int length) { + public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumLowerCase(admin, length); @@ -1234,17 +1230,17 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of lower case letters required in the * password. */ - public int getPasswordMinimumLowerCase(ComponentName admin) { + public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) { return getPasswordMinimumLowerCase(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumLowerCase(ComponentName admin, int userHandle) { + public int getPasswordMinimumLowerCase(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumLowerCase(admin, userHandle); @@ -1276,7 +1272,7 @@ public class DevicePolicyManager { * @param length The new desired minimum number of letters required in the * password. A value of 0 means there is no restriction. */ - public void setPasswordMinimumLetters(ComponentName admin, int length) { + public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumLetters(admin, length); @@ -1293,16 +1289,16 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of letters required in the password. */ - public int getPasswordMinimumLetters(ComponentName admin) { + public int getPasswordMinimumLetters(@Nullable ComponentName admin) { return getPasswordMinimumLetters(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumLetters(ComponentName admin, int userHandle) { + public int getPasswordMinimumLetters(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumLetters(admin, userHandle); @@ -1334,7 +1330,7 @@ public class DevicePolicyManager { * @param length The new desired minimum number of numerical digits required * in the password. A value of 0 means there is no restriction. */ - public void setPasswordMinimumNumeric(ComponentName admin, int length) { + public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumNumeric(admin, length); @@ -1352,16 +1348,16 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of numerical digits required in the password. */ - public int getPasswordMinimumNumeric(ComponentName admin) { + public int getPasswordMinimumNumeric(@Nullable ComponentName admin) { return getPasswordMinimumNumeric(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumNumeric(ComponentName admin, int userHandle) { + public int getPasswordMinimumNumeric(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumNumeric(admin, userHandle); @@ -1393,7 +1389,7 @@ public class DevicePolicyManager { * @param length The new desired minimum number of symbols required in the * password. A value of 0 means there is no restriction. */ - public void setPasswordMinimumSymbols(ComponentName admin, int length) { + public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumSymbols(admin, length); @@ -1410,16 +1406,16 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of symbols required in the password. */ - public int getPasswordMinimumSymbols(ComponentName admin) { + public int getPasswordMinimumSymbols(@Nullable ComponentName admin) { return getPasswordMinimumSymbols(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) { + public int getPasswordMinimumSymbols(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumSymbols(admin, userHandle); @@ -1451,7 +1447,7 @@ public class DevicePolicyManager { * @param length The new desired minimum number of letters required in the * password. A value of 0 means there is no restriction. */ - public void setPasswordMinimumNonLetter(ComponentName admin, int length) { + public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordMinimumNonLetter(admin, length); @@ -1469,16 +1465,16 @@ public class DevicePolicyManager { * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * - * @param admin The name of the admin component to check, or null to + * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of letters required in the password. */ - public int getPasswordMinimumNonLetter(ComponentName admin) { + public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) { return getPasswordMinimumNonLetter(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordMinimumNonLetter(ComponentName admin, int userHandle) { + public int getPasswordMinimumNonLetter(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordMinimumNonLetter(admin, userHandle); @@ -1511,7 +1507,7 @@ public class DevicePolicyManager { * @param length The new desired length of password history. A value of 0 * means there is no restriction. */ - public void setPasswordHistoryLength(ComponentName admin, int length) { + public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) { if (mService != null) { try { mService.setPasswordHistoryLength(admin, length); @@ -1543,7 +1539,7 @@ public class DevicePolicyManager { * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 * means there is no restriction (unlimited). */ - public void setPasswordExpirationTimeout(ComponentName admin, long timeout) { + public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) { if (mService != null) { try { mService.setPasswordExpirationTimeout(admin, timeout); @@ -1557,12 +1553,12 @@ public class DevicePolicyManager { * Get the password expiration timeout for the given admin. The expiration timeout is the * recurring expiration timeout provided in the call to * {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the - * aggregate of all policy administrators if admin is null. + * aggregate of all policy administrators if {@code admin} is null. * - * @param admin The name of the admin component to check, or null to aggregate all admins. + * @param admin The name of the admin component to check, or {@code null} to aggregate all admins. * @return The timeout for the given admin or the minimum of all timeouts */ - public long getPasswordExpirationTimeout(ComponentName admin) { + public long getPasswordExpirationTimeout(@Nullable ComponentName admin) { if (mService != null) { try { return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId()); @@ -1580,10 +1576,10 @@ public class DevicePolicyManager { * If admin is null, then a composite of all expiration timeouts is returned * - which will be the minimum of all timeouts. * - * @param admin The name of the admin component to check, or null to aggregate all admins. + * @param admin The name of the admin component to check, or {@code null} to aggregate all admins. * @return The password expiration time, in ms. */ - public long getPasswordExpiration(ComponentName admin) { + public long getPasswordExpiration(@Nullable ComponentName admin) { if (mService != null) { try { return mService.getPasswordExpiration(admin, UserHandle.myUserId()); @@ -1597,16 +1593,16 @@ public class DevicePolicyManager { /** * Retrieve the current password history length for all admins of this * user and its profiles or a particular one. - * @param admin The name of the admin component to check, or null to aggregate + * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. * @return The length of the password history */ - public int getPasswordHistoryLength(ComponentName admin) { + public int getPasswordHistoryLength(@Nullable ComponentName admin) { return getPasswordHistoryLength(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getPasswordHistoryLength(ComponentName admin, int userHandle) { + public int getPasswordHistoryLength(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getPasswordHistoryLength(admin, userHandle); @@ -1705,7 +1701,7 @@ public class DevicePolicyManager { * @param num The number of failed password attempts at which point the * device will wipe its data. */ - public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) { + public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) { if (mService != null) { try { mService.setMaximumFailedPasswordsForWipe(admin, num); @@ -1719,15 +1715,15 @@ public class DevicePolicyManager { * Retrieve the current maximum number of login attempts that are allowed * before the device wipes itself, for all admins of this user and its profiles * or a particular one. - * @param admin The name of the admin component to check, or null to aggregate + * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. */ - public int getMaximumFailedPasswordsForWipe(ComponentName admin) { + public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) { return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getMaximumFailedPasswordsForWipe(ComponentName admin, int userHandle) { + public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getMaximumFailedPasswordsForWipe(admin, userHandle); @@ -1824,7 +1820,7 @@ public class DevicePolicyManager { * @param timeMs The new desired maximum time to lock in milliseconds. * A value of 0 means there is no restriction. */ - public void setMaximumTimeToLock(ComponentName admin, long timeMs) { + public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) { if (mService != null) { try { mService.setMaximumTimeToLock(admin, timeMs); @@ -1837,17 +1833,17 @@ public class DevicePolicyManager { /** * Retrieve the current maximum time to unlock for all admins of this user * and its profiles or a particular one. - * @param admin The name of the admin component to check, or null to aggregate + * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. * @return time in milliseconds for the given admin or the minimum value (strictest) of * all admins if admin is null. Returns 0 if there are no restrictions. */ - public long getMaximumTimeToLock(ComponentName admin) { + public long getMaximumTimeToLock(@Nullable ComponentName admin) { return getMaximumTimeToLock(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public long getMaximumTimeToLock(ComponentName admin, int userHandle) { + public long getMaximumTimeToLock(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getMaximumTimeToLock(admin, userHandle); @@ -1922,21 +1918,20 @@ public class DevicePolicyManager { * this method; if it has not, a security exception will be thrown. * Only the first device admin can set the proxy. If a second admin attempts * to set the proxy, the {@link ComponentName} of the admin originally setting the - * proxy will be returned. If successful in setting the proxy, null will + * proxy will be returned. If successful in setting the proxy, {@code null} will * be returned. * The method can be called repeatedly by the device admin alrady setting the * proxy to update the proxy and exclusion list. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param proxySpec the global proxy desired. Must be an HTTP Proxy. * Pass Proxy.NO_PROXY to reset the proxy. * @param exclusionList a list of domains to be excluded from the global proxy. - * @return returns null if the proxy was successfully set, or a {@link ComponentName} - * of the device admin that sets thew proxy otherwise. + * @return {@code null} if the proxy was successfully set, or otherwise a {@link ComponentName} + * of the device admin that sets the proxy. * @hide */ - public ComponentName setGlobalProxy(ComponentName admin, Proxy proxySpec, + public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec, List<String> exclusionList ) { if (proxySpec == null) { throw new NullPointerException(); @@ -2001,7 +1996,8 @@ public class DevicePolicyManager { * @param proxyInfo The a {@link ProxyInfo} object defining the new global * HTTP proxy. A {@code null} value will clear the global HTTP proxy. */ - public void setRecommendedGlobalProxy(ComponentName admin, ProxyInfo proxyInfo) { + public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo + proxyInfo) { if (mService != null) { try { mService.setRecommendedGlobalProxy(admin, proxyInfo); @@ -2013,8 +2009,8 @@ public class DevicePolicyManager { /** * Returns the component name setting the global proxy. - * @return ComponentName object of the device admin that set the global proxy, or - * null if no admin has set the proxy. + * @return ComponentName object of the device admin that set the global proxy, or {@code null} + * if no admin has set the proxy. * @hide */ public ComponentName getGlobalProxyAdmin() { @@ -2147,7 +2143,7 @@ public class DevicePolicyManager { * {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use * {@link #getStorageEncryptionStatus()} to query the actual device state. */ - public int setStorageEncryption(ComponentName admin, boolean encrypt) { + public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) { if (mService != null) { try { return mService.setStorageEncryption(admin, encrypt); @@ -2167,7 +2163,7 @@ public class DevicePolicyManager { * administrators. * @return true if the admin(s) are requesting encryption, false if not. */ - public boolean getStorageEncryption(ComponentName admin) { + public boolean getStorageEncryption(@Nullable ComponentName admin) { if (mService != null) { try { return mService.getStorageEncryption(admin, UserHandle.myUserId()); @@ -2216,14 +2212,14 @@ public class DevicePolicyManager { /** * Installs the given certificate as a user CA. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. * @param certBuffer encoded form of the certificate to install. * * @return false if the certBuffer cannot be parsed or installation is * interrupted, true otherwise. */ - public boolean installCaCert(ComponentName admin, byte[] certBuffer) { + public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { try { return mService.installCaCert(admin, certBuffer); @@ -2237,11 +2233,11 @@ public class DevicePolicyManager { /** * Uninstalls the given certificate from trusted user CAs, if present. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. * @param certBuffer encoded form of the certificate to remove. */ - public void uninstallCaCert(ComponentName admin, byte[] certBuffer) { + public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { try { final String alias = getCaCertAlias(certBuffer); @@ -2259,11 +2255,11 @@ public class DevicePolicyManager { * If a user has installed any certificates by other means than device policy these will be * included too. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. * @return a List of byte[] arrays, each encoding one user CA certificate. */ - public List<byte[]> getInstalledCaCerts(ComponentName admin) { + public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) { List<byte[]> certs = new ArrayList<byte[]>(); if (mService != null) { try { @@ -2287,10 +2283,10 @@ public class DevicePolicyManager { * Uninstalls all custom trusted CA certificates from the profile. Certificates installed by * means other than device policy will also be removed, except for system CA certificates. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. */ - public void uninstallAllUserCaCerts(ComponentName admin) { + public void uninstallAllUserCaCerts(@Nullable ComponentName admin) { if (mService != null) { for (String alias : new TrustedCertificateStore().userAliases()) { try { @@ -2305,11 +2301,11 @@ public class DevicePolicyManager { /** * Returns whether this certificate is installed as a trusted CA. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. * @param certBuffer encoded form of the certificate to look up. */ - public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) { + public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { try { mService.enforceCanManageCaCerts(admin); @@ -2327,21 +2323,21 @@ public class DevicePolicyManager { * Called by a device or profile owner to install a certificate and private key pair. The * keypair will be visible to all apps within the profile. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. Use - * <code>null</code> if calling from a delegated certificate installer. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if calling from a delegated certificate installer. * @param privKey The private key to install. * @param cert The certificate to install. * @param alias The private key alias under which to install the certificate. If a certificate * with that alias already exists, it will be overwritten. * @return {@code true} if the keys were installed, {@code false} otherwise. */ - public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert, + public boolean installKeyPair(@Nullable ComponentName admin, PrivateKey privKey, Certificate cert, String alias) { try { final byte[] pemCert = Credentials.convertToPem(cert); final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm()) .getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded(); - return mService.installKeyPair(who, pkcs8Key, pemCert, alias); + return mService.installKeyPair(admin, pkcs8Key, pemCert, alias); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { @@ -2353,7 +2349,7 @@ public class DevicePolicyManager { } /** - * Returns the alias of a given CA certificate in the certificate store, or null if it + * @return the alias of a given CA certificate in the certificate store, or {@code null} if it * doesn't exist. */ private static String getCaCertAlias(byte[] certBuffer) throws CertificateException { @@ -2373,15 +2369,15 @@ public class DevicePolicyManager { * it is later cleared by calling this method with a null value or uninstallling the certificate * installer. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param installerPackage The package name of the certificate installer which will be given - * access. If <code>null</code> is given the current package will be cleared. + * access. If {@code null} is given the current package will be cleared. */ - public void setCertInstallerPackage(ComponentName who, String installerPackage) - throws SecurityException { + public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String + installerPackage) throws SecurityException { if (mService != null) { try { - mService.setCertInstallerPackage(who, installerPackage); + mService.setCertInstallerPackage(admin, installerPackage); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -2392,14 +2388,14 @@ public class DevicePolicyManager { * Called by a profile owner or device owner to retrieve the certificate installer for the * current user. null if none is set. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. - * @return The package name of the current delegated certificate installer. <code>null</code> + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @return The package name of the current delegated certificate installer, or {@code null} * if none is set. */ - public String getCertInstallerPackage(ComponentName who) throws SecurityException { + public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException { if (mService != null) { try { - return mService.getCertInstallerPackage(who); + return mService.getCertInstallerPackage(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -2419,7 +2415,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled Whether or not the camera should be disabled. */ - public void setCameraDisabled(ComponentName admin, boolean disabled) { + public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { try { mService.setCameraDisabled(admin, disabled); @@ -2432,15 +2428,15 @@ public class DevicePolicyManager { /** * Determine whether or not the device's cameras have been disabled for this user, * either by the current admin, if specified, or all admins. - * @param admin The name of the admin component to check, or null to check if any admins + * @param admin The name of the admin component to check, or {@code null} to check whether any admins * have disabled the camera */ - public boolean getCameraDisabled(ComponentName admin) { + public boolean getCameraDisabled(@Nullable ComponentName admin) { return getCameraDisabled(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public boolean getCameraDisabled(ComponentName admin, int userHandle) { + public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getCameraDisabled(admin, userHandle); @@ -2463,7 +2459,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled Whether screen capture is disabled or not. */ - public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) { + public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { try { mService.setScreenCaptureDisabled(admin, disabled); @@ -2476,15 +2472,15 @@ public class DevicePolicyManager { /** * Determine whether or not screen capture has been disabled by the current * admin, if specified, or all admins. - * @param admin The name of the admin component to check, or null to check if any admins + * @param admin The name of the admin component to check, or {@code null} to check whether any admins * have disabled screen capture. */ - public boolean getScreenCaptureDisabled(ComponentName admin) { + public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) { return getScreenCaptureDisabled(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public boolean getScreenCaptureDisabled(ComponentName admin, int userHandle) { + public boolean getScreenCaptureDisabled(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getScreenCaptureDisabled(admin, userHandle); @@ -2507,7 +2503,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param required Whether auto time is set required or not. */ - public void setAutoTimeRequired(ComponentName admin, boolean required) { + public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) { if (mService != null) { try { mService.setAutoTimeRequired(admin, required); @@ -2561,7 +2557,7 @@ public class DevicePolicyManager { * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FINGERPRINT}, * {@link #KEYGUARD_DISABLE_FEATURES_ALL} */ - public void setKeyguardDisabledFeatures(ComponentName admin, int which) { + public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) { if (mService != null) { try { mService.setKeyguardDisabledFeatures(admin, which); @@ -2574,17 +2570,17 @@ public class DevicePolicyManager { /** * Determine whether or not features have been disabled in keyguard either by the current * admin, if specified, or all admins. - * @param admin The name of the admin component to check, or null to check if any admins + * @param admin The name of the admin component to check, or {@code null} to check whether any admins * have disabled features in keyguard. * @return bitfield of flags. See {@link #setKeyguardDisabledFeatures(ComponentName, int)} * for a list. */ - public int getKeyguardDisabledFeatures(ComponentName admin) { + public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) { return getKeyguardDisabledFeatures(admin, UserHandle.myUserId()); } /** @hide per-user version */ - public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) { + public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) { if (mService != null) { try { return mService.getKeyguardDisabledFeatures(admin, userHandle); @@ -2598,7 +2594,8 @@ public class DevicePolicyManager { /** * @hide */ - public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) { + public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing, + int userHandle) { if (mService != null) { try { mService.setActiveAdmin(policyReceiver, refreshing, userHandle); @@ -2611,15 +2608,15 @@ public class DevicePolicyManager { /** * @hide */ - public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { + public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) { setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); } /** - * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data + * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data * @hide */ - public DeviceAdminInfo getAdminInfo(ComponentName cn) { + public DeviceAdminInfo getAdminInfo(@NonNull ComponentName cn) { ActivityInfo ai; try { ai = mContext.getPackageManager().getReceiverInfo(cn, @@ -2646,7 +2643,7 @@ public class DevicePolicyManager { /** * @hide */ - public void getRemoveWarning(ComponentName admin, RemoteCallback result) { + public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) { if (mService != null) { try { mService.getRemoveWarning(admin, result, UserHandle.myUserId()); @@ -2740,10 +2737,10 @@ public class DevicePolicyManager { /** * Used to determine if a particular package has been registered as a Device Owner app. * A device owner app is a special device admin that cannot be deactivated by the user, once - * activated as a device admin. It also cannot be uninstalled. To check if a particular + * activated as a device admin. It also cannot be uninstalled. To check whether a particular * package is currently registered as the device owner app, pass in the package name from * {@link Context#getPackageName()} to this method.<p/>This is useful for device - * admin apps that want to check if they are also registered as the device owner app. The + * admin apps that want to check whether they are also registered as the device owner app. The * exact mechanism by which a device admin app is registered as a device owner app is defined by * the setup process. * @param packageName the package name of the app, to compare with the registered device owner @@ -2820,19 +2817,20 @@ public class DevicePolicyManager { * MANAGE_DEVICE_ADMINS permission before the device is provisioned or by a device owner app. A * device initializer app is granted device owner privileges during device initialization and * profile owner privileges during secondary user initialization. - * @param who Which {@link DeviceAdminReceiver} this request is associated with, or null if not - * called by the device owner. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or + * {@code null} if not called by the device owner. * @param initializer Which {@link DeviceAdminReceiver} to make device initializer. * @return whether the component was successfully registered as the device initializer. * @throws IllegalArgumentException if the componentname is null or invalid * @throws IllegalStateException if the caller is not device owner or the device has * already been provisioned or a device initializer already exists. */ - public boolean setDeviceInitializer(ComponentName who, ComponentName initializer) + public boolean setDeviceInitializer(@Nullable ComponentName admin, + @NonNull ComponentName initializer) throws IllegalArgumentException, IllegalStateException { if (mService != null) { try { - return mService.setDeviceInitializer(who, initializer); + return mService.setDeviceInitializer(admin, initializer); } catch (RemoteException re) { Log.w(TAG, "Failed to set device initializer"); } @@ -2863,12 +2861,12 @@ public class DevicePolicyManager { * subsequently created users. This method can be called by either the device owner or device * initializer itself. The caller must be an active administrator. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ - public void clearDeviceInitializerApp(ComponentName who) { + public void clearDeviceInitializerApp(@NonNull ComponentName admin) { if (mService != null) { try { - mService.clearDeviceInitializer(who); + mService.clearDeviceInitializer(admin); } catch (RemoteException re) { Log.w(TAG, "Failed to clear device initializer"); } @@ -2927,7 +2925,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return whether the user is now enabled. */ - public boolean setUserEnabled(ComponentName admin) { + public boolean setUserEnabled(@NonNull ComponentName admin) { if (mService != null) { try { return mService.setUserEnabled(admin); @@ -2955,7 +2953,7 @@ public class DevicePolicyManager { * the user has already been set up. */ @SystemApi - public boolean setActiveProfileOwner(ComponentName admin, @Deprecated String ownerName) + public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName) throws IllegalArgumentException { if (mService != null) { try { @@ -2980,7 +2978,7 @@ public class DevicePolicyManager { * @return */ @SystemApi - public void clearProfileOwner(ComponentName admin) { + public void clearProfileOwner(@NonNull ComponentName admin) { if (mService != null) { try { mService.clearProfileOwner(admin); @@ -2992,14 +2990,14 @@ public class DevicePolicyManager { /** * @hide - * Checks if the user was already setup. + * Checks whether the user was already setup. */ public boolean hasUserSetupCompleted() { if (mService != null) { try { return mService.hasUserSetupCompleted(); } catch (RemoteException re) { - Log.w(TAG, "Failed to check if user setup has completed"); + Log.w(TAG, "Failed to check whether user setup has completed"); } } return true; @@ -3021,7 +3019,7 @@ public class DevicePolicyManager { * @throws IllegalArgumentException if admin is null, the package isn't installed, or the * preconditions mentioned are not met. */ - public boolean setProfileOwner(ComponentName admin, @Deprecated String ownerName, + public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName, int userHandle) throws IllegalArgumentException { if (admin == null) { throw new NullPointerException("admin cannot be null"); @@ -3048,7 +3046,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ - public void setProfileEnabled(ComponentName admin) { + public void setProfileEnabled(@NonNull ComponentName admin) { if (mService != null) { try { mService.setProfileEnabled(admin); @@ -3066,12 +3064,13 @@ public class DevicePolicyManager { * @see #isProfileOwnerApp * @see #isDeviceOwnerApp * + * @param admin Which {@link DeviceAdminReceiver} this request is associate with. * @param profileName The name of the profile. */ - public void setProfileName(ComponentName who, String profileName) { + public void setProfileName(@NonNull ComponentName admin, String profileName) { if (mService != null) { try { - mService.setProfileName(who, profileName); + mService.setProfileName(admin, profileName); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -3102,7 +3101,7 @@ public class DevicePolicyManager { /** * @hide - * @return the packageName of the owner of the given user profile or null if no profile + * @return the packageName of the owner of the given user profile or {@code null} if no profile * owner has been set for that user. * @throws IllegalArgumentException if the userId is invalid. */ @@ -3130,8 +3129,8 @@ public class DevicePolicyManager { /** * @hide - * @return the human readable name of the organisation associated with this DPM or null if - * one is not set. + * @return the human readable name of the organisation associated with this DPM or {@code null} + * if one is not set. * @throws IllegalArgumentException if the userId is invalid. */ public String getProfileOwnerName() throws IllegalArgumentException { @@ -3185,8 +3184,8 @@ public class DevicePolicyManager { * @param filter The IntentFilter for which a default handler is added. * @param activity The Activity that is added as default intent handler. */ - public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter, - ComponentName activity) { + public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter, + @NonNull ComponentName activity) { if (mService != null) { try { mService.addPersistentPreferredActivity(admin, filter, activity); @@ -3206,7 +3205,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package for which preferences are removed. */ - public void clearPackagePersistentPreferredActivities(ComponentName admin, + public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { @@ -3241,7 +3240,7 @@ public class DevicePolicyManager { * * @see UserManager#KEY_RESTRICTIONS_PENDING */ - public void setApplicationRestrictions(ComponentName admin, String packageName, + public void setApplicationRestrictions(@NonNull ComponentName admin, String packageName, Bundle settings) { if (mService != null) { try { @@ -3271,8 +3270,8 @@ public class DevicePolicyManager { * then it's up to the TrustAgent itself to aggregate the values from all device admins. * <p>Consult documentation for the specific TrustAgent to determine legal options parameters. */ - public void setTrustAgentConfiguration(ComponentName admin, ComponentName target, - PersistableBundle configuration) { + public void setTrustAgentConfiguration(@NonNull ComponentName admin, + @NonNull ComponentName target, PersistableBundle configuration) { if (mService != null) { try { mService.setTrustAgentConfiguration(admin, target, configuration); @@ -3296,14 +3295,14 @@ public class DevicePolicyManager { * @param agent Which component to get enabled features for. * @return configuration for the given trust agent. */ - public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin, - ComponentName agent) { + public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin, + @NonNull ComponentName agent) { return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId()); } /** @hide per-user version */ - public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin, - ComponentName agent, int userHandle) { + public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin, + @NonNull ComponentName agent, int userHandle) { if (mService != null) { try { return mService.getTrustAgentConfiguration(admin, agent, userHandle); @@ -3321,13 +3320,13 @@ public class DevicePolicyManager { * <p>The calling device admin must be a profile owner. If it is not, a * security exception will be thrown. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled If true caller-Id information in the managed profile is not displayed. */ - public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) { + public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { try { - mService.setCrossProfileCallerIdDisabled(who, disabled); + mService.setCrossProfileCallerIdDisabled(admin, disabled); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -3341,12 +3340,12 @@ public class DevicePolicyManager { * <p>The calling device admin must be a profile owner. If it is not, a * security exception will be thrown. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ - public boolean getCrossProfileCallerIdDisabled(ComponentName who) { + public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) { if (mService != null) { try { - return mService.getCrossProfileCallerIdDisabled(who); + return mService.getCrossProfileCallerIdDisabled(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -3396,15 +3395,15 @@ public class DevicePolicyManager { * <p> * This API works on managed profile only. * - * @param who Which {@link DeviceAdminReceiver} this request is associated + * @param admin Which {@link DeviceAdminReceiver} this request is associated * with. * @param disabled If true, bluetooth devices cannot access enterprise * contacts. */ - public void setBluetoothContactSharingDisabled(ComponentName who, boolean disabled) { + public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { try { - mService.setBluetoothContactSharingDisabled(who, disabled); + mService.setBluetoothContactSharingDisabled(admin, disabled); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -3420,13 +3419,13 @@ public class DevicePolicyManager { * <p> * This API works on managed profile only. * - * @param who Which {@link DeviceAdminReceiver} this request is associated + * @param admin Which {@link DeviceAdminReceiver} this request is associated * with. */ - public boolean getBluetoothContactSharingDisabled(ComponentName who) { + public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) { if (mService != null) { try { - return mService.getBluetoothContactSharingDisabled(who); + return mService.getBluetoothContactSharingDisabled(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -3465,7 +3464,7 @@ public class DevicePolicyManager { * @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and * {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported. */ - public void addCrossProfileIntentFilter(ComponentName admin, IntentFilter filter, int flags) { + public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) { if (mService != null) { try { mService.addCrossProfileIntentFilter(admin, filter, flags); @@ -3481,7 +3480,7 @@ public class DevicePolicyManager { * Only removes those that have been set by the profile owner. * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ - public void clearCrossProfileIntentFilters(ComponentName admin) { + public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) { if (mService != null) { try { mService.clearCrossProfileIntentFilters(admin); @@ -3512,7 +3511,7 @@ public class DevicePolicyManager { * @return true if setting the restriction succeeded. It fail if there is * one or more non-system accessibility services enabled, that are not in the list. */ - public boolean setPermittedAccessibilityServices(ComponentName admin, + public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin, List<String> packageNames) { if (mService != null) { try { @@ -3533,7 +3532,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of accessiblity service package names. */ - public List<String> getPermittedAccessibilityServices(ComponentName admin) { + public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) { if (mService != null) { try { return mService.getPermittedAccessibilityServices(admin); @@ -3591,7 +3590,7 @@ public class DevicePolicyManager { * one or more non-system input methods currently enabled that are not in * the packageNames list. */ - public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) { + public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) { if (mService != null) { try { return mService.setPermittedInputMethods(admin, packageNames); @@ -3612,7 +3611,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of input method package names. */ - public List<String> getPermittedInputMethods(ComponentName admin) { + public List<String> getPermittedInputMethods(@NonNull ComponentName admin) { if (mService != null) { try { return mService.getPermittedInputMethods(admin); @@ -3655,9 +3654,10 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param name the user's name * @see UserHandle - * @return the UserHandle object for the created user, or null if the user could not be created. + * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the + * user could not be created. */ - public UserHandle createUser(ComponentName admin, String name) { + public UserHandle createUser(@NonNull ComponentName admin, String name) { try { return mService.createUser(admin, name); } catch (RemoteException re) { @@ -3688,10 +3688,11 @@ public class DevicePolicyManager { * @param adminExtras Extras that will be passed to onEnable of the admin receiver * on the new user. * @see UserHandle - * @return the UserHandle object for the created user, or null if the user could not be created. + * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the + * user could not be created. */ - public UserHandle createAndInitializeUser(ComponentName admin, String name, String ownerName, - ComponentName profileOwnerComponent, Bundle adminExtras) { + public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name, + String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) { try { return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent, adminExtras); @@ -3709,7 +3710,7 @@ public class DevicePolicyManager { * @param userHandle the user to remove. * @return {@code true} if the user was removed, {@code false} otherwise. */ - public boolean removeUser(ComponentName admin, UserHandle userHandle) { + public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) { try { return mService.removeUser(admin, userHandle); } catch (RemoteException re) { @@ -3727,7 +3728,7 @@ public class DevicePolicyManager { * * @see Intent#ACTION_USER_FOREGROUND */ - public boolean switchUser(ComponentName admin, UserHandle userHandle) { + public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) { try { return mService.switchUser(admin, userHandle); } catch (RemoteException re) { @@ -3749,7 +3750,7 @@ public class DevicePolicyManager { * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle} * if no restrictions have been set. */ - public Bundle getApplicationRestrictions(ComponentName admin, String packageName) { + public Bundle getApplicationRestrictions(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { return mService.getApplicationRestrictions(admin, packageName); @@ -3771,7 +3772,7 @@ public class DevicePolicyManager { * @param key The key of the restriction. See the constants in * {@link android.os.UserManager} for the list of keys. */ - public void addUserRestriction(ComponentName admin, String key) { + public void addUserRestriction(@NonNull ComponentName admin, String key) { if (mService != null) { try { mService.setUserRestriction(admin, key, true); @@ -3792,7 +3793,7 @@ public class DevicePolicyManager { * @param key The key of the restriction. See the constants in * {@link android.os.UserManager} for the list of keys. */ - public void clearUserRestriction(ComponentName admin, String key) { + public void clearUserRestriction(@NonNull ComponentName admin, String key) { if (mService != null) { try { mService.setUserRestriction(admin, key, false); @@ -3812,7 +3813,7 @@ public class DevicePolicyManager { * unhidden. * @return boolean Whether the hidden setting of the package was successfully updated. */ - public boolean setApplicationHidden(ComponentName admin, String packageName, + public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName, boolean hidden) { if (mService != null) { try { @@ -3831,7 +3832,7 @@ public class DevicePolicyManager { * @param packageName The name of the package to retrieve the hidden status of. * @return boolean {@code true} if the package is hidden, {@code false} otherwise. */ - public boolean isApplicationHidden(ComponentName admin, String packageName) { + public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { return mService.isApplicationHidden(admin, packageName); @@ -3849,7 +3850,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package to be re-enabled in the current profile. */ - public void enableSystemApp(ComponentName admin, String packageName) { + public void enableSystemApp(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { mService.enableSystemApp(admin, packageName); @@ -3868,7 +3869,7 @@ public class DevicePolicyManager { * intent will be re-enabled in the current profile. * @return int The number of activities that matched the intent and were installed. */ - public int enableSystemApp(ComponentName admin, Intent intent) { + public int enableSystemApp(@NonNull ComponentName admin, Intent intent) { if (mService != null) { try { return mService.enableSystemAppWithIntent(admin, intent); @@ -3894,7 +3895,7 @@ public class DevicePolicyManager { * @param disabled The boolean indicating that account management will be disabled (true) or * enabled (false). */ - public void setAccountManagementDisabled(ComponentName admin, String accountType, + public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType, boolean disabled) { if (mService != null) { try { @@ -3950,7 +3951,7 @@ public class DevicePolicyManager { * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent) * @see UserManager#DISALLOW_CREATE_WINDOWS */ - public void setLockTaskPackages(ComponentName admin, String[] packages) + public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages) throws SecurityException { if (mService != null) { try { @@ -3967,7 +3968,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @hide */ - public String[] getLockTaskPackages(ComponentName admin) { + public String[] getLockTaskPackages(@NonNull ComponentName admin) { if (mService != null) { try { return mService.getLockTaskPackages(admin); @@ -4024,7 +4025,7 @@ public class DevicePolicyManager { * @param setting The name of the setting to update. * @param value The value to update the setting to. */ - public void setGlobalSetting(ComponentName admin, String setting, String value) { + public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) { if (mService != null) { try { mService.setGlobalSetting(admin, setting, value); @@ -4052,7 +4053,7 @@ public class DevicePolicyManager { * @param setting The name of the setting to update. * @param value The value to update the setting to. */ - public void setSecureSetting(ComponentName admin, String setting, String value) { + public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) { if (mService != null) { try { mService.setSecureSetting(admin, setting, value); @@ -4072,7 +4073,8 @@ public class DevicePolicyManager { * {@link RestrictionsReceiver}. If this param is null, * it removes the restrictions provider previously assigned. */ - public void setRestrictionsProvider(ComponentName admin, ComponentName provider) { + public void setRestrictionsProvider(@NonNull ComponentName admin, + @Nullable ComponentName provider) { if (mService != null) { try { mService.setRestrictionsProvider(admin, provider); @@ -4088,7 +4090,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param on {@code true} to mute master volume, {@code false} to turn mute off. */ - public void setMasterVolumeMuted(ComponentName admin, boolean on) { + public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) { if (mService != null) { try { mService.setMasterVolumeMuted(admin, on); @@ -4104,7 +4106,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return {@code true} if master volume is muted, {@code false} if it's not. */ - public boolean isMasterVolumeMuted(ComponentName admin) { + public boolean isMasterVolumeMuted(@NonNull ComponentName admin) { if (mService != null) { try { return mService.isMasterVolumeMuted(admin); @@ -4123,7 +4125,7 @@ public class DevicePolicyManager { * @param packageName package to change. * @param uninstallBlocked true if the user shouldn't be able to uninstall the package. */ - public void setUninstallBlocked(ComponentName admin, String packageName, + public void setUninstallBlocked(@NonNull ComponentName admin, String packageName, boolean uninstallBlocked) { if (mService != null) { try { @@ -4139,16 +4141,16 @@ public class DevicePolicyManager { * Requires the caller to be the profile owner if checking a specific admin's policy. * <p> * <strong>Note:</strong> Starting from {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}, the - * behavior of this API is changed such that passing <code>null</code> as the <code>admin</code> + * behavior of this API is changed such that passing {@code null} as the {@code admin} * parameter will return if any admin has blocked the uninstallation. Before L MR1, passing - * <code>null</code> will cause a NullPointerException to be raised. + * {@code null} will cause a NullPointerException to be raised. * - * @param admin The name of the admin component whose blocking policy will be checked, or null - * to check if any admin has blocked the uninstallation. + * @param admin The name of the admin component whose blocking policy will be checked, or + * {@code null} to check whether any admin has blocked the uninstallation. * @param packageName package to check. * @return true if uninstallation is blocked. */ - public boolean isUninstallBlocked(ComponentName admin, String packageName) { + public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) { if (mService != null) { try { return mService.isUninstallBlocked(admin, packageName); @@ -4168,7 +4170,6 @@ public class DevicePolicyManager { * provides a different widget type. * <p> * <strong>Note:</strong> By default no widget provider package is white-listed. - * </p> * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package from which widget providers are white-listed. @@ -4177,7 +4178,7 @@ public class DevicePolicyManager { * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #getCrossProfileWidgetProviders(android.content.ComponentName) */ - public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) { + public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { return mService.addCrossProfileWidgetProvider(admin, packageName); @@ -4195,7 +4196,6 @@ public class DevicePolicyManager { * android.content.ComponentName, String)}. * <p> * <strong>Note:</strong> By default no widget provider package is white-listed. - * </p> * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package from which widget providers are no longer @@ -4205,7 +4205,7 @@ public class DevicePolicyManager { * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #getCrossProfileWidgetProviders(android.content.ComponentName) */ - public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) { + public boolean removeCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) { if (mService != null) { try { return mService.removeCrossProfileWidgetProvider(admin, packageName); @@ -4226,7 +4226,7 @@ public class DevicePolicyManager { * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) */ - public List<String> getCrossProfileWidgetProviders(ComponentName admin) { + public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) { if (mService != null) { try { List<String> providers = mService.getCrossProfileWidgetProviders(admin); @@ -4246,7 +4246,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param icon the bitmap to set as the photo. */ - public void setUserIcon(ComponentName admin, Bitmap icon) { + public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) { try { mService.setUserIcon(admin, icon); } catch (RemoteException re) { @@ -4273,16 +4273,17 @@ public class DevicePolicyManager { * Called by device owners to set a local system update policy. When a new policy is set, * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted. * - * @param who Which {@link DeviceAdminReceiver} this request is associated with. All components - * in the device owner package can set system update policies and the most recent policy takes + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All + * components in the device owner package can set system update policies and the + * most recent policy takes * effect. - * @param policy the new policy, or null to clear the current policy. + * @param policy the new policy, or {@code null} to clear the current policy. * @see SystemUpdatePolicy */ - public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) { + public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) { if (mService != null) { try { - mService.setSystemUpdatePolicy(who, policy); + mService.setSystemUpdatePolicy(admin, policy); } catch (RemoteException re) { Log.w(TAG, "Error calling setSystemUpdatePolicy", re); } @@ -4292,7 +4293,7 @@ public class DevicePolicyManager { /** * Retrieve a local system update policy set previously by {@link #setSystemUpdatePolicy}. * - * @return The current policy object, or null if no policy is set. + * @return The current policy object, or {@code null} if no policy is set. */ public SystemUpdatePolicy getSystemUpdatePolicy() { if (mService != null) { @@ -4319,7 +4320,7 @@ public class DevicePolicyManager { * @return {@code false} if attempting to disable the keyguard while a lock password was in * place. {@code true} otherwise. */ - public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) { + public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) { try { return mService.setKeyguardDisabled(admin, disabled); } catch (RemoteException re) { @@ -4339,7 +4340,7 @@ public class DevicePolicyManager { * @return {@code false} if attempting to disable the status bar failed. * {@code true} otherwise. */ - public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) { + public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) { try { return mService.setStatusBarDisabled(admin, disabled); } catch (RemoteException re) { @@ -4377,7 +4378,8 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param activity The Activity to be started by default during user setup. */ - public void setPreferredSetupActivity(ComponentName admin, ComponentName activity) { + public void setPreferredSetupActivity(@NonNull ComponentName admin, + @NonNull ComponentName activity) { try { mService.setPreferredSetupActivity(admin, activity); } catch (RemoteException re) { @@ -4395,7 +4397,7 @@ public class DevicePolicyManager { * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT}, * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}. */ - public void setPermissionPolicy(ComponentName admin, int policy) { + public void setPermissionPolicy(@NonNull ComponentName admin, int policy) { try { mService.setPermissionPolicy(admin, policy); } catch (RemoteException re) { @@ -4409,7 +4411,7 @@ public class DevicePolicyManager { * @param admin Which profile or device owner this request is associated with. * @return the current policy for future permission requests. */ - public int getPermissionPolicy(ComponentName admin) { + public int getPermissionPolicy(@NonNull ComponentName admin) { try { return mService.getPermissionPolicy(admin); } catch (RemoteException re) { @@ -4439,7 +4441,7 @@ public class DevicePolicyManager { * @see #PERMISSION_GRANT_STATE_DEFAULT * @see #PERMISSION_GRANT_STATE_GRANTED */ - public boolean setPermissionGrantState(ComponentName admin, String packageName, + public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName, String permission, int grantState) { try { return mService.setPermissionGrantState(admin, packageName, permission, grantState); @@ -4466,7 +4468,7 @@ public class DevicePolicyManager { * @see #setPermissionGrantState(ComponentName, String, String, int) * @see PackageManager#checkPermission(String, String) */ - public int getPermissionGrantState(ComponentName admin, String packageName, + public int getPermissionGrantState(@NonNull ComponentName admin, String packageName, String permission) { try { return mService.getPermissionGrantState(admin, packageName, permission); diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index 254408a..a9328bc 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -32,4 +32,5 @@ interface IUsageStatsManager { UsageEvents queryEvents(long beginTime, long endTime, String callingPackage); void setAppInactive(String packageName, boolean inactive, int userId); boolean isAppInactive(String packageName, int userId); + void whitelistAppTemporarily(String packageName, long duration, int userId); } diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index 34699d8..c74b0f2 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.SystemApi; import android.content.Context; import android.content.pm.ParceledListSlice; import android.os.RemoteException; @@ -245,4 +246,25 @@ public final class UsageStatsManager { // fall through } } + + /** + * {@hide} + * Temporarily whitelist the specified app for a short duration. This is to allow an app + * receiving a high priority message to be able to access the network and acquire wakelocks + * even if the device is in power-save mode or the app is currently considered inactive. + * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission. + * @param packageName The package name of the app to whitelist. + * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that + * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes. + * @param user The user for whom the package should be whitelisted. Passing in a user that is + * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission. + * @see #isAppInactive(String) + */ + @SystemApi + public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) { + try { + mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier()); + } catch (RemoteException re) { + } + } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index b22b914..8107a97 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -410,6 +410,7 @@ public final class BluetoothAdapter { * Broadcast Action: The Bluetooth adapter state has changed in LE only mode. * @hide */ + @SystemApi public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; @@ -620,17 +621,18 @@ public final class BluetoothAdapter { * @return true if the local Bluetooth LE adapter is turned on * @hide */ - public boolean isLeEnabled() { - final int state = getLeState(); - if (state == BluetoothAdapter.STATE_ON) { - if (DBG) Log.d (TAG, "STATE_ON"); - } else if (state == BluetoothAdapter.STATE_BLE_ON) { - if (DBG) Log.d (TAG, "STATE_BLE_ON"); - } else { - if (DBG) Log.d (TAG, "STATE_OFF"); - return false; - } - return true; + @SystemApi + public boolean isLeEnabled() { + final int state = getLeState(); + if (state == BluetoothAdapter.STATE_ON) { + if (DBG) Log.d (TAG, "STATE_ON"); + } else if (state == BluetoothAdapter.STATE_BLE_ON) { + if (DBG) Log.d (TAG, "STATE_BLE_ON"); + } else { + if (DBG) Log.d (TAG, "STATE_OFF"); + return false; + } + return true; } /** @@ -680,6 +682,7 @@ public final class BluetoothAdapter { * immediate error * @hide */ + @SystemApi public boolean disableBLE() { if (!isBleScanAlwaysAvailable()) return false; @@ -742,6 +745,7 @@ public final class BluetoothAdapter { * immediate error * @hide */ + @SystemApi public boolean enableBLE() { if (!isBleScanAlwaysAvailable()) return false; diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index 602bfea..268295d 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -16,6 +16,8 @@ package android.os; +import android.os.UserHandle; + /** @hide */ interface IDeviceIdleController { void addPowerSaveWhitelistApp(String name); @@ -23,5 +25,7 @@ interface IDeviceIdleController { String[] getSystemPowerWhitelist(); String[] getFullPowerWhitelist(); int[] getAppIdWhitelist(); + int[] getAppIdTempWhitelist(); boolean isPowerSaveWhitelistApp(String name); + void addPowerSaveTempWhitelistApp(String name, long duration, int userId); } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 1d9d7d2..8b18f32 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -928,6 +928,14 @@ public final class PowerManager { = "android.os.action.POWER_SAVE_WHITELIST_CHANGED"; /** + * @hide Intent that is broadcast when the set of temporarily whitelisted apps has changed. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED + = "android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change. * This broadcast is only sent to registered receivers. * diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index e523285..e742f98 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -137,6 +137,8 @@ public abstract class PowerManagerInternal { public abstract void setDeviceIdleWhitelist(int[] appids); + public abstract void setDeviceIdleTempWhitelist(int[] appids); + public abstract void updateUidProcState(int uid, int procState); public abstract void uidGone(int uid); diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 76a5f967..df2e5f9 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -7930,8 +7930,6 @@ public final class ContactsContract { /** * API for inquiring about the general status of the provider. - * - * @hide */ public static final class ProviderStatus { @@ -7965,21 +7963,16 @@ public final class ContactsContract { public static final int STATUS_NORMAL = 0; /** - * The status used when the provider is in the process of upgrading. Contacts - * are temporarily unaccessible. - */ - public static final int STATUS_UPGRADING = 1; - - /** - * The status used during a locale change. + * The provider won't respond to queries. It is in the middle of a long running task, such + * as a database upgrade or locale change. */ - public static final int STATUS_CHANGING_LOCALE = 3; + public static final int STATUS_BUSY = 1; /** * The status that indicates that there are no accounts and no contacts * on the device. */ - public static final int STATUS_NO_ACCOUNTS_NO_CONTACTS = 4; + public static final int STATUS_EMPTY = 2; } /** diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3b1587a..cfd504d 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6351,7 +6351,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } View next = rootView.findViewInsideOutShouldExist(this, mAccessibilityTraversalBeforeId); - if (next != null) { + if (next != null && next.includeForAccessibility()) { info.setTraversalBefore(next); } } @@ -6363,7 +6363,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } View next = rootView.findViewInsideOutShouldExist(this, mAccessibilityTraversalAfterId); - if (next != null) { + if (next != null && next.includeForAccessibility()) { info.setTraversalAfter(next); } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index f0c86e5..45bc1df 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -309,6 +309,7 @@ public interface WindowManager extends ViewManager { * Window type: a above sub-panel on top of an application window and it's * sub-panel windows. These windows are displayed on top of their attached window * and any {@link #TYPE_APPLICATION_SUB_PANEL} panels. + * @hide */ public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c775365..439affe 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -81,6 +81,7 @@ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" /> <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" /> + <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" /> <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" /> @@ -2136,6 +2137,12 @@ <permission android:name="android.permission.CHANGE_APP_IDLE_STATE" android:protectionLevel="signature" /> + <!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to + access the network and acquire wakelocks. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" + android:protectionLevel="system|signature" /> + <!-- @SystemApi Allows an application to collect battery statistics --> <permission android:name="android.permission.BATTERY_STATS" android:protectionLevel="signature|system|development" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 93fcb2f..45dad8d 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1785,16 +1785,11 @@ <java-symbol type="string" name="smv_process" /> <java-symbol type="string" name="tethered_notification_message" /> <java-symbol type="string" name="tethered_notification_title" /> - <java-symbol type="string" name="throttle_warning_notification_message" /> - <java-symbol type="string" name="throttle_warning_notification_title" /> - <java-symbol type="string" name="throttled_notification_message" /> - <java-symbol type="string" name="throttled_notification_title" /> <java-symbol type="string" name="usb_accessory_notification_title" /> <java-symbol type="string" name="usb_cd_installer_notification_title" /> <java-symbol type="string" name="usb_mtp_notification_title" /> <java-symbol type="string" name="usb_charging_notification_title" /> <java-symbol type="string" name="usb_notification_message" /> - <java-symbol type="string" name="use_physical_keyboard" /> <java-symbol type="string" name="usb_ptp_notification_title" /> <java-symbol type="string" name="usb_midi_notification_title" /> <java-symbol type="string" name="vpn_text" /> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java index e3d2a99..0380e21 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java @@ -217,4 +217,8 @@ public final class LocalBluetoothAdapter { syncBluetoothState(); } } + + public BluetoothDevice getRemoteDevice(String address) { + return mAdapter.getRemoteDevice(address); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index f324933..cf3b7c8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -357,17 +357,19 @@ public class WifiTracker { } private void updateNetworkInfo(NetworkInfo networkInfo) { - /* sticky broadcasts can call this when wifi is disabled */ - if (!mWifiManager.isWifiEnabled()) { - mScanner.pause(); - return; - } + if (mScanner != null) { + /* sticky broadcasts can call this when wifi is disabled */ + if (!mWifiManager.isWifiEnabled()) { + mScanner.pause(); + return; + } - if (networkInfo != null && - networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) { - mScanner.pause(); - } else { - mScanner.resume(); + if (networkInfo != null && + networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) { + mScanner.pause(); + } else { + mScanner.resume(); + } } mLastInfo = mWifiManager.getConnectionInfo(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index bc42105..0dcc0b9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -33,6 +33,7 @@ import android.content.pm.UserInfo; import android.media.AudioManager; import android.media.SoundPool; import android.os.Bundle; +import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -381,14 +382,17 @@ public class KeyguardViewMediator extends SystemUI { + ",state=" + simState + ")"); } - try { - int size = mKeyguardStateCallbacks.size(); - boolean simPinSecure = mUpdateMonitor.isSimPinSecure(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + boolean simPinSecure = mUpdateMonitor.isSimPinSecure(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onSimSecureStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onSimSecureStateChanged", e); } switch (simState) { @@ -551,6 +555,7 @@ public class KeyguardViewMediator extends SystemUI { // Assume keyguard is showing (unless it's disabled) until we know for sure... setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser())); + updateInputRestrictedLocked(); mTrustManager.reportKeyguardShowingChanged(); mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext, @@ -954,13 +959,16 @@ public class KeyguardViewMediator extends SystemUI { boolean inputRestricted = isInputRestricted(); if (mInputRestricted != inputRestricted) { mInputRestricted = inputRestricted; - try { - int size = mKeyguardStateCallbacks.size(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onDeviceProvisioned", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onDeviceProvisioned", e); } } } @@ -1544,13 +1552,16 @@ public class KeyguardViewMediator extends SystemUI { private void setShowingLocked(boolean showing) { if (showing != mShowing) { mShowing = showing; - try { - int size = mKeyguardStateCallbacks.size(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onShowingStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged", e); } updateInputRestrictedLocked(); mTrustManager.reportKeyguardShowingChanged(); @@ -1565,7 +1576,7 @@ public class KeyguardViewMediator extends SystemUI { callback.onShowingStateChanged(mShowing); callback.onInputRestrictedStateChanged(mInputRestricted); } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e); + Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged or onInputRestrictedStateChanged", e); } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 6d02365..9e3cf37 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -180,7 +180,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color)); mNotificationStyle = new Notification.BigPictureStyle() - .bigPicture(picture); + .bigPicture(picture.createAshmemBitmap()); mNotificationBuilder.setStyle(mNotificationStyle); // For "public" situations we want to show all the same info but @@ -203,7 +203,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // On the tablet, the large icon makes the notification appear as if it is clickable (and // on small devices, the large icon is not shown) so defer showing the large icon until // we compose the final post-save notification below. - mNotificationBuilder.setLargeIcon(icon); + mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap()); // But we still don't set it for the expanded view, allowing the smallIcon to show here. mNotificationStyle.bigLargeIcon((Bitmap) null); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index cfc95bf..686e24c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -272,7 +272,7 @@ public class MobileSignalController extends SignalController< } private boolean isCarrierNetworkChangeActive() { - return !hasService() && mCurrentState.carrierNetworkChangeMode; + return mCurrentState.carrierNetworkChangeMode; } public void handleBroadcast(Intent intent) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index dd6f272..2df1980 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -391,35 +391,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { } - public void testCarrierNetworkChange_carrierNetworkChangeWhileConnected() { - int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; - - setupDefaultSignal(); - setLevel(strength); - - // API call is made - setCarrierNetworkChange(true /* enabled */); - - // Boolean value is set, but we still have a signal, should be showing normal - verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, - DEFAULT_ICON /* typeIcon */); - - // Lose voice but still have data - setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); - verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, - DEFAULT_ICON /* typeIcon */); - - // Voice but no data - setVoiceRegState(ServiceState.STATE_IN_SERVICE); - setDataRegState(ServiceState.STATE_OUT_OF_SERVICE); - verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, - DEFAULT_ICON /* typeIcon */); - } - - public void testCarrierNetworkChange_carrierNetworkChangeWhileDisconnected() { + public void testCarrierNetworkChange_carrierNetworkChange() { int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; setupDefaultSignal(); @@ -430,20 +402,16 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, DEFAULT_ICON /* typeIcon */); - // API call is made and all connectivity lost + // API call is made setCarrierNetworkChange(true /* enabled */); - setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); - setDataRegState(ServiceState.STATE_OUT_OF_SERVICE); - // Out of service and carrier network change is true, show special indicator + // Carrier network change is true, show special indicator verifyLastMobileDataIndicators(true /* visible */, TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE[0][0] /* strengthIcon */, 0 /* typeIcon */); // Revert back setCarrierNetworkChange(false /* enabled */); - setVoiceRegState(ServiceState.STATE_IN_SERVICE); - setDataRegState(ServiceState.STATE_IN_SERVICE); // Verify back in previous state verifyLastMobileDataIndicators(true /* visible */, diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 9b7b2d3..e9759c3 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -16,14 +16,19 @@ package com.android.server; +import android.Manifest; +import android.app.ActivityManagerNative; import android.app.AlarmManager; +import android.app.AppGlobals; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.TriggerEvent; @@ -47,7 +52,9 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.util.SparseLongArray; import android.util.TimeUtils; import android.util.Xml; import android.view.Display; @@ -55,6 +62,7 @@ import android.view.Display; import com.android.internal.app.IBatteryStats; import com.android.internal.os.AtomicFile; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; @@ -72,6 +80,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; +import java.util.Arrays; /** * Keeps track of device idleness and drives low power mode based on that. @@ -79,7 +88,8 @@ import java.nio.charset.StandardCharsets; public class DeviceIdleController extends SystemService { private static final String TAG = "DeviceIdleController"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean DEBUG = false; + private static final boolean COMPRESS_TIME = false; public static final String SERVICE_NAME = "deviceidle"; @@ -94,29 +104,31 @@ public class DeviceIdleController extends SystemService { * immediately after going inactive just because we don't want to be continually running * the significant motion sensor whenever the screen is off. */ - private static final long DEFAULT_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L - : 2 * 60 * 1000L; + private static final long DEFAULT_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L + : 3 * 60 * 1000L; /** * This is the time, after seeing motion, that we wait after becoming inactive from * that until we start looking for motion again. */ - private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !DEBUG ? 10*60*1000L + private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L : 60 * 1000L; /** * This is the time, after the inactive timeout elapses, that we will wait looking * for significant motion until we truly consider the device to be idle. */ - private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L - : 2 * 60 * 1000L; + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L + : 3 * 60 * 1000L; /** * This is the initial time, after being idle, that we will allow ourself to be back * in the IDLE_PENDING state allowing the system to run normally until we return to idle. */ - private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 5*60*1000L + : 30 * 1000L; /** * Maximum pending idle timeout (time spent running) we will be allowed to use. */ - private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L + : 60 * 1000L; /** * Scaling factor to apply to current pending idle timeout each time we cycle through * that state. @@ -126,13 +138,13 @@ public class DeviceIdleController extends SystemService { * This is the initial time that we want to sit in the idle state before waking up * again to return to pending idle and allowing normal work to run. */ - private static final long DEFAULT_IDLE_TIMEOUT = !DEBUG ? 60*60*1000L - : 5 * 60 * 1000L; + private static final long DEFAULT_IDLE_TIMEOUT = !COMPRESS_TIME ? 60*60*1000L + : 6 * 60 * 1000L; /** * Maximum idle duration we will be allowed to use. */ - private static final long DEFAULT_MAX_IDLE_TIMEOUT = !DEBUG ? 6*60*60*1000L - : 10 * 60 * 1000L; + private static final long DEFAULT_MAX_IDLE_TIMEOUT = !COMPRESS_TIME ? 6*60*60*1000L + : 30 * 60 * 1000L; /** * Scaling factor to apply to current idle timeout each time we cycle through that state. */ @@ -141,8 +153,13 @@ public class DeviceIdleController extends SystemService { * This is the minimum time we will allow until the next upcoming alarm for us to * actually go in to idle mode. */ - private static final long DEFAULT_MIN_TIME_TO_ALARM = !DEBUG ? 60*60*1000L - : 5 * 60 * 1000L; + private static final long DEFAULT_MIN_TIME_TO_ALARM = !COMPRESS_TIME ? 60*60*1000L + : 6 * 60 * 1000L; + + /** + * Max amount of time to temporarily whitelist an app when it receives a high priority tickle. + */ + private static final long MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L; private AlarmManager mAlarmManager; private IBatteryStats mBatteryStats; @@ -210,6 +227,17 @@ public class DeviceIdleController extends SystemService { */ private int[] mPowerSaveWhitelistAppIdArray = new int[0]; + /** + * List of end times for UIDs that are temporarily marked as being allowed to access + * the network and acquire wakelocks. Times are in milliseconds. + */ + private SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray(); + + /** + * Current app IDs of temporarily whitelist apps for high-priority messages. + */ + private int[] mTempWhitelistAppIdArray = new int[0]; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { @@ -252,6 +280,7 @@ public class DeviceIdleController extends SystemService { static final int MSG_REPORT_IDLE_ON = 2; static final int MSG_REPORT_IDLE_OFF = 3; static final int MSG_REPORT_ACTIVE = 4; + static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5; final class MyHandler extends Handler { MyHandler(Looper looper) { @@ -294,6 +323,10 @@ public class DeviceIdleController extends SystemService { getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); } } break; + case MSG_TEMP_APP_WHITELIST_TIMEOUT: { + int uid = msg.arg1; + checkTempAppWhitelistTimeout(uid); + } break; } } } @@ -325,10 +358,39 @@ public class DeviceIdleController extends SystemService { return getAppIdWhitelistInternal(); } + @Override public int[] getAppIdTempWhitelist() { + return getAppIdTempWhitelistInternal(); + } + @Override public boolean isPowerSaveWhitelistApp(String name) { return isPowerSaveWhitelistAppInternal(name); } + @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration, + int userId) throws RemoteException { + getContext().enforceCallingPermission( + Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, + "No permission to change device idle whitelist"); + userId = ActivityManagerNative.getDefault().handleIncomingUser( + Binder.getCallingPid(), + Binder.getCallingUid(), + userId, + /*allowAll=*/ false, + /*requireFull=*/ false, + "addAppBrieflyToWhitelist", null); + final long token = Binder.clearCallingIdentity(); + try { + PackageInfo pi = AppGlobals.getPackageManager() + .getPackageInfo(packageName, 0, userId); + if (pi == null) return; + DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName, + duration, userId); + } catch (RemoteException re) { + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { DeviceIdleController.this.dump(fd, pw, args); } @@ -481,6 +543,70 @@ public class DeviceIdleController extends SystemService { } } + public int[] getAppIdTempWhitelistInternal() { + synchronized (this) { + return mTempWhitelistAppIdArray; + } + } + + /** + * Adds an app to the temporary whitelist and resets the endTime for granting the + * app an exemption to access network and acquire wakelocks. + */ + public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration, + int userId) { + if (duration > MAX_TEMP_APP_WHITELIST_DURATION) { + duration = MAX_TEMP_APP_WHITELIST_DURATION; + } + try { + int uid = getContext().getPackageManager().getPackageUid(packageName, userId); + int appId = UserHandle.getAppId(uid); + final long timeNow = System.currentTimeMillis(); + synchronized (this) { + long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId); + // Set the new end time + mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration); + if (DEBUG) { + Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist"); + } + if (currentEndTime == 0) { + // No pending timeout for the app id, post a delayed message + postTempActiveTimeoutMessage(appId, duration); + updateTempWhitelistAppIdsLocked(); + reportTempWhitelistChangedLocked(); + } + } + } catch (NameNotFoundException e) { + } + } + + private void postTempActiveTimeoutMessage(int uid, long delay) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0), + delay); + } + + void checkTempAppWhitelistTimeout(int uid) { + final long timeNow = System.currentTimeMillis(); + synchronized (this) { + long endTime = mTempWhitelistAppIdEndTimes.get(uid); + if (endTime == 0) { + // Nothing to do + return; + } + if (timeNow >= endTime) { + mTempWhitelistAppIdEndTimes.delete(uid); + if (DEBUG) { + Slog.d(TAG, "Removing UID " + uid + " from temp whitelist"); + } + updateTempWhitelistAppIdsLocked(); + reportTempWhitelistChangedLocked(); + } else { + // Need more time + postTempActiveTimeoutMessage(uid, endTime - timeNow); + } + } + } + void updateDisplayLocked() { mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); // We consider any situation where the display is showing something to be it on, @@ -659,14 +785,41 @@ public class DeviceIdleController extends SystemService { } mPowerSaveWhitelistAppIdArray = appids; if (mLocalPowerManager != null) { + if (DEBUG) { + Slog.d(TAG, "Setting wakelock whitelist to " + + Arrays.toString(mPowerSaveWhitelistAppIdArray)); + } mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray); } } + private void updateTempWhitelistAppIdsLocked() { + final int size = mTempWhitelistAppIdEndTimes.size(); + if (mTempWhitelistAppIdArray.length != size) { + mTempWhitelistAppIdArray = new int[size]; + } + for (int i = 0; i < size; i++) { + mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i); + } + if (mLocalPowerManager != null) { + if (DEBUG) { + Slog.d(TAG, "Setting wakelock temp whitelist to " + + Arrays.toString(mTempWhitelistAppIdArray)); + } + mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray); + } + } + private void reportPowerSaveWhitelistChangedLocked() { Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - getContext().sendBroadcast(intent); + getContext().sendBroadcastAsUser(intent, UserHandle.OWNER); + } + + private void reportTempWhitelistChangedLocked() { + Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + getContext().sendBroadcastAsUser(intent, UserHandle.OWNER); } void readConfigFileLocked() { @@ -817,11 +970,18 @@ public class DeviceIdleController extends SystemService { } if (args != null) { + int userId = UserHandle.USER_OWNER; for (int i=0; i<args.length; i++) { String arg = args[i]; if ("-h".equals(arg)) { dumpHelp(pw); return; + } else if ("-u".equals(arg)) { + i++; + if (i < args.length) { + arg = args[i]; + userId = Integer.parseInt(arg); + } } else if ("-a".equals(arg)) { // Ignore, we always dump all. } else if ("step".equals(arg)) { @@ -873,6 +1033,17 @@ public class DeviceIdleController extends SystemService { } } return; + } else if ("tempwhitelist".equals(arg)) { + i++; + if (i >= args.length) { + pw.println("At least one package name must be specified"); + return; + } + while (i < args.length) { + arg = args[i]; + i++; + addPowerSaveTempWhitelistAppInternal(arg, 10000L, userId); + } } else if (arg.length() > 0 && arg.charAt(0) == '-'){ pw.println("Unknown option: " + arg); return; diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index d214a20..3315c89 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -17,6 +17,7 @@ package com.android.server.accounts; import android.Manifest; +import android.accounts.AbstractAccountAuthenticator; import android.accounts.Account; import android.accounts.AccountAndUser; import android.accounts.AccountAuthenticatorResponse; @@ -49,6 +50,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.RegisteredServicesCache; import android.content.pm.RegisteredServicesCacheListener; import android.content.pm.ResolveInfo; +import android.content.pm.Signature; import android.content.pm.UserInfo; import android.database.Cursor; import android.database.DatabaseUtils; @@ -84,6 +86,11 @@ import com.google.android.collect.Sets; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -93,6 +100,7 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -166,6 +174,10 @@ public class AccountManagerService private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION = new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT}; private static final Intent ACCOUNTS_CHANGED_INTENT; + static { + ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); + ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + } private static final String COUNT_OF_MATCHING_GRANTS = "" + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS @@ -177,6 +189,7 @@ public class AccountManagerService private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT = AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)"; + private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE, AUTHTOKENS_AUTHTOKEN}; @@ -205,6 +218,10 @@ public class AccountManagerService /** protected by the {@link #cacheLock} */ private final HashMap<Account, HashMap<String, String>> authTokenCache = new HashMap<Account, HashMap<String, String>>(); + + /** protected by the {@link #cacheLock} */ + private final HashMap<Account, WeakReference<TokenCache>> accountTokenCaches = new HashMap<>(); + /** * protected by the {@link #cacheLock} * @@ -237,12 +254,6 @@ public class AccountManagerService new AtomicReference<AccountManagerService>(); private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{}; - static { - ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); - ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - } - - /** * This should only be called by system code. One should only call this after the service * has started. @@ -425,6 +436,7 @@ public class AccountManagerService final Account account = new Account(accountName, accountType); accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); + accounts.accountTokenCaches.remove(account); } else { ArrayList<String> accountNames = accountNamesByType.get(accountType); if (accountNames == null) { @@ -1337,9 +1349,10 @@ public class AccountManagerService @Override public void invalidateAuthToken(String accountType, String authToken) { + int callerUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "invalidateAuthToken: accountType " + accountType - + ", caller's uid " + Binder.getCallingUid() + + ", caller's uid " + callerUid + ", pid " + Binder.getCallingPid()); } if (accountType == null) throw new IllegalArgumentException("accountType is null"); @@ -1353,6 +1366,7 @@ public class AccountManagerService db.beginTransaction(); try { invalidateAuthTokenLocked(accounts, db, accountType, authToken); + invalidateCustomTokenLocked(accounts, accountType, authToken); db.setTransactionSuccessful(); } finally { db.endTransaction(); @@ -1363,6 +1377,26 @@ public class AccountManagerService } } + private void invalidateCustomTokenLocked( + UserAccounts accounts, + String accountType, + String authToken) { + if (authToken == null || accountType == null) { + return; + } + // Also wipe out cached token in memory. + for (Account a : accounts.accountTokenCaches.keySet()) { + if (a.type.equals(accountType)) { + WeakReference<TokenCache> tokenCacheRef = + accounts.accountTokenCaches.get(a); + TokenCache cache = null; + if (tokenCacheRef != null && (cache = tokenCacheRef.get()) != null) { + cache.remove(authToken); + } + } + } + } + private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db, String accountType, String authToken) { if (authToken == null || accountType == null) { @@ -1385,14 +1419,41 @@ public class AccountManagerService String accountName = cursor.getString(1); String authTokenType = cursor.getString(2); db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null); - writeAuthTokenIntoCacheLocked(accounts, db, new Account(accountName, accountType), - authTokenType, null); + writeAuthTokenIntoCacheLocked( + accounts, + db, + new Account(accountName, accountType), + authTokenType, + null); } } finally { cursor.close(); } } + private void saveCachedToken( + UserAccounts accounts, + Account account, + String callerPkg, + byte[] callerSigDigest, + String tokenType, + String token, + long expiryMillis) { + + if (account == null || tokenType == null || callerPkg == null || callerSigDigest == null) { + return; + } + cancelNotification(getSigninRequiredNotificationId(accounts, account), + new UserHandle(accounts.userId)); + synchronized (accounts.cacheLock) { + TokenCache cache = getTokenCacheForAccountLocked(accounts, account); + if (cache != null) { + cache.put(token, tokenType, callerPkg, callerSigDigest, expiryMillis); + } + return; + } + } + private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account, String type, String authToken) { if (account == null || type == null) { @@ -1510,6 +1571,7 @@ public class AccountManagerService db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId); db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId); accounts.authTokenCache.remove(account); + accounts.accountTokenCaches.remove(account); db.setTransactionSuccessful(); String action = (password == null || password.length() == 0) ? @@ -1673,9 +1735,14 @@ public class AccountManagerService } @Override - public void getAuthToken(IAccountManagerResponse response, final Account account, - final String authTokenType, final boolean notifyOnAuthFailure, - final boolean expectActivityLaunch, Bundle loginOptionsIn) { + public void getAuthToken( + IAccountManagerResponse response, + final Account account, + final String authTokenType, + final boolean notifyOnAuthFailure, + final boolean expectActivityLaunch, + final Bundle loginOptions) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getAuthToken: " + account + ", response " + response @@ -1707,19 +1774,33 @@ public class AccountManagerService final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo; authenticatorInfo = mAuthenticatorCache.getServiceInfo( AuthenticatorDescription.newKey(account.type), accounts.userId); + final boolean customTokens = - authenticatorInfo != null && authenticatorInfo.type.customTokens; + authenticatorInfo != null && authenticatorInfo.type.customTokens; // skip the check if customTokens final int callerUid = Binder.getCallingUid(); final boolean permissionGranted = customTokens || permissionIsGranted(account, authTokenType, callerUid); - final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() : - loginOptionsIn; + // Get the calling package. We will use it for the purpose of caching. + final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME); + List<String> callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid)); + if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) { + String msg = String.format( + "Uid %s is attempting to illegally masquerade as package %s!", + callerUid, + callerPkg); + throw new SecurityException(msg); + } + // let authenticator know the identity of the caller loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid); loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid()); + + // Distill the caller's package signatures into a single digest. + final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg); + if (notifyOnAuthFailure) { loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true); } @@ -1740,6 +1821,28 @@ public class AccountManagerService } } + if (customTokens) { + /* + * Look up tokens in the new cache only if the loginOptions don't have parameters + * outside of those expected to be injected by the AccountManager, e.g. + * ANDORID_PACKAGE_NAME. + */ + String token = readCachedTokenInternal( + accounts, + account, + authTokenType, + callerPkg, + callerPkgSigDigest); + if (token != null) { + Bundle result = new Bundle(); + result.putString(AccountManager.KEY_AUTHTOKEN, token); + result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); + onResult(response, result); + return; + } + } + new Session(accounts, response, account.type, expectActivityLaunch, false /* stripAuthTokenFromResult */, account.name, false /* authDetailsRequired */) { @@ -1786,9 +1889,26 @@ public class AccountManagerService "the type and name should not be empty"); return; } + Account resultAccount = new Account(name, type); if (!customTokens) { - saveAuthTokenToDatabase(mAccounts, new Account(name, type), - authTokenType, authToken); + saveAuthTokenToDatabase( + mAccounts, + resultAccount, + authTokenType, + authToken); + } + long expiryMillis = result.getLong( + AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0L); + if (customTokens + && expiryMillis > System.currentTimeMillis()) { + saveCachedToken( + mAccounts, + account, + callerPkg, + callerPkgSigDigest, + authTokenType, + authToken, + expiryMillis); } } @@ -1807,6 +1927,25 @@ public class AccountManagerService } } + private byte[] calculatePackageSignatureDigest(String callerPkg) { + MessageDigest digester; + try { + digester = MessageDigest.getInstance("SHA-256"); + PackageInfo pkgInfo = mPackageManager.getPackageInfo( + callerPkg, PackageManager.GET_SIGNATURES); + for (Signature sig : pkgInfo.signatures) { + digester.update(sig.toByteArray()); + } + } catch (NoSuchAlgorithmException x) { + Log.wtf(TAG, "SHA-256 should be available", x); + digester = null; + } catch (NameNotFoundException e) { + Log.w(TAG, "Could not find packageinfo for: " + callerPkg); + digester = null; + } + return (digester == null) ? null : digester.digest(); + } + private void createNoCredentialsPermissionNotification(Account account, Intent intent, int userId) { int uid = intent.getIntExtra( @@ -2745,13 +2884,13 @@ public class AccountManagerService if (result != null) { boolean isSuccessfulConfirmCreds = result.getBoolean( AccountManager.KEY_BOOLEAN_RESULT, false); - boolean isSuccessfulUpdateCreds = + boolean isSuccessfulUpdateCreds = result.containsKey(AccountManager.KEY_ACCOUNT_NAME) && result.containsKey(AccountManager.KEY_ACCOUNT_TYPE); - // We should only update lastAuthenticated time, if + // We should only update lastAuthenticated time, if // mUpdateLastAuthenticatedTime is true and the confirmRequest // or updateRequest was successful - boolean needUpdate = mUpdateLastAuthenticatedTime + boolean needUpdate = mUpdateLastAuthenticatedTime && (isSuccessfulConfirmCreds || isSuccessfulUpdateCreds); if (needUpdate || mAuthDetailsRequired) { boolean accountPresent = isAccountPresentForCaller(mAccountName, mAccountType); @@ -3398,7 +3537,6 @@ public class AccountManagerService return; } } - String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions); Log.w(TAG, " " + msg); throw new SecurityException(msg); @@ -3796,6 +3934,18 @@ public class AccountManagerService } } + protected String readCachedTokenInternal( + UserAccounts accounts, + Account account, + String tokenType, + String callingPackage, + byte[] pkgSigDigest) { + synchronized (accounts.cacheLock) { + TokenCache cache = getTokenCacheForAccountLocked(accounts, account); + return cache.get(tokenType, callingPackage, pkgSigDigest); + } + } + protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db, Account account, String key, String value) { HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account); @@ -3877,6 +4027,17 @@ public class AccountManagerService return authTokensForAccount; } + protected TokenCache getTokenCacheForAccountLocked(UserAccounts accounts, Account account) { + WeakReference<TokenCache> cacheRef = accounts.accountTokenCaches.get(account); + TokenCache cache; + if (cacheRef == null || (cache = cacheRef.get()) == null) { + cache = new TokenCache(); + cacheRef = new WeakReference<>(cache); + accounts.accountTokenCaches.put(account, cacheRef); + } + return cache; + } + private Context getContextForUser(UserHandle user) { try { return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user); diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java new file mode 100644 index 0000000..70a7010 --- /dev/null +++ b/services/core/java/com/android/server/accounts/TokenCache.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.accounts; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +/** + * TokenCaches manage tokens associated with an account in memory. + */ +/* default */ class TokenCache { + + private static class Value { + public final String token; + public final long expiryEpochMillis; + + public Value(String token, long expiryEpochMillis) { + this.token = token; + this.expiryEpochMillis = expiryEpochMillis; + } + } + + private static class Key { + public final String packageName; + public final String tokenType; + public final byte[] sigDigest; + + public Key(String tokenType, String packageName, byte[] sigDigest) { + this.tokenType = tokenType; + this.packageName = packageName; + this.sigDigest = sigDigest; + } + + @Override + public boolean equals(Object o) { + if (o != null && o instanceof Key) { + Key cacheKey = (Key) o; + return Objects.equals(packageName, cacheKey.packageName) + && Objects.equals(tokenType, cacheKey.tokenType) + && Arrays.equals(sigDigest, cacheKey.sigDigest); + } else { + return false; + } + } + + @Override + public int hashCode() { + return packageName.hashCode() ^ tokenType.hashCode() ^ Arrays.hashCode(sigDigest); + } + } + + /** + * Map associating basic token lookup information with with actual tokens (and optionally their + * expiration times). + */ + private HashMap<Key, Value> mCachedTokens = new HashMap<>(); + + /** + * Map associated tokens with an Evictor that will manage evicting the token from the cache. + * This reverse lookup is needed because very little information is given at token invalidation + * time. + */ + private HashMap<String, Evictor> mTokenEvictors = new HashMap<>(); + + private class Evictor { + private final String mToken; + private final List<Key> mKeys; + + public Evictor(String token) { + mKeys = new ArrayList<>(); + mToken = token; + } + + public void add(Key k) { + mKeys.add(k); + } + + public void evict() { + for (Key k : mKeys) { + mCachedTokens.remove(k); + } + // Clear out the evictor reference. + mTokenEvictors.remove(mToken); + } + } + + /** + * Caches the specified token until the specified expiryMillis. The token will be associated + * with the given token type, package name, and digest of signatures. + * + * @param token + * @param tokenType + * @param packageName + * @param sigDigest + * @param expiryMillis + */ + public void put( + String token, + String tokenType, + String packageName, + byte[] sigDigest, + long expiryMillis) { + if (token == null || System.currentTimeMillis() > expiryMillis) { + return; + } + Key k = new Key(tokenType, packageName, sigDigest); + // Prep evictor. No token should be cached without a corresponding evictor. + Evictor evictor = mTokenEvictors.get(token); + if (evictor == null) { + evictor = new Evictor(token); + } + evictor.add(k); + mTokenEvictors.put(token, evictor); + // Then cache values. + Value v = new Value(token, expiryMillis); + mCachedTokens.put(k, v); + } + + /** + * Evicts the specified token from the cache. This should be called as part of a token + * invalidation workflow. + */ + public void remove(String token) { + Evictor evictor = mTokenEvictors.get(token); + if (evictor == null) { + // This condition is expected if the token isn't cached. + return; + } + evictor.evict(); + } + + /** + * Gets a token from the cache if possible. + */ + public String get(String tokenType, String packageName, byte[] sigDigest) { + Key k = new Key(tokenType, packageName, sigDigest); + Value v = mCachedTokens.get(k); + long currentTime = System.currentTimeMillis(); + if (v != null && currentTime < v.expiryEpochMillis) { + return v.token; + } else if (v != null) { + remove(v.token); + } + return null; + } +} diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index fa4d204..333db5d 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -518,7 +518,7 @@ public final class ActiveServices { // r.record is null if findServiceLocked() failed the caller permission check if (r.record == null) { throw new SecurityException( - "Permission Denial: Accessing service " + r.record.name + "Permission Denial: Accessing service" + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + " requires " + r.permission); diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java index 777a9dd..9347c24 100644 --- a/services/core/java/com/android/server/camera/CameraService.java +++ b/services/core/java/com/android/server/camera/CameraService.java @@ -20,10 +20,15 @@ import android.content.Context; import android.content.pm.UserInfo; import android.hardware.ICameraService; import android.hardware.ICameraServiceProxy; +import android.os.Handler; import android.os.IBinder; +import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.UserManager; +import android.util.Slog; +import com.android.server.ServiceThread; import com.android.server.SystemService; import java.util.Collection; @@ -36,7 +41,8 @@ import java.util.Set; * * @hide */ -public class CameraService extends SystemService { +public class CameraService extends SystemService implements Handler.Callback { + private static final String TAG = "CameraService_proxy"; /** * This must match the ICameraService.aidl definition @@ -49,7 +55,14 @@ public class CameraService extends SystemService { public static final int NO_EVENT = 0; // NOOP public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle + // Handler message codes + private static final int MSG_SWITCH_USER = 1; + + private static final int RETRY_DELAY_TIME = 20; //ms + private final Context mContext; + private final ServiceThread mHandlerThread; + private final Handler mHandler; private UserManager mUserManager; private final Object mLock = new Object(); @@ -58,18 +71,29 @@ public class CameraService extends SystemService { private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() { @Override public void pingForUserUpdate() { - // Binder call - synchronized(mLock) { - if (mEnabledCameraUsers != null) { - notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers); - } - } + notifySwitchWithRetries(30); } }; public CameraService(Context context) { super(context); mContext = context; + mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper(), this); + } + + @Override + public boolean handleMessage(Message msg) { + switch(msg.what) { + case MSG_SWITCH_USER: { + notifySwitchWithRetries(msg.arg1); + } break; + default: { + Slog.e(TAG, "CameraService error, invalid message: " + msg.what); + } break; + } + return true; } @Override @@ -119,12 +143,30 @@ public class CameraService extends SystemService { return handles; } - private void notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) { + private void notifySwitchWithRetries(int retries) { + synchronized(mLock) { + if (mEnabledCameraUsers == null) { + return; + } + if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) { + retries = 0; + } + } + if (retries <= 0) { + return; + } + Slog.i(TAG, "Could not notify camera service of user switch, retrying..."); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null), + RETRY_DELAY_TIME); + } + + private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) { // Forward the user switch event to the native camera service running in the mediaserver // process. IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME); if (cameraServiceBinder == null) { - return; // Camera service not active, cannot evict user clients. + Slog.w(TAG, "Could not notify mediaserver, camera service not available."); + return false; // Camera service not active, cannot evict user clients. } ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder); @@ -132,8 +174,11 @@ public class CameraService extends SystemService { try { cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles)); } catch (RemoteException e) { + Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e); // Not much we can do if camera service is dead. + return false; } + return true; } private static int[] toArray(Collection<Integer> c) { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 792d4ba..7673af4 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -283,9 +283,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub /** * UIDs that have been white-listed to always be able to have network access * in power save mode. + * TODO: An int array might be sufficient */ private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray(); + private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray(); + /** Set of ifaces that are metered. */ private ArraySet<String> mMeteredIfaces = new ArraySet<>(); /** Set of over-limit templates that have been notified. */ @@ -371,6 +374,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub } } + void updatePowerSaveTempWhitelistLocked() { + try { + final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist(); + mPowerSaveTempWhitelistAppIds.clear(); + if (whitelist != null) { + for (int uid : whitelist) { + mPowerSaveTempWhitelistAppIds.put(uid, true); + } + } + } catch (RemoteException e) { + } + } + public void systemReady() { if (!isBandwidthControlEnabled()) { Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy"); @@ -392,6 +408,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub if (mRestrictPower != enabled) { mRestrictPower = enabled; updateRulesForGlobalChangeLocked(true); + updateRulesForTempWhitelistChangeLocked(); } } } @@ -404,6 +421,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) { updateRulesForGlobalChangeLocked(true); + updateRulesForTempWhitelistChangeLocked(); updateNotificationsLocked(); } } @@ -428,6 +446,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub // listen for changes to power save whitelist final IntentFilter whitelistFilter = new IntentFilter( PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED); mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler); // watch for network interfaces to be claimed @@ -496,8 +515,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub public void onReceive(Context context, Intent intent) { // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected synchronized (mRulesLock) { - updatePowerSaveWhitelistLocked(); - updateRulesForGlobalChangeLocked(false); + if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) { + updatePowerSaveWhitelistLocked(); + updateRulesForGlobalChangeLocked(false); + } else { + updatePowerSaveTempWhitelistLocked(); + updateRulesForTempWhitelistChangeLocked(); + } } } }; @@ -2019,6 +2043,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub } } + void updateRulesForTempWhitelistChangeLocked() { + final List<UserInfo> users = mUserManager.getUsers(); + for (UserInfo user : users) { + for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) { + int appId = mPowerSaveTempWhitelistAppIds.keyAt(i); + int uid = UserHandle.getUid(user.id, appId); + updateRulesForUidLocked(uid); + } + } + } + private static boolean isUidValidForRules(int uid) { // allow rules on specific system services, and any apps if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID @@ -2065,8 +2100,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub // derive active rules based on policy and active state + int appId = UserHandle.getAppId(uid); int uidRules = RULE_ALLOW_ALL; - if (uidIdle && !mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid))) { + if (uidIdle && !mPowerSaveWhitelistAppIds.get(appId) + && !mPowerSaveTempWhitelistAppIds.get(appId)) { uidRules = RULE_REJECT_ALL; } else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { // uid in background, and policy says to block metered data @@ -2077,7 +2114,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub uidRules = RULE_REJECT_METERED; } } else if (mRestrictPower || mDeviceIdleMode) { - final boolean whitelisted = mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid)); + final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId) + || mPowerSaveTempWhitelistAppIds.get(appId); if (!whitelisted && !uidForeground && (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) { // uid is in background, restrict power use mode is on (so we want to diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f9bfe72..9b619c7 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4991,7 +4991,7 @@ public class PackageManagerService extends IPackageManager.Stub { scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null); } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); + Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage(), e); // Delete invalid userdata apps if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 7bd5b78..c8397e2 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -497,6 +497,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { * be done once per window. */ private WindowState mWinDismissingKeyguard; + /** When window is currently dismissing the keyguard, dismissing the keyguard must handle + * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN + * lock SIM card. This variable is used to record the previous keyguard secure state for + * monitoring secure state change on window dismissing keyguard. */ + private boolean mSecureDismissingKeyguard; + /** The window that is currently showing "over" the keyguard. If there is an app window * belonging to another app on top of this the keyguard shows. If there is a fullscreen * app window under this, still dismiss the keyguard but don't show the app underneath. Show @@ -4272,9 +4278,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDismissKeyguard == DISMISS_KEYGUARD_NONE) { if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win); - mDismissKeyguard = mWinDismissingKeyguard == win ? - DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; + mDismissKeyguard = (mWinDismissingKeyguard == win + && mSecureDismissingKeyguard == mKeyguardSecure) + ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; mWinDismissingKeyguard = win; + mSecureDismissingKeyguard = mKeyguardSecure; mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure; } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) { if (DEBUG_LAYOUT) Slog.v(TAG, @@ -4460,6 +4468,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } else { mWinDismissingKeyguard = null; + mSecureDismissingKeyguard = false; mKeyguardHidden = false; if (setKeyguardOccludedLw(false)) { changes |= FINISH_LAYOUT_REDO_LAYOUT diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index c1fe984..3af97db 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -438,6 +438,9 @@ public final class PowerManagerService extends SystemService // Set of app ids that we will always respect the wake locks for. int[] mDeviceIdleWhitelist = new int[0]; + // Set of app ids that are temporarily allowed to acquire wakelocks due to high-pri message + int[] mDeviceIdleTempWhitelist = new int[0]; + private final SparseIntArray mUidState = new SparseIntArray(); // True if theater mode is enabled @@ -2320,6 +2323,15 @@ public final class PowerManagerService extends SystemService } } + void setDeviceIdleTempWhitelistInternal(int[] appids) { + synchronized (mLock) { + mDeviceIdleTempWhitelist = appids; + if (mDeviceIdleMode) { + updateWakeLockDisabledStatesLocked(); + } + } + } + void updateUidProcStateInternal(int uid, int procState) { synchronized (mLock) { mUidState.put(uid, procState); @@ -2372,6 +2384,7 @@ public final class PowerManagerService extends SystemService // for application uids that are not whitelisted. if (appid >= Process.FIRST_APPLICATION_UID && Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 && + Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 && mUidState.get(wakeLock.mOwnerUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY) > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { @@ -2579,6 +2592,7 @@ public final class PowerManagerService extends SystemService pw.println(" mBatteryLevelLow=" + mBatteryLevelLow); pw.println(" mDeviceIdleMode=" + mDeviceIdleMode); pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist)); + pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist)); pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime)); pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime)); pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime)); @@ -3478,6 +3492,11 @@ public final class PowerManagerService extends SystemService } @Override + public void setDeviceIdleTempWhitelist(int[] appids) { + setDeviceIdleTempWhitelistInternal(appids); + } + + @Override public void updateUidProcState(int uid, int procState) { updateUidProcStateInternal(uid, procState); } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index e5981fb..4b62c40 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -408,7 +408,7 @@ public final class ShutdownThread extends Thread { } // If it's to reboot into recovery, invoke uncrypt via init service. - if (mRebootReason.equals(PowerManager.REBOOT_RECOVERY)) { + if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) { uncrypt(); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f914369..5d6df26 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -238,6 +238,7 @@ class DisplayContent { final TaskStack stack = win.getStack(); if (win.isVisibleLw() && stack != null && stack != focusedStack) { mTmpRect.set(win.mVisibleFrame); + // If no intersection, we need mTmpRect to be unmodified. mTmpRect.intersect(win.mVisibleInsets); mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 7cdf8b2..4545032 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -144,7 +144,11 @@ public class TaskStack { bounds = mTmpRect; mFullscreen = true; } else { - bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect + // ensure bounds are entirely within the display rect + if (!bounds.intersect(mTmpRect)) { + // Can't set bounds outside the containing display.. Sorry! + return false; + } mFullscreen = mTmpRect.equals(bounds); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5c9f87e..7019453 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -208,7 +208,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_APP_ORIENTATION = false; static final boolean DEBUG_CONFIGURATION = false; static final boolean DEBUG_APP_TRANSITIONS = false; - static final boolean DEBUG_STARTING_WINDOW = false; + static final boolean DEBUG_STARTING_WINDOW = true; static final boolean DEBUG_WALLPAPER = false; static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; static final boolean DEBUG_DRAG = false; @@ -2272,6 +2272,16 @@ public class WindowManagerService extends IWindowManager.Stub } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) { mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY; } + if (target.mWallpaperXStep >= 0) { + mLastWallpaperXStep = target.mWallpaperXStep; + } else if (changingTarget.mWallpaperXStep >= 0) { + mLastWallpaperXStep = changingTarget.mWallpaperXStep; + } + if (target.mWallpaperYStep >= 0) { + mLastWallpaperYStep = target.mWallpaperYStep; + } else if (changingTarget.mWallpaperYStep >= 0) { + mLastWallpaperYStep = changingTarget.mWallpaperYStep; + } } for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { @@ -6223,7 +6233,10 @@ public class WindowManagerService extends IWindowManager.Stub int bottom = wf.bottom - cr.bottom; frame.union(left, top, right, bottom); ws.getStackBounds(stackBounds); - frame.intersect(stackBounds); + if (!frame.intersect(stackBounds)) { + // Set frame empty if there's no intersection. + frame.setEmpty(); + } } if (ws.mAppToken != null && ws.mAppToken.token == appToken && @@ -6270,12 +6283,16 @@ public class WindowManagerService extends IWindowManager.Stub if (!includeFullDisplay) { // Constrain frame to the screen size. - frame.intersect(0, 0, dw, dh); + if (!frame.intersect(0, 0, dw, dh)) { + frame.setEmpty(); + } } else { // Caller just wants entire display. frame.set(0, 0, dw, dh); } - + if (frame.isEmpty()) { + return null; + } if (width < 0) { width = frame.width(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b8b243c..eda7f79 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -547,7 +547,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { } // Make sure the containing frame is within the content frame so we don't layout // resized window under screen decorations. - mContainingFrame.intersect(cf); + if (!mContainingFrame.intersect(cf)) { + mContainingFrame.set(cf); + } mDisplayFrame.set(mContainingFrame); } else { mContainingFrame.set(pf); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index ff3bb28..23057c4 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -90,23 +90,24 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; - static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + static final boolean DEBUG = false; + private static final boolean COMPRESS_TIME = false; private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; - private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; + private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. - static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 4 + static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE; // 12 hours of screen-on time sans dream-time - static final long DEFAULT_WALLCLOCK_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 8 + static final long DEFAULT_WALLCLOCK_APP_IDLE_THRESHOLD_MILLIS = COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE; // 2 days - static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE + static final long DEFAULT_CHECK_IDLE_INTERVAL = COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE; // 8 hours - static final long DEFAULT_PAROLE_INTERVAL = DEBUG ? ONE_MINUTE * 10 + static final long DEFAULT_PAROLE_INTERVAL = COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE; // 24 hours between paroles - static final long DEFAULT_PAROLE_DURATION = DEBUG ? ONE_MINUTE + static final long DEFAULT_PAROLE_DURATION = COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE; // 10 minutes // Handler message types. @@ -338,7 +339,6 @@ public class UsageStatsService extends SystemService implements /** Check all running users' apps to see if they enter an idle state. */ void checkIdleStates() { - if (DEBUG) Slog.d(TAG, "Checking idle state"); final int[] runningUsers; try { runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); @@ -994,6 +994,12 @@ public class UsageStatsService extends SystemService implements } @Override + public void whitelistAppTemporarily(String packageName, long duration, int userId) + throws RemoteException { + mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index f29a6ed..f51cb65 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -264,12 +264,19 @@ public class TelephonyManager { /** * The emergency dialer may choose to present activities with intent filters for this * action as emergency assistance buttons that launch the activity when clicked. + * + * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE"; /** + * @hide + */ + public static final boolean EMERGENCY_ASSISTANCE_ENABLED = false; + + /** * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast * for a String containing the new call state. * diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index 3dae917..cbe7c5d 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -61,6 +61,7 @@ public: mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), mVersionCode(NULL), mVersionName(NULL), mReplaceVersion(false), mCustomPackage(NULL), mExtraPackages(NULL), mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), + mSkipSymbolsWithoutDefaultLocalization(false), mProduct(NULL), mUseCrunchCache(false), mErrorOnFailedInsert(false), mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL), mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL), @@ -191,6 +192,8 @@ public: void setDebugMode(bool val) { mDebugMode = val; } bool getNonConstantId() const { return mNonConstantId; } void setNonConstantId(bool val) { mNonConstantId = val; } + bool getSkipSymbolsWithoutDefaultLocalization() const { return mSkipSymbolsWithoutDefaultLocalization; } + void setSkipSymbolsWithoutDefaultLocalization(bool val) { mSkipSymbolsWithoutDefaultLocalization = val; } const char* getProduct() const { return mProduct; } void setProduct(const char * val) { mProduct = val; } void setUseCrunchCache(bool val) { mUseCrunchCache = val; } @@ -315,6 +318,7 @@ private: const char* mMaxResVersion; bool mDebugMode; bool mNonConstantId; + bool mSkipSymbolsWithoutDefaultLocalization; const char* mProduct; bool mUseCrunchCache; bool mErrorOnFailedInsert; diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 7dee585..f832c60 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -212,6 +212,9 @@ void usage(void) " --ignore-assets\n" " Assets to be ignored. Default pattern is:\n" " %s\n" + " --skip-symbols-without-default-localization\n" + " Prevents symbols from being generated for strings that do not have a default\n" + " localization\n" " --no-version-vectors\n" " Do not automatically generate versioned copies of vector XML resources.\n", gDefaultIgnoreAssets); @@ -659,6 +662,8 @@ int main(int argc, char* const argv[]) bundle.setProduct(argv[0]); } else if (strcmp(cp, "-non-constant-id") == 0) { bundle.setNonConstantId(true); + } else if (strcmp(cp, "-skip-symbols-without-default-localization") == 0) { + bundle.setSkipSymbolsWithoutDefaultLocalization(true); } else if (strcmp(cp, "-shared-lib") == 0) { bundle.setNonConstantId(true); bundle.setBuildSharedLibrary(true); diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index beb94fd..5d20815 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1604,7 +1604,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil if (table.hasResources()) { sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - err = table.addSymbols(symbols); + err = table.addSymbols(symbols, bundle->getSkipSymbolsWithoutDefaultLocalization()); if (err < NO_ERROR) { return err; } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 3b146da..e64fdf7 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -913,6 +913,7 @@ status_t compileResourceFile(Bundle* bundle, if (code == ResXMLTree::START_TAG) { const String16* curTag = NULL; String16 curType; + String16 curName; int32_t curFormat = ResTable_map::TYPE_ANY; bool curIsBag = false; bool curIsBagReplaceOnOverwrite = false; @@ -1321,6 +1322,10 @@ status_t compileResourceFile(Bundle* bundle, ssize_t attri = block.indexOfAttribute(NULL, "type"); if (attri >= 0) { curType = String16(block.getAttributeStringValue(attri, &len)); + ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); + if (nameIdx >= 0) { + curName = String16(block.getAttributeStringValue(nameIdx, &len)); + } ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); if (formatIdx >= 0) { String16 formatStr = String16(block.getAttributeStringValue( @@ -1363,6 +1368,9 @@ status_t compileResourceFile(Bundle* bundle, } if (name.size() > 0) { + if (locale.size() == 0) { + outTable->addDefaultLocalization(name); + } if (translatable == false16) { curIsFormatted = false; // Untranslatable strings must only exist in the default [empty] locale @@ -1658,6 +1666,9 @@ status_t compileResourceFile(Bundle* bundle, hasErrors = localHasErrors = true; } else if (err == NO_ERROR) { + if (curType == string16 && !curParams.language[0] && !curParams.country[0]) { + outTable->addDefaultLocalization(curName); + } if (curIsPseudolocalizable && localeIsDefined(curParams) && bundle->getPseudolocalize() > 0) { // pseudolocalize here @@ -2622,8 +2633,11 @@ status_t ResourceTable::assignResourceIds() return firstError; } -status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) { +status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols, + bool skipSymbolsWithoutDefaultLocalization) { const size_t N = mOrderedPackages.size(); + const String8 defaultLocale; + const String16 stringType("string"); size_t pi; for (pi=0; pi<N; pi++) { @@ -2664,6 +2678,19 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) { return UNKNOWN_ERROR; } if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) { + + if (skipSymbolsWithoutDefaultLocalization && + t->getName() == stringType) { + + // Don't generate symbols for strings without a default localization. + if (mHasDefaultLocalization.find(c->getName()) + == mHasDefaultLocalization.end()) { + // printf("Skip symbol [%08x] %s\n", rid, + // String8(c->getName()).string()); + continue; + } + } + typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos()); String16 comment(c->getComment()); @@ -2686,6 +2713,12 @@ ResourceTable::addLocalization(const String16& name, const String8& locale, cons mLocalizations[name][locale] = src; } +void +ResourceTable::addDefaultLocalization(const String16& name) +{ + mHasDefaultLocalization.insert(name); +} + /*! * Flag various sorts of localization problems. '+' indicates checks already implemented; diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 9644224..2c1bec1 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -235,8 +235,10 @@ public: const ConfigDescription* config = NULL); status_t assignResourceIds(); - status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL); + status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL, + bool skipSymbolsWithoutDefaultLocalization = false); void addLocalization(const String16& name, const String8& locale, const SourcePos& src); + void addDefaultLocalization(const String16& name); status_t validateLocalizations(void); status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, @@ -588,6 +590,8 @@ private: // key = string resource name, value = set of locales in which that name is defined std::map<String16, std::map<String8, SourcePos>> mLocalizations; + // set of string resources names that have a default localization + std::set<String16> mHasDefaultLocalization; std::queue<CompileResourceWorkItem> mWorkQueue; }; |
