Merge "Add ability to get device by address" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index d38e75a..aa0f946 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2716,6 +2716,7 @@
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 {
@@ -37390,7 +37391,6 @@
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..9b2f0a0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -71,6 +71,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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";
@@ -39651,7 +39658,6 @@
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 @@
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 @@
}
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 @@
}
}
+ @Override
public void confirmCredentials(IAccountAuthenticatorResponse response,
Account account, Bundle options) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -162,6 +172,7 @@
}
}
+ @Override
public void getAuthTokenLabel(IAccountAuthenticatorResponse response,
String authTokenType)
throws RemoteException {
@@ -184,6 +195,7 @@
}
}
+ @Override
public void getAuthToken(IAccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions)
throws RemoteException {
@@ -209,6 +221,7 @@
}
}
+ @Override
public void updateCredentials(IAccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle loginOptions) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -234,6 +247,7 @@
}
}
+ @Override
public void editProperties(IAccountAuthenticatorResponse response,
String accountType) throws RemoteException {
checkBinderPermission();
@@ -248,6 +262,7 @@
}
}
+ @Override
public void hasFeatures(IAccountAuthenticatorResponse response,
Account account, String[] features) throws RemoteException {
checkBinderPermission();
@@ -262,6 +277,7 @@
}
}
+ @Override
public void getAccountRemovalAllowed(IAccountAuthenticatorResponse response,
Account account) throws RemoteException {
checkBinderPermission();
@@ -276,6 +292,7 @@
}
}
+ @Override
public void getAccountCredentialsForCloning(IAccountAuthenticatorResponse response,
Account account) throws RemoteException {
checkBinderPermission();
@@ -291,6 +308,7 @@
}
}
+ @Override
public void addAccountFromCredentials(IAccountAuthenticatorResponse response,
Account account,
Bundle accountCredentials) throws RemoteException {
@@ -410,21 +428,42 @@
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 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 @@
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 @@
* <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 @@
*
* <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 @@
* 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 @@
/**
* 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 @@
*
* <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 @@
* 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 @@
* 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 @@
/**
- * 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 @@
* 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 @@
/**
* 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 @@
* {@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 @@
/**
* 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 @@
* @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 @@
/**
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* 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 @@
* 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 @@
/**
* 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 @@
* @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 @@
* 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 @@
* @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 @@
/**
* 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 @@
* 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 @@
* @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 @@
/**
* 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 @@
* {@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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
* 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 @@
* 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 @@
/**
* 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 @@
* 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 @@
}
/**
- * 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 @@
* 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 @@
* 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 @@
* @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 @@
/**
* 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 @@
* @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 @@
/**
* 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 @@
* @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 @@
* {@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 @@
/**
* 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 @@
/**
* @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 @@
/**
* @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 @@
/**
* @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 @@
/**
* 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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* @return
*/
@SystemApi
- public void clearProfileOwner(ComponentName admin) {
+ public void clearProfileOwner(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.clearProfileOwner(admin);
@@ -2992,14 +2990,14 @@
/**
* @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 @@
* @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 @@
*
* @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 @@
* @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 @@
/**
* @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 @@
/**
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* 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 @@
* @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 @@
* <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 @@
* <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 @@
* <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 @@
* <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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
*
* @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 @@
* {@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 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* {@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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
/**
* 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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 @@
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 @@
// 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 @@
* 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 @@
* @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 @@
* immediate error
* @hide
*/
+ @SystemApi
public boolean disableBLE() {
if (!isBleScanAlwaysAvailable()) return false;
@@ -742,6 +745,7 @@
* immediate error
* @hide
*/
+ @SystemApi
public boolean enableBLE() {
if (!isBleScanAlwaysAvailable()) return false;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f0c3f2d..8bcd5d1 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -160,7 +160,6 @@
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- StrictMode.noteResourceMismatch(v);
return v.coerceToString();
}
@@ -183,24 +182,6 @@
*/
@Nullable
public String getString(int index) {
- return getString(index, true);
- }
-
- /**
- * Returns a string representation of the value at the given index,
- * optionally throwing a resource mismatch strict mode violation if the
- * value must be coerced to a string.
- *
- * @param index the index of the attribute to retrieve
- * @param strict {@code true} to throw a strict mode violation for string
- * coercion, {@code false} otherwise
- * @return a string representation of the value at the given index, or
- * {@code null} if the resource could not be coerced to a string
- * @see StrictMode#noteResourceMismatch(Object)
- * @hide Used internally for view attribute inspection.
- */
- @Nullable
- public String getString(int index, boolean strict) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
@@ -216,9 +197,6 @@
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- if (strict) {
- StrictMode.noteResourceMismatch(v);
- }
final CharSequence cs = v.coerceToString();
return cs != null ? cs.toString() : null;
}
@@ -292,7 +270,6 @@
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- StrictMode.noteResourceMismatch(v);
final CharSequence cs = v.coerceToString();
return cs != null ? cs.toString() : null;
}
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 @@
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 @@
= "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 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/view/View.java b/core/java/android/view/View.java
index 3e621b1..cfd504d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4510,7 +4510,7 @@
}
attributes[i] = resourceName;
- attributes[i + 1] = t.getString(index, false);
+ attributes[i + 1] = t.getString(index);
i += 2;
}
@@ -6351,7 +6351,7 @@
}
View next = rootView.findViewInsideOutShouldExist(this,
mAccessibilityTraversalBeforeId);
- if (next != null) {
+ if (next != null && next.includeForAccessibility()) {
info.setTraversalBefore(next);
}
}
@@ -6363,7 +6363,7 @@
}
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 @@
* 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/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 @@
}
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/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 @@
.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 @@
// 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 @@
}
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 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 @@
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.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 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.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 @@
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 @@
* 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 @@
* 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 @@
* 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 @@
*/
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 @@
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 @@
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
} break;
+ case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
+ int uid = msg.arg1;
+ checkTempAppWhitelistTimeout(uid);
+ } break;
}
}
}
@@ -325,10 +358,39 @@
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 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 @@
}
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 @@
}
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 @@
}
}
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.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 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.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 @@
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 @@
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 @@
/** 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 @@
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 @@
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 @@
@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 @@
db.beginTransaction();
try {
invalidateAuthTokenLocked(accounts, db, accountType, authToken);
+ invalidateCustomTokenLocked(accounts, accountType, authToken);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -1363,6 +1377,26 @@
}
}
+ 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 @@
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 @@
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 @@
}
@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 @@
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 @@
}
}
+ 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 @@
"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 @@
}
}
+ 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 @@
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 @@
return;
}
}
-
String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
Log.w(TAG, " " + msg);
throw new SecurityException(msg);
@@ -3796,6 +3934,18 @@
}
}
+ 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 @@
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 @@
// 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.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 @@
*
* @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 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 @@
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 @@
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 @@
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 @@
/**
* 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 @@
}
}
+ 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 @@
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
}
}
}
@@ -404,6 +421,7 @@
if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
updateNotificationsLocked();
}
}
@@ -428,6 +446,7 @@
// 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 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 @@
}
}
+ 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 @@
// 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 @@
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 @@
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 @@
* 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 @@
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 @@
}
} 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 @@
// 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 @@
}
}
+ 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 @@
// 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 @@
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 @@
}
@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 @@
}
// 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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
}
// 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 @@
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 @@
/** 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 @@
}
@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/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 @@
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 @@
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 @@
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 @@
" --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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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;
};