summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AccountManager.java155
-rw-r--r--core/java/android/app/ActivityManager.java4
-rw-r--r--core/java/android/app/AlarmManager.java23
-rw-r--r--core/java/android/app/AssistContent.java11
-rw-r--r--core/java/android/app/AssistStructure.java190
-rw-r--r--core/java/android/app/DownloadManager.java2
-rw-r--r--core/java/android/app/LoadedApk.java17
-rw-r--r--core/java/android/app/Notification.java13
-rw-r--r--core/java/android/app/admin/DeviceInitializerStatus.java145
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java146
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/app/usage/UsageEvents.java10
-rw-r--r--core/java/android/app/usage/UsageStats.java22
-rw-r--r--core/java/android/content/ContentProvider.java91
-rw-r--r--core/java/android/content/ContentProviderClient.java103
-rw-r--r--core/java/android/content/ContentResolver.java153
-rw-r--r--core/java/android/content/IntentFilter.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java19
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java9
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java14
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java5
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java20
-rw-r--r--core/java/android/hardware/camera2/legacy/RequestThreadManager.java26
-rw-r--r--core/java/android/inputmethodservice/Keyboard.java21
-rw-r--r--core/java/android/os/BatteryStats.java20
-rw-r--r--core/java/android/os/FileUtils.java26
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java3
-rw-r--r--core/java/android/os/PowerManager.java5
-rw-r--r--core/java/android/os/storage/DiskInfo.java8
-rw-r--r--core/java/android/os/storage/IMountServiceListener.java26
-rw-r--r--core/java/android/os/storage/StorageEventListener.java3
-rw-r--r--core/java/android/os/storage/StorageManager.java12
-rw-r--r--core/java/android/os/storage/VolumeInfo.java2
-rw-r--r--core/java/android/provider/ContactsContract.java153
-rw-r--r--core/java/android/provider/Settings.java59
-rw-r--r--core/java/android/speech/tts/UtteranceProgressListener.java12
-rw-r--r--core/java/android/text/TextUtils.java9
-rw-r--r--core/java/android/util/ArrayMap.java11
-rw-r--r--core/java/android/util/ArraySet.java30
-rw-r--r--core/java/android/util/KeyValueListParser.java114
-rw-r--r--core/java/android/util/TimeUtils.java86
-rw-r--r--core/java/android/view/Choreographer.java32
-rw-r--r--core/java/android/view/View.java40
-rw-r--r--core/java/android/view/ViewGroup.java4
-rw-r--r--core/java/android/view/ViewRootImpl.java11
-rw-r--r--core/java/android/view/ViewStructure.java11
-rw-r--r--core/java/android/webkit/WebViewFactory.java6
-rw-r--r--core/java/android/widget/Editor.java4
-rw-r--r--core/java/android/widget/FastScroller.java6
-rw-r--r--core/java/android/widget/GridView.java2
-rw-r--r--core/java/android/widget/LinearLayout.java4
-rw-r--r--core/java/android/widget/ListView.java6
-rw-r--r--core/java/android/widget/ScrollView.java4
-rw-r--r--core/java/android/widget/Spinner.java4
-rw-r--r--core/java/android/widget/TabWidget.java3
-rw-r--r--core/java/android/widget/TableRow.java2
-rw-r--r--core/java/android/widget/TextView.java27
-rw-r--r--core/java/com/android/internal/app/ResolverComparator.java2
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java22
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java11
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/widget/AbsActionBarView.java32
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java122
-rw-r--r--core/java/com/android/internal/widget/DecorToolbar.java2
-rw-r--r--core/java/com/android/internal/widget/SlidingTab.java8
-rw-r--r--core/java/com/android/internal/widget/ToolbarWidgetWrapper.java25
66 files changed, 1205 insertions, 968 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 31e129b..993b53d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -51,10 +51,7 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import static android.Manifest.permission.AUTHENTICATE_ACCOUNTS;
import static android.Manifest.permission.GET_ACCOUNTS;
-import static android.Manifest.permission.MANAGE_ACCOUNTS;
-import static android.Manifest.permission.USE_CREDENTIALS;
/**
* This class provides access to a centralized registry of the user's
@@ -319,14 +316,12 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that owns the specified account.
*
- * @param account The account to query for a password
+ * @param account The account to query for a password. Must not be {@code null}.
* @return The account's password, null if none or if the account doesn't exist
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public String getPassword(final Account account) {
if (account == null) throw new IllegalArgumentException("account is null");
try {
@@ -345,14 +340,12 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that owns the specified account.
*
* @param account The account to query for user data
* @return The user data, null if the account or key doesn't exist
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public String getUserData(final Account account, final String key) {
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
@@ -662,10 +655,8 @@ public class AccountManager {
* wizards associated with authenticators, not directly by applications.
*
* <p>It is safe to call this method from the main thread.
- *
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the added account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that owns the specified account.
*
* @param account The {@link Account} to add
* @param password The password to associate with the account, null for none
@@ -673,7 +664,6 @@ public class AccountManager {
* @return True if the account was successfully added, false if the account
* already exists, the account is null, or another error occurs.
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
if (account == null) throw new IllegalArgumentException("account is null");
try {
@@ -692,14 +682,13 @@ public class AccountManager {
* <p>
* It is not safe to call this method from the main thread. As such, call it
* from another thread.
- * <p>
- * This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and should be
- * called from the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that owns the specified account.
*
* @param account The {@link Account} to be updated.
+ * @return boolean {@code true} if the authentication of the account has been successfully
+ * acknowledged. Otherwise {@code false}.
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public boolean notifyAccountAuthenticated(Account account) {
if (account == null)
throw new IllegalArgumentException("account is null");
@@ -717,9 +706,8 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
* @param account The {@link Account} to rename
* @param newName String name to be associated with the account.
@@ -731,7 +719,6 @@ public class AccountManager {
* after the name change. If successful the account's name will be the
* specified new name.
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public AccountManagerFuture<Account> renameAccount(
final Account account,
@Size(min = 1) final String newName,
@@ -783,11 +770,8 @@ public class AccountManager {
* The authenticator may have its own policies preventing account
* deletion, in which case the account will not be deleted.
*
- * <p>This method may be called from any thread, but the returned
- * {@link AccountManagerFuture} must not be used on the main thread.
- *
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
* @param account The {@link Account} to remove
* @param callback Callback to invoke when the request completes,
@@ -800,15 +784,16 @@ public class AccountManager {
* {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
* instead
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
@Deprecated
public AccountManagerFuture<Boolean> removeAccount(final Account account,
AccountManagerCallback<Boolean> callback, Handler handler) {
if (account == null) throw new IllegalArgumentException("account is null");
return new Future2Task<Boolean>(handler, callback) {
+ @Override
public void doWork() throws RemoteException {
mService.removeAccount(mResponse, account, false);
}
+ @Override
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
throw new AuthenticatorException("no result in response");
@@ -827,8 +812,8 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
* @param account The {@link Account} to remove
* @param activity The {@link Activity} context to use for launching a new
@@ -855,11 +840,11 @@ public class AccountManager {
* adding accounts (of this type) has been disabled by policy
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> removeAccount(final Account account,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
if (account == null) throw new IllegalArgumentException("account is null");
return new AmsTask(activity, handler, callback) {
+ @Override
public void doWork() throws RemoteException {
mService.removeAccount(mResponse, account, activity != null);
}
@@ -880,9 +865,11 @@ public class AccountManager {
if (account == null) throw new IllegalArgumentException("account is null");
if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
return new Future2Task<Boolean>(handler, callback) {
+ @Override
public void doWork() throws RemoteException {
mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
}
+ @Override
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
throw new AuthenticatorException("no result in response");
@@ -918,17 +905,14 @@ public class AccountManager {
* in which case the account will not be deleted.
* <p>
* It is safe to call this method from the main thread.
- * <p>
- * This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and to have the
- * same UID or signature as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
* @param account The {@link Account} to delete.
* @return True if the account was successfully deleted, false if the
* account did not exist, the account is null, or another error
* occurs.
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public boolean removeAccountExplicitly(Account account) {
if (account == null) throw new IllegalArgumentException("account is null");
try {
@@ -948,14 +932,9 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS} or
- * {@link android.Manifest.permission#USE_CREDENTIALS}
- *
* @param accountType The account type of the auth token to invalidate, must not be null
* @param authToken The auth token to invalidate, may be null
*/
- @RequiresPermission(anyOf = {MANAGE_ACCOUNTS, USE_CREDENTIALS})
public void invalidateAuthToken(final String accountType, final String authToken) {
if (accountType == null) throw new IllegalArgumentException("accountType is null");
try {
@@ -976,16 +955,15 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
- * @param account The account to fetch an auth token for
- * @param authTokenType The type of auth token to fetch, see {#getAuthToken}
+ * @param account The account for which an auth token is to be fetched. Cannot be {@code null}.
+ * @param authTokenType The type of auth token to fetch. Cannot be {@code null}.
* @return The cached auth token for this account and type, or null if
* no auth token is cached or the account does not exist.
+ * @see #getAuthToken
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public String peekAuthToken(final Account account, final String authTokenType) {
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
@@ -1005,14 +983,12 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
- * @param account The account to set a password for
+ * @param account The account whose password is to be set. Cannot be {@code null}.
* @param password The password to set, null to clear the password
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public void setPassword(final Account account, final String password) {
if (account == null) throw new IllegalArgumentException("account is null");
try {
@@ -1030,14 +1006,14 @@ public class AccountManager {
* permissions, and may be used by applications or management interfaces
* to "sign out" from an account.
*
- * <p>It is safe to call this method from the main thread.
+ * <p>This method only successfully clear the account's password when the
+ * caller has the same signature as the authenticator that owns the
+ * specified account. Otherwise, this method will silently fail.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}
+ * <p>It is safe to call this method from the main thread.
*
* @param account The account whose password to clear
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public void clearPassword(final Account account) {
if (account == null) throw new IllegalArgumentException("account is null");
try {
@@ -1055,15 +1031,13 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
- * @param account The account to set the userdata for
- * @param key The userdata key to set. Must not be null
- * @param value The value to set, null to clear this userdata key
+ * @param account Account whose user data is to be set. Must not be {@code null}.
+ * @param key String user data key to set. Must not be null
+ * @param value String value to set, {@code null} to clear this user data key
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public void setUserData(final Account account, final String key, final String value) {
if (account == null) throw new IllegalArgumentException("account is null");
if (key == null) throw new IllegalArgumentException("key is null");
@@ -1083,15 +1057,13 @@ public class AccountManager {
*
* <p>It is safe to call this method from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
- * and to have the same UID as the account's authenticator.
+ * <p>This method requires the caller to have a signature match with the
+ * authenticator that manages the specified account.
*
* @param account The account to set an auth token for
* @param authTokenType The type of the auth token, see {#getAuthToken}
* @param authToken The auth token to add to the cache
*/
- @RequiresPermission(AUTHENTICATE_ACCOUNTS)
public void setAuthToken(Account account, final String authTokenType, final String authToken) {
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
@@ -1110,9 +1082,6 @@ public class AccountManager {
* <p>This method may block while a network request completes, and must
* never be made from the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#USE_CREDENTIALS}.
- *
* @param account The account to fetch an auth token for
* @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
* @param notifyAuthFailure If true, display a notification and return null
@@ -1126,7 +1095,6 @@ public class AccountManager {
* @throws java.io.IOException if the authenticator experienced an I/O problem
* creating a new auth token, usually because of network trouble
*/
- @RequiresPermission(USE_CREDENTIALS)
public String blockingGetAuthToken(Account account, String authTokenType,
boolean notifyAuthFailure)
throws OperationCanceledException, IOException, AuthenticatorException {
@@ -1165,9 +1133,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#USE_CREDENTIALS}.
- *
* @param account The account to fetch an auth token for
* @param authTokenType The auth token type, an authenticator-dependent
* string token, must not be null
@@ -1201,7 +1166,6 @@ public class AccountManager {
* authenticator-dependent. The caller should verify the validity of the
* account before requesting an auth token.
*/
- @RequiresPermission(USE_CREDENTIALS)
public AccountManagerFuture<Bundle> getAuthToken(
final Account account, final String authTokenType, final Bundle options,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
@@ -1253,9 +1217,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#USE_CREDENTIALS}.
- *
* @param account The account to fetch an auth token for
* @param authTokenType The auth token type, an authenticator-dependent
* string token, must not be null
@@ -1292,7 +1253,6 @@ public class AccountManager {
* boolean, AccountManagerCallback, android.os.Handler)} instead
*/
@Deprecated
- @RequiresPermission(USE_CREDENTIALS)
public AccountManagerFuture<Bundle> getAuthToken(
final Account account, final String authTokenType,
final boolean notifyAuthFailure,
@@ -1333,9 +1293,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#USE_CREDENTIALS}.
- *
* @param account The account to fetch an auth token for
* @param authTokenType The auth token type, an authenticator-dependent
* string token, must not be null
@@ -1371,7 +1328,6 @@ public class AccountManager {
* authenticator-dependent. The caller should verify the validity of the
* account before requesting an auth token.
*/
- @RequiresPermission(USE_CREDENTIALS)
public AccountManagerFuture<Bundle> getAuthToken(
final Account account, final String authTokenType, final Bundle options,
final boolean notifyAuthFailure,
@@ -1401,9 +1357,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
- *
* @param accountType The type of account to add; must not be null
* @param authTokenType The type of auth token (see {@link #getAuthToken})
* this account will need to be able to generate, null for none
@@ -1441,7 +1394,6 @@ public class AccountManager {
* creating a new account, usually because of network trouble
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> addAccount(final String accountType,
final String authTokenType, final String[] requiredFeatures,
final Bundle addAccountOptions,
@@ -1586,9 +1538,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
- *
* @param account The account to confirm password knowledge for
* @param options Authenticator-specific options for the request;
* if the {@link #KEY_PASSWORD} string field is present, the
@@ -1615,11 +1564,11 @@ public class AccountManager {
* If no activity or password was specified, the returned Bundle contains
* {@link #KEY_INTENT} with the {@link Intent} needed to launch the
* password prompt.
- *
+ *
* <p>Also the returning Bundle may contain {@link
* #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the
* credential was validated/created.
- *
+ *
* If an error occurred,{@link AccountManagerFuture#getResult()} throws:
* <ul>
* <li> {@link AuthenticatorException} if the authenticator failed to respond
@@ -1629,7 +1578,6 @@ public class AccountManager {
* verifying the password, usually because of network trouble
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
final Bundle options,
final Activity activity,
@@ -1668,9 +1616,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
- *
* @param account The account to update credentials for
* @param authTokenType The credentials entered must allow an auth token
* of this type to be created (but no actual auth token is returned);
@@ -1706,7 +1651,6 @@ public class AccountManager {
* verifying the password, usually because of network trouble
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> updateCredentials(final Account account,
final String authTokenType,
final Bundle options, final Activity activity,
@@ -1729,8 +1673,8 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
+ * <p>This method requires the caller to have the same signature as the
+ * authenticator associated with the specified account type.
*
* @param accountType The account type associated with the authenticator
* to adjust
@@ -1758,7 +1702,6 @@ public class AccountManager {
* updating settings, usually because of network trouble
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> editProperties(final String accountType,
final Activity activity, final AccountManagerCallback<Bundle> callback,
final Handler handler) {
@@ -2253,9 +2196,6 @@ public class AccountManager {
* <p>This method may be called from any thread, but the returned
* {@link AccountManagerFuture} must not be used on the main thread.
*
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
- *
* @param accountType The account type required
* (see {@link #getAccountsByType}), must not be null
* @param authTokenType The desired auth token type
@@ -2292,7 +2232,6 @@ public class AccountManager {
* updating settings, usually because of network trouble
* </ul>
*/
- @RequiresPermission(MANAGE_ACCOUNTS)
public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
final String accountType, final String authTokenType, final String[] features,
final Activity activity, final Bundle addAccountOptions,
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index da345a6..b65593d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2812,7 +2812,9 @@ public class ActivityManager {
* continues running even if the process is killed and restarted. To remove the watch,
* use {@link #clearWatchHeapLimit()}.
*
- * <p>This API only work if running on a debuggable (userdebug or eng) build.</p>
+ * <p>This API only work if the calling process has been marked as
+ * {@link ApplicationInfo#FLAG_DEBUGGABLE} or this is running on a debuggable
+ * (userdebug or eng) build.</p>
*
* <p>Callers can optionally implement {@link #ACTION_REPORT_HEAP_LIMIT} to directly
* handle heap limit reports themselves.</p>
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 5e7bd0d..9ea1606 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -142,13 +142,22 @@ public class AlarmManager {
public static final int FLAG_ALLOW_WHILE_IDLE = 1<<2;
/**
+ * Flag for alarms: same as {@link #FLAG_ALLOW_WHILE_IDLE}, but doesn't have restrictions
+ * on how frequently it can be scheduled. Only available (and automatically applied) to
+ * system alarms.
+ *
+ * @hide
+ */
+ public static final int FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED = 1<<3;
+
+ /**
* Flag for alarms: this alarm marks the point where we would like to come out of idle
* mode. It may be moved by the alarm manager to match the first wake-from-idle alarm.
* Scheduling an alarm with this flag puts the alarm manager in to idle mode, where it
* avoids scheduling any further alarms until the marker alarm is executed.
* @hide
*/
- public static final int FLAG_IDLE_UNTIL = 1<<3;
+ public static final int FLAG_IDLE_UNTIL = 1<<4;
private final IAlarmManager mService;
private final boolean mAlwaysExact;
@@ -565,6 +574,12 @@ public class AlarmManager {
* of the device when idle (and thus cause significant battery blame to the app scheduling
* them), so they should be used with care.
*
+ * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+ * for a particular application. Under normal system operation, it will not dispatch these
+ * alarms more than about every minute (at which point every such pending alarm is
+ * dispatched); when in low-power idle modes this duration may be significantly longer,
+ * such as 15 minutes.</p>
+ *
* <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
* out of order with any other alarms, even those from the same app. This will clearly happen
* when the device is idle (since this alarm can go off while idle, when any other alarms
@@ -608,6 +623,12 @@ public class AlarmManager {
* of the device when idle (and thus cause significant battery blame to the app scheduling
* them), so they should be used with care.
*
+ * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+ * for a particular application. Under normal system operation, it will not dispatch these
+ * alarms more than about every minute (at which point every such pending alarm is
+ * dispatched); when in low-power idle modes this duration may be significantly longer,
+ * such as 15 minutes.</p>
+ *
* <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
* out of order with any other alarms, even those from the same app. This will clearly happen
* when the device is idle (since this alarm can go off while idle, when any other alarms
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index 173b237..0df9ce5 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -35,6 +35,7 @@ public class AssistContent {
private Intent mIntent;
private ClipData mClipData;
private Uri mUri;
+ private final Bundle mExtras;
/**
* @hide
@@ -53,6 +54,7 @@ public class AssistContent {
}
public AssistContent() {
+ mExtras = new Bundle();
}
/**
@@ -143,6 +145,13 @@ public class AssistContent {
return mUri;
}
+ /**
+ * Return Bundle for extra vendor-specific data that can be modified and examined.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
/** @hide */
public AssistContent(Parcel in) {
if (in.readInt() != 0) {
@@ -155,6 +164,7 @@ public class AssistContent {
mUri = Uri.CREATOR.createFromParcel(in);
}
mIsAppProvidedIntent = in.readInt() == 1;
+ mExtras = in.readBundle();
}
/** @hide */
@@ -178,5 +188,6 @@ public class AssistContent {
dest.writeInt(0);
}
dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
+ dest.writeBundle(mExtras);
}
}
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 0f69817..7f6dae5 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -131,6 +131,7 @@ public class AssistStructure {
final int mWidth;
final int mHeight;
final CharSequence mTitle;
+ final int mDisplayId;
final ViewNode mRoot;
WindowNode(AssistStructure assist, ViewRootImpl root) {
@@ -142,6 +143,7 @@ public class AssistStructure {
mWidth = rect.width();
mHeight = rect.height();
mTitle = root.getTitle();
+ mDisplayId = root.getDisplayId();
mRoot = new ViewNode();
ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
if ((root.getWindowFlags()&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
@@ -160,6 +162,7 @@ public class AssistStructure {
mWidth = in.readInt();
mHeight = in.readInt();
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mDisplayId = in.readInt();
mRoot = new ViewNode(in, preader);
}
@@ -169,29 +172,58 @@ public class AssistStructure {
out.writeInt(mWidth);
out.writeInt(mHeight);
TextUtils.writeToParcel(mTitle, out, 0);
+ out.writeInt(mDisplayId);
mRoot.writeToParcel(out, pwriter);
}
+ /**
+ * Returns the left edge of the window, in pixels, relative to the left
+ * edge of the screen.
+ */
public int getLeft() {
return mX;
}
+ /**
+ * Returns the top edge of the window, in pixels, relative to the top
+ * edge of the screen.
+ */
public int getTop() {
return mY;
}
+ /**
+ * Returns the total width of the window in pixels.
+ */
public int getWidth() {
return mWidth;
}
+ /**
+ * Returns the total height of the window in pixels.
+ */
public int getHeight() {
return mHeight;
}
+ /**
+ * Returns the title associated with the window, if it has one.
+ */
public CharSequence getTitle() {
return mTitle;
}
+ /**
+ * Returns the ID of the display this window is on, for use with
+ * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}.
+ */
+ public int getDisplayId() {
+ return mDisplayId;
+ }
+
+ /**
+ * Returns the {@link ViewNode} containing the root content of the window.
+ */
public ViewNode getRootViewNode() {
return mRoot;
}
@@ -325,146 +357,288 @@ public class AssistStructure {
}
}
+ /**
+ * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
+ */
public int getId() {
return mId;
}
+ /**
+ * If {@link #getId()} is a resource identifier, this is the package name of that
+ * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
+ * for more information.
+ */
public String getIdPackage() {
return mIdPackage;
}
+ /**
+ * If {@link #getId()} is a resource identifier, this is the type name of that
+ * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
+ * for more information.
+ */
public String getIdType() {
return mIdType;
}
+ /**
+ * If {@link #getId()} is a resource identifier, this is the entry name of that
+ * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
+ * for more information.
+ */
public String getIdEntry() {
return mIdEntry;
}
+ /**
+ * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
+ */
public int getLeft() {
return mX;
}
+ /**
+ * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
+ */
public int getTop() {
return mY;
}
+ /**
+ * Returns the current X scroll offset of this view, as per
+ * {@link android.view.View#getScrollX() View.getScrollX()}.
+ */
public int getScrollX() {
return mScrollX;
}
+ /**
+ * Returns the current Y scroll offset of this view, as per
+ * {@link android.view.View#getScrollX() View.getScrollY()}.
+ */
public int getScrollY() {
return mScrollY;
}
+ /**
+ * Returns the width of this view, in pixels.
+ */
public int getWidth() {
return mWidth;
}
+ /**
+ * Returns the height of this view, in pixels.
+ */
public int getHeight() {
return mHeight;
}
+ /**
+ * Returns the visibility mode of this view, as per
+ * {@link android.view.View#getVisibility() View.getVisibility()}.
+ */
public int getVisibility() {
return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
}
+ /**
+ * Returns true if assist data has been blocked starting at this node in the hierarchy.
+ */
public boolean isAssistBlocked() {
return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0;
}
+ /**
+ * Returns true if this node is in an enabled state.
+ */
public boolean isEnabled() {
return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
}
+ /**
+ * Returns true if this node is clickable by the user.
+ */
public boolean isClickable() {
return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
}
+ /**
+ * Returns true if this node can take input focus.
+ */
public boolean isFocusable() {
return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
}
+ /**
+ * Returns true if this node currently had input focus at the time that the
+ * structure was collected.
+ */
public boolean isFocused() {
return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
}
+ /**
+ * Returns true if this node currently had accessibility focus at the time that the
+ * structure was collected.
+ */
public boolean isAccessibilityFocused() {
return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
}
+ /**
+ * Returns true if this node represents something that is checkable by the user.
+ */
public boolean isCheckable() {
return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
}
+ /**
+ * Returns true if this node is currently in a checked state.
+ */
public boolean isChecked() {
return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
}
+ /**
+ * Returns true if this node has currently been selected by the user.
+ */
public boolean isSelected() {
return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
}
+ /**
+ * Returns true if this node has currently been activated by the user.
+ */
public boolean isActivated() {
return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
}
+ /**
+ * Returns true if this node is something the user can perform a long click/press on.
+ */
public boolean isLongClickable() {
return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
}
+ /**
+ * Returns true if this node is something the user can perform a context click on.
+ */
public boolean isContextClickable() {
return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
}
+ /**
+ * Returns the class name of the node's implementation, indicating its behavior.
+ * For example, a button will report "android.widget.Button" meaning it behaves
+ * like a {@link android.widget.Button}.
+ */
public String getClassName() {
return mClassName;
}
+ /**
+ * Returns any content description associated with the node, which semantically describes
+ * its purpose for accessibility and other uses.
+ */
public CharSequence getContentDescription() {
return mContentDescription;
}
+ /**
+ * Returns any text associated with the node that is displayed to the user, or null
+ * if there is none.
+ */
public CharSequence getText() {
return mText != null ? mText.mText : null;
}
+ /**
+ * If {@link #getText()} is non-null, this is where the current selection starts.
+ */
public int getTextSelectionStart() {
return mText != null ? mText.mTextSelectionStart : -1;
}
+ /**
+ * If {@link #getText()} is non-null, this is where the current selection starts.
+ * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
+ * indicating the cursor position.
+ */
public int getTextSelectionEnd() {
return mText != null ? mText.mTextSelectionEnd : -1;
}
+ /**
+ * If {@link #getText()} is non-null, this is the main text color associated with it.
+ * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+ * Note that the text may also contain style spans that modify the color of specific
+ * parts of the text.
+ */
public int getTextColor() {
return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
}
+ /**
+ * If {@link #getText()} is non-null, this is the main text background color associated
+ * with it.
+ * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+ * Note that the text may also contain style spans that modify the color of specific
+ * parts of the text.
+ */
public int getTextBackgroundColor() {
return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
}
+ /**
+ * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
+ * with it.
+ * Note that the text may also contain style spans that modify the size of specific
+ * parts of the text.
+ */
public float getTextSize() {
return mText != null ? mText.mTextSize : 0;
}
+ /**
+ * If {@link #getText()} is non-null, this is the main text style associated
+ * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
+ * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
+ * {@link #TEXT_STYLE_UNDERLINE}.
+ * Note that the text may also contain style spans that modify the style of specific
+ * parts of the text.
+ */
public int getTextStyle() {
return mText != null ? mText.mTextStyle : 0;
}
+ /**
+ * Return additional hint text associated with the node; this is typically used with
+ * a node that takes user input, describing to the user what the input means.
+ */
public String getHint() {
return mText != null ? mText.mHint : null;
}
+ /**
+ * Return a Bundle containing optional vendor-specific extension information.
+ */
public Bundle getExtras() {
return mExtras;
}
+ /**
+ * Return the number of children this node has.
+ */
public int getChildCount() {
return mChildren != null ? mChildren.length : 0;
}
+ /**
+ * Return a child of this node, given an index value from 0 to
+ * {@link #getChildCount()}-1.
+ */
public ViewNode getChildAt(int index) {
return mChildren[index];
}
@@ -663,6 +837,19 @@ public class AssistStructure {
}
@Override
+ public int addChildCount(int num) {
+ if (mNode.mChildren == null) {
+ setChildCount(num);
+ return 0;
+ }
+ final int start = mNode.mChildren.length;
+ ViewNode[] newArray = new ViewNode[start + num];
+ System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
+ mNode.mChildren = newArray;
+ return start;
+ }
+
+ @Override
public int getChildCount() {
return mNode.mChildren != null ? mNode.mChildren.length : 0;
}
@@ -801,6 +988,9 @@ public class AssistStructure {
return assistBundle.getParcelable(ASSIST_KEY);
}
+ /**
+ * Return the activity this AssistStructure came from.
+ */
public ComponentName getActivityComponent() {
ensureData();
return mActivityComponent;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 2ed8b0f..5327646 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -418,7 +418,7 @@ public class DownloadManager {
private int mNotificationVisibility = VISIBILITY_VISIBLE;
/**
- * @param uri the HTTP URI to download.
+ * @param uri the HTTP or HTTPS URI to download.
*/
public Request(Uri uri) {
if (uri == null) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 9604789..c2bf28a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -55,6 +55,7 @@ import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
+import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
@@ -166,6 +167,7 @@ public final class LoadedApk {
if (runtimeIsa.equals(secondaryIsa)) {
final ApplicationInfo modified = new ApplicationInfo(info);
modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
+ modified.primaryCpuAbi = modified.secondaryCpuAbi;
return modified;
}
}
@@ -272,8 +274,9 @@ public final class LoadedApk {
}
}
- final ArrayList<String> zipPaths = new ArrayList<>();
- final ArrayList<String> libPaths = new ArrayList<>();
+ final List<String> zipPaths = new ArrayList<>();
+ final List<String> apkPaths = new ArrayList<>();
+ final List<String> libPaths = new ArrayList<>();
if (mRegisterPackage) {
try {
@@ -329,6 +332,8 @@ public final class LoadedApk {
}
}
+ apkPaths.addAll(zipPaths);
+
if (mSharedLibraries != null) {
for (String lib : mSharedLibraries) {
if (!zipPaths.contains(lib)) {
@@ -346,6 +351,14 @@ public final class LoadedApk {
}
final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+
+ // Add path to libraries in apk for current abi
+ if (mApplicationInfo.primaryCpuAbi != null) {
+ for (String apk : apkPaths) {
+ libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
+ }
+ }
+
final String lib = TextUtils.join(File.pathSeparator, libPaths);
/*
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 96c6878..33a47b2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1331,11 +1331,14 @@ public class Notification implements Parcelable
public Notification(Context context, int icon, CharSequence tickerText, long when,
CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
{
- this.when = when;
- this.icon = icon;
- this.tickerText = tickerText;
- setLatestEventInfo(context, contentTitle, contentText,
- PendingIntent.getActivity(context, 0, contentIntent, 0));
+ new Builder(context)
+ .setWhen(when)
+ .setSmallIcon(icon)
+ .setTicker(tickerText)
+ .setContentTitle(contentTitle)
+ .setContentText(contentText)
+ .setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0))
+ .buildInto(this);
}
/**
diff --git a/core/java/android/app/admin/DeviceInitializerStatus.java b/core/java/android/app/admin/DeviceInitializerStatus.java
deleted file mode 100644
index 7de518b..0000000
--- a/core/java/android/app/admin/DeviceInitializerStatus.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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 android.app.admin;
-
-/**
- * Defines constants designating device provisioning status used with {@link
- * android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}.
- *
- * This class contains flag constants that define special status codes:
- * <ul>
- * <li>{@link #FLAG_STATUS_ERROR} is used to define provisioning error status codes
- * <li>{@link #FLAG_STATUS_CUSTOM} is used to define custom status codes
- * <li>{@link #FLAG_STATUS_HIGH_PRIORITY} is used to define high priority status codes
- * </ul>
- *
- * <p>Status codes used by ManagedProvisioning are also defined in this class. These status codes
- * include provisioning errors and status codes.
- * <ul>
- * <li>{@link #STATUS_ERROR_CONNECT_WIFI}
- * <li>{@link #STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING}
- * <li>{@link #STATUS_ERROR_DOWNLOAD_PACKAGE}
- * <li>{@link #STATUS_ERROR_INSTALL_PACKAGE}
- * <li>{@link #STATUS_ERROR_SET_DEVICE_POLICY}
- * <li>{@link #STATUS_ERROR_DELETE_APPS}
- * <li>{@link #STATUS_ERROR_DOUBLE_BUMP}
- * <li>{@link #STATUS_STATE_CONNECTING_BLUETOOTH_PROXY}
- * <li>{@link #STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY}
- * <li>{@link #STATUS_STATE_DEVICE_PROVISIONED}
- * </ul>
- */
-public class DeviceInitializerStatus {
- /**
- * A flag used to designate an error status.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isErrorStatus(int)
- */
- public static final int FLAG_STATUS_ERROR = 0x01000000;
-
- /**
- * A flag used to designate a custom status. Custom status codes will be defined by device
- * initializer agents.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isCustomStatus(int)
- */
- public static final int FLAG_STATUS_CUSTOM = 0x02000000;
-
- /**
- * A bit flag used to designate a reserved status. Reserved status codes will not be defined
- * in AOSP.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- */
- public static final int FLAG_STATUS_RESERVED = 0x04000000;
-
- /**
- * A flag used to indicate that a status message is high priority.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isHighPriority(int)
- */
- public static final int FLAG_STATUS_HIGH_PRIORITY = 0x08000000;
-
- /**
- * Device provisioning status code that indicates that a device is connecting to establish
- * a Bluetooth network proxy.
- */
- public static final int STATUS_STATE_CONNECTING_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 8;
-
- /**
- * Device provisioning status code that indicates that a connected Bluetooth network proxy
- * is being shut down.
- */
- public static final int STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 9;
-
- /**
- * Device provisioning status code that indicates that a device has been successfully
- * provisioned.
- */
- public static final int STATUS_STATE_DEVICE_PROVISIONED = FLAG_STATUS_HIGH_PRIORITY | 10;
-
- /**
- * Device provisioning error status code that indicates that a device could not connect to
- * a Wi-Fi network.
- */
- public static final int STATUS_ERROR_CONNECT_WIFI = FLAG_STATUS_ERROR | 21;
-
- /**
- * Device provisioning error status indicating that factory reset protection is enabled on
- * the provisioned device and cannot be disabled with the provided data.
- */
- public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING =
- FLAG_STATUS_ERROR | 22;
-
- /**
- * Device provisioning error status indicating that device administrator and device initializer
- * packages could not be downloaded and verified successfully.
- */
- public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = FLAG_STATUS_ERROR | 23;
-
- /**
- * Device provisioning error status indicating that device owner and device initializer packages
- * could not be installed.
- */
- public static final int STATUS_ERROR_INSTALL_PACKAGE = FLAG_STATUS_ERROR | 24;
-
- /**
- * Device provisioning error status indicating that the device owner or device initializer
- * components could not be set.
- */
- public static final int STATUS_ERROR_SET_DEVICE_POLICY = FLAG_STATUS_ERROR | 25;
-
- /**
- * Device provisioning error status indicating that deleting non-required applications during
- * provisioning failed.
- */
- public static final int STATUS_ERROR_DELETE_APPS = FLAG_STATUS_ERROR | 26;
-
- /**
- * Device provisioning error status code that indicates that a provisioning attempt has failed
- * because the device has already been provisioned or that provisioning has already started.
- */
- public static final int STATUS_ERROR_DOUBLE_BUMP = FLAG_STATUS_ERROR | 30;
-
- private DeviceInitializerStatus() {}
-}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index e5ed150..9f49154 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -149,6 +149,7 @@ public class DevicePolicyManager {
* <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
* <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
* </ul>
*
* <p> When device owner provisioning has completed, an intent of the type
@@ -163,14 +164,19 @@ public class DevicePolicyManager {
= "android.app.action.PROVISION_MANAGED_DEVICE";
/**
- * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
- * a mobile device management application that starts managed profile provisioning to pass data
- * to itself on the managed profile when provisioning completes. The mobile device management
- * application sends this extra in an intent with the action
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+ * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
+ * allows a mobile device management application which starts managed provisioning to pass data
+ * to itself.
+ * <p>
+ * If used with {@link #ACTION_PROVISION_MANAGED_PROFILE} it can be used by the application that
+ * sends the intent to pass data to itself on the newly created profile.
+ * If used with {@link #ACTION_PROVISION_MANAGED_DEVICE} it allows passing data to the same
+ * instance of the app on the primary user.
+ * <p>
+ * In both cases the application receives the data in
* {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
- * during the managed profile provisioning.
+ * during the managed provisioning.
*/
public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
@@ -400,7 +406,7 @@ public class DevicePolicyManager {
* A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
* location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM} should be
+ * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be
* present. The provided checksum should match the checksum of the file at the download
* location. If the checksum doesn't match an error will be shown to the user and the user will
* be asked to factory reset the device.
@@ -412,24 +418,24 @@ public class DevicePolicyManager {
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
/**
- * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any certificate of the
+ * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
* android package archive at the download location specified in {@link
* #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>The certificates of an android package archive can be obtained using
+ * <p>The signatures of an android package archive can be obtained using
* {@link android.content.pm.PackageManager#getPackageArchiveInfo} with flag
* {@link android.content.pm.PackageManager#GET_SIGNATURES}.
*
* <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM} should be
- * present. The provided checksum should match the checksum of any certificate of the file at
+ * present. The provided checksum should match the checksum of any signature of the file at
* the download location. If the checksum does not match an error will be shown to the user and
* the user will be asked to factory reset the device.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
* provisioning via an NFC bump.
*/
- public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM
- = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
+ public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
/**
* Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
@@ -508,7 +514,7 @@ public class DevicePolicyManager {
* location specified in
* {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM}
+ * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM}
* should be present. The provided checksum should match the checksum of the file at the
* download location. If the checksum doesn't match an error will be shown to the user and the
* user will be asked to factory reset the device.
@@ -520,68 +526,24 @@ public class DevicePolicyManager {
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
/**
- * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any certificate of the
+ * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
* android package archive at the download location specified in {@link
* #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>The certificates of an android package archive can be obtained using
+ * <p>The signatures of an android package archive can be obtained using
* {@link android.content.pm.PackageManager#getPackageArchiveInfo} with flag
* {@link android.content.pm.PackageManager#GET_SIGNATURES}.
*
* <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}
- * should be present. The provided checksum should match the checksum of any certificate of the
+ * should be present. The provided checksum should match the checksum of any signature of the
* file at the download location. If the checksum doesn't match an error will be shown to the
* user and the user will be asked to factory reset the device.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
* provisioning via an NFC bump.
*/
- public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM
- = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM";
-
- /**
- * A String extra holding the MAC address of the Bluetooth device to connect to with status
- * updates during provisioning.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_MAC_ADDRESS
- = "android.app.extra.PROVISIONING_BT_MAC_ADDRESS";
-
- /**
- * A String extra holding the Bluetooth service UUID on the device to connect to with status
- * updates during provisioning.
- *
- * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_UUID
- = "android.app.extra.PROVISIONING_BT_UUID";
-
- /**
- * A String extra holding a unique identifier used to identify the device connecting over
- * Bluetooth. This identifier will be part of every status message sent to the remote device.
- *
- * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_DEVICE_ID
- = "android.app.extra.PROVISIONING_BT_DEVICE_ID";
-
- /**
- * A Boolean extra that that will cause a provisioned device to temporarily proxy network
- * traffic over Bluetooth. When a Wi-Fi network is available, the network proxy will stop.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_USE_PROXY
- = "android.app.extra.PROVISIONING_BT_USE_PROXY";
+ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM
+ = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM";
/**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
@@ -665,11 +627,7 @@ public class DevicePolicyManager {
* Replaces {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. The value of the property
* should be converted to a String via
* {@link android.content.ComponentName#flattenToString()}</li>
- * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_MAC_ADDRESS}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_UUID}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_DEVICE_ID}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_USE_PROXY}, optional</li></ul>
+ * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li></ul>
*
* <p> When device owner provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -727,45 +685,6 @@ public class DevicePolicyManager {
= "android.app.action.SET_PROFILE_OWNER";
/**
- * Protected broadcast action that will be sent to managed provisioning to notify it that a
- * status update has been reported by the device initializer. The status update will be
- * reported to the remote setup device over Bluetooth.
- *
- * <p>Broadcasts with this action must supply a
- * {@linkplain DeviceInitializerStatus#FLAG_STATUS_CUSTOM custom} status code in the
- * {@link EXTRA_DEVICE_INITIALIZER_STATUS_CODE} extra.
- *
- * <p>Broadcasts may optionally contain a description in the
- * {@link EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION} extra.
- * @hide
- */
- @SystemApi
- public static final String ACTION_SEND_DEVICE_INITIALIZER_STATUS
- = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
-
- /**
- * An integer extra that contains the status code that defines a status update. This extra must
- * sent as part of a broadcast with an action of {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
- *
- * <p>The status code sent with this extra must be a custom status code as defined by
- * {@link DeviceInitializerStatus#FLAG_STATUS_CUSTOM}.
- * @hide
- */
- @SystemApi
- public static final String EXTRA_DEVICE_INITIALIZER_STATUS_CODE
- = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE";
-
- /**
- * A {@code String} extra that contains an optional description accompanying a status update.
- * This extra my be sent as part of a broadcast with an action of
- * {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
- * @hide
- */
- @SystemApi
- public static final String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION
- = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION";
-
- /**
* @hide
* Name of the profile owner admin that controls the user.
*/
@@ -4291,21 +4210,6 @@ public class DevicePolicyManager {
}
/**
- * Called by device initializer to send a provisioning status update to the remote setup device.
- *
- * @param statusCode a custom status code value as defined by
- * {@link DeviceInitializerStatus#FLAG_STATUS_CUSTOM}.
- * @param description custom description of the status code sent
- */
- public void sendDeviceInitializerStatus(int statusCode, String description) {
- try {
- mService.sendDeviceInitializerStatus(statusCode, description);
- } catch (RemoteException re) {
- Log.w(TAG, "Could not send device initializer status", re);
- }
- }
-
- /**
* 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.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a700806..376a3d8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -220,7 +220,6 @@ interface IDevicePolicyManager {
void setUserIcon(in ComponentName admin, in Bitmap icon);
- void sendDeviceInitializerStatus(int statusCode, String description);
void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy);
SystemUpdatePolicy getSystemUpdatePolicy();
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 58279d7..369b692 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -68,9 +68,15 @@ public final class UsageEvents implements Parcelable {
public static final int CONFIGURATION_CHANGE = 5;
/**
- * An event type denoting that a package was interacted with in some way.
+ * An event type denoting that a package was interacted with in some way by the system.
+ * @hide
*/
- public static final int INTERACTION = 6;
+ public static final int SYSTEM_INTERACTION = 6;
+
+ /**
+ * An event type denoting that a package was interacted with in some way by the user.
+ */
+ public static final int USER_INTERACTION = 7;
/**
* {@hide}
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 81c7422..0fce4e2 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -41,11 +41,19 @@ public final class UsageStats implements Parcelable {
public long mEndTimeStamp;
/**
+ * Last time used by the user with an explicit action (notification, activity launch).
* {@hide}
*/
public long mLastTimeUsed;
/**
+ * The last time the package was used via implicit, non-user initiated actions (service
+ * was bound, etc).
+ * {@hide}
+ */
+ public long mLastTimeSystemUsed;
+
+ /**
* Last time the package was used and the beginning of the idle countdown.
* This uses a different timebase that is about how much the device has been in use in general.
* {@hide}
@@ -82,6 +90,7 @@ public final class UsageStats implements Parcelable {
mLaunchCount = stats.mLaunchCount;
mLastEvent = stats.mLastEvent;
mBeginIdleTime = stats.mBeginIdleTime;
+ mLastTimeSystemUsed = stats.mLastTimeSystemUsed;
}
public String getPackageName() {
@@ -119,6 +128,16 @@ public final class UsageStats implements Parcelable {
/**
* @hide
+ * Get the last time this package was used by the system (not the user). This can be different
+ * from {@link #getLastTimeUsed()} when the system binds to one of this package's services.
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeSystemUsed() {
+ return mLastTimeSystemUsed;
+ }
+
+ /**
+ * @hide
* Get the last time this package was active, measured in milliseconds. This timestamp
* uses a timebase that represents how much the device was used and not wallclock time.
*/
@@ -151,6 +170,7 @@ public final class UsageStats implements Parcelable {
mEndTimeStamp = right.mEndTimeStamp;
mLastTimeUsed = right.mLastTimeUsed;
mBeginIdleTime = right.mBeginIdleTime;
+ mLastTimeSystemUsed = right.mLastTimeSystemUsed;
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
@@ -172,6 +192,7 @@ public final class UsageStats implements Parcelable {
dest.writeInt(mLaunchCount);
dest.writeInt(mLastEvent);
dest.writeLong(mBeginIdleTime);
+ dest.writeLong(mLastTimeSystemUsed);
}
public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -186,6 +207,7 @@ public final class UsageStats implements Parcelable {
stats.mLaunchCount = in.readInt();
stats.mLastEvent = in.readInt();
stats.mBeginIdleTime = in.readLong();
+ stats.mLastTimeSystemUsed = in.readLong();
return stats;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index e916b9f..d4c4437 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -19,6 +19,7 @@ package android.content;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.pm.PathPermission;
@@ -635,7 +636,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* {@link #onCreate} has been called -- this will return {@code null} in the
* constructor.
*/
- public final Context getContext() {
+ public final @Nullable Context getContext() {
return mContext;
}
@@ -663,7 +664,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @throws SecurityException if the calling package doesn't belong to the
* calling UID.
*/
- public final String getCallingPackage() {
+ public final @Nullable String getCallingPackage() {
final String pkg = mCallingPackage.get();
if (pkg != null) {
mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
@@ -712,7 +713,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param permission Name of the permission required for read-only access.
*/
- protected final void setReadPermission(String permission) {
+ protected final void setReadPermission(@Nullable String permission) {
mReadPermission = permission;
}
@@ -723,7 +724,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*/
- public final String getReadPermission() {
+ public final @Nullable String getReadPermission() {
return mReadPermission;
}
@@ -734,7 +735,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param permission Name of the permission required for read/write access.
*/
- protected final void setWritePermission(String permission) {
+ protected final void setWritePermission(@Nullable String permission) {
mWritePermission = permission;
}
@@ -745,7 +746,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*/
- public final String getWritePermission() {
+ public final @Nullable String getWritePermission() {
return mWritePermission;
}
@@ -756,7 +757,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param permissions Array of path permission descriptions.
*/
- protected final void setPathPermissions(PathPermission[] permissions) {
+ protected final void setPathPermissions(@Nullable PathPermission[] permissions) {
mPathPermissions = permissions;
}
@@ -767,7 +768,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*/
- public final PathPermission[] getPathPermissions() {
+ public final @Nullable PathPermission[] getPathPermissions() {
return mPathPermissions;
}
@@ -893,8 +894,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* If {@code null} then the provider is free to define the sort order.
* @return a Cursor or {@code null}.
*/
- public abstract Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder);
+ public abstract @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder);
/**
* Implement this to handle query requests from clients with support for cancellation.
@@ -959,9 +961,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* when the query is executed.
* @return a Cursor or {@code null}.
*/
- public Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- CancellationSignal cancellationSignal) {
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
return query(uri, projection, selection, selectionArgs, sortOrder);
}
@@ -983,7 +985,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @param uri the URI to query.
* @return a MIME type string, or {@code null} if there is no type.
*/
- public abstract String getType(Uri uri);
+ public abstract @Nullable String getType(@NonNull Uri uri);
/**
* Implement this to support canonicalization of URIs that refer to your
@@ -1015,7 +1017,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return Return the canonical representation of <var>url</var>, or null if
* canonicalization of that Uri is not supported.
*/
- public Uri canonicalize(Uri url) {
+ public @Nullable Uri canonicalize(@NonNull Uri url) {
return null;
}
@@ -1033,7 +1035,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* the data identified by the canonical representation can not be found in
* the current environment.
*/
- public Uri uncanonicalize(Uri url) {
+ public @Nullable Uri uncanonicalize(@NonNull Uri url) {
return url;
}
@@ -1066,7 +1068,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* This must not be {@code null}.
* @return The URI for the newly inserted item.
*/
- public abstract Uri insert(Uri uri, ContentValues values);
+ public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
/**
* Override this to handle requests to insert a set of new rows, or the
@@ -1083,7 +1085,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* This must not be {@code null}.
* @return The number of values that were inserted.
*/
- public int bulkInsert(Uri uri, ContentValues[] values) {
+ public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
insert(uri, values[i]);
@@ -1111,7 +1113,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return The number of rows affected.
* @throws SQLException
*/
- public abstract int delete(Uri uri, String selection, String[] selectionArgs);
+ public abstract int delete(@NonNull Uri uri, @Nullable String selection,
+ @Nullable String[] selectionArgs);
/**
* Implement this to handle requests to update one or more rows.
@@ -1130,8 +1133,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @param selection An optional filter to match rows to update.
* @return the number of rows affected.
*/
- public abstract int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs);
+ public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable String selection, @Nullable String[] selectionArgs);
/**
* Override this to handle requests to open a file blob.
@@ -1190,7 +1193,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #getType(android.net.Uri)
* @see ParcelFileDescriptor#parseMode(String)
*/
- public ParcelFileDescriptor openFile(Uri uri, String mode)
+ public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
throws FileNotFoundException {
throw new FileNotFoundException("No files supported by provider at "
+ uri);
@@ -1260,8 +1263,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #getType(android.net.Uri)
* @see ParcelFileDescriptor#parseMode(String)
*/
- public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
- throws FileNotFoundException {
+ public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
+ @Nullable CancellationSignal signal) throws FileNotFoundException {
return openFile(uri, mode);
}
@@ -1316,7 +1319,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openFileHelper(Uri, String)
* @see #getType(android.net.Uri)
*/
- public AssetFileDescriptor openAssetFile(Uri uri, String mode)
+ public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode)
throws FileNotFoundException {
ParcelFileDescriptor fd = openFile(uri, mode);
return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
@@ -1379,8 +1382,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openFileHelper(Uri, String)
* @see #getType(android.net.Uri)
*/
- public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
- throws FileNotFoundException {
+ public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
+ @Nullable CancellationSignal signal) throws FileNotFoundException {
return openAssetFile(uri, mode);
}
@@ -1398,8 +1401,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return Returns a new ParcelFileDescriptor that can be used by the
* client to access the file.
*/
- protected final ParcelFileDescriptor openFileHelper(Uri uri,
- String mode) throws FileNotFoundException {
+ protected final @NonNull ParcelFileDescriptor openFileHelper(@NonNull Uri uri,
+ @NonNull String mode) throws FileNotFoundException {
Cursor c = query(uri, new String[]{"_data"}, null, null, null);
int count = (c != null) ? c.getCount() : 0;
if (count != 1) {
@@ -1445,7 +1448,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openTypedAssetFile(Uri, String, Bundle)
* @see ClipDescription#compareMimeTypes(String, String)
*/
- public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+ public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
return null;
}
@@ -1494,8 +1497,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openAssetFile(Uri, String)
* @see ClipDescription#compareMimeTypes(String, String)
*/
- public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
- throws FileNotFoundException {
+ public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+ @NonNull String mimeTypeFilter, @Nullable Bundle opts) throws FileNotFoundException {
if ("*/*".equals(mimeTypeFilter)) {
// If they can take anything, the untyped open call is good enough.
return openAssetFile(uri, "r");
@@ -1561,9 +1564,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @see #openAssetFile(Uri, String)
* @see ClipDescription#compareMimeTypes(String, String)
*/
- public AssetFileDescriptor openTypedAssetFile(
- Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
- throws FileNotFoundException {
+ public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+ @NonNull String mimeTypeFilter, @Nullable Bundle opts,
+ @Nullable CancellationSignal signal) throws FileNotFoundException {
return openTypedAssetFile(uri, mimeTypeFilter, opts);
}
@@ -1585,8 +1588,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @param opts Options supplied by caller.
* @param args Your own custom arguments.
*/
- public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
- Bundle opts, T args);
+ public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri,
+ @NonNull String mimeType, @Nullable Bundle opts, @Nullable T args);
}
/**
@@ -1606,9 +1609,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* the pipe. This should be returned to the caller for reading; the caller
* is responsible for closing it when done.
*/
- public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
- final Bundle opts, final T args, final PipeDataWriter<T> func)
- throws FileNotFoundException {
+ public @NonNull <T> ParcelFileDescriptor openPipeHelper(final @NonNull Uri uri,
+ final @NonNull String mimeType, final @Nullable Bundle opts, final @Nullable T args,
+ final @NonNull PipeDataWriter<T> func) throws FileNotFoundException {
try {
final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
@@ -1713,8 +1716,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @throws OperationApplicationException thrown if any operation fails.
* @see ContentProviderOperation#apply
*/
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
- throws OperationApplicationException {
+ public @NonNull ContentProviderResult[] applyBatch(
+ @NonNull ArrayList<ContentProviderOperation> operations)
+ throws OperationApplicationException {
final int numOperations = operations.size();
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i < numOperations; i++) {
@@ -1741,7 +1745,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
* @return provider-defined return value. May be {@code null}, which is also
* the default for providers which don't implement any call methods.
*/
- public Bundle call(String method, @Nullable String arg, @Nullable Bundle extras) {
+ public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
+ @Nullable Bundle extras) {
return null;
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index e15ac94..d12595f 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -16,6 +16,8 @@
package android.content;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
@@ -30,6 +32,7 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
@@ -109,14 +112,19 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#query ContentProvider.query} */
- public Cursor query(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) throws RemoteException {
+ public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) throws RemoteException {
return query(url, projection, selection, selectionArgs, sortOrder, null);
}
/** See {@link ContentProvider#query ContentProvider.query} */
- public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
- String sortOrder, CancellationSignal cancellationSignal) throws RemoteException {
+ public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)
+ throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
ICancellationSignal remoteCancellationSignal = null;
@@ -138,7 +146,9 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#getType ContentProvider.getType} */
- public String getType(Uri url) throws RemoteException {
+ public @Nullable String getType(@NonNull Uri url) throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.getType(url);
@@ -153,7 +163,11 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
- public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
+ public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
+ throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+
beforeRemote();
try {
return mContentProvider.getStreamTypes(url, mimeTypeFilter);
@@ -168,7 +182,9 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#canonicalize} */
- public final Uri canonicalize(Uri url) throws RemoteException {
+ public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.canonicalize(mPackageName, url);
@@ -183,7 +199,9 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#uncanonicalize} */
- public final Uri uncanonicalize(Uri url) throws RemoteException {
+ public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.uncanonicalize(mPackageName, url);
@@ -198,7 +216,10 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#insert ContentProvider.insert} */
- public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
+ public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
+ throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.insert(mPackageName, url, initialValues);
@@ -213,7 +234,11 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
- public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
+ public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
+ throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(initialValues, "initialValues");
+
beforeRemote();
try {
return mContentProvider.bulkInsert(mPackageName, url, initialValues);
@@ -228,8 +253,10 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#delete ContentProvider.delete} */
- public int delete(Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
+ public int delete(@NonNull Uri url, @Nullable String selection,
+ @Nullable String[] selectionArgs) throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
@@ -244,8 +271,10 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#update ContentProvider.update} */
- public int update(Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
+ @Nullable String[] selectionArgs) throws RemoteException {
+ Preconditions.checkNotNull(url, "url");
+
beforeRemote();
try {
return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
@@ -266,7 +295,7 @@ public class ContentProviderClient {
* you use the {@link ContentResolver#openFileDescriptor
* ContentResolver.openFileDescriptor} API instead.
*/
- public ParcelFileDescriptor openFile(Uri url, String mode)
+ public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode)
throws RemoteException, FileNotFoundException {
return openFile(url, mode, null);
}
@@ -278,8 +307,11 @@ public class ContentProviderClient {
* you use the {@link ContentResolver#openFileDescriptor
* ContentResolver.openFileDescriptor} API instead.
*/
- public ParcelFileDescriptor openFile(Uri url, String mode, CancellationSignal signal)
- throws RemoteException, FileNotFoundException {
+ public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
+ @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(mode, "mode");
+
beforeRemote();
try {
ICancellationSignal remoteSignal = null;
@@ -306,7 +338,7 @@ public class ContentProviderClient {
* you use the {@link ContentResolver#openAssetFileDescriptor
* ContentResolver.openAssetFileDescriptor} API instead.
*/
- public AssetFileDescriptor openAssetFile(Uri url, String mode)
+ public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode)
throws RemoteException, FileNotFoundException {
return openAssetFile(url, mode, null);
}
@@ -318,8 +350,11 @@ public class ContentProviderClient {
* you use the {@link ContentResolver#openAssetFileDescriptor
* ContentResolver.openAssetFileDescriptor} API instead.
*/
- public AssetFileDescriptor openAssetFile(Uri url, String mode, CancellationSignal signal)
- throws RemoteException, FileNotFoundException {
+ public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
+ @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(mode, "mode");
+
beforeRemote();
try {
ICancellationSignal remoteSignal = null;
@@ -340,15 +375,19 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
- public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
- String mimeType, Bundle opts) throws RemoteException, FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mimeType, @Nullable Bundle opts)
+ throws RemoteException, FileNotFoundException {
return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
}
/** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
- public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
- String mimeType, Bundle opts, CancellationSignal signal)
- throws RemoteException, FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mimeType, @Nullable Bundle opts, @Nullable CancellationSignal signal)
+ throws RemoteException, FileNotFoundException {
+ Preconditions.checkNotNull(uri, "uri");
+ Preconditions.checkNotNull(mimeType, "mimeType");
+
beforeRemote();
try {
ICancellationSignal remoteSignal = null;
@@ -370,8 +409,11 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
- throws RemoteException, OperationApplicationException {
+ public @NonNull ContentProviderResult[] applyBatch(
+ @NonNull ArrayList<ContentProviderOperation> operations)
+ throws RemoteException, OperationApplicationException {
+ Preconditions.checkNotNull(operations, "operations");
+
beforeRemote();
try {
return mContentProvider.applyBatch(mPackageName, operations);
@@ -386,7 +428,10 @@ public class ContentProviderClient {
}
/** See {@link ContentProvider#call(String, String, Bundle)} */
- public Bundle call(String method, String arg, Bundle extras) throws RemoteException {
+ public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
+ @Nullable Bundle extras) throws RemoteException {
+ Preconditions.checkNotNull(method, "method");
+
beforeRemote();
try {
return mContentProvider.call(mPackageName, method, arg, extras);
@@ -436,7 +481,7 @@ public class ContentProviderClient {
* @return If the associated {@link ContentProvider} is local, returns it.
* Otherwise returns null.
*/
- public ContentProvider getLocalContentProvider() {
+ public @Nullable ContentProvider getLocalContentProvider() {
return ContentProvider.coerceToLocalContentProvider(mContentProvider);
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 96a80e7..057001c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
@@ -47,6 +48,8 @@ import android.util.Log;
import dalvik.system.CloseGuard;
+import com.android.internal.util.Preconditions;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -320,7 +323,9 @@ public abstract class ContentResolver {
* using the content:// scheme.
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
*/
- public final String getType(Uri url) {
+ public final @Nullable String getType(@NonNull Uri url) {
+ Preconditions.checkNotNull(url, "url");
+
// XXX would like to have an acquireExistingUnstableProvider for this.
IContentProvider provider = acquireExistingProvider(url);
if (provider != null) {
@@ -371,7 +376,10 @@ public abstract class ContentResolver {
* data streams that match the given mimeTypeFilter. If there are none,
* null is returned.
*/
- public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
+ public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -418,8 +426,9 @@ public abstract class ContentResolver {
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
- public final Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder) {
+ public final @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) {
return query(uri, projection, selection, selectionArgs, sortOrder, null);
}
@@ -457,9 +466,10 @@ public abstract class ContentResolver {
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
- public final Cursor query(final Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- CancellationSignal cancellationSignal) {
+ public final @Nullable Cursor query(final @NonNull Uri uri, @Nullable String[] projection,
+ @Nullable String selection, @Nullable String[] selectionArgs,
+ @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
+ Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
@@ -555,7 +565,8 @@ public abstract class ContentResolver {
*
* @see #uncanonicalize
*/
- public final Uri canonicalize(Uri url) {
+ public final @Nullable Uri canonicalize(@NonNull Uri url) {
+ Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -590,7 +601,8 @@ public abstract class ContentResolver {
*
* @see #canonicalize
*/
- public final Uri uncanonicalize(Uri url) {
+ public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
+ Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -626,8 +638,9 @@ public abstract class ContentResolver {
* @throws FileNotFoundException if the provided URI could not be opened.
* @see #openAssetFileDescriptor(Uri, String)
*/
- public final InputStream openInputStream(Uri uri)
+ public final @Nullable InputStream openInputStream(@NonNull Uri uri)
throws FileNotFoundException {
+ Preconditions.checkNotNull(uri, "uri");
String scheme = uri.getScheme();
if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
// Note: left here to avoid breaking compatibility. May be removed
@@ -658,7 +671,7 @@ public abstract class ContentResolver {
* openOutputStream(uri, "w")}.
* @throws FileNotFoundException if the provided URI could not be opened.
*/
- public final OutputStream openOutputStream(Uri uri)
+ public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
throws FileNotFoundException {
return openOutputStream(uri, "w");
}
@@ -682,7 +695,7 @@ public abstract class ContentResolver {
* @throws FileNotFoundException if the provided URI could not be opened.
* @see #openAssetFileDescriptor(Uri, String)
*/
- public final OutputStream openOutputStream(Uri uri, String mode)
+ public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
throws FileNotFoundException {
AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
try {
@@ -729,8 +742,8 @@ public abstract class ContentResolver {
* file exists under the URI or the mode is invalid.
* @see #openAssetFileDescriptor(Uri, String)
*/
- public final ParcelFileDescriptor openFileDescriptor(Uri uri, String mode)
- throws FileNotFoundException {
+ public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
+ @NonNull String mode) throws FileNotFoundException {
return openFileDescriptor(uri, mode, null);
}
@@ -774,8 +787,9 @@ public abstract class ContentResolver {
* file exists under the URI or the mode is invalid.
* @see #openAssetFileDescriptor(Uri, String)
*/
- public final ParcelFileDescriptor openFileDescriptor(Uri uri,
- String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
+ public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
+ @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
+ throws FileNotFoundException {
AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
if (afd == null) {
return null;
@@ -844,8 +858,8 @@ public abstract class ContentResolver {
* @throws FileNotFoundException Throws FileNotFoundException of no
* file exists under the URI or the mode is invalid.
*/
- public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, String mode)
- throws FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mode) throws FileNotFoundException {
return openAssetFileDescriptor(uri, mode, null);
}
@@ -900,8 +914,12 @@ public abstract class ContentResolver {
* @throws FileNotFoundException Throws FileNotFoundException of no
* file exists under the URI or the mode is invalid.
*/
- public final AssetFileDescriptor openAssetFileDescriptor(Uri uri,
- String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
+ throws FileNotFoundException {
+ Preconditions.checkNotNull(uri, "uri");
+ Preconditions.checkNotNull(mode, "mode");
+
String scheme = uri.getScheme();
if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
if (!"r".equals(mode)) {
@@ -1023,8 +1041,8 @@ public abstract class ContentResolver {
* @throws FileNotFoundException Throws FileNotFoundException of no
* data of the desired type exists under the URI.
*/
- public final AssetFileDescriptor openTypedAssetFileDescriptor(
- Uri uri, String mimeType, Bundle opts) throws FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException {
return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
}
@@ -1059,9 +1077,12 @@ public abstract class ContentResolver {
* @throws FileNotFoundException Throws FileNotFoundException of no
* data of the desired type exists under the URI.
*/
- public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
- String mimeType, Bundle opts, CancellationSignal cancellationSignal)
- throws FileNotFoundException {
+ public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+ @NonNull String mimeType, @Nullable Bundle opts,
+ @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
+ Preconditions.checkNotNull(uri, "uri");
+ Preconditions.checkNotNull(mimeType, "mimeType");
+
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
throw new FileNotFoundException("No content provider: " + uri);
@@ -1197,8 +1218,8 @@ public abstract class ContentResolver {
* the field. Passing an empty ContentValues will create an empty row.
* @return the URL of the newly created row.
*/
- public final Uri insert(Uri url, ContentValues values)
- {
+ public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) {
+ Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1234,9 +1255,11 @@ public abstract class ContentResolver {
* @throws RemoteException thrown if a RemoteException is encountered while attempting
* to communicate with a remote provider.
*/
- public ContentProviderResult[] applyBatch(String authority,
- ArrayList<ContentProviderOperation> operations)
- throws RemoteException, OperationApplicationException {
+ public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
+ @NonNull ArrayList<ContentProviderOperation> operations)
+ throws RemoteException, OperationApplicationException {
+ Preconditions.checkNotNull(authority, "authority");
+ Preconditions.checkNotNull(operations, "operations");
ContentProviderClient provider = acquireContentProviderClient(authority);
if (provider == null) {
throw new IllegalArgumentException("Unknown authority " + authority);
@@ -1258,8 +1281,9 @@ public abstract class ContentResolver {
* the field. Passing null will create an empty row.
* @return the number of newly created rows.
*/
- public final int bulkInsert(Uri url, ContentValues[] values)
- {
+ public final int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] values) {
+ Preconditions.checkNotNull(url, "url");
+ Preconditions.checkNotNull(values, "values");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1289,8 +1313,9 @@ public abstract class ContentResolver {
(excluding the WHERE itself).
* @return The number of rows deleted.
*/
- public final int delete(Uri url, String where, String[] selectionArgs)
- {
+ public final int delete(@NonNull Uri url, @Nullable String where,
+ @Nullable String[] selectionArgs) {
+ Preconditions.checkNotNull(url, "url");
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1323,8 +1348,9 @@ public abstract class ContentResolver {
* @return the number of rows updated.
* @throws NullPointerException if uri or values are null
*/
- public final int update(Uri uri, ContentValues values, String where,
- String[] selectionArgs) {
+ public final int update(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable String where, @Nullable String[] selectionArgs) {
+ Preconditions.checkNotNull(uri, "uri");
IContentProvider provider = acquireProvider(uri);
if (provider == null) {
throw new IllegalArgumentException("Unknown URI " + uri);
@@ -1358,14 +1384,10 @@ public abstract class ContentResolver {
* @throws NullPointerException if uri or method is null
* @throws IllegalArgumentException if uri is not known
*/
- public final Bundle call(
- Uri uri, String method, @Nullable String arg, @Nullable Bundle extras) {
- if (uri == null) {
- throw new NullPointerException("uri == null");
- }
- if (method == null) {
- throw new NullPointerException("method == null");
- }
+ public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
+ @Nullable String arg, @Nullable Bundle extras) {
+ Preconditions.checkNotNull(uri, "uri");
+ Preconditions.checkNotNull(method, "method");
IContentProvider provider = acquireProvider(uri);
if (provider == null) {
throw new IllegalArgumentException("Unknown URI " + uri);
@@ -1467,12 +1489,12 @@ public abstract class ContentResolver {
* @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
* that services the content at uri or null if there isn't one.
*/
- public final ContentProviderClient acquireContentProviderClient(Uri uri) {
+ public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
+ Preconditions.checkNotNull(uri, "uri");
IContentProvider provider = acquireProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, true);
}
-
return null;
}
@@ -1487,7 +1509,9 @@ public abstract class ContentResolver {
* @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
* with the authority of name or null if there isn't one.
*/
- public final ContentProviderClient acquireContentProviderClient(String name) {
+ public final @Nullable ContentProviderClient acquireContentProviderClient(
+ @NonNull String name) {
+ Preconditions.checkNotNull(name, "name");
IContentProvider provider = acquireProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, true);
@@ -1512,7 +1536,9 @@ public abstract class ContentResolver {
* can acquire a new one if you would like to try to restart the provider
* and perform new operations on it.
*/
- public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) {
+ public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
+ @NonNull Uri uri) {
+ Preconditions.checkNotNull(uri, "uri");
IContentProvider provider = acquireUnstableProvider(uri);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
@@ -1537,7 +1563,9 @@ public abstract class ContentResolver {
* can acquire a new one if you would like to try to restart the provider
* and perform new operations on it.
*/
- public final ContentProviderClient acquireUnstableContentProviderClient(String name) {
+ public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
+ @NonNull String name) {
+ Preconditions.checkNotNull(name, "name");
IContentProvider provider = acquireUnstableProvider(name);
if (provider != null) {
return new ContentProviderClient(this, provider, false);
@@ -1559,8 +1587,10 @@ public abstract class ContentResolver {
* @param observer The object that receives callbacks when changes occur.
* @see #unregisterContentObserver
*/
- public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
- ContentObserver observer) {
+ public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendents,
+ @NonNull ContentObserver observer) {
+ Preconditions.checkNotNull(uri, "uri");
+ Preconditions.checkNotNull(observer, "observer");
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
}
@@ -1580,7 +1610,8 @@ public abstract class ContentResolver {
* @param observer The previously registered observer that is no longer needed.
* @see #registerContentObserver
*/
- public final void unregisterContentObserver(ContentObserver observer) {
+ public final void unregisterContentObserver(@NonNull ContentObserver observer) {
+ Preconditions.checkNotNull(observer, "observer");
try {
IContentObserver contentObserver = observer.releaseContentObserver();
if (contentObserver != null) {
@@ -1603,7 +1634,7 @@ public abstract class ContentResolver {
* has requested to receive self-change notifications by implementing
* {@link ContentObserver#deliverSelfNotifications()} to return true.
*/
- public void notifyChange(Uri uri, ContentObserver observer) {
+ public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
notifyChange(uri, observer, true /* sync to network */);
}
@@ -1623,7 +1654,9 @@ public abstract class ContentResolver {
* @param syncToNetwork If true, attempt to sync the change to the network.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
- public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+ public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
+ boolean syncToNetwork) {
+ Preconditions.checkNotNull(uri, "uri");
notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
}
@@ -1653,7 +1686,9 @@ public abstract class ContentResolver {
*
* @see #getPersistedUriPermissions()
*/
- public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
+ public void takePersistableUriPermission(@NonNull Uri uri,
+ @Intent.AccessUriMode int modeFlags) {
+ Preconditions.checkNotNull(uri, "uri");
try {
ActivityManagerNative.getDefault().takePersistableUriPermission(
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
@@ -1669,7 +1704,9 @@ public abstract class ContentResolver {
*
* @see #getPersistedUriPermissions()
*/
- public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
+ public void releasePersistableUriPermission(@NonNull Uri uri,
+ @Intent.AccessUriMode int modeFlags) {
+ Preconditions.checkNotNull(uri, "uri");
try {
ActivityManagerNative.getDefault().releasePersistableUriPermission(
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
@@ -1686,7 +1723,7 @@ public abstract class ContentResolver {
* @see #takePersistableUriPermission(Uri, int)
* @see #releasePersistableUriPermission(Uri, int)
*/
- public List<UriPermission> getPersistedUriPermissions() {
+ public @NonNull List<UriPermission> getPersistedUriPermissions() {
try {
return ActivityManagerNative.getDefault()
.getPersistedUriPermissions(mPackageName, true).getList();
@@ -1701,7 +1738,7 @@ public abstract class ContentResolver {
* <em>from</em> the calling app. Only grants taken with
* {@link #takePersistableUriPermission(Uri, int)} are returned.
*/
- public List<UriPermission> getOutgoingPersistedUriPermissions() {
+ public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
try {
return ActivityManagerNative.getDefault()
.getPersistedUriPermissions(mPackageName, false).getList();
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 33c0b87..08c5236 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -254,12 +254,14 @@ public class IntentFilter implements Parcelable {
* HTTP scheme.
*
* @see #addDataScheme(String)
+ * @hide
*/
public static final String SCHEME_HTTP = "http";
/**
* HTTPS scheme.
*
* @see #addDataScheme(String)
+ * @hide
*/
public static final String SCHEME_HTTPS = "https";
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 83b0140..c92c256 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -36,6 +36,7 @@ import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Build;
import android.os.Bundle;
+import android.os.FileUtils;
import android.os.PatternMatcher;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -1194,7 +1195,8 @@ public class PackageParser {
}
}
- private static String validateName(String name, boolean requiresSeparator) {
+ private static String validateName(String name, boolean requireSeparator,
+ boolean requireFilename) {
final int N = name.length();
boolean hasSep = false;
boolean front = true;
@@ -1216,7 +1218,10 @@ public class PackageParser {
}
return "bad character '" + c + "'";
}
- return hasSep || !requiresSeparator
+ if (requireFilename && !FileUtils.isValidExtFilename(name)) {
+ return "Invalid filename";
+ }
+ return hasSep || !requireSeparator
? null : "must have at least one '.' separator";
}
@@ -1240,7 +1245,7 @@ public class PackageParser {
final String packageName = attrs.getAttributeValue(null, "package");
if (!"android".equals(packageName)) {
- final String error = validateName(packageName, true);
+ final String error = validateName(packageName, true, true);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
"Invalid manifest package: " + error);
@@ -1252,7 +1257,7 @@ public class PackageParser {
if (splitName.length() == 0) {
splitName = null;
} else {
- final String error = validateName(splitName, false);
+ final String error = validateName(splitName, false, false);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
"Invalid manifest split: " + error);
@@ -1391,7 +1396,7 @@ public class PackageParser {
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
if (str != null && str.length() > 0) {
- String nameError = validateName(str, true);
+ String nameError = validateName(str, true, false);
if (nameError != null && !"android".equals(pkgName)) {
outError[0] = "<manifest> specifies bad sharedUserId name \""
+ str + "\": " + nameError;
@@ -1973,7 +1978,7 @@ public class PackageParser {
return null;
}
String subName = proc.substring(1);
- String nameError = validateName(subName, false);
+ String nameError = validateName(subName, false, false);
if (nameError != null) {
outError[0] = "Invalid " + type + " name " + proc + " in package "
+ pkg + ": " + nameError;
@@ -1981,7 +1986,7 @@ public class PackageParser {
}
return (pkg + proc).intern();
}
- String nameError = validateName(proc, true);
+ String nameError = validateName(proc, true, false);
if (nameError != null && !"system".equals(proc)) {
outError[0] = "Invalid " + type + " name " + proc + " in package "
+ pkg + ": " + nameError;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ed167f0..8512b23 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -52,6 +52,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -79,7 +80,7 @@ public class CameraDeviceImpl extends CameraDevice {
private volatile StateCallbackKK mSessionStateCallback;
private final Handler mDeviceHandler;
- private volatile boolean mClosing = false;
+ private final AtomicBoolean mClosing = new AtomicBoolean();
private boolean mInError = false;
private boolean mIdle = true;
@@ -906,6 +907,10 @@ public class CameraDeviceImpl extends CameraDevice {
@Override
public void close() {
synchronized (mInterfaceLock) {
+ if (mClosing.getAndSet(true)) {
+ return;
+ }
+
try {
if (mRemoteDevice != null) {
mRemoteDevice.disconnect();
@@ -1917,7 +1922,7 @@ public class CameraDeviceImpl extends CameraDevice {
/** Whether the camera device has started to close (may not yet have finished) */
private boolean isClosed() {
- return mClosing;
+ return mClosing.get();
}
private CameraCharacteristics getCharacteristics() {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index a3a998e..2fb3203 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -85,7 +85,10 @@ public class LegacyCameraDevice implements AutoCloseable {
private static final int GRALLOC_USAGE_HW_RENDER = 0x00000200;
private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000;
- public static final int MAX_DIMEN_FOR_ROUNDING = 1080; // maximum allowed width for rounding
+ public static final int MAX_DIMEN_FOR_ROUNDING = 1920; // maximum allowed width for rounding
+
+ // Keep up to date with values in system/core/include/system/window.h
+ public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1;
private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
if (holder == null) {
@@ -690,6 +693,13 @@ public class LegacyCameraDevice implements AutoCloseable {
LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp));
}
+ static void setScalingMode(Surface surface, int mode)
+ throws BufferQueueAbandonedException {
+ checkNotNull(surface);
+ LegacyExceptionUtils.throwOnError(nativeSetScalingMode(surface, mode));
+ }
+
+
private static native int nativeDetectSurfaceType(Surface surface);
private static native int nativeDetectSurfaceDimens(Surface surface,
@@ -717,5 +727,7 @@ public class LegacyCameraDevice implements AutoCloseable {
private static native int nativeDetectSurfaceUsageFlags(Surface surface);
+ private static native int nativeSetScalingMode(Surface surface, int scalingMode);
+
static native int nativeGetJpegFooterSize();
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 33a802b..8bdd42a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -415,8 +415,9 @@ public class LegacyMetadataMapper {
Range<Integer>[] ranges = new Range[rangesSize];
int i = 0;
for (int[] r : fpsRanges) {
- ranges[i++] = Range.create(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
- r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+ ranges[i++] = Range.create(
+ (int) Math.floor(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] / 1000.0),
+ (int) Math.ceil(r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.0));
}
m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index d5d7f0d..6a44ac5 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -162,17 +162,19 @@ public class LegacyRequestMapper {
if (aeFpsRange != null) {
int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange);
- // TODO - Should we enforce that all HAL1 devices must include (30, 30) FPS range?
- boolean supported = false;
+ int[] rangeToApply = null;
for(int[] range : params.getSupportedPreviewFpsRange()) {
- if (legacyFps[0] == range[0] && legacyFps[1] == range[1]) {
- supported = true;
+ // Round range up/down to integer FPS value
+ int intRangeLow = (int) Math.floor(range[0] / 1000.0) * 1000;
+ int intRangeHigh = (int) Math.ceil(range[1] / 1000.0) * 1000;
+ if (legacyFps[0] == intRangeLow && legacyFps[1] == intRangeHigh) {
+ rangeToApply = range;
break;
}
}
- if (supported) {
- params.setPreviewFpsRange(legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
- legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+ if (rangeToApply != null) {
+ params.setPreviewFpsRange(rangeToApply[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
+ rangeToApply[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
} else {
Log.w(TAG, "Unsupported FPS range set [" + legacyFps[0] + "," + legacyFps[1] + "]");
}
@@ -626,8 +628,8 @@ public class LegacyRequestMapper {
private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) {
int[] legacyFps = new int[2];
- legacyFps[Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower();
- legacyFps[Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper();
+ legacyFps[Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower() * 1000;
+ legacyFps[Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper() * 1000;
return legacyFps;
}
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 5ea1ab8..4866598 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -187,8 +187,18 @@ public class RequestThreadManager {
private final Camera.ErrorCallback mErrorCallback = new Camera.ErrorCallback() {
@Override
public void onError(int i, Camera camera) {
- Log.e(TAG, "Received error " + i + " from the Camera1 ErrorCallback");
- mDeviceState.setError(CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+ switch(i) {
+ case Camera.CAMERA_ERROR_EVICTED: {
+ flush();
+ mDeviceState.setError(
+ CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED);
+ } break;
+ default: {
+ Log.e(TAG, "Received error " + i + " from the Camera1 ErrorCallback");
+ mDeviceState.setError(
+ CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+ } break;
+ }
}
};
@@ -384,6 +394,8 @@ public class RequestThreadManager {
callbackOutputSizes.add(outSize);
break;
default:
+ LegacyCameraDevice.setScalingMode(s, LegacyCameraDevice.
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
mPreviewOutputs.add(s);
previewOutputSizes.add(outSize);
break;
@@ -412,6 +424,9 @@ public class RequestThreadManager {
mParams.setPreviewFpsRange(bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+ Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs,
+ callbackOutputSizes, mParams);
+
if (previewOutputSizes.size() > 0) {
Size largestOutput = SizeAreaComparator.findLargestByArea(previewOutputSizes);
@@ -419,6 +434,9 @@ public class RequestThreadManager {
// Find largest jpeg dimension - assume to have the same aspect ratio as sensor.
Size largestJpegDimen = ParameterUtils.getLargestSupportedJpegSizeByArea(mParams);
+ Size chosenJpegDimen = (smallestSupportedJpegSize != null) ? smallestSupportedJpegSize
+ : largestJpegDimen;
+
List<Size> supportedPreviewSizes = ParameterUtils.convertSizeList(
mParams.getSupportedPreviewSizes());
@@ -430,7 +448,7 @@ public class RequestThreadManager {
for (Size s : supportedPreviewSizes) {
long currArea = s.getWidth() * s.getHeight();
long bestArea = bestPreviewDimen.getWidth() * bestPreviewDimen.getHeight();
- if (checkAspectRatiosMatch(largestJpegDimen, s) && (currArea < bestArea &&
+ if (checkAspectRatiosMatch(chosenJpegDimen, s) && (currArea < bestArea &&
currArea >= largestOutputArea)) {
bestPreviewDimen = s;
}
@@ -451,8 +469,6 @@ public class RequestThreadManager {
}
}
- Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs,
- callbackOutputSizes, mParams);
if (smallestSupportedJpegSize != null) {
/*
* Set takePicture size to the smallest supported JPEG size large enough
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 45f1889..a5490ef 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -400,16 +400,27 @@ public class Keyboard {
public void onPressed() {
pressed = !pressed;
}
-
+
/**
- * Changes the pressed state of the key. If it is a sticky key, it will also change the
- * toggled state of the key if the finger was release inside.
- * @param inside whether the finger was released inside the key
+ * Changes the pressed state of the key.
+ *
+ * <p>Toggled state of the key will be flipped when all the following conditions are
+ * fulfilled:</p>
+ *
+ * <ul>
+ * <li>This is a sticky key, that is, {@link #sticky} is {@code true}.
+ * <li>The parameter {@code inside} is {@code true}.
+ * <li>{@link android.os.Build.VERSION#SDK_INT} is greater than
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
+ * </ul>
+ *
+ * @param inside whether the finger was released inside the key. Works only on Android M and
+ * later. See the method document for details.
* @see #onPressed()
*/
public void onReleased(boolean inside) {
pressed = !pressed;
- if (sticky) {
+ if (sticky && inside) {
on = !on;
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a6efc58..d165240 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1177,8 +1177,13 @@ public abstract class BatteryStats implements Parcelable {
public static final int EVENT_ALARM = 0x000e;
// Record that we have decided we need to collect new stats data.
public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
+ // Event for a package becoming inactive due to being unused for a period of time.
+ public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
+ // Event for a package becoming active due to an interaction.
+ public static final int EVENT_PACKAGE_ACTIVE = 0x0011;
+
// Number of event types.
- public static final int EVENT_COUNT = 0x0010;
+ public static final int EVENT_COUNT = 0x0012;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -1835,12 +1840,12 @@ public abstract class BatteryStats implements Parcelable {
public static final String[] HISTORY_EVENT_NAMES = new String[] {
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
- "motion", "active", "pkginst", "pkgunin", "alarm", "stats"
+ "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
- "Esm", "Eac", "Epi", "Epu", "Eal", "Est"
+ "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
};
/**
@@ -3536,8 +3541,15 @@ public abstract class BatteryStats implements Parcelable {
}
printmAh(pw, bs.totalPowerMah);
- if (bs.drainType == BatterySipper.DrainType.APP) {
+ if (bs.usagePowerMah != bs.totalPowerMah) {
+ // If the usage (generic power) isn't the whole amount, we list out
+ // what components are involved in the calculation.
+
pw.print(" (");
+ if (bs.usagePowerMah != 0) {
+ pw.print(" usage=");
+ printmAh(pw, bs.usagePowerMah);
+ }
if (bs.cpuPowerMah != 0) {
pw.print(" cpu=");
printmAh(pw, bs.cpuPowerMah);
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 917271d..864225a 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -24,6 +24,8 @@ import android.util.Log;
import android.util.Slog;
import android.webkit.MimeTypeMap;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -34,6 +36,7 @@ import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
@@ -456,6 +459,7 @@ public class FileUtils {
res.append('_');
}
}
+ trimFilename(res, 255);
return res.toString();
}
@@ -504,9 +508,31 @@ public class FileUtils {
res.append('_');
}
}
+ // Even though vfat allows 255 UCS-2 chars, we might eventually write to
+ // ext4 through a FUSE layer, so use that limit.
+ trimFilename(res, 255);
+ return res.toString();
+ }
+
+ @VisibleForTesting
+ public static String trimFilename(String str, int maxBytes) {
+ final StringBuilder res = new StringBuilder(str);
+ trimFilename(res, maxBytes);
return res.toString();
}
+ private static void trimFilename(StringBuilder res, int maxBytes) {
+ byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8);
+ if (raw.length > maxBytes) {
+ maxBytes -= 3;
+ while (raw.length > maxBytes) {
+ res.deleteCharAt(res.length() / 2);
+ raw = res.toString().getBytes(StandardCharsets.UTF_8);
+ }
+ res.insert(res.length() / 2, "...");
+ }
+ }
+
public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
if (path == null) return null;
final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 1c9c713..135f369 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -621,6 +621,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
final int fd = getFd();
Parcel.clearFileDescriptor(mFd);
writeCommStatusAndClose(Status.DETACHED, null);
+ mClosed = true;
+ mGuard.close();
+ releaseResources();
return fd;
}
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8b18f32..7a1aa1e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -878,7 +878,10 @@ public final class PowerManager {
* off network access to apps. You can monitor for changes to this state with
* {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}.
*
- * @return Returns true if currently in low power mode, else false.
+ * @return Returns true if currently in active device idle mode, else false. This is
+ * when idle mode restrictions are being actively applied; it will return false if the
+ * device is in a long-term idle mode but currently running a maintenance window where
+ * restrictions have been lifted.
*/
public boolean isDeviceIdleMode() {
try {
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 04e54aa..397d87e 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -40,6 +40,8 @@ public class DiskInfo implements Parcelable {
"android.os.storage.action.DISK_SCANNED";
public static final String EXTRA_DISK_ID =
"android.os.storage.extra.DISK_ID";
+ public static final String EXTRA_VOLUME_COUNT =
+ "android.os.storage.extra.VOLUME_COUNT";
public static final int FLAG_ADOPTABLE = 1 << 0;
public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
@@ -80,6 +82,12 @@ public class DiskInfo implements Parcelable {
if (label.toLowerCase().contains("generic")) {
return false;
}
+ if (label.toLowerCase().startsWith("usb")) {
+ return false;
+ }
+ if (label.toLowerCase().startsWith("multiple")) {
+ return false;
+ }
return true;
}
diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java
index c958fb0..cade9d7 100644
--- a/core/java/android/os/storage/IMountServiceListener.java
+++ b/core/java/android/os/storage/IMountServiceListener.java
@@ -113,6 +113,13 @@ public interface IMountServiceListener extends IInterface {
reply.writeNoException();
return true;
}
+ case TRANSACTION_onDiskDestroyed: {
+ data.enforceInterface(DESCRIPTOR);
+ final DiskInfo disk = (DiskInfo) data.readParcelable(null);
+ onDiskDestroyed(disk);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -246,6 +253,22 @@ public interface IMountServiceListener extends IInterface {
_data.recycle();
}
}
+
+ @Override
+ public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeParcelable(disk, 0);
+ mRemote.transact(Stub.TRANSACTION_onDiskDestroyed, _data, _reply,
+ android.os.IBinder.FLAG_ONEWAY);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
}
static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0);
@@ -254,6 +277,7 @@ public interface IMountServiceListener extends IInterface {
static final int TRANSACTION_onVolumeRecordChanged = (IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_onVolumeForgotten = (IBinder.FIRST_CALL_TRANSACTION + 4);
static final int TRANSACTION_onDiskScanned = (IBinder.FIRST_CALL_TRANSACTION + 5);
+ static final int TRANSACTION_onDiskDestroyed = (IBinder.FIRST_CALL_TRANSACTION + 6);
}
/**
@@ -280,4 +304,6 @@ public interface IMountServiceListener extends IInterface {
public void onVolumeForgotten(String fsUuid) throws RemoteException;
public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException;
+
+ public void onDiskDestroyed(DiskInfo disk) throws RemoteException;
}
diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java
index 214c60d..4cf83fd 100644
--- a/core/java/android/os/storage/StorageEventListener.java
+++ b/core/java/android/os/storage/StorageEventListener.java
@@ -49,4 +49,7 @@ public class StorageEventListener {
public void onDiskScanned(DiskInfo disk, int volumeCount) {
}
+
+ public void onDiskDestroyed(DiskInfo disk) {
+ }
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 4bbaaa1..9b26f24 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -101,6 +101,7 @@ public class StorageManager {
private static final int MSG_VOLUME_RECORD_CHANGED = 3;
private static final int MSG_VOLUME_FORGOTTEN = 4;
private static final int MSG_DISK_SCANNED = 5;
+ private static final int MSG_DISK_DESTROYED = 6;
final StorageEventListener mCallback;
final Handler mHandler;
@@ -135,6 +136,10 @@ public class StorageManager {
mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
args.recycle();
return true;
+ case MSG_DISK_DESTROYED:
+ mCallback.onDiskDestroyed((DiskInfo) args.arg1);
+ args.recycle();
+ return true;
}
args.recycle();
return false;
@@ -184,6 +189,13 @@ public class StorageManager {
args.argi2 = volumeCount;
mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
}
+
+ @Override
+ public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
+ final SomeArgs args = SomeArgs.obtain();
+ args.arg1 = disk;
+ mHandler.obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
+ }
}
/**
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 372725f..8d11527 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -55,6 +55,8 @@ public class VolumeInfo implements Parcelable {
"android.os.storage.action.VOLUME_STATE_CHANGED";
public static final String EXTRA_VOLUME_ID =
"android.os.storage.extra.VOLUME_ID";
+ public static final String EXTRA_VOLUME_STATE =
+ "android.os.storage.extra.VOLUME_STATE";
/** Stub volume representing internal private storage */
public static final String ID_PRIVATE_INTERNAL = "private";
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d9c412b..aebe7f1 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8931,157 +8931,4 @@ public final class ContactsContract {
public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
}
}
-
- /**
- * @hide
- */
- protected interface MetadataSyncColumns {
-
- /**
- * The raw contact backup id.
- * A reference to the {@link ContactsContract.RawContacts#BACKUP_ID} that save the
- * persistent unique id for each raw contact within its source system.
- *
- * @hide
- */
- public static final String RAW_CONTACT_BACKUP_ID = "raw_contact_backup_id";
-
- /**
- * The account type to which the raw_contact of this item is associated. See
- * {@link RawContacts#ACCOUNT_TYPE}
- *
- * @hide
- */
- public static final String ACCOUNT_TYPE = "account_type";
-
- /**
- * The account name to which the raw_contact of this item is associated. See
- * {@link RawContacts#ACCOUNT_NAME}
- *
- * @hide
- */
- public static final String ACCOUNT_NAME = "account_name";
-
- /**
- * The data set within the account that the raw_contact of this row belongs to. This allows
- * multiple sync adapters for the same account type to distinguish between
- * each others' data.
- * {@link RawContacts#DATA_SET}
- *
- * @hide
- */
- public static final String DATA_SET = "data_set";
-
- /**
- * A text column contains the Json string got from People API. The Json string contains
- * all the metadata related to the raw contact, i.e., all the data fields and
- * aggregation exceptions.
- *
- * Here is an example of the Json string got from the actual schema.
- * <pre>
- * {
- * "unique_contact_id": {
- * "account_type": "CUSTOM_ACCOUNT",
- * "custom_account_type": "facebook",
- * "account_name": "android-test",
- * "contact_id": "1111111",
- * "data_set": "FOCUS"
- * },
- * "contact_prefs": {
- * "send_to_voicemail": true,
- * "starred": false,
- * "pinned": 2
- * },
- * "aggregation_data": [
- * {
- * "type": "TOGETHER",
- * "contact_ids": [
- * {
- * "account_type": "GOOGLE_ACCOUNT",
- * "account_name": "android-test2",
- * "contact_id": "2222222",
- * "data_set": "GOOGLE_PLUS"
- * },
- * {
- * "account_type": "GOOGLE_ACCOUNT",
- * "account_name": "android-test3",
- * "contact_id": "3333333",
- * "data_set": "CUSTOM",
- * "custom_data_set": "custom type"
- * }
- * ]
- * }
- * ],
- * "field_data": [
- * {
- * "field_data_id": "1001",
- * "field_data_prefs": {
- * "is_primary": true,
- * "is_super_primary": true
- * },
- * "usage_stats": [
- * {
- * "usage_type": "CALL",
- * "last_time_used": 10000001,
- * "usage_count": 10
- * }
- * ]
- * }
- * ]
- * }
- * </pre>
- *
- * @hide
- */
- public static final String DATA = "data";
-
- /**
- * The "deleted" flag: "0" by default, "1" if the row has been marked
- * for deletion. When {@link android.content.ContentResolver#delete} is
- * called on a raw contact, updating MetadataSync table to set the flag of the raw contact
- * as "1", then metadata sync adapter deletes the raw contact metadata on the server.
- * <P>Type: INTEGER</P>
- *
- * @hide
- */
- public static final String DELETED = "deleted";
- }
-
- /**
- * Constants for the metadata sync table. This table is used to cache the metadata_sync data
- * from server before it is merged into other CP2 tables.
- *
- * @hide
- */
- public static final class MetadataSync implements BaseColumns, MetadataSyncColumns {
-
- /** The authority for the contacts metadata */
- public static final String METADATA_AUTHORITY = "com.android.contacts.metadata";
-
- /** A content:// style uri to the authority for the contacts metadata */
- public static final Uri METADATA_AUTHORITY_URI = Uri.parse(
- "content://" + METADATA_AUTHORITY);
-
- /**
- * This utility class cannot be instantiated
- */
- private MetadataSync() {
- }
-
- /**
- * The content:// style URI for this table.
- */
- public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI,
- "metadata_sync");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
- }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 167d8e5..e335f6d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5551,13 +5551,6 @@ public final class Settings {
public static final String SLEEP_TIMEOUT = "sleep_timeout";
/**
- * Duration in milliseconds that an app should be inactive before it is considered idle.
- * <p/>Type: Long
- * @hide
- */
- public static final String APP_IDLE_DURATION = "app_idle_duration";
-
- /**
* Controls whether double tap to wake is enabled.
* @hide
*/
@@ -7087,6 +7080,58 @@ public final class Settings {
BLUETOOTH_SAP_PRIORITY_PREFIX = "bluetooth_sap_priority_";
/**
+ * Device Idle (Doze) specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "inactive_timeout=60000,sensing_timeout=400000"
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * inactive_to (long)
+ * sensing_to (long)
+ * motion_inactive_to (long)
+ * idle_after_inactive_to (long)
+ * idle_pending_to (long)
+ * max_idle_pending_to (long)
+ * idle_pending_factor (float)
+ * idle_to (long)
+ * max_idle_to (long)
+ * idle_factor (float)
+ * min_time_to_alarm (long)
+ * max_temp_app_whitelist_duration (long)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * @see com.android.server.DeviceIdleController.Constants
+ */
+ public static final String DEVICE_IDLE_CONSTANTS = "device_idle_constants";
+
+ /**
+ * App standby (app idle) specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "idle_duration=5000,parole_interval=4500"
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * idle_duration (long)
+ * wallclock_threshold (long)
+ * parole_interval (long)
+ * parole_duration (long)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * @see com.android.server.usage.UsageStatsService.SettingsObserver
+ */
+ public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index 9eb22ef..890ea3d 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -61,16 +61,16 @@ public abstract class UtteranceProgressListener {
/**
* Called when an utterance has been stopped while in progress or flushed from the
- * synthesis queue. This can happen if client calls {@link TextToSpeech#stop()}
- * or use {@link TextToSpeech#QUEUE_FLUSH} as an argument in
+ * synthesis queue. This can happen if a client calls {@link TextToSpeech#stop()}
+ * or uses {@link TextToSpeech#QUEUE_FLUSH} as an argument with the
* {@link TextToSpeech#speak} or {@link TextToSpeech#synthesizeToFile} methods.
*
* @param utteranceId the utterance ID of the utterance.
- * @param isStarted If true, then utterance was interrupted while being synthesized
- * and it's output is incomplete. If it's false, then utterance was flushed
+ * @param interrupted If true, then the utterance was interrupted while being synthesized
+ * and its output is incomplete. If false, then the utterance was flushed
* before the synthesis started.
*/
- public void onStop(String utteranceId, boolean isStarted) {
+ public void onStop(String utteranceId, boolean interrupted) {
}
/**
@@ -99,7 +99,7 @@ public abstract class UtteranceProgressListener {
}
@Override
- public void onStop(String utteranceId, boolean isStarted) {
+ public void onStop(String utteranceId, boolean interrupted) {
listener.onUtteranceCompleted(utteranceId);
}
};
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6c4d8fd..d51aa79 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1790,6 +1790,15 @@ public class TextUtils {
}
}
+ /**
+ * Return localized string representing the given number of selected items.
+ *
+ * @hide
+ */
+ public static CharSequence formatSelectedCount(int count) {
+ return Resources.getSystem().getQuantityString(R.plurals.selected_count, count, count);
+ }
+
private static Object sLock = new Object();
private static char[] sTemp = null;
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 6ed3885..4ee9807 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -266,7 +266,7 @@ public final class ArrayMap<K, V> implements Map<K, V> {
/**
* Create a new ArrayMap with the mappings from the given ArrayMap.
*/
- public ArrayMap(ArrayMap map) {
+ public ArrayMap(ArrayMap<K, V> map) {
this();
if (map != null) {
putAll(map);
@@ -843,7 +843,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
* in the array map.
*
* <p><b>Note:</b> this is a very inefficient way to access the array contents, it
- * requires generating a number of temporary objects.</p>
+ * requires generating a number of temporary objects and allocates additional state
+ * information associated with the container that will remain for the life of the container.</p>
*
* <p><b>Note:</b></p> the semantics of this
* Set are subtly different than that of a {@link java.util.HashMap}: most important,
@@ -861,7 +862,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
* in the array map.
*
* <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
- * requires generating a number of temporary objects.</p>
+ * requires generating a number of temporary objects and allocates additional state
+ * information associated with the container that will remain for the life of the container.</p>
*/
@Override
public Set<K> keySet() {
@@ -873,7 +875,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
* in the array map.
*
* <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
- * requires generating a number of temporary objects.</p>
+ * requires generating a number of temporary objects and allocates additional state
+ * information associated with the container that will remain for the life of the container.</p>
*/
@Override
public Collection<V> values() {
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 7da3941..b7a3c42 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -42,8 +42,6 @@ import java.util.Set;
* you have no control over this shrinking -- if you set a capacity and then remove an
* item, it may reduce the capacity to better match the current size. In the future an
* explicit call to set the capacity should turn off this aggressive shrinking behavior.</p>
- *
- * @hide
*/
public final class ArraySet<E> implements Collection<E>, Set<E> {
private static final boolean DEBUG = false;
@@ -660,11 +658,24 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
return mCollections;
}
+ /**
+ * Return an {@link java.util.Iterator} over all values in the set.
+ *
+ * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it
+ * requires generating a number of temporary objects and allocates additional state
+ * information associated with the container that will remain for the life of the container.</p>
+ */
@Override
public Iterator<E> iterator() {
return getCollection().getKeySet().iterator();
}
+ /**
+ * Determine if the array set contains all of the values in the given collection.
+ * @param collection The collection whose contents are to be checked against.
+ * @return Returns true if this array set contains a value for every entry
+ * in <var>collection</var>, else returns false.
+ */
@Override
public boolean containsAll(Collection<?> collection) {
Iterator<?> it = collection.iterator();
@@ -676,6 +687,10 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
return true;
}
+ /**
+ * Perform an {@link #add(Object)} of all values in <var>collection</var>
+ * @param collection The collection whose contents are to be retrieved.
+ */
@Override
public boolean addAll(Collection<? extends E> collection) {
ensureCapacity(mSize + collection.size());
@@ -686,6 +701,11 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
return added;
}
+ /**
+ * Remove all values in the array set that exist in the given collection.
+ * @param collection The collection whose contents are to be used to remove values.
+ * @return Returns true if any values were removed from the array set, else false.
+ */
@Override
public boolean removeAll(Collection<?> collection) {
boolean removed = false;
@@ -695,6 +715,12 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
return removed;
}
+ /**
+ * Remove all values in the array set that do <b>not</b> exist in the given collection.
+ * @param collection The collection whose contents are to be used to determine which
+ * values to keep.
+ * @return Returns true if any values were removed from the array set, else false.
+ */
@Override
public boolean retainAll(Collection<?> collection) {
boolean removed = false;
diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java
new file mode 100644
index 0000000..4abdde0
--- /dev/null
+++ b/core/java/android/util/KeyValueListParser.java
@@ -0,0 +1,114 @@
+/*
+ * 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 android.util;
+
+import android.text.TextUtils;
+
+/**
+ * Parses a list of key=value pairs, separated by some delimiter, and puts the results in
+ * an internal Map. Values can be then queried by key, or if not found, a default value
+ * can be used.
+ * @hide
+ */
+public class KeyValueListParser {
+ private final ArrayMap<String, String> mValues = new ArrayMap<>();
+ private final TextUtils.StringSplitter mSplitter;
+
+ /**
+ * Constructs a new KeyValueListParser. This can be reused for different strings
+ * by calling {@link #setString(String)}.
+ * @param delim The delimiter that separates key=value pairs.
+ */
+ public KeyValueListParser(char delim) {
+ mSplitter = new TextUtils.SimpleStringSplitter(delim);
+ }
+
+ /**
+ * Resets the parser with a new string to parse. The string is expected to be in the following
+ * format:
+ * <pre>key1=value,key2=value,key3=value</pre>
+ *
+ * where the delimiter is a comma.
+ *
+ * @param str the string to parse.
+ * @throws IllegalArgumentException if the string is malformed.
+ */
+ public void setString(String str) throws IllegalArgumentException {
+ mValues.clear();
+ if (str != null) {
+ mSplitter.setString(str);
+ for (String pair : mSplitter) {
+ int sep = pair.indexOf('=');
+ if (sep < 0) {
+ mValues.clear();
+ throw new IllegalArgumentException(
+ "'" + pair + "' in '" + str + "' is not a valid key-value pair");
+ }
+ mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim());
+ }
+ }
+ }
+
+ /**
+ * Get the value for key as a long.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found, or the value was not a long.
+ * @return the long value associated with the key.
+ */
+ public long getLong(String key, long def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ // fallthrough
+ }
+ }
+ return def;
+ }
+
+ /**
+ * Get the value for key as a float.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found, or the value was not a float.
+ * @return the float value associated with the key.
+ */
+ public float getFloat(String key, float def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ try {
+ return Float.parseFloat(value);
+ } catch (NumberFormatException e) {
+ // fallthrough
+ }
+ }
+ return def;
+ }
+
+ /**
+ * Get the value for key as a string.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found.
+ * @return the string value associated with the key.
+ */
+ public String getString(String key, String def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ return value;
+ }
+ return def;
+ }
+}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index f7d2821..353388d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -246,41 +246,65 @@ public class TimeUtils {
public static final long NANOS_PER_MS = 1000000;
private static final Object sFormatSync = new Object();
- private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
-
- private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1;
+ private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
+ private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
static private int accumField(int amt, int suffix, boolean always, int zeropad) {
- if (amt > 99 || (always && zeropad >= 3)) {
- return 3+suffix;
- }
- if (amt > 9 || (always && zeropad >= 2)) {
- return 2+suffix;
- }
- if (always || amt > 0) {
- return 1+suffix;
+ if (amt > 999) {
+ int num = 0;
+ while (amt != 0) {
+ num++;
+ amt /= 10;
+ }
+ return num + suffix;
+ } else {
+ if (amt > 99 || (always && zeropad >= 3)) {
+ return 3+suffix;
+ }
+ if (amt > 9 || (always && zeropad >= 2)) {
+ return 2+suffix;
+ }
+ if (always || amt > 0) {
+ return 1+suffix;
+ }
}
return 0;
}
- static private int printField(char[] formatStr, int amt, char suffix, int pos,
+ static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
boolean always, int zeropad) {
if (always || amt > 0) {
final int startPos = pos;
- if ((always && zeropad >= 3) || amt > 99) {
- int dig = amt/100;
- formatStr[pos] = (char)(dig + '0');
- pos++;
- amt -= (dig*100);
- }
- if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
- int dig = amt/10;
- formatStr[pos] = (char)(dig + '0');
+ if (amt > 999) {
+ int tmp = 0;
+ while (amt != 0 && tmp < sTmpFormatStr.length) {
+ int dig = amt % 10;
+ sTmpFormatStr[tmp] = (char)(dig + '0');
+ tmp++;
+ amt /= 10;
+ }
+ tmp--;
+ while (tmp >= 0) {
+ formatStr[pos] = sTmpFormatStr[tmp];
+ pos++;
+ tmp--;
+ }
+ } else {
+ if ((always && zeropad >= 3) || amt > 99) {
+ int dig = amt/100;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*100);
+ }
+ if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
+ int dig = amt/10;
+ formatStr[pos] = (char)(dig + '0');
+ pos++;
+ amt -= (dig*10);
+ }
+ formatStr[pos] = (char)(amt + '0');
pos++;
- amt -= (dig*10);
}
- formatStr[pos] = (char)(amt + '0');
- pos++;
formatStr[pos] = suffix;
pos++;
}
@@ -312,10 +336,6 @@ public class TimeUtils {
duration = -duration;
}
- if (duration > LARGEST_DURATION) {
- duration = LARGEST_DURATION;
- }
-
int millis = (int)(duration%1000);
int seconds = (int) Math.floor(duration / 1000);
int days = 0, hours = 0, minutes = 0;
@@ -353,11 +373,11 @@ public class TimeUtils {
int start = pos;
boolean zeropad = fieldLen != 0;
- pos = printField(formatStr, days, 'd', pos, false, 0);
- pos = printField(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
- pos = printField(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
+ pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
+ pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
+ pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
formatStr[pos] = 's';
return pos + 1;
}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index d2b6533..a865307 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -22,6 +22,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.Trace;
import android.util.Log;
import android.util.TimeUtils;
@@ -160,6 +161,14 @@ public final class Choreographer {
FrameInfo mFrameInfo = new FrameInfo();
/**
+ * Must be kept in sync with CALLBACK_* ints below, used to index into this array.
+ * @hide
+ */
+ private static final String[] CALLBACK_TRACE_TITLES = {
+ "input", "animation", "traversal", "commit"
+ };
+
+ /**
* Callback type: Input callback. Runs first.
* @hide
*/
@@ -584,16 +593,22 @@ public final class Choreographer {
mLastFrameTimeNanos = frameTimeNanos;
}
- mFrameInfo.markInputHandlingStart();
- doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
+
+ mFrameInfo.markInputHandlingStart();
+ doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
- mFrameInfo.markAnimationsStart();
- doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
+ mFrameInfo.markAnimationsStart();
+ doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
- mFrameInfo.markPerformTraversalsStart();
- doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
+ mFrameInfo.markPerformTraversalsStart();
+ doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
- doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
+ doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
if (DEBUG_FRAMES) {
final long endNanos = System.nanoTime();
@@ -627,6 +642,7 @@ public final class Choreographer {
// safe by ensuring the commit time is always at least one frame behind.
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
+ Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
if (jitterNanos >= 2 * mFrameIntervalNanos) {
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
+ mFrameIntervalNanos;
@@ -644,6 +660,7 @@ public final class Choreographer {
}
}
try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
@@ -661,6 +678,7 @@ public final class Choreographer {
callbacks = next;
} while (callbacks != null);
}
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index be372d0..0df8ea9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -741,6 +741,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private static boolean sUseBrokenMakeMeasureSpec = false;
/**
+ * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
+ */
+ static boolean sUseZeroUnspecifiedMeasureSpec = false;
+
+ /**
* Ignore any optimizations using the measure cache.
*/
private static boolean sIgnoreMeasureCache = false;
@@ -3796,6 +3801,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
+ // In MNC and newer, our widgets can pass a "hint" value in the size
+ // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
+ // know what the expected parent size is going to be, so e.g. list items can size
+ // themselves at 1/3 the size of their container. It breaks older apps though,
+ // specifically apps that use some popular open source libraries.
+ sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < MNC;
+
sCompatibilityDone = true;
}
}
@@ -17163,21 +17175,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * If the view has a ColorDrawable background, returns the color of that
- * drawable.
- *
- * @return The color of the ColorDrawable background, if set, otherwise 0.
- * @hide
- */
- @ColorInt
- public int getBackgroundColor() {
- if (mBackground instanceof ColorDrawable) {
- return ((ColorDrawable) mBackground).getColor();
- }
- return 0;
- }
-
- /**
* Set the background to a given resource. The resource should refer to
* a Drawable object or 0 to remove the background.
* @param resid The identifier of the resource.
@@ -21032,6 +21029,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
+ * will automatically get a size of 0. Older apps expect this.
+ *
+ * @hide internal use only for compatibility with system widgets and older apps
+ */
+ public static int makeSafeMeasureSpec(int size, int mode) {
+ if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
+ return 0;
+ }
+ return makeMeasureSpec(size, mode);
+ }
+
+ /**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index dd32f85..89743e5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5963,12 +5963,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
- resultSize = size;
+ resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
- resultSize = size;
+ resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e1e0154..8b57d96 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -663,6 +663,10 @@ public final class ViewRootImpl implements ViewParent,
return mWindowAttributes.flags;
}
+ public int getDisplayId() {
+ return mDisplay.getDisplayId();
+ }
+
public CharSequence getTitle() {
return mWindowAttributes.getTitle();
}
@@ -1105,12 +1109,7 @@ public final class ViewRootImpl implements ViewParent,
Debug.startMethodTracing("ViewAncestor");
}
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
- try {
- performTraversals();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
+ performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 8ceb166..d06cd83 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -201,6 +201,17 @@ public abstract class ViewStructure {
public abstract void setChildCount(int num);
/**
+ * Add to this view's child count. This increases the current child count by
+ * <var>num</var> children beyond what was last set by {@link #setChildCount}
+ * or {@link #addChildCount}. The index at which the new child starts in the child
+ * array is returned.
+ *
+ * @param num The number of new children to add.
+ * @return Returns the index in the child array at which the new children start.
+ */
+ public abstract int addChildCount(int num);
+
+ /**
* Return the child count as set by {@link #setChildCount}.
*/
public abstract int getChildCount();
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index b7d529e..b4ef58a 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -333,8 +333,8 @@ public final class WebViewFactory {
newVmSize = Math.max(newVmSize, f.length());
continue;
}
- if (path.contains("!")) {
- String[] split = TextUtils.split(path, "!");
+ if (path.contains("!/")) {
+ String[] split = TextUtils.split(path, "!/");
if (split.length == 2) {
try {
ZipFile z = new ZipFile(split[0]);
@@ -384,7 +384,7 @@ public final class WebViewFactory {
ZipEntry e = z.getEntry(entry);
if (e != null && e.getMethod() == ZipEntry.STORED) {
// Return a path formatted for dlopen() load from APK.
- return apkPath + "!" + entry;
+ return apkPath + "!/" + entry;
}
}
} catch (IOException e) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index e43237a..cf6a018 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1162,6 +1162,10 @@ public class Editor {
// We do not hide the span controllers, since they can be added when a new text is
// inserted into the text view (voice IME).
hideCursorControllers();
+ // Reset drag accelerator.
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.resetTouchOffsets();
+ }
stopTextActionMode();
}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index f06f3c2..11d7026 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -662,7 +662,7 @@ class FastScroller {
final int adjMaxWidth = maxWidth - marginLeft - marginRight;
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+ final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
MeasureSpec.UNSPECIFIED);
view.measure(widthMeasureSpec, heightMeasureSpec);
@@ -702,7 +702,7 @@ class FastScroller {
final int containerWidth = container.width();
final int adjMaxWidth = containerWidth - marginLeft - marginRight;
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+ final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
MeasureSpec.UNSPECIFIED);
preview.measure(widthMeasureSpec, heightMeasureSpec);
@@ -768,7 +768,7 @@ class FastScroller {
final Rect container = mContainerRect;
final int maxWidth = container.width();
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+ final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
MeasureSpec.UNSPECIFIED);
track.measure(widthMeasureSpec, heightMeasureSpec);
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index dcaafa5..f994d4a 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1073,7 +1073,7 @@ public class GridView extends AbsListView {
p.forceAdd = true;
int childHeightSpec = getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
+ MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
MeasureSpec.UNSPECIFIED), 0, p.height);
int childWidthSpec = getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 9d14254..056323d 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1062,9 +1062,9 @@ public class LinearLayout extends ViewGroup {
// use as much space as it wants because we can shrink things
// later (and re-measure).
if (baselineAligned) {
- final int freeWidthSpec = MeasureSpec.makeMeasureSpec(
+ final int freeWidthSpec = MeasureSpec.makeSafeMeasureSpec(
MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.UNSPECIFIED);
- final int freeHeightSpec = MeasureSpec.makeMeasureSpec(
+ final int freeHeightSpec = MeasureSpec.makeSafeMeasureSpec(
MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED);
child.measure(freeWidthSpec, freeHeightSpec);
} else {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index f8b965f..fd0395a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1206,7 +1206,7 @@ public class ListView extends AbsListView {
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
+ childHeightSpec = MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
@@ -1943,7 +1943,7 @@ public class ListView extends AbsListView {
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+ childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
@@ -2698,7 +2698,7 @@ public class ListView extends AbsListView {
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+ childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 11904e1..58a94b9 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1263,7 +1263,7 @@ public class ScrollView extends FrameLayout {
childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft
+ mPaddingRight, lp.width);
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -1277,7 +1277,7 @@ public class ScrollView extends FrameLayout {
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
- final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 6fe34dd..fdabe91 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -812,9 +812,9 @@ public class Spinner extends AbsSpinner implements OnClickListener {
View itemView = null;
int itemType = 0;
final int widthMeasureSpec =
- MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
+ MeasureSpec.makeSafeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec =
- MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
+ MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
// Make sure the number of items we'll measure is capped. If it's a huge data set
// with wildly varying sizes, oh well.
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index aa7168c..d9cff4e 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -174,7 +174,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
// First, measure with no constraint
final int width = MeasureSpec.getSize(widthMeasureSpec);
- final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
+ final int unspecifiedWidth = MeasureSpec.makeSafeMeasureSpec(width,
+ MeasureSpec.UNSPECIFIED);
mImposedTabsHeight = -1;
super.measureHorizontal(unspecifiedWidth, heightMeasureSpec);
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index d4288d6..f7f9c91 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -303,7 +303,7 @@ public class TableRow extends LinearLayout {
spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT);
break;
case LayoutParams.MATCH_PARENT:
- spec = MeasureSpec.makeMeasureSpec(
+ spec = MeasureSpec.makeSafeMeasureSpec(
MeasureSpec.getSize(heightMeasureSpec),
MeasureSpec.UNSPECIFIED);
break;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 353901c..78b5d5d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8790,7 +8790,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void onProvideStructure(ViewStructure structure) {
super.onProvideStructure(structure);
- final boolean isPassword = hasPasswordTransformationMethod();
+ final boolean isPassword = hasPasswordTransformationMethod()
+ || isPasswordInputType(getInputType());
if (!isPassword) {
structure.setText(getText(), getSelectionStart(), getSelectionEnd());
@@ -9244,25 +9245,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* If provided, this ActionMode.Callback will be used to create the ActionMode when text
* insertion is initiated in this View.
- *
* The standard implementation populates the menu with a subset of Select All,
* Paste and Replace actions, depending on what this View supports.
*
- * A custom implementation can add new entries in the default menu in its
- * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
- * default actions can also be removed from the menu using
+ * <p>A custom implementation can add new entries in the default menu in its
+ * {@link android.view.ActionMode.Callback#onPrepareActionMode(android.view.ActionMode,
+ * android.view.Menu)} method. The default actions can also be removed from the menu using
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
- * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.
+ * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.</p>
*
- * Returning false from
- * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
- * the action mode from being started.
+ * <p>Returning false from
+ * {@link android.view.ActionMode.Callback#onCreateActionMode(android.view.ActionMode,
+ * android.view.Menu)} will prevent the action mode from being started.</p>
*
- * Action click events should be handled by the custom implementation of
- * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
+ * <p>Action click events should be handled by the custom implementation of
+ * {@link android.view.ActionMode.Callback#onActionItemClicked(android.view.ActionMode,
+ * android.view.MenuItem)}.</p>
*
- * Note that text insertion mode is not started when a TextView receives focus and the
- * {@link android.R.attr#selectAllOnFocus} flag has been set.
+ * <p>Note that text insertion mode is not started when a TextView receives focus and the
+ * {@link android.R.attr#selectAllOnFocus} flag has been set.</p>
*/
public void setCustomInsertionActionModeCallback(ActionMode.Callback actionModeCallback) {
createEditorIfNeeded();
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 42668f1..585cdf1 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -45,7 +45,7 @@ import java.util.Map;
class ResolverComparator implements Comparator<ResolvedComponentInfo> {
private static final String TAG = "ResolverComparator";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
// Two weeks
private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 7ae7d0f..05cfd81 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -47,7 +47,6 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.ActionMode;
-import android.view.ActionMode.Callback;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -106,6 +105,10 @@ public class WindowDecorActionBar extends ActionBar implements
private static final int INVALID_POSITION = -1;
+ // The fade duration for toolbar and action bar when entering/exiting action mode.
+ private static final long FADE_OUT_DURATION_MS = 100;
+ private static final long FADE_IN_DURATION_MS = 200;
+
private int mContextDisplayMode;
private boolean mHasEmbeddedTabs;
@@ -866,8 +869,21 @@ public class WindowDecorActionBar extends ActionBar implements
hideForActionMode();
}
- mDecorToolbar.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
- mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+ Animator fadeIn, fadeOut;
+ if (toActionMode) {
+ fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.GONE,
+ FADE_OUT_DURATION_MS);
+ fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
+ FADE_IN_DURATION_MS);
+ } else {
+ fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
+ FADE_IN_DURATION_MS);
+ fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
+ FADE_OUT_DURATION_MS);
+ }
+ AnimatorSet set = new AnimatorSet();
+ set.playSequentially(fadeOut, fadeIn);
+ set.start();
// mTabScrollView's visibility is not affected by action mode.
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 4290e22..6a85afb 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -587,6 +587,7 @@ public final class BatteryStatsHelper {
bs.add(wbs);
}
bs.computeMobilemspp();
+ bs.sumPower();
}
private void addIdleUsage() {
@@ -612,9 +613,8 @@ public final class BatteryStatsHelper {
private void addWiFiUsage() {
BatterySipper bs = new BatterySipper(DrainType.WIFI, null, 0);
mWifiPowerCalculator.calculateRemaining(bs, mStats, mRawRealtime, mRawUptime, mStatsType);
- bs.sumPower();
- if (bs.totalPowerMah > 0 || !mWifiSippers.isEmpty()) {
- aggregateSippers(bs, mWifiSippers, "WIFI");
+ aggregateSippers(bs, mWifiSippers, "WIFI");
+ if (bs.totalPowerMah > 0) {
mUsageList.add(bs);
}
}
@@ -627,8 +627,8 @@ public final class BatteryStatsHelper {
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
mBluetoothPowerCalculator.calculateRemaining(bs, mStats, mRawRealtime, mRawUptime,
mStatsType);
- if (bs.sumPower() > 0) {
- aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
+ aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
+ if (bs.totalPowerMah > 0) {
mUsageList.add(bs);
}
}
@@ -639,7 +639,6 @@ public final class BatteryStatsHelper {
BatterySipper bs = new BatterySipper(DrainType.USER, null, 0);
bs.userId = userId;
aggregateSippers(bs, mUserSippers.valueAt(i), "User");
- bs.sumPower();
mUsageList.add(bs);
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 087db78..07d1fc8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4634,7 +4634,7 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override
public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
int bin = 0;
- while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) {
+ while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) {
csph = csph >> 3;
bin++;
}
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 850ea23..35eeca7 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -136,10 +136,11 @@ public abstract class AbsActionBarView extends ViewGroup {
return getVisibility();
}
- public void animateToVisibility(int visibility) {
+ public Animator setupAnimatorToVisibility(int visibility, long duration) {
if (mVisibilityAnim != null) {
mVisibilityAnim.cancel();
}
+
if (visibility == VISIBLE) {
if (getVisibility() != VISIBLE) {
setAlpha(0);
@@ -147,38 +148,43 @@ public abstract class AbsActionBarView extends ViewGroup {
mMenuView.setAlpha(0);
}
}
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
- anim.setDuration(FADE_DURATION);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 1);
+ anim.setDuration(duration);
anim.setInterpolator(sAlphaInterpolator);
if (mSplitView != null && mMenuView != null) {
AnimatorSet set = new AnimatorSet();
- ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
- splitAnim.setDuration(FADE_DURATION);
+ ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 1);
+ splitAnim.setDuration(duration);
set.addListener(mVisAnimListener.withFinalVisibility(visibility));
set.play(anim).with(splitAnim);
- set.start();
+ return set;
} else {
anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
- anim.start();
+ return anim;
}
} else {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
- anim.setDuration(FADE_DURATION);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 0);
+ anim.setDuration(duration);
anim.setInterpolator(sAlphaInterpolator);
if (mSplitView != null && mMenuView != null) {
AnimatorSet set = new AnimatorSet();
- ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
- splitAnim.setDuration(FADE_DURATION);
+ ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 0);
+ splitAnim.setDuration(duration);
set.addListener(mVisAnimListener.withFinalVisibility(visibility));
set.play(anim).with(splitAnim);
- set.start();
+ return set;
} else {
anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
- anim.start();
+ return anim;
}
}
}
+ public void animateToVisibility(int visibility) {
+ Animator anim = setupAnimatorToVisibility(visibility, FADE_DURATION);
+ anim.start();
+ }
+
@Override
public void setVisibility(int visibility) {
if (visibility != getVisibility()) {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 106272b..693b194 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -21,10 +21,6 @@ import android.widget.ActionMenuPresenter;
import android.widget.ActionMenuView;
import com.android.internal.view.menu.MenuBuilder;
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -35,14 +31,13 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* @hide
*/
-public class ActionBarContextView extends AbsActionBarView implements AnimatorListener {
+public class ActionBarContextView extends AbsActionBarView {
private static final String TAG = "ActionBarContextView";
private CharSequence mTitle;
@@ -59,14 +54,6 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
private boolean mTitleOptional;
private int mCloseItemLayout;
- private Animator mCurrentAnimation;
- private boolean mAnimateInOnLayout;
- private int mAnimationMode;
-
- private static final int ANIMATE_IDLE = 0;
- private static final int ANIMATE_IN = 1;
- private static final int ANIMATE_OUT = 2;
-
public ActionBarContextView(Context context) {
this(context, null);
}
@@ -255,43 +242,23 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
mMenuView.setBackgroundDrawable(mSplitBackground);
mSplitView.addView(mMenuView, layoutParams);
}
-
- mAnimateInOnLayout = true;
}
public void closeMode() {
- if (mAnimationMode == ANIMATE_OUT) {
- // Called again during close; just finish what we were doing.
- return;
- }
if (mClose == null) {
killMode();
return;
}
- finishAnimation();
- mAnimationMode = ANIMATE_OUT;
- mCurrentAnimation = makeOutAnimation();
- mCurrentAnimation.start();
- }
-
- private void finishAnimation() {
- final Animator a = mCurrentAnimation;
- if (a != null) {
- mCurrentAnimation = null;
- a.end();
- }
}
public void killMode() {
- finishAnimation();
removeAllViews();
if (mSplitView != null) {
mSplitView.removeView(mMenuView);
}
mCustomView = null;
mMenuView = null;
- mAnimateInOnLayout = false;
}
@Override
@@ -343,7 +310,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with android:layout_height=\"wrap_content\"");
}
-
+
final int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
int maxHeight = mContentHeight > 0 ?
@@ -353,7 +320,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
final int height = maxHeight - verticalPadding;
final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
-
+
if (mClose != null) {
availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
@@ -367,7 +334,7 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
if (mTitleLayout != null && mCustomView == null) {
if (mTitleOptional) {
- final int titleWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth,
+ final int titleWidthSpec = MeasureSpec.makeSafeMeasureSpec(contentWidth,
MeasureSpec.UNSPECIFIED);
mTitleLayout.measure(titleWidthSpec, childSpecHeight);
final int titleWidth = mTitleLayout.getMeasuredWidth();
@@ -411,66 +378,13 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
}
}
- private Animator makeInAnimation() {
- mClose.setTranslationX(-mClose.getWidth() -
- ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
- ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", 0);
- buttonAnimator.setDuration(200);
- buttonAnimator.addListener(this);
- buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
- AnimatorSet set = new AnimatorSet();
- AnimatorSet.Builder b = set.play(buttonAnimator);
-
- if (mMenuView != null) {
- final int count = mMenuView.getChildCount();
- if (count > 0) {
- for (int i = count - 1, j = 0; i >= 0; i--, j++) {
- View child = mMenuView.getChildAt(i);
- child.setScaleY(0);
- ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0, 1);
- a.setDuration(300);
- b.with(a);
- }
- }
- }
-
- return set;
- }
-
- private Animator makeOutAnimation() {
- ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX",
- -mClose.getWidth() - ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
- buttonAnimator.setDuration(200);
- buttonAnimator.addListener(this);
- buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
- AnimatorSet set = new AnimatorSet();
- AnimatorSet.Builder b = set.play(buttonAnimator);
-
- if (mMenuView != null) {
- final int count = mMenuView.getChildCount();
- if (count > 0) {
- for (int i = 0; i < 0; i++) {
- View child = mMenuView.getChildAt(i);
- child.setScaleY(0);
- ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0);
- a.setDuration(300);
- b.with(a);
- }
- }
- }
-
- return set;
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final boolean isLayoutRtl = isLayoutRtl();
int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
final int y = getPaddingTop();
final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
-
+
if (mClose != null && mClose.getVisibility() != GONE) {
MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
final int startMargin = (isLayoutRtl ? lp.rightMargin : lp.leftMargin);
@@ -479,12 +393,6 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
x += positionChild(mClose, x, y, contentHeight, isLayoutRtl);
x = next(x, endMargin, isLayoutRtl);
- if (mAnimateInOnLayout) {
- mAnimationMode = ANIMATE_IN;
- mCurrentAnimation = makeInAnimation();
- mCurrentAnimation.start();
- mAnimateInOnLayout = false;
- }
}
if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
@@ -503,26 +411,6 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi
}
@Override
- public void onAnimationStart(Animator animation) {
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mAnimationMode == ANIMATE_OUT) {
- killMode();
- }
- mAnimationMode = ANIMATE_IDLE;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
-
- @Override
public boolean shouldDelayChildPressedState() {
return false;
}
diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java
index fb413b5..fe70d7b 100644
--- a/core/java/com/android/internal/widget/DecorToolbar.java
+++ b/core/java/com/android/internal/widget/DecorToolbar.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
+import android.animation.Animator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
@@ -87,6 +88,7 @@ public interface DecorToolbar {
void setCustomView(View view);
View getCustomView();
void animateToVisibility(int visibility);
+ Animator setupAnimatorToVisibility(int visibility, long duration);
void setNavigationIcon(Drawable icon);
void setNavigationIcon(int resId);
void setNavigationContentDescription(CharSequence description);
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index 0066ed0..79adada 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -403,10 +403,10 @@ public class SlidingTab extends ViewGroup {
public void measure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- tab.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
- View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
- text.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
- View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+ tab.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+ text.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
}
/**
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 54df87b..32aae72 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -19,6 +19,7 @@ package com.android.internal.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.app.ActionBar;
import android.content.Context;
import android.content.res.TypedArray;
@@ -59,6 +60,8 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
private static final int AFFECTS_LOGO_MASK =
ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO;
+ // Default fade duration for fading in/out tool bar.
+ private static final long DEFAULT_FADE_DURATION_MS = 200;
private Toolbar mToolbar;
@@ -571,9 +574,19 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
@Override
public void animateToVisibility(int visibility) {
+ Animator anim = setupAnimatorToVisibility(visibility, DEFAULT_FADE_DURATION_MS);
+ if (anim != null) {
+ anim.start();
+ }
+ }
+
+ @Override
+ public Animator setupAnimatorToVisibility(int visibility, long duration) {
+
if (visibility == View.GONE) {
- mToolbar.animate().alpha(0)
- .setListener(new AnimatorListenerAdapter() {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(mToolbar, View.ALPHA, 1, 0);
+ anim.setDuration(duration);
+ anim.addListener(new AnimatorListenerAdapter() {
private boolean mCanceled = false;
@Override
public void onAnimationEnd(Animator animation) {
@@ -587,15 +600,19 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
mCanceled = true;
}
});
+ return anim;
} else if (visibility == View.VISIBLE) {
- mToolbar.animate().alpha(1)
- .setListener(new AnimatorListenerAdapter() {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(mToolbar, View.ALPHA, 0, 1);
+ anim.setDuration(duration);
+ anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mToolbar.setVisibility(View.VISIBLE);
}
});
+ return anim;
}
+ return null;
}
@Override