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/animation/Animator.java14
-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/ApplicationPackageManager.java69
-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/Presentation.java4
-rw-r--r--core/java/android/app/admin/DeviceInitializerStatus.java145
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java162
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-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/ContentProviderOperation.java54
-rw-r--r--core/java/android/content/ContentResolver.java153
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/Intent.java23
-rw-r--r--core/java/android/content/IntentFilter.java2
-rw-r--r--core/java/android/content/pm/IOnPermissionsChangeListener.aidl25
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.java40
-rw-r--r--core/java/android/content/pm/PackageParser.java19
-rw-r--r--core/java/android/hardware/SensorManager.java4
-rw-r--r--core/java/android/hardware/SystemSensorManager.java6
-rw-r--r--core/java/android/hardware/camera2/CameraCaptureSession.java25
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java40
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java18
-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/hardware/camera2/utils/SurfaceUtils.java6
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl10
-rw-r--r--core/java/android/hardware/usb/UsbManager.java40
-rw-r--r--core/java/android/inputmethodservice/ExtractEditLayout.java172
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java9
-rw-r--r--core/java/android/inputmethodservice/Keyboard.java21
-rw-r--r--core/java/android/net/NetworkFactory.java32
-rw-r--r--core/java/android/os/BatteryStats.java99
-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/RemoteCallbackList.java1
-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.java19
-rw-r--r--core/java/android/preference/SeekBarDialogPreference.java19
-rw-r--r--core/java/android/preference/SeekBarVolumizer.java44
-rw-r--r--core/java/android/preference/VolumePreference.java28
-rw-r--r--core/java/android/printservice/PrintService.java13
-rw-r--r--core/java/android/provider/ContactsContract.java153
-rw-r--r--core/java/android/provider/DocumentsContract.java6
-rw-r--r--core/java/android/provider/Settings.java74
-rw-r--r--core/java/android/service/carrier/CarrierService.java48
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java2
-rw-r--r--core/java/android/speech/tts/UtteranceProgressListener.java12
-rw-r--r--core/java/android/text/Spanned.java11
-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/MenuInflater.java32
-rw-r--r--core/java/android/view/MenuItem.java24
-rw-r--r--core/java/android/view/SurfaceView.java2
-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/ViewPropertyAnimator.java15
-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/ActionMenuPresenter.java73
-rw-r--r--core/java/android/widget/ActionMenuView.java50
-rw-r--r--core/java/android/widget/Editor.java48
-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/ListPopupWindow.java5
-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.java38
-rw-r--r--core/java/android/widget/Toolbar.java163
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java82
-rw-r--r--core/java/com/android/internal/app/ResolverComparator.java215
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java22
-rw-r--r--core/java/com/android/internal/logging/MetricsConstants.java21
-rw-r--r--core/java/com/android/internal/logging/MetricsLogger.java1
-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/view/menu/ActionMenuItem.java49
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItemView.java3
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java58
-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/FloatingToolbar.java39
-rw-r--r--core/java/com/android/internal/widget/SlidingTab.java8
-rw-r--r--core/java/com/android/internal/widget/ToolbarWidgetWrapper.java25
108 files changed, 2157 insertions, 1778 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/animation/Animator.java b/core/java/android/animation/Animator.java
index da48709..aa1be9a 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -211,11 +211,15 @@ public abstract class Animator implements Cloneable {
public abstract boolean isRunning();
/**
- * Returns whether this Animator has been started and not yet ended. This state is a superset
- * of the state of {@link #isRunning()}, because an Animator with a nonzero
- * {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during the
- * delay phase, whereas {@link #isRunning()} will return true only after the delay phase
- * is complete.
+ * Returns whether this Animator has been started and not yet ended. For reusable
+ * Animators (which most Animators are, apart from the one-shot animator produced by
+ * {@link android.view.ViewAnimationUtils#createCircularReveal(
+ * android.view.View, int, int, float, float) createCircularReveal()}),
+ * this state is a superset of {@link #isRunning()}, because an Animator with a
+ * nonzero {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during
+ * the delay phase, whereas {@link #isRunning()} will return true only after the delay phase
+ * is complete. Non-reusable animators will always return true after they have been
+ * started, because they cannot return to a non-started state.
*
* @return Whether the Animator has been started and not yet ended.
*/
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/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 41e3db8..cb1e7aa 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -31,6 +31,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
+import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
@@ -88,6 +89,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/*package*/
@@ -1048,6 +1050,38 @@ final class ApplicationPackageManager extends PackageManager {
}
}
+ @Override
+ public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ synchronized (mPermissionListeners) {
+ if (mPermissionListeners.get(listener) != null) {
+ return;
+ }
+ OnPermissionsChangeListenerDelegate delegate =
+ new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
+ try {
+ mPM.addOnPermissionsChangeListener(delegate);
+ mPermissionListeners.put(listener, delegate);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+ }
+
+ @Override
+ public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ synchronized (mPermissionListeners) {
+ IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
+ if (delegate != null) {
+ try {
+ mPM.removeOnPermissionsChangeListener(delegate);
+ mPermissionListeners.remove(listener);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+ }
+ }
+
static void configurationChanged() {
synchronized (sSync) {
sIconCache.clear();
@@ -2139,4 +2173,39 @@ final class ApplicationPackageManager extends PackageManager {
= new ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>>();
private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
= new ArrayMap<ResourceName, WeakReference<CharSequence>>();
+
+ private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener>
+ mPermissionListeners = new ArrayMap<>();
+
+ public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub
+ implements Handler.Callback{
+ private static final int MSG_PERMISSIONS_CHANGED = 1;
+
+ private final OnPermissionsChangedListener mListener;
+ private final Handler mHandler;
+
+
+ public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener,
+ Looper looper) {
+ mListener = listener;
+ mHandler = new Handler(looper, this);
+ }
+
+ @Override
+ public void onPermissionsChanged(int uid) {
+ mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_PERMISSIONS_CHANGED: {
+ final int uid = msg.arg1;
+ mListener.onPermissionsChanged(uid);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
}
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/Presentation.java b/core/java/android/app/Presentation.java
index bb45abb4..e110dcb 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -213,7 +213,7 @@ public class Presentation extends Dialog {
// dismiss the presentation immediately. This case is expected
// to be rare but surprising, so we'll write a log message about it.
if (!isConfigurationStillValid()) {
- Log.i(TAG, "Presentation is being immediately dismissed because the "
+ Log.i(TAG, "Presentation is being dismissed because the "
+ "display metrics have changed since it was created.");
mHandler.sendEmptyMessage(MSG_CANCEL);
}
@@ -274,6 +274,8 @@ public class Presentation extends Dialog {
// is invalid and the application must recreate the presentation to get
// a new context.
if (!isConfigurationStillValid()) {
+ Log.i(TAG, "Presentation is being dismissed because the "
+ + "display metrics have changed since it was created.");
cancel();
}
}
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 3ab0e01..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.
*/
@@ -2275,7 +2194,7 @@ public class DevicePolicyManager {
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
- mService.uninstallCaCert(admin, alias);
+ mService.uninstallCaCerts(admin, new String[] {alias});
} catch (CertificateException e) {
Log.w(TAG, "Unable to parse certificate", e);
} catch (RemoteException e) {
@@ -2322,12 +2241,11 @@ public class DevicePolicyManager {
*/
public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
if (mService != null) {
- for (String alias : new TrustedCertificateStore().userAliases()) {
- try {
- mService.uninstallCaCert(admin, alias);
- } catch (RemoteException re) {
- Log.w(TAG, "Failed talking with device policy service", re);
- }
+ try {
+ mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
+ .toArray(new String[0]));
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed talking with device policy service", re);
}
}
}
@@ -3976,6 +3894,9 @@ public class DevicePolicyManager {
* <p>Any packages that shares uid with an allowed package will also be allowed
* to activate lock task.
*
+ * From {@link android.os.Build.VERSION_CODES#MNC} removing packages from the lock task
+ * package list results in locked tasks belonging to those packages to be finished.
+ *
* This function can only be called by the device owner.
* @param packages The list of packages allowed to enter lock task mode
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -4289,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 8c7b20a..376a3d8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -128,7 +128,7 @@ interface IDevicePolicyManager {
boolean hasUserSetupCompleted();
boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
- void uninstallCaCert(in ComponentName admin, in String alias);
+ void uninstallCaCerts(in ComponentName admin, in String[] aliases);
void enforceCanManageCaCerts(in ComponentName admin);
boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias);
@@ -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 72e701d..494f821 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;
@@ -639,7 +640,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;
}
@@ -667,7 +668,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);
@@ -716,7 +717,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;
}
@@ -727,7 +728,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;
}
@@ -738,7 +739,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;
}
@@ -749,7 +750,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;
}
@@ -760,7 +761,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;
}
@@ -771,7 +772,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;
}
@@ -897,8 +898,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.
@@ -963,9 +965,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);
}
@@ -987,7 +989,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
@@ -1019,7 +1021,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;
}
@@ -1037,7 +1039,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;
}
@@ -1070,7 +1072,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
@@ -1087,7 +1089,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]);
@@ -1115,7 +1117,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.
@@ -1134,8 +1137,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.
@@ -1194,7 +1197,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);
@@ -1264,8 +1267,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);
}
@@ -1320,7 +1323,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;
@@ -1383,8 +1386,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);
}
@@ -1402,8 +1405,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) {
@@ -1449,7 +1452,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;
}
@@ -1498,8 +1501,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");
@@ -1565,9 +1568,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);
}
@@ -1589,8 +1592,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);
}
/**
@@ -1610,9 +1613,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();
@@ -1717,8 +1720,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++) {
@@ -1745,7 +1749,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/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 49ac062..fd1e24a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -28,6 +28,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+/**
+ * Represents a single operation to be performed as part of a batch of operations.
+ *
+ * @see ContentProvider#applyBatch(ArrayList)
+ */
public class ContentProviderOperation implements Parcelable {
/** @hide exposed for unit tests */
public final static int TYPE_INSERT = 1;
@@ -195,10 +200,19 @@ public class ContentProviderOperation implements Parcelable {
return new Builder(TYPE_ASSERT, uri);
}
+ /**
+ * Gets the Uri for the target of the operation.
+ */
public Uri getUri() {
return mUri;
}
+ /**
+ * Returns true if the operation allows yielding the database to other transactions
+ * if the database is contended.
+ *
+ * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+ */
public boolean isYieldAllowed() {
return mYieldAllowed;
}
@@ -208,26 +222,58 @@ public class ContentProviderOperation implements Parcelable {
return mType;
}
+ /**
+ * Returns true if the operation represents an insertion.
+ *
+ * @see #newInsert
+ */
public boolean isInsert() {
return mType == TYPE_INSERT;
}
+ /**
+ * Returns true if the operation represents a deletion.
+ *
+ * @see #newDelete
+ */
public boolean isDelete() {
return mType == TYPE_DELETE;
}
+ /**
+ * Returns true if the operation represents an update.
+ *
+ * @see #newUpdate
+ */
public boolean isUpdate() {
return mType == TYPE_UPDATE;
}
+ /**
+ * Returns true if the operation represents an assert query.
+ *
+ * @see #newAssertQuery
+ */
public boolean isAssertQuery() {
return mType == TYPE_ASSERT;
}
+ /**
+ * Returns true if the operation represents an insertion, deletion, or update.
+ *
+ * @see #isInsert
+ * @see #isDelete
+ * @see #isUpdate
+ */
public boolean isWriteOperation() {
return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
}
+ /**
+ * Returns true if the operation represents an assert query.
+ *
+ * @see #isAssertQuery
+ */
public boolean isReadOperation() {
return mType == TYPE_ASSERT;
}
@@ -617,7 +663,7 @@ public class ContentProviderOperation implements Parcelable {
}
/**
- * If set then if the number of rows affected by this operation do not match
+ * If set then if the number of rows affected by this operation does not match
* this count {@link OperationApplicationException} will be throw.
* This can only be used with builders of type update, delete, or assert.
* @return this builder, to allow for chaining.
@@ -631,6 +677,12 @@ public class ContentProviderOperation implements Parcelable {
return this;
}
+ /**
+ * If set to true then the operation allows yielding the database to other transactions
+ * if the database is contended.
+ * @return this builder, to allow for chaining.
+ * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+ */
public Builder withYieldAllowed(boolean yieldAllowed) {
mYieldAllowed = yieldAllowed;
return this;
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/Context.java b/core/java/android/content/Context.java
index a434c7b..970623a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1256,7 +1256,7 @@ public abstract class Context {
* @param intent The description of the activity to start.
*
* @throws ActivityNotFoundException &nbsp;
- *
+ *`
* @see #startActivity(Intent, Bundle)
* @see PackageManager#resolveActivity
*/
@@ -2443,8 +2443,6 @@ public abstract class Context {
*
* @param serviceClass The class of the desired service.
* @return The service name or null if the class is not a supported system service.
- *
- * @hide
*/
public abstract String getSystemServiceName(Class<?> serviceClass);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 25be96a..5190037 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1576,13 +1576,17 @@ public class Intent implements Parcelable, Cloneable {
* Broadcast action that requests current permission granted information. It will respond
* to the request by sending a broadcast with action defined by
* {@link #EXTRA_GET_PERMISSIONS_RESPONSE_INTENT}. The response will contain
- * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT} with contents described below or a null upon
- * failure.
+ * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}, as well as
+ * {@link #EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT}, with contents described below or
+ * a null upon failure.
*
- * <p>If {@link #EXTRA_PACKAGE_NAME} is included then the number of permissions granted and the
- * number of permissions requested by that package will be calculated and included as the first
+ * <p>If {@link #EXTRA_PACKAGE_NAME} is included then the number of permissions granted, the
+ * number of permissions requested and the number of granted additional permissions
+ * by that package will be calculated and included as the first
* and second elements respectively of an int[] in the response as
- * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}.
+ * {@link #EXTRA_GET_PERMISSIONS_COUNT_RESULT}. The response will also deliver the list
+ * of localized permission group names that are granted in
+ * {@link #EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT}.
*
* <p>If {@link #EXTRA_PACKAGE_NAME} is not included then the number of apps granted any runtime
* permissions and the total number of apps requesting runtime permissions will be the first
@@ -1602,7 +1606,14 @@ public class Intent implements Parcelable, Cloneable {
= "android.intent.extra.GET_PERMISSIONS_COUNT_RESULT";
/**
- * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_COUNT} broadcast.
+ * List of CharSequence of localized permission group labels.
+ * @hide
+ */
+ public static final String EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT
+ = "android.intent.extra.GET_PERMISSIONS_GROUP_LIST_RESULT";
+
+ /**
+ * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_COUNT} broadcasts.
* @hide
*/
public static final String EXTRA_GET_PERMISSIONS_RESPONSE_INTENT
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/IOnPermissionsChangeListener.aidl b/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
new file mode 100644
index 0000000..7791b50
--- /dev/null
+++ b/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.content.pm;
+
+/**
+ * Listener for changes in the permissions for installed packages.
+ * {@hide}
+ */
+oneway interface IOnPermissionsChangeListener {
+ void onPermissionsChanged(int uid);
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 00b8c71..0c07bc3 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,6 +31,7 @@ import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.KeySet;
@@ -490,4 +491,7 @@ interface IPackageManager {
KeySet getSigningKeySet(String packageName);
boolean isPackageSignedByKeySet(String packageName, in KeySet ks);
boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks);
+
+ void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+ void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 68092c8..bd50ca0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,11 +16,13 @@
package android.content.pm;
+import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringRes;
@@ -78,6 +80,21 @@ public abstract class PackageManager {
}
/**
+ * Listener for changes in permissions granted to a UID.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface OnPermissionsChangedListener {
+
+ /**
+ * Called when the permissions for a UID change.
+ * @param uid The UID with a change.
+ */
+ public void onPermissionsChanged(int uid);
+ }
+
+ /**
* {@link PackageInfo} flag: return information about
* activities in the package in {@link PackageInfo#activities}.
*/
@@ -2636,7 +2653,7 @@ public abstract class PackageManager {
/**
* Retrieve the official name associated with a user id. This name is
- * guaranteed to never change, though it is possibly for the underlying
+ * guaranteed to never change, though it is possible for the underlying
* user id to be changed. That is, if you are storing information about
* user ids in persistent storage, you should use the string returned
* by this function instead of the raw user-id.
@@ -4295,6 +4312,27 @@ public abstract class PackageManager {
public abstract boolean isSafeMode();
/**
+ * Adds a listener for permission changes for installed packages.
+ *
+ * @param listener The listener to add.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
+ public abstract void addOnPermissionsChangeListener(OnPermissionsChangedListener listener);
+
+ /**
+ * Remvoes a listener for permission changes for installed packages.
+ *
+ * @param listener The listener to remove.
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener);
+
+ /**
* Return the {@link KeySet} associated with the String alias for this
* application.
*
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/SensorManager.java b/core/java/android/hardware/SensorManager.java
index fda889f..d6b1142 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1577,7 +1577,7 @@ public abstract class SensorManager {
* Significant Motion, Step Counter etc.
*
* The tests which call this API need to have {@code
- * android.permission.HARDWARE_TEST} permission which isn't
+ * android.permission.LOCATION_HADWARE} permission which isn't
* available for third party applications.
*
* @param enable True to set the HAL in DATA_INJECTION mode.
@@ -1607,7 +1607,7 @@ public abstract class SensorManager {
* the HAL is already in data injection mode.
*
* The tests which call this API need to have {@code
- * android.permission.HARDWARE_TEST} permission which isn't
+ * android.permission.LOCATION_HARDWARE} permission which isn't
* available for third party applications.
*
* @param sensor The sensor to inject.
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 22a9e9c..d7960af 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -80,7 +80,7 @@ public class SystemSensorManager extends SensorManager {
nativeClassInit();
}
mHasDataInjectionPermissions = context.checkSelfPermission(
- Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
+ Manifest.permission.LOCATION_HARDWARE) == PackageManager.PERMISSION_GRANTED;
}
// initialize the sensor list
@@ -233,7 +233,7 @@ public class SystemSensorManager extends SensorManager {
protected boolean enableDataInjectionImpl(boolean enable) {
if (!mHasDataInjectionPermissions) {
throw new SecurityException("Permission denial. Calling enableDataInjection without "
- + Manifest.permission.HARDWARE_TEST);
+ + Manifest.permission.LOCATION_HARDWARE);
}
synchronized (mLock) {
int ret = nativeEnableDataInjection(mNativeInstance, enable);
@@ -256,7 +256,7 @@ public class SystemSensorManager extends SensorManager {
long timestamp) {
if (!mHasDataInjectionPermissions) {
throw new SecurityException("Permission denial. Calling injectSensorData without "
- + Manifest.permission.HARDWARE_TEST);
+ + Manifest.permission.LOCATION_HARDWARE);
}
synchronized (mLock) {
if (!mDataInjectionMode) {
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 82d40d3..c547b06 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -150,9 +150,17 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when this
* capture session was created.</p>
*
- * <p>Multiple requests can be in progress at once. They are processed in
- * first-in, first-out order, with minimal delays between each
- * capture. Requests submitted through this method have higher priority than
+ * <p>Multiple regular and reprocess requests can be in progress at once. If there are only
+ * regular requests or reprocess requests in progress, they are processed in first-in,
+ * first-out order. If there are both regular and reprocess requests in progress, regular
+ * requests are processed in first-in, first-out order and reprocess requests are processed in
+ * first-in, first-out order, respectively. However, the processing order of a regular request
+ * and a reprocess request in progress is not specified. In other words, a regular request
+ * will always be processed before regular requets that are submitted later. A reprocess request
+ * will always be processed before reprocess requests that are submitted later. However, a
+ * regular request may not be processed before reprocess requests that are submitted later.<p>
+ *
+ * <p>Requests submitted through this method have higher priority than
* those submitted through {@link #setRepeatingRequest} or
* {@link #setRepeatingBurst}, and will be processed as soon as the current
* repeat/repeatBurst processing completes.</p>
@@ -207,10 +215,13 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* not be interleaved with requests submitted by other capture or repeat
* calls.
*
- * <p>The requests will be captured in order, each capture producing one {@link CaptureResult}
- * and image buffers for one or more target {@link android.view.Surface surfaces}. The target
- * surfaces (set with {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces
- * provided when this capture session was created.</p>
+ * <p>Regular and reprocess requests can be mixed together in a single burst. Regular requests
+ * will be captured in order and reprocess requests will be processed in order, respectively.
+ * However, the processing order between a regular request and a reprocess request is not
+ * specified. Each capture produces one {@link CaptureResult} and image buffers for one or more
+ * target {@link android.view.Surface surfaces}. The target surfaces (set with
+ * {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when
+ * this capture session was created.</p>
*
* <p>The main difference between this method and simply calling
* {@link #capture} repeatedly is that this method guarantees that no
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index c073ba5..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,13 +1922,35 @@ 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() {
return mCharacteristics;
}
+ /**
+ * A high speed output surface can only be preview or hardware encoder surface.
+ *
+ * @param surface The high speed output surface to be checked.
+ */
+ private void checkHighSpeedSurfaceFormat(Surface surface) {
+ // TODO: remove this override since the default format should be
+ // ImageFormat.PRIVATE. b/9487482
+ final int HAL_FORMAT_RGB_START = 1; // HAL_PIXEL_FORMAT_RGBA_8888 from graphics.h
+ final int HAL_FORMAT_RGB_END = 5; // HAL_PIXEL_FORMAT_BGRA_8888 from graphics.h
+ int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
+ if (surfaceFormat >= HAL_FORMAT_RGB_START &&
+ surfaceFormat <= HAL_FORMAT_RGB_END) {
+ surfaceFormat = ImageFormat.PRIVATE;
+ }
+
+ if (surfaceFormat != ImageFormat.PRIVATE) {
+ throw new IllegalArgumentException("Surface format(" + surfaceFormat + ") is not"
+ + " for preview or hardware video encoding!");
+ }
+ }
+
private void checkConstrainedHighSpeedSurfaces(Collection<Surface> surfaces,
Range<Integer> fpsRange) {
if (surfaces == null || surfaces.size() == 0 || surfaces.size() > 2) {
@@ -1948,15 +1975,10 @@ public class CameraDeviceImpl extends CameraDevice {
}
for (Surface surface : surfaces) {
+ checkHighSpeedSurfaceFormat(surface);
+
// Surface size must be supported high speed sizes.
Size surfaceSize = SurfaceUtils.getSurfaceSize(surface);
- int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
-
- if (surfaceFormat != ImageFormat.PRIVATE) {
- throw new IllegalArgumentException("Surface format is not for preview or"
- + " hardware video encoding" + surfaceFormat);
- }
-
if (!highSpeedSizes.contains(surfaceSize)) {
throw new IllegalArgumentException("Surface size " + surfaceSize.toString() + " is"
+ " not part of the high speed supported size list " +
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index cc9d496..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) {
@@ -565,7 +568,7 @@ public class LegacyCameraDevice implements AutoCloseable {
throw new IllegalArgumentException("Surface was abandoned", e);
}
- return previewConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ return previewConsumer;
}
public static boolean isVideoEncoderConsumer(Surface output) {
@@ -583,7 +586,7 @@ public class LegacyCameraDevice implements AutoCloseable {
throw new IllegalArgumentException("Surface was abandoned", e);
}
- return videoEncoderConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ return videoEncoderConsumer;
}
/**
@@ -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/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 32e74e2..40005a5 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -16,6 +16,7 @@
package android.hardware.camera2.utils;
+import android.graphics.ImageFormat;
import android.hardware.camera2.legacy.LegacyCameraDevice;
import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
import android.util.Size;
@@ -27,7 +28,7 @@ import android.view.Surface;
public class SurfaceUtils {
/**
- * Check if a surface is for preview consumer.
+ * Check if a surface is for preview consumer based on consumer end point Gralloc usage flags.
*
* @param surface The surface to be checked.
* @return true if the surface is for preview consumer, false otherwise.
@@ -37,7 +38,8 @@ public class SurfaceUtils {
}
/**
- * Check if the surface is for hardware video encoder consumer.
+ * Check if the surface is for hardware video encoder consumer based on consumer end point
+ * Gralloc usage flags.
*
* @param surface The surface to be checked.
* @return true if the surface is for hardware video encoder consumer, false otherwise.
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 881dc0f..31a6a96 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -85,6 +85,16 @@ interface IUsbManager
/* Sets the current USB function. */
void setCurrentFunction(String function);
+ /* Sets whether USB data (for example, MTP exposed pictures) should be made
+ * available on the USB connection. Unlocking data should only be done with
+ * user involvement, since exposing pictures or other data could leak sensitive
+ * user information.
+ */
+ void setUsbDataUnlocked(boolean unlock);
+
+ /* Returns true iff sensitive user data is exposed on the USB connection. */
+ boolean isUsbDataUnlocked();
+
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 000d41f..c83f466 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -142,6 +142,16 @@ public class UsbManager {
public static final String USB_CONFIGURED = "configured";
/**
+ * Boolean extra indicating whether confidential user data, such as photos, should be
+ * made available on the USB connection. This variable will only be set when the user
+ * has explicitly asked for this data to be unlocked.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
+ *
+ * {@hide}
+ */
+ public static final String USB_DATA_UNLOCKED = "unlocked";
+
+ /**
* Name of the USB mass storage USB function.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast
*
@@ -464,4 +474,34 @@ public class UsbManager {
Log.e(TAG, "RemoteException in setCurrentFunction", e);
}
}
+
+ /**
+ * Sets whether USB data (for example, MTP exposed pictures) should be made available
+ * on the USB connection. Unlocking usb data should only be done with user involvement,
+ * since exposing pictures or other data could leak sensitive user information.
+ *
+ * {@hide}
+ */
+ public void setUsbDataUnlocked(boolean unlocked) {
+ try {
+ mService.setUsbDataUnlocked(unlocked);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setUsbDataUnlocked", e);
+ }
+ }
+
+ /**
+ * Returns {@code true} iff access to sensitive USB data is currently allowed.
+ *
+ * {@hide}
+ */
+ public boolean isUsbDataUnlocked() {
+ try {
+ return mService.isUsbDataUnlocked();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in isUsbDataUnlocked", e);
+ }
+ return false;
+ }
+
}
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index e902443..37ca4b4 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -16,30 +16,19 @@
package android.inputmethodservice;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuPopupHelper;
-
import android.content.Context;
import android.util.AttributeSet;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.LinearLayout;
/**
- * ExtractEditLayout provides an ActionMode presentation for the
- * limited screen real estate in extract mode.
+ * ExtractEditLayout provides an ActionMode presentation for the limited screen real estate in
+ * extract mode.
*
* @hide
*/
public class ExtractEditLayout extends LinearLayout {
- ExtractActionMode mActionMode;
Button mExtractActionButton;
- Button mEditButton;
public ExtractEditLayout(Context context) {
super(context);
@@ -50,165 +39,8 @@ public class ExtractEditLayout extends LinearLayout {
}
@Override
- public ActionMode startActionModeForChild(View sourceView, ActionMode.Callback cb) {
- final ExtractActionMode mode = new ExtractActionMode(cb);
- if (mode.dispatchOnCreate()) {
- mode.invalidate();
- mExtractActionButton.setVisibility(INVISIBLE);
- mEditButton.setVisibility(VISIBLE);
- mActionMode = mode;
- sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- return mode;
- }
- return null;
- }
-
- /**
- * @return true if an action mode is currently active.
- */
- public boolean isActionModeStarted() {
- return mActionMode != null;
- }
-
- /**
- * Finishes a possibly started action mode.
- */
- public void finishActionMode() {
- if (mActionMode != null) {
- mActionMode.finish();
- }
- }
-
- @Override
public void onFinishInflate() {
super.onFinishInflate();
mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
- mEditButton = (Button) findViewById(com.android.internal.R.id.inputExtractEditButton);
- mEditButton.setOnClickListener(new OnClickListener() {
- public void onClick(View clicked) {
- if (mActionMode != null) {
- new MenuPopupHelper(getContext(), mActionMode.mMenu, clicked).show();
- }
- }
- });
- }
-
- private class ExtractActionMode extends ActionMode implements MenuBuilder.Callback {
- private ActionMode.Callback mCallback;
- MenuBuilder mMenu;
-
- public ExtractActionMode(Callback cb) {
- mMenu = new MenuBuilder(getContext());
- mMenu.setCallback(this);
- mCallback = cb;
- }
-
- @Override
- public void setTitle(CharSequence title) {
- // Title will not be shown.
- }
-
- @Override
- public void setTitle(int resId) {
- // Title will not be shown.
- }
-
- @Override
- public void setSubtitle(CharSequence subtitle) {
- // Subtitle will not be shown.
- }
-
- @Override
- public void setSubtitle(int resId) {
- // Subtitle will not be shown.
- }
-
- @Override
- public boolean isTitleOptional() {
- // Not only is it optional, it will *never* be shown.
- return true;
- }
-
- @Override
- public void setCustomView(View view) {
- // Custom view is not supported here.
- }
-
- @Override
- public void invalidate() {
- mMenu.stopDispatchingItemsChanged();
- try {
- mCallback.onPrepareActionMode(this, mMenu);
- } finally {
- mMenu.startDispatchingItemsChanged();
- }
- }
-
- public boolean dispatchOnCreate() {
- mMenu.stopDispatchingItemsChanged();
- try {
- return mCallback.onCreateActionMode(this, mMenu);
- } finally {
- mMenu.startDispatchingItemsChanged();
- }
- }
-
- @Override
- public void finish() {
- if (mActionMode != this) {
- // Not the active action mode - no-op
- return;
- }
-
- mCallback.onDestroyActionMode(this);
- mCallback = null;
-
- mMenu.close();
-
- mExtractActionButton.setVisibility(VISIBLE);
- mEditButton.setVisibility(INVISIBLE);
-
- sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-
- mActionMode = null;
- }
-
- @Override
- public Menu getMenu() {
- return mMenu;
- }
-
- @Override
- public CharSequence getTitle() {
- return null;
- }
-
- @Override
- public CharSequence getSubtitle() {
- return null;
- }
-
- @Override
- public View getCustomView() {
- return null;
- }
-
- @Override
- public MenuInflater getMenuInflater() {
- return new MenuInflater(getContext());
- }
-
- @Override
- public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
- if (mCallback != null) {
- return mCallback.onActionItemClicked(this, item);
- }
- return false;
- }
-
- @Override
- public void onMenuModeChange(MenuBuilder menu) {
- }
-
}
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a7afa91..ae74b9a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1797,16 +1797,9 @@ public class InputMethodService extends AbstractInputMethodService {
private void requestShowSelf(int flags) {
mImm.showSoftInputFromInputMethod(mToken, flags);
}
-
+
private boolean handleBack(boolean doIt) {
if (mShowInputRequested) {
- if (isExtractViewShown() && mExtractView instanceof ExtractEditLayout) {
- ExtractEditLayout extractEditLayout = (ExtractEditLayout) mExtractView;
- if (extractEditLayout.isActionModeStarted()) {
- if (doIt) extractEditLayout.finishActionMode();
- return true;
- }
- }
// If the soft input area is shown, back closes it and we
// consume the back key.
if (doIt) requestHideSelf(0);
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/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index e47220b..5f46c73 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -24,8 +24,13 @@ import android.os.Messenger;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* A NetworkFactory is an entity that creates NetworkAgent objects.
* The bearers register with ConnectivityService using {@link #register} and
@@ -157,6 +162,11 @@ public class NetworkFactory extends Handler {
this.score = score;
this.requested = false;
}
+
+ @Override
+ public String toString() {
+ return "{" + request + ", score=" + score + ", requested=" + requested + "}";
+ }
}
private void handleAddRequest(NetworkRequest request, int score) {
@@ -176,9 +186,9 @@ public class NetworkFactory extends Handler {
private void handleRemoveRequest(NetworkRequest request) {
NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
- if (n != null && n.requested) {
+ if (n != null) {
mNetworkRequests.remove(request.requestId);
- releaseNetworkFor(n.request);
+ if (n.requested) releaseNetworkFor(n.request);
}
}
@@ -273,15 +283,31 @@ public class NetworkFactory extends Handler {
sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
}
+ @VisibleForTesting
+ protected int getRequestCount() {
+ return mNetworkRequests.size();
+ }
+
protected void log(String s) {
Log.d(LOG_TAG, s);
}
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println(toString());
+ pw.increaseIndent();
+ for (int i = 0; i < mNetworkRequests.size(); i++) {
+ pw.println(mNetworkRequests.valueAt(i));
+ }
+ pw.decreaseIndent();
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
- append(mNetworkRequests.size()).append("}");
+ append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
+ append("}");
return sb.toString();
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c9609e5..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"
};
/**
@@ -3489,57 +3494,97 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
for (int i=0; i<sippers.size(); i++) {
final BatterySipper bs = sippers.get(i);
+ pw.print(prefix);
switch (bs.drainType) {
case IDLE:
- pw.print(prefix); pw.print(" Idle: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Idle: ");
break;
case CELL:
- pw.print(prefix); pw.print(" Cell standby: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Cell standby: ");
break;
case PHONE:
- pw.print(prefix); pw.print(" Phone calls: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Phone calls: ");
break;
case WIFI:
- pw.print(prefix); pw.print(" Wifi: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Wifi: ");
break;
case BLUETOOTH:
- pw.print(prefix); pw.print(" Bluetooth: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Bluetooth: ");
break;
case SCREEN:
- pw.print(prefix); pw.print(" Screen: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Screen: ");
break;
case FLASHLIGHT:
- pw.print(prefix); pw.print(" Flashlight: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Flashlight: ");
break;
case APP:
- pw.print(prefix); pw.print(" Uid ");
+ pw.print(" Uid ");
UserHandle.formatUid(pw, bs.uidObj.getUid());
- pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
+ pw.print(": ");
break;
case USER:
- pw.print(prefix); pw.print(" User "); pw.print(bs.userId);
- pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
+ pw.print(" User "); pw.print(bs.userId);
+ pw.print(": ");
break;
case UNACCOUNTED:
- pw.print(prefix); pw.print(" Unaccounted: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Unaccounted: ");
break;
case OVERCOUNTED:
- pw.print(prefix); pw.print(" Over-counted: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Over-counted: ");
break;
case CAMERA:
- pw.print(prefix); pw.print(" Camera: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Camera: ");
+ break;
+ default:
+ pw.print(" ???: ");
break;
}
+ printmAh(pw, bs.totalPowerMah);
+
+ 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);
+ }
+ if (bs.wakeLockPowerMah != 0) {
+ pw.print(" wake=");
+ printmAh(pw, bs.wakeLockPowerMah);
+ }
+ if (bs.mobileRadioPowerMah != 0) {
+ pw.print(" radio=");
+ printmAh(pw, bs.mobileRadioPowerMah);
+ }
+ if (bs.wifiPowerMah != 0) {
+ pw.print(" wifi=");
+ printmAh(pw, bs.wifiPowerMah);
+ }
+ if (bs.gpsPowerMah != 0) {
+ pw.print(" gps=");
+ printmAh(pw, bs.gpsPowerMah);
+ }
+ if (bs.sensorPowerMah != 0) {
+ pw.print(" sensor=");
+ printmAh(pw, bs.sensorPowerMah);
+ }
+ if (bs.cameraPowerMah != 0) {
+ pw.print(" camera=");
+ printmAh(pw, bs.cameraPowerMah);
+ }
+ if (bs.flashlightPowerMah != 0) {
+ pw.print(" flash=");
+ printmAh(pw, bs.flashlightPowerMah);
+ }
+ pw.print(" )");
+ }
+ pw.println();
}
pw.println();
}
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/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d2a9cdc..5849350 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -77,7 +77,6 @@ public class RemoteCallbackList<E extends IInterface> {
public boolean register(E callback) {
return register(callback, null);
}
-
/**
* Add a new callback to the list. This callback will remain in the list
* until a corresponding call to {@link #unregister} or its hosting process
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 2622ee0..8d11527 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -32,7 +32,9 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.SparseArray;
+import android.util.SparseIntArray;
+import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -53,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";
@@ -80,6 +84,7 @@ public class VolumeInfo implements Parcelable {
private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
+ private static SparseIntArray sStateToDescrip = new SparseIntArray();
private static final Comparator<VolumeInfo>
sDescriptionComparator = new Comparator<VolumeInfo>() {
@@ -116,6 +121,16 @@ public class VolumeInfo implements Parcelable {
sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTABLE, Intent.ACTION_MEDIA_UNMOUNTABLE);
sEnvironmentToBroadcast.put(Environment.MEDIA_REMOVED, Intent.ACTION_MEDIA_REMOVED);
sEnvironmentToBroadcast.put(Environment.MEDIA_BAD_REMOVAL, Intent.ACTION_MEDIA_BAD_REMOVAL);
+
+ sStateToDescrip.put(VolumeInfo.STATE_UNMOUNTED, R.string.ext_media_status_unmounted);
+ sStateToDescrip.put(VolumeInfo.STATE_CHECKING, R.string.ext_media_status_checking);
+ sStateToDescrip.put(VolumeInfo.STATE_MOUNTED, R.string.ext_media_status_mounted);
+ sStateToDescrip.put(VolumeInfo.STATE_MOUNTED_READ_ONLY, R.string.ext_media_status_mounted_ro);
+ sStateToDescrip.put(VolumeInfo.STATE_FORMATTING, R.string.ext_media_status_formatting);
+ sStateToDescrip.put(VolumeInfo.STATE_EJECTING, R.string.ext_media_status_ejecting);
+ sStateToDescrip.put(VolumeInfo.STATE_UNMOUNTABLE, R.string.ext_media_status_unmountable);
+ sStateToDescrip.put(VolumeInfo.STATE_REMOVED, R.string.ext_media_status_removed);
+ sStateToDescrip.put(VolumeInfo.STATE_BAD_REMOVAL, R.string.ext_media_status_bad_removal);
}
/** vold state */
@@ -201,6 +216,10 @@ public class VolumeInfo implements Parcelable {
return state;
}
+ public int getStateDescription() {
+ return sStateToDescrip.get(state, 0);
+ }
+
public @Nullable String getFsUuid() {
return fsUuid;
}
diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java
index 9a08827..eeb69a3 100644
--- a/core/java/android/preference/SeekBarDialogPreference.java
+++ b/core/java/android/preference/SeekBarDialogPreference.java
@@ -18,29 +18,28 @@ package android.preference;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
+import com.android.internal.R;
+
/**
* @hide
*/
public class SeekBarDialogPreference extends DialogPreference {
- private static final String TAG = "SeekBarDialogPreference";
-
- private Drawable mMyIcon;
+ private final Drawable mMyIcon;
public SeekBarDialogPreference(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog);
createActionButtons();
// Steal the XML dialogIcon attribute's value
mMyIcon = getDialogIcon();
+
setDialogIcon(null);
}
@@ -49,7 +48,7 @@ public class SeekBarDialogPreference extends DialogPreference {
}
public SeekBarDialogPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
+ this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
}
public SeekBarDialogPreference(Context context) {
@@ -58,15 +57,15 @@ public class SeekBarDialogPreference extends DialogPreference {
// Allow subclasses to override the action buttons
public void createActionButtons() {
- setPositiveButtonText(android.R.string.ok);
- setNegativeButtonText(android.R.string.cancel);
+ setPositiveButtonText(R.string.ok);
+ setNegativeButtonText(R.string.cancel);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
- final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon);
+ final ImageView iconView = (ImageView) view.findViewById(R.id.icon);
if (mMyIcon != null) {
iconView.setImageDrawable(mMyIcon);
} else {
@@ -75,6 +74,6 @@ public class SeekBarDialogPreference extends DialogPreference {
}
protected static SeekBar getSeekBar(View dialogView) {
- return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar);
+ return (SeekBar) dialogView.findViewById(R.id.seekbar);
}
}
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 4bd085f..979c828 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +32,7 @@ import android.os.HandlerThread;
import android.os.Message;
import android.preference.VolumePreference.VolumeStore;
import android.provider.Settings;
+import android.provider.Settings.Global;
import android.provider.Settings.System;
import android.util.Log;
import android.widget.SeekBar;
@@ -46,7 +48,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
public interface Callback {
void onSampleStarting(SeekBarVolumizer sbv);
void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch);
- void onMuted(boolean muted);
+ void onMuted(boolean muted, boolean zenMuted);
}
private final Context mContext;
@@ -54,6 +56,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private final Callback mCallback;
private final Uri mDefaultUri;
private final AudioManager mAudioManager;
+ private final NotificationManager mNotificationManager;
private final int mStreamType;
private final int mMaxStreamVolume;
private boolean mAffectedByRingerMode;
@@ -63,12 +66,14 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private Handler mHandler;
private Observer mVolumeObserver;
private int mOriginalStreamVolume;
+ private int mLastAudibleStreamVolume;
private Ringtone mRingtone;
private int mLastProgress = -1;
private boolean mMuted;
private SeekBar mSeekBar;
private int mVolumeBeforeMute = -1;
private int mRingerMode;
+ private int mZenMode;
private static final int MSG_SET_STREAM_VOLUME = 0;
private static final int MSG_START_SAMPLE = 1;
@@ -78,19 +83,22 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
mContext = context;
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = context.getSystemService(AudioManager.class);
+ mNotificationManager = context.getSystemService(NotificationManager.class);
mStreamType = streamType;
mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType);
mNotificationOrRing = isNotificationOrRing(mStreamType);
if (mNotificationOrRing) {
mRingerMode = mAudioManager.getRingerModeInternal();
}
+ mZenMode = mNotificationManager.getZenMode();
mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType);
mCallback = callback;
mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
+ mLastAudibleStreamVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType);
mMuted = mAudioManager.isStreamMute(mStreamType);
if (mCallback != null) {
- mCallback.onMuted(mMuted);
+ mCallback.onMuted(mMuted, isZenMuted());
}
if (defaultUri == null) {
if (mStreamType == AudioManager.STREAM_RING) {
@@ -119,8 +127,17 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
mSeekBar.setOnSeekBarChangeListener(this);
}
+ private boolean isZenMuted() {
+ return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS
+ || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ }
+
protected void updateSeekBar() {
- if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ final boolean zenMuted = isZenMuted();
+ mSeekBar.setEnabled(!zenMuted);
+ if (zenMuted) {
+ mSeekBar.setProgress(mLastAudibleStreamVolume);
+ } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
mSeekBar.setProgress(0);
} else if (mMuted) {
mSeekBar.setProgress(0);
@@ -316,11 +333,12 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (msg.what == UPDATE_SLIDER) {
if (mSeekBar != null) {
mLastProgress = msg.arg1;
- final boolean muted = msg.arg2 != 0;
+ mLastAudibleStreamVolume = Math.abs(msg.arg2);
+ final boolean muted = msg.arg2 < 0;
if (muted != mMuted) {
mMuted = muted;
if (mCallback != null) {
- mCallback.onMuted(mMuted);
+ mCallback.onMuted(mMuted, isZenMuted());
}
}
updateSeekBar();
@@ -328,16 +346,18 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
}
- public void postUpdateSlider(int volume, boolean mute) {
- obtainMessage(UPDATE_SLIDER, volume, mute ? 1 : 0).sendToTarget();
+ public void postUpdateSlider(int volume, int lastAudibleVolume, boolean mute) {
+ final int arg2 = lastAudibleVolume * (mute ? -1 : 1);
+ obtainMessage(UPDATE_SLIDER, volume, arg2).sendToTarget();
}
}
private void updateSlider() {
if (mSeekBar != null && mAudioManager != null) {
final int volume = mAudioManager.getStreamVolume(mStreamType);
+ final int lastAudibleVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType);
final boolean mute = mAudioManager.isStreamMute(mStreamType);
- mUiHandler.postUpdateSlider(volume, mute);
+ mUiHandler.postUpdateSlider(volume, lastAudibleVolume, mute);
}
}
@@ -362,6 +382,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (listening) {
final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+ filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
mContext.registerReceiver(this, filter);
} else {
mContext.unregisterReceiver(this);
@@ -379,7 +400,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (mSeekBar != null && streamMatch && streamValue != -1) {
final boolean muted = mAudioManager.isStreamMute(mStreamType)
|| streamValue == 0;
- mUiHandler.postUpdateSlider(streamValue, muted);
+ mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
}
} else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
if (mNotificationOrRing) {
@@ -388,6 +409,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (mAffectedByRingerMode) {
updateSlider();
}
+ } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
+ mZenMode = mNotificationManager.getZenMode();
+ updateSlider();
}
}
}
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index a2da01b..8a66c24 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -26,14 +26,13 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.SeekBar;
+import com.android.internal.R;
+
/**
* @hide
*/
public class VolumePreference extends SeekBarDialogPreference implements
PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
-
- static final String TAG = "VolumePreference";
-
private int mStreamType;
/** May be null if the dialog isn't visible. */
@@ -44,7 +43,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.VolumePreference, defStyleAttr, defStyleRes);
+ R.styleable.VolumePreference, defStyleAttr, defStyleRes);
mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
a.recycle();
}
@@ -54,7 +53,11 @@ public class VolumePreference extends SeekBarDialogPreference implements
}
public VolumePreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
+ this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
+ }
+
+ public VolumePreference(Context context) {
+ this(context, null);
}
public void setStreamType(int streamType) {
@@ -65,7 +68,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
- final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ final SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar);
mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this);
mSeekBarVolumizer.start();
mSeekBarVolumizer.setSeekBar(seekBar);
@@ -128,14 +131,17 @@ public class VolumePreference extends SeekBarDialogPreference implements
getPreferenceManager().unregisterOnActivityStopListener(this);
if (mSeekBarVolumizer != null) {
- Dialog dialog = getDialog();
+ final Dialog dialog = getDialog();
if (dialog != null && dialog.isShowing()) {
- View view = dialog.getWindow().getDecorView()
- .findViewById(com.android.internal.R.id.seekbar);
- if (view != null) view.setOnKeyListener(null);
+ final View view = dialog.getWindow().getDecorView().findViewById(R.id.seekbar);
+ if (view != null) {
+ view.setOnKeyListener(null);
+ }
+
// Stopped while dialog was showing, revert changes
mSeekBarVolumizer.revertVolume();
}
+
mSeekBarVolumizer.stop();
mSeekBarVolumizer = null;
}
@@ -155,7 +161,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
}
@Override
- public void onMuted(boolean muted) {
+ public void onMuted(boolean muted, boolean zenMuted) {
// noop
}
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 527c8ae..6295822 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -231,6 +231,19 @@ public abstract class PrintService extends Service {
*/
public static final String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
+ /**
+ * If you declared an optional activity with advanced print options via the
+ * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
+ * attribute, this extra is used to pass in the meta-data for the currently printed
+ * document as a {@link android.print.PrintDocumentInfo} to your activity allowing
+ * you to inspect it.
+ *
+ * @see #EXTRA_PRINT_JOB_INFO
+ * @see #EXTRA_PRINTER_INFO
+ */
+ public static final String EXTRA_PRINT_DOCUMENT_INFO =
+ "android.printservice.extra.PRINT_DOCUMENT_INFO";
+
private Handler mHandler;
private IPrintServiceClient mClient;
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/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 69338b0..30535ff 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,12 @@ public final class DocumentsContract {
public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
/**
+ * Set this in a DocumentsUI intent to cause a package's own roots to be
+ * excluded from the roots list.
+ */
+ public static final String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
+
+ /**
* Included in {@link AssetFileDescriptor#getExtras()} when returned
* thumbnail should be rotated.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 640f434..e335f6d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -577,6 +577,21 @@ public final class Settings {
"android.settings.APPLICATION_DETAILS_SETTINGS";
/**
+ * Activity Action: Show screen for controlling which apps can ignore battery optimizations.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: The Intent's data URI specifies the application package name
+ * to be shown, with the "package" scheme. That is "package:com.my.app".
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS =
+ "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
+
+ /**
* @hide
* Activity Action: Show the "app ops" settings screen.
* <p>
@@ -5536,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
*/
@@ -7072,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/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 5f83452..225e70d 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -14,10 +14,15 @@
package android.service.carrier;
+import android.annotation.CallSuper;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.ITelephonyRegistry;
/**
* A service that exposes carrier-specific functionality to the system.
@@ -45,10 +50,16 @@ public abstract class CarrierService extends Service {
public static final String CONFIG_SERVICE_INTERFACE = "android.service.carrier.ConfigService";
public static final String BIND_SERVICE_INTERFACE = "android.service.carrier.BindService";
+ private static ITelephonyRegistry sRegistry;
+
private final ICarrierService.Stub mStubWrapper;
public CarrierService() {
mStubWrapper = new ICarrierServiceWrapper();
+ if (sRegistry == null) {
+ sRegistry = ITelephonyRegistry.Stub.asInterface(
+ ServiceManager.getService("telephony.registry"));
+ }
}
/**
@@ -83,9 +94,39 @@ public abstract class CarrierService extends Service {
*/
public abstract PersistableBundle onLoadConfig(CarrierIdentifier id);
- /** @hide */
+ /**
+ * Informs the system of an intentional upcoming carrier network change by
+ * a carrier app. This call is optional and is only used to allow the
+ * system to provide alternative UI while telephony is performing an action
+ * that may result in intentional, temporary network lack of connectivity.
+ * <p>
+ * Based on the active parameter passed in, this method will either show or
+ * hide the alternative UI. There is no timeout associated with showing
+ * this UX, so a carrier app must be sure to call with active set to false
+ * sometime after calling with it set to true.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges.
+ * @see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}
+ *
+ * @param active Whether the carrier network change is or shortly will be
+ * active. Set this value to true to begin showing
+ * alternative UI and false to stop.
+ */
+ public final void notifyCarrierNetworkChange(boolean active) {
+ try {
+ if (sRegistry != null) sRegistry.notifyCarrierNetworkChange(active);
+ } catch (RemoteException | NullPointerException ex) {}
+ }
+
+ /**
+ * If overriding this method, call through to the super method for any unknown actions.
+ * {@inheritDoc}
+ */
@Override
- public final IBinder onBind(Intent intent) {
+ @CallSuper
+ public IBinder onBind(Intent intent) {
switch (intent.getAction()) {
case CONFIG_SERVICE_INTERFACE:
case BIND_SERVICE_INTERFACE:
@@ -98,11 +139,8 @@ public abstract class CarrierService extends Service {
/**
* A wrapper around ICarrierService that forwards calls to implementations of
* {@link CarrierService}.
- *
- * @hide
*/
private class ICarrierServiceWrapper extends ICarrierService.Stub {
-
@Override
public PersistableBundle getCarrierConfig(CarrierIdentifier id) {
return CarrierService.this.onLoadConfig(id);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b8493d4..8c6cd09 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -646,7 +646,7 @@ public abstract class NotificationListenerService extends Service {
private void createLegacyIconExtras(Notification n) {
Icon smallIcon = n.getSmallIcon();
Icon largeIcon = n.getLargeIcon();
- if (smallIcon.getType() == Icon.TYPE_RESOURCE) {
+ if (smallIcon != null && smallIcon.getType() == Icon.TYPE_RESOURCE) {
n.extras.putInt(Notification.EXTRA_SMALL_ICON, smallIcon.getResId());
n.icon = smallIcon.getResId();
}
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/Spanned.java b/core/java/android/text/Spanned.java
index b4622e0..a785d1b 100644
--- a/core/java/android/text/Spanned.java
+++ b/core/java/android/text/Spanned.java
@@ -187,12 +187,11 @@ extends CharSequence
public int getSpanFlags(Object tag);
/**
- * Return the first offset greater than or equal to <code>start</code>
- * where a markup object of class <code>type</code> begins or ends,
- * or <code>limit</code> if there are no starts or ends greater than or
- * equal to <code>start</code> but less than <code>limit</code>. Specify
- * <code>null</code> or Object.class for the type if you want every
- * transition regardless of type.
+ * Return the first offset greater than <code>start</code> where a markup
+ * object of class <code>type</code> begins or ends, or <code>limit</code>
+ * if there are no starts or ends greater than <code>start</code> but less
+ * than <code>limit</code>. Specify <code>null</code> or Object.class for
+ * the type if you want every transition regardless of type.
*/
public int nextSpanTransition(int start, int limit, Class type);
}
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/MenuInflater.java b/core/java/android/view/MenuInflater.java
index dc8cadf..1c67ba7 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -25,11 +25,8 @@ import android.annotation.MenuRes;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -337,11 +334,6 @@ public class MenuInflater {
private ActionProvider itemActionProvider;
- private ColorStateList itemIconTintList;
- private boolean itemIconTintListSet;
- private PorterDuff.Mode itemIconTintMode;
- private boolean itemIconTintModeSet;
-
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -432,23 +424,6 @@ public class MenuInflater {
itemActionProvider = null;
}
- if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTint)) {
- itemIconTintList = a.getColorStateList(
- com.android.internal.R.styleable.MenuItem_iconTint);
- itemIconTintListSet = true;
- } else {
- itemIconTintList = null;
- itemIconTintListSet = false;
- }
- if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTintMode)) {
- itemIconTintMode = Drawable.parseTintMode(
- a.getInt(com.android.internal.R.styleable.MenuItem_iconTintMode, -1), null);
- itemIconTintModeSet = true;
- } else {
- itemIconTintMode = null;
- itemIconTintModeSet = false;
- }
-
a.recycle();
itemAdded = false;
@@ -511,13 +486,6 @@ public class MenuInflater {
if (itemActionProvider != null) {
item.setActionProvider(itemActionProvider);
}
-
- if (itemIconTintListSet) {
- item.setIconTintList(itemIconTintList);
- }
- if (itemIconTintModeSet) {
- item.setIconTintMode(itemIconTintMode);
- }
}
public MenuItem addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 2948007..9e8b97e 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -21,8 +21,6 @@ import android.annotation.LayoutRes;
import android.annotation.StringRes;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
@@ -601,26 +599,4 @@ public interface MenuItem {
* @return This menu item instance for call chaining
*/
public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
-
- /**
- * Applies a tint to the icon drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
- * <p>
- * Subsequent calls to {@link android.view.MenuItem#setIcon(android.graphics.drawable.Drawable)}
- * will automatically mutate the drawable and apply the specified tint and tint mode.
- *
- * @param tint the tint to apply, may be {@code null} to clear tint
- * @return This menu item instance for call chaining
- */
- public MenuItem setIconTintList(ColorStateList tint);
-
- /**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setIconTintList(ColorStateList)} to the icon drawable. The default mode is {@link
- * PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
- * @return This menu item instance for call chaining
- */
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 160c662..7d48a9a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -523,7 +523,7 @@ public class SurfaceView extends View {
mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
mNewSurface);
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
- mReportDrawNeeded = true;
+ reportDrawNeeded = true;
}
if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
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/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index f18b7ac..bd45007 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -80,18 +80,12 @@ public class ViewPropertyAnimator {
/**
* The interpolator of the underlying Animator object. By default, we don't set the interpolator
- * on the Animator and just use its default interpolator. If the interpolator is ever set on
- * this Animator, then we use the interpolator that it was set to.
+ * on the Animator and just use its default interpolator. If the interpolator is set to a
+ * non-null value on this Animator, then we use the interpolator that it was set to.
*/
private TimeInterpolator mInterpolator;
/**
- * A flag indicating whether the interpolator has been set on this object. If not, we don't set
- * the interpolator on the underlying Animator, but instead just use its default interpolator.
- */
- private boolean mInterpolatorSet = false;
-
- /**
* Listener for the lifecycle events of the underlying ValueAnimator object.
*/
private Animator.AnimatorListener mListener = null;
@@ -338,7 +332,6 @@ public class ViewPropertyAnimator {
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
- mInterpolatorSet = true;
mInterpolator = interpolator;
return this;
}
@@ -349,7 +342,7 @@ public class ViewPropertyAnimator {
* @return The timing interpolator for this animation.
*/
public TimeInterpolator getInterpolator() {
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
return mInterpolator;
} else {
// Just return the default from ValueAnimator, since that's what we'd get if
@@ -897,7 +890,7 @@ public class ViewPropertyAnimator {
if (mDurationSet) {
animator.setDuration(mDuration);
}
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
animator.setInterpolator(mInterpolator);
}
animator.start();
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/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index f08141c..a5696ee 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -21,10 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -64,6 +62,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter
private static final boolean ACTIONBAR_ANIMATIONS_ENABLED = false;
private OverflowMenuButton mOverflowButton;
+ private Drawable mPendingOverflowIcon;
+ private boolean mPendingOverflowIconSet;
private boolean mReserveOverflow;
private boolean mReserveOverflowSet;
private int mWidthLimit;
@@ -85,8 +85,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
private OpenOverflowRunnable mPostedOpenRunnable;
private ActionMenuPopupCallback mPopupCallback;
- private TintInfo mOverflowTintInfo;
-
final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
int mOpenSubMenuId;
@@ -154,9 +152,13 @@ public class ActionMenuPresenter extends BaseMenuPresenter
if (mReserveOverflow) {
if (mOverflowButton == null) {
mOverflowButton = new OverflowMenuButton(mSystemContext);
+ if (mPendingOverflowIconSet) {
+ mOverflowButton.setImageDrawable(mPendingOverflowIcon);
+ mPendingOverflowIcon = null;
+ mPendingOverflowIconSet = false;
+ }
final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
mOverflowButton.measure(spec, spec);
- applyOverflowTint();
}
width -= mOverflowButton.getMeasuredWidth();
} else {
@@ -198,6 +200,24 @@ public class ActionMenuPresenter extends BaseMenuPresenter
mExpandedActionViewsExclusive = isExclusive;
}
+ public void setOverflowIcon(Drawable icon) {
+ if (mOverflowButton != null) {
+ mOverflowButton.setImageDrawable(icon);
+ } else {
+ mPendingOverflowIconSet = true;
+ mPendingOverflowIcon = icon;
+ }
+ }
+
+ public Drawable getOverflowIcon() {
+ if (mOverflowButton != null) {
+ return mOverflowButton.getDrawable();
+ } else if (mPendingOverflowIconSet) {
+ return mPendingOverflowIcon;
+ }
+ return null;
+ }
+
@Override
public MenuView getMenuView(ViewGroup root) {
MenuView oldMenuView = mMenuView;
@@ -449,7 +469,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
if (hasOverflow) {
if (mOverflowButton == null) {
mOverflowButton = new OverflowMenuButton(mSystemContext);
- applyOverflowTint();
}
ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
if (parent != mMenuView) {
@@ -764,40 +783,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
}
- public void setOverflowTintList(ColorStateList tint) {
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintList = tint;
- mOverflowTintInfo.mHasTintList = true;
-
- applyOverflowTint();
- }
-
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintMode = tintMode;
- mOverflowTintInfo.mHasTintMode = true;
-
- applyOverflowTint();
- }
-
- private void applyOverflowTint() {
- final TintInfo tintInfo = mOverflowTintInfo;
- if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) {
- if (mOverflowButton != null) {
- if (tintInfo.mHasTintList) {
- mOverflowButton.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mOverflowButton.setImageTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
private static class SavedState implements Parcelable {
public int openSubMenuId;
@@ -1023,13 +1008,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
}
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
-
/**
* This class holds layout information for a menu item. This is used to determine
* pre- and post-layout information about menu items, which will then be used to
@@ -1077,5 +1055,4 @@ public class ActionMenuPresenter extends BaseMenuPresenter
this.animType = animType;
}
}
-
}
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 278a8fb..1f02c3b 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -16,11 +16,11 @@
package android.widget;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
-import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
@@ -541,39 +541,35 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
dismissPopupMenus();
}
- /** @hide */
- public boolean isOverflowReserved() {
- return mReserveOverflow;
- }
-
- /** @hide */
- public void setOverflowReserved(boolean reserveOverflow) {
- mReserveOverflow = reserveOverflow;
- }
-
/**
- * Applies a tint to the overflow drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+ * Set the icon to use for the overflow button.
*
- * @param tint the tint to apply, may be {@code null} to clear tint
+ * @param icon Drawable to set, may be null to clear the icon
*/
- public void setOverflowTintList(ColorStateList tint) {
- if (mPresenter != null) {
- mPresenter.setOverflowTintList(tint);
- }
+ public void setOverflowIcon(@Nullable Drawable icon) {
+ getMenu();
+ mPresenter.setOverflowIcon(icon);
}
/**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setOverflowTintList(ColorStateList)} to the overflow drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
+ * Return the current drawable used as the overflow icon.
*
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
+ * @return The overflow icon drawable
*/
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mPresenter != null) {
- mPresenter.setOverflowTintMode(tintMode);
- }
+ @Nullable
+ public Drawable getOverflowIcon() {
+ getMenu();
+ return mPresenter.getOverflowIcon();
+ }
+
+ /** @hide */
+ public boolean isOverflowReserved() {
+ return mReserveOverflow;
+ }
+
+ /** @hide */
+ public void setOverflowReserved(boolean reserveOverflow) {
+ mReserveOverflow = reserveOverflow;
}
@Override
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cd110b7..cf6a018 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -262,6 +262,8 @@ public class Editor {
}
};
+ boolean mIsInsertionActionModeStartPending = false;
+
Editor(TextView textView) {
mTextView = textView;
// Synchronize the filter list, which places the undo input filter at the end.
@@ -990,7 +992,7 @@ public class Editor {
}
public boolean performLongClick(boolean handled) {
- // Long press in empty space moves cursor and starts the selection action mode.
+ // Long press in empty space moves cursor and starts the insertion action mode.
if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY) &&
mInsertionControllerEnabled) {
final int offset = mTextView.getOffsetForPosition(mLastDownPositionX,
@@ -998,7 +1000,7 @@ public class Editor {
stopTextActionMode();
Selection.setSelection((Spannable) mTextView.getText(), offset);
getInsertionController().show();
- startInsertionActionMode();
+ mIsInsertionActionModeStartPending = true;
handled = true;
}
@@ -1160,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();
}
@@ -1710,14 +1716,14 @@ public class Editor {
}
/**
- * @return true if the selection mode was actually started.
+ * Start an Insertion action mode.
*/
- private boolean startInsertionActionMode() {
+ void startInsertionActionMode() {
if (mInsertionActionModeRunnable != null) {
mTextView.removeCallbacks(mInsertionActionModeRunnable);
}
if (extractedTextModeWillBeStarted()) {
- return false;
+ return;
}
stopTextActionMode();
@@ -1725,7 +1731,9 @@ public class Editor {
new TextActionModeCallback(false /* hasSelection */);
mTextActionMode = mTextView.startActionMode(
actionModeCallback, ActionMode.TYPE_FLOATING);
- return mTextActionMode != null;
+ if (mTextActionMode != null && getInsertionController() != null) {
+ getInsertionController().show();
+ }
}
/**
@@ -1796,7 +1804,7 @@ public class Editor {
private boolean startSelectionActionModeInternal() {
if (mTextActionMode != null) {
- // Selection action mode is already started
+ // Text action mode is already started
mTextActionMode.invalidate();
return false;
}
@@ -3299,7 +3307,6 @@ public class Editor {
if (mSelectionModifierCursorController != null) {
mSelectionModifierCursorController.hide();
- mSelectionModifierCursorController.resetTouchOffsets();
}
mTextActionMode = null;
@@ -3874,7 +3881,7 @@ public class Editor {
private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
private static final int RECENT_CUT_COPY_DURATION = 15 * 1000; // seconds
- // Used to detect taps on the insertion handle, which will affect the selection action mode
+ // Used to detect taps on the insertion handle, which will affect the insertion action mode
private float mDownPositionX, mDownPositionY;
private Runnable mHider;
@@ -3899,17 +3906,20 @@ public class Editor {
// timeout has passed.
if (!mDoubleTap && !isCursorInsideEasyCorrectionSpan()
&& (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION)) {
- if (mInsertionActionModeRunnable == null) {
- mInsertionActionModeRunnable = new Runnable() {
- public void run() {
- startInsertionActionMode();
- }
- };
+ if (mTextActionMode == null) {
+ if (mInsertionActionModeRunnable == null) {
+ mInsertionActionModeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ startInsertionActionMode();
+ }
+ };
+ }
+ mTextView.postDelayed(
+ mInsertionActionModeRunnable,
+ ViewConfiguration.getDoubleTapTimeout() + 1);
}
- mTextView.postDelayed(
- mInsertionActionModeRunnable,
- ViewConfiguration.getDoubleTapTimeout() + 1);
}
hideAfterDelay();
@@ -3976,7 +3986,7 @@ public class Editor {
final int touchSlop = viewConfiguration.getScaledTouchSlop();
if (distanceSquared < touchSlop * touchSlop) {
- // Tapping on the handle toggles the selection action mode.
+ // Tapping on the handle toggles the insertion action mode.
if (mTextActionMode != null) {
mTextActionMode.finish();
} else {
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/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 94b9416..afc683a 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -618,12 +618,11 @@ public class ListPopupWindow {
heightSpec = mDropDownHeight;
}
- mPopup.setWidth(widthSpec);
- mPopup.setHeight(heightSpec);
mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
- mDropDownVerticalOffset, -1, -1);
+ mDropDownVerticalOffset, (widthSpec < 0)? -1 : widthSpec,
+ (heightSpec < 0)? -1 : heightSpec);
} else {
final int widthSpec;
if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
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 b68934b..78b5d5d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8320,12 +8320,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final boolean superResult = super.onTouchEvent(event);
/*
- * Don't handle the release after a long press, because it will
- * move the selection away from whatever the menu action was
- * trying to affect.
+ * Don't handle the release after a long press, because it will move the selection away from
+ * whatever the menu action was trying to affect. If the long press should have triggered an
+ * insertion action mode, we can now actually show it.
*/
if (mEditor != null && mEditor.mDiscardNextActionUp && action == MotionEvent.ACTION_UP) {
mEditor.mDiscardNextActionUp = false;
+
+ if (mEditor.mIsInsertionActionModeStartPending) {
+ mEditor.startInsertionActionMode();
+ mEditor.mIsInsertionActionModeStartPending = false;
+ }
return superResult;
}
@@ -8785,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());
@@ -9239,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/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 62d948d..8ace0f3 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -25,9 +25,8 @@ import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.app.ActionBar;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.TypedArray;
-import android.graphics.PorterDuff;
+import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -110,9 +109,6 @@ public class Toolbar extends ViewGroup {
private ImageButton mNavButtonView;
private ImageView mLogoView;
- private TintInfo mOverflowTintInfo;
- private TintInfo mNavTintInfo;
-
private Drawable mCollapseIcon;
private CharSequence mCollapseDescription;
private ImageButton mCollapseButtonView;
@@ -275,21 +271,6 @@ public class Toolbar extends ViewGroup {
if (!TextUtils.isEmpty(navDesc)) {
setNavigationContentDescription(navDesc);
}
-
- if (a.hasValue(R.styleable.Toolbar_overflowTint)) {
- setOverflowTintList(a.getColorStateList(R.styleable.Toolbar_overflowTint));
- }
- if (a.hasValue(R.styleable.Toolbar_overflowTintMode)) {
- setOverflowTintMode(Drawable.parseTintMode(
- a.getInt(R.styleable.Toolbar_overflowTintMode, -1), null));
- }
- if (a.hasValue(R.styleable.Toolbar_navigationTint)) {
- setNavigationTintList(a.getColorStateList(R.styleable.Toolbar_navigationTint));
- }
- if (a.hasValue(R.styleable.Toolbar_navigationTintMode)) {
- setNavigationTintMode(Drawable.parseTintMode(
- a.getInt(R.styleable.Toolbar_navigationTintMode, -1), null));
- }
a.recycle();
}
@@ -830,101 +811,37 @@ public class Toolbar extends ViewGroup {
}
/**
- * Applies a tint to the icon drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
- * <p>
- * Subsequent calls to {@link #setNavigationIcon(Drawable)} will automatically mutate
- * the drawable and apply the specified tint and tint mode.
- *
- * @param tint the tint to apply, may be {@code null} to clear tint
- *
- * @attr ref android.R.styleable#Toolbar_navigationTint
- */
- public void setNavigationTintList(ColorStateList tint) {
- if (mNavTintInfo == null) {
- mNavTintInfo = new TintInfo();
- }
- mNavTintInfo.mTintList = tint;
- mNavTintInfo.mHasTintList = true;
-
- applyNavigationTint();
- }
-
- /**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setNavigationTintList(ColorStateList)} to the navigation drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
- *
- * @attr ref android.R.styleable#Toolbar_navigationTintMode
- */
- public void setNavigationTintMode(PorterDuff.Mode tintMode) {
- if (mNavTintInfo == null) {
- mNavTintInfo = new TintInfo();
- }
- mNavTintInfo.mTintMode = tintMode;
- mNavTintInfo.mHasTintMode = true;
-
- applyNavigationTint();
- }
-
- /**
- * Applies a tint to the overflow drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+ * Return the Menu shown in the toolbar.
*
- * @param tint the tint to apply, may be {@code null} to clear tint
+ * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
+ * an XML menu resource, use {@link #inflateMenu(int)}.</p>
*
- * @attr ref android.R.styleable#Toolbar_overflowTint
+ * @return The toolbar's Menu
*/
- public void setOverflowTintList(ColorStateList tint) {
- if (mMenuView != null) {
- // If the menu view is available, directly set the tint
- mMenuView.setOverflowTintList(tint);
- } else {
- // Otherwise we will record the value
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintList = tint;
- mOverflowTintInfo.mHasTintList = true;
- }
+ public Menu getMenu() {
+ ensureMenu();
+ return mMenuView.getMenu();
}
/**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setOverflowTintList(ColorStateList)} to the overflow drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
+ * Set the icon to use for the overflow button.
*
- * @attr ref android.R.styleable#Toolbar_overflowTintMode
+ * @param icon Drawable to set, may be null to clear the icon
*/
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mMenuView != null) {
- // If the menu view is available, directly set the tint mode
- mMenuView.setOverflowTintMode(tintMode);
- } else {
- // Otherwise we will record the value
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintMode = tintMode;
- mOverflowTintInfo.mHasTintMode = true;
- }
+ public void setOverflowIcon(@Nullable Drawable icon) {
+ ensureMenu();
+ mMenuView.setOverflowIcon(icon);
}
/**
- * Return the Menu shown in the toolbar.
- *
- * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
- * an XML menu resource, use {@link #inflateMenu(int)}.</p>
+ * Return the current drawable used as the overflow icon.
*
- * @return The toolbar's Menu
+ * @return The overflow icon drawable
*/
- public Menu getMenu() {
+ @Nullable
+ public Drawable getOverflowIcon() {
ensureMenu();
- return mMenuView.getMenu();
+ return mMenuView.getOverflowIcon();
}
private void ensureMenu() {
@@ -950,17 +867,6 @@ public class Toolbar extends ViewGroup {
lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mMenuView.setLayoutParams(lp);
addSystemView(mMenuView);
-
- if (mOverflowTintInfo != null) {
- // If we have tint info for the overflow, set it on the menu view now
- if (mOverflowTintInfo.mHasTintList) {
- mMenuView.setOverflowTintList(mOverflowTintInfo.mTintList);
- }
- if (mOverflowTintInfo.mHasTintMode) {
- mMenuView.setOverflowTintMode(mOverflowTintInfo.mTintMode);
- }
- mOverflowTintInfo = null;
- }
}
}
@@ -1114,7 +1020,6 @@ public class Toolbar extends ViewGroup {
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.START | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mNavButtonView.setLayoutParams(lp);
- applyNavigationTint();
}
}
@@ -1133,7 +1038,6 @@ public class Toolbar extends ViewGroup {
collapseActionView();
}
});
- applyNavigationTint();
}
}
@@ -1885,30 +1789,6 @@ public class Toolbar extends ViewGroup {
return mPopupContext;
}
- private void applyNavigationTint() {
- final TintInfo tintInfo = mNavTintInfo;
- if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) {
- if (mNavButtonView != null) {
- if (tintInfo.mHasTintList) {
- mNavButtonView.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mNavButtonView.setImageTintMode(tintInfo.mTintMode);
- }
- }
-
- if (mCollapseButtonView != null) {
- // We will use the same tint for the collapse button
- if (tintInfo.mHasTintList) {
- mCollapseButtonView.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mCollapseButtonView.setImageTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
/**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
@@ -2136,11 +2016,4 @@ public class Toolbar extends ViewGroup {
public void onRestoreInstanceState(Parcelable state) {
}
}
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ba4af89..39c86f9 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -18,8 +18,6 @@ package com.android.internal.app;
import android.app.Activity;
import android.app.ActivityThread;
-import android.app.usage.UsageStats;
-import android.app.usage.UsageStatsManager;
import android.os.AsyncTask;
import android.provider.Settings;
import android.text.TextUtils;
@@ -64,14 +62,11 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.widget.ResolverDrawerLayout;
-import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -100,10 +95,7 @@ public class ResolverActivity extends Activity {
private boolean mResolvingHome = false;
private int mProfileSwitchMessageId = -1;
private final ArrayList<Intent> mIntents = new ArrayList<>();
-
- private UsageStatsManager mUsm;
- private Map<String, UsageStats> mStats;
- private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+ private ResolverComparator mResolverComparator;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -222,10 +214,6 @@ public class ResolverActivity extends Activity {
}
mPm = getPackageManager();
- mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
-
- final long sinceTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
- mStats = mUsm.queryAndAggregateUsageStats(sinceTime, System.currentTimeMillis());
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
@@ -236,6 +224,10 @@ public class ResolverActivity extends Activity {
// Add our initial intent as the first item, regardless of what else has already been added.
mIntents.add(0, new Intent(intent));
+ final String referrerPackage = getReferrerPackageName();
+
+ mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage);
+
configureContentView(mIntents, initialIntents, rList, alwaysUseOption);
// Prevent the Resolver window from becoming the top fullscreen window and thus from taking
@@ -265,7 +257,6 @@ public class ResolverActivity extends Activity {
// Try to initialize the title icon if we have a view for it and a title to match
final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
if (titleIcon != null) {
- final String referrerPackage = getReferrerPackageName();
ApplicationInfo ai = null;
try {
if (!TextUtils.isEmpty(referrerPackage)) {
@@ -1175,8 +1166,8 @@ public class ResolverActivity extends Activity {
}
}
if (N > 1) {
- Collections.sort(currentResolveList,
- new ResolverComparator(ResolverActivity.this, getTargetIntent()));
+ mResolverComparator.compute(currentResolveList);
+ Collections.sort(currentResolveList, mResolverComparator);
}
// First put the initial items at the top.
if (mInitialIntents != null) {
@@ -1651,63 +1642,4 @@ public class ResolverActivity extends Activity {
&& match <= IntentFilter.MATCH_CATEGORY_PATH;
}
- class ResolverComparator implements Comparator<ResolvedComponentInfo> {
- private final Collator mCollator;
- private final boolean mHttp;
-
- public ResolverComparator(Context context, Intent intent) {
- mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
- String scheme = intent.getScheme();
- mHttp = "http".equals(scheme) || "https".equals(scheme);
- }
-
- @Override
- public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
- final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
- final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
-
- // We want to put the one targeted to another user at the end of the dialog.
- if (lhs.targetUserId != UserHandle.USER_CURRENT) {
- return 1;
- }
-
- if (mHttp) {
- // Special case: we want filters that match URI paths/schemes to be
- // ordered before others. This is for the case when opening URIs,
- // to make native apps go above browsers.
- final boolean lhsSpecific = isSpecificUriMatch(lhs.match);
- final boolean rhsSpecific = isSpecificUriMatch(rhs.match);
- if (lhsSpecific != rhsSpecific) {
- return lhsSpecific ? -1 : 1;
- }
- }
-
- if (mStats != null) {
- final long timeDiff =
- getPackageTimeSpent(rhs.activityInfo.packageName) -
- getPackageTimeSpent(lhs.activityInfo.packageName);
-
- if (timeDiff != 0) {
- return timeDiff > 0 ? 1 : -1;
- }
- }
-
- CharSequence sa = lhs.loadLabel(mPm);
- if (sa == null) sa = lhs.activityInfo.name;
- CharSequence sb = rhs.loadLabel(mPm);
- if (sb == null) sb = rhs.activityInfo.name;
-
- return mCollator.compare(sa.toString(), sb.toString());
- }
-
- private long getPackageTimeSpent(String packageName) {
- if (mStats != null) {
- final UsageStats stats = mStats.get(packageName);
- if (stats != null) {
- return stats.getTotalTimeInForeground();
- }
- }
- return 0;
- }
- }
}
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
new file mode 100644
index 0000000..585cdf1
--- /dev/null
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Ranks and compares packages based on usage stats.
+ */
+class ResolverComparator implements Comparator<ResolvedComponentInfo> {
+ private static final String TAG = "ResolverComparator";
+
+ private static final boolean DEBUG = false;
+
+ // Two weeks
+ private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+
+ private static final long RECENCY_TIME_PERIOD = 1000 * 60 * 60 * 12;
+
+ private static final float RECENCY_MULTIPLIER = 3.f;
+
+ private final Collator mCollator;
+ private final boolean mHttp;
+ private final PackageManager mPm;
+ private final UsageStatsManager mUsm;
+ private final Map<String, UsageStats> mStats;
+ private final long mCurrentTime;
+ private final long mSinceTime;
+ private final LinkedHashMap<ComponentName, ScoredTarget> mScoredTargets = new LinkedHashMap<>();
+ private final String mReferrerPackage;
+
+ public ResolverComparator(Context context, Intent intent, String referrerPackage) {
+ mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
+ String scheme = intent.getScheme();
+ mHttp = "http".equals(scheme) || "https".equals(scheme);
+ mReferrerPackage = referrerPackage;
+
+ mPm = context.getPackageManager();
+ mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
+
+ mCurrentTime = System.currentTimeMillis();
+ mSinceTime = mCurrentTime - USAGE_STATS_PERIOD;
+ mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
+ }
+
+ public void compute(List<ResolvedComponentInfo> targets) {
+ mScoredTargets.clear();
+
+ final long recentSinceTime = mCurrentTime - RECENCY_TIME_PERIOD;
+
+ long mostRecentlyUsedTime = recentSinceTime + 1;
+ long mostTimeSpent = 1;
+ int mostLaunched = 1;
+
+ for (ResolvedComponentInfo target : targets) {
+ final ScoredTarget scoredTarget
+ = new ScoredTarget(target.getResolveInfoAt(0).activityInfo);
+ mScoredTargets.put(target.name, scoredTarget);
+ final UsageStats pkStats = mStats.get(target.name.getPackageName());
+ if (pkStats != null) {
+ // Only count recency for apps that weren't the caller
+ // since the caller is always the most recent.
+ // Persistent processes muck this up, so omit them too.
+ if (!target.name.getPackageName().equals(mReferrerPackage)
+ && !isPersistentProcess(target)) {
+ final long lastTimeUsed = pkStats.getLastTimeUsed();
+ scoredTarget.lastTimeUsed = lastTimeUsed;
+ if (lastTimeUsed > mostRecentlyUsedTime) {
+ mostRecentlyUsedTime = lastTimeUsed;
+ }
+ }
+ final long timeSpent = pkStats.getTotalTimeInForeground();
+ scoredTarget.timeSpent = timeSpent;
+ if (timeSpent > mostTimeSpent) {
+ mostTimeSpent = timeSpent;
+ }
+ final int launched = pkStats.mLaunchCount;
+ scoredTarget.launchCount = launched;
+ if (launched > mostLaunched) {
+ mostLaunched = launched;
+ }
+ }
+ }
+
+
+ if (DEBUG) {
+ Log.d(TAG, "compute - mostRecentlyUsedTime: " + mostRecentlyUsedTime
+ + " mostTimeSpent: " + mostTimeSpent
+ + " recentSinceTime: " + recentSinceTime
+ + " mostLaunched: " + mostLaunched);
+ }
+
+ for (ScoredTarget target : mScoredTargets.values()) {
+ final float recency = (float) Math.max(target.lastTimeUsed - recentSinceTime, 0)
+ / (mostRecentlyUsedTime - recentSinceTime);
+ final float recencyScore = recency * recency * RECENCY_MULTIPLIER;
+ final float usageTimeScore = (float) target.timeSpent / mostTimeSpent;
+ final float launchCountScore = (float) target.launchCount / mostLaunched;
+
+ target.score = recencyScore + usageTimeScore + launchCountScore;
+ if (DEBUG) {
+ Log.d(TAG, "Scores: recencyScore: " + recencyScore
+ + " usageTimeScore: " + usageTimeScore
+ + " launchCountScore: " + launchCountScore
+ + " - " + target);
+ }
+ }
+ }
+
+ static boolean isPersistentProcess(ResolvedComponentInfo rci) {
+ if (rci != null && rci.getCount() > 0) {
+ return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
+ ApplicationInfo.FLAG_PERSISTENT) != 0;
+ }
+ return false;
+ }
+
+ @Override
+ public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
+ final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
+ final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
+
+ // We want to put the one targeted to another user at the end of the dialog.
+ if (lhs.targetUserId != UserHandle.USER_CURRENT) {
+ return 1;
+ }
+
+ if (mHttp) {
+ // Special case: we want filters that match URI paths/schemes to be
+ // ordered before others. This is for the case when opening URIs,
+ // to make native apps go above browsers.
+ final boolean lhsSpecific = ResolverActivity.isSpecificUriMatch(lhs.match);
+ final boolean rhsSpecific = ResolverActivity.isSpecificUriMatch(rhs.match);
+ if (lhsSpecific != rhsSpecific) {
+ return lhsSpecific ? -1 : 1;
+ }
+ }
+
+ if (mStats != null) {
+ final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
+ lhs.activityInfo.packageName, lhs.activityInfo.name));
+ final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
+ rhs.activityInfo.packageName, rhs.activityInfo.name));
+ final float diff = rhsTarget.score - lhsTarget.score;
+
+ if (diff != 0) {
+ return diff > 0 ? 1 : -1;
+ }
+ }
+
+ CharSequence sa = lhs.loadLabel(mPm);
+ if (sa == null) sa = lhs.activityInfo.name;
+ CharSequence sb = rhs.loadLabel(mPm);
+ if (sb == null) sb = rhs.activityInfo.name;
+
+ return mCollator.compare(sa.toString().trim(), sb.toString().trim());
+ }
+
+ static class ScoredTarget {
+ public final ComponentInfo componentInfo;
+ public float score;
+ public long lastTimeUsed;
+ public long timeSpent;
+ public long launchCount;
+
+ public ScoredTarget(ComponentInfo ci) {
+ componentInfo = ci;
+ }
+
+ @Override
+ public String toString() {
+ return "ScoredTarget{" + componentInfo
+ + " score: " + score
+ + " lastTimeUsed: " + lastTimeUsed
+ + " timeSpent: " + timeSpent
+ + " launchCount: " + launchCount
+ + "}";
+ }
+ }
+}
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/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
index 65dc743..8c6b79b 100644
--- a/core/java/com/android/internal/logging/MetricsConstants.java
+++ b/core/java/com/android/internal/logging/MetricsConstants.java
@@ -208,6 +208,27 @@ public interface MetricsConstants {
public static final int APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
public static final int APPLICATIONS_HIGH_POWER_APPS = 184;
public static final int FUELGAUGE_HIGH_POWER_DETAILS = 185;
+ public static final int ACTION_LS_UNLOCK = 186;
+ public static final int ACTION_LS_SHADE = 187;
+ public static final int ACTION_LS_HINT = 188;
+ public static final int ACTION_LS_CAMERA = 189;
+ public static final int ACTION_LS_DIALER = 190;
+ public static final int ACTION_LS_LOCK = 191;
+ public static final int ACTION_LS_NOTE = 192;
+ public static final int ACTION_LS_QS = 193;
+ public static final int ACTION_SHADE_QS_PULL = 194;
+ public static final int ACTION_SHADE_QS_TAP = 195;
+ public static final int LOCKSCREEN = 196;
+ public static final int BOUNCER = 197;
+ public static final int SCREEN = 198;
+ public static final int NOTIFICATION_ALERT = 199;
+ public static final int ACTION_EMERGENCY_CALL = 200;
+ public static final int APPLICATIONS_MANAGE_ASSIST = 201;
+ public static final int PROCESS_STATS_SUMMARY = 202;
+ public static final int ACTION_ROTATION_LOCK = 203;
+ public static final int ACTION_NOTE_CONTROLS = 204;
+ public static final int ACTION_NOTE_INFO = 205;
+ public static final int ACTION_APP_NOTE_SETTINGS = 206;
//aliases
public static final int DEVICEINFO_STORAGE = DEVICEINFO_MEMORY;
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 2f21efd..230d96d 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,7 +27,6 @@ import android.view.View;
*/
public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
- public static final int ACTION_EMERGENCY_CALL = 200;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
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/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 00af401..ed676bb 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -18,8 +18,6 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.view.ActionProvider;
import android.view.ContextMenu.ContextMenuInfo;
@@ -44,7 +42,6 @@ public class ActionMenuItem implements MenuItem {
private Drawable mIconDrawable;
private int mIconResId = NO_ICON;
- private TintInfo mIconTintInfo;
private Context mContext;
@@ -161,14 +158,12 @@ public class ActionMenuItem implements MenuItem {
public MenuItem setIcon(Drawable icon) {
mIconDrawable = icon;
mIconResId = NO_ICON;
- applyIconTint();
return this;
}
public MenuItem setIcon(int iconRes) {
mIconResId = iconRes;
mIconDrawable = mContext.getDrawable(iconRes);
- applyIconTint();
return this;
}
@@ -279,48 +274,4 @@ public class ActionMenuItem implements MenuItem {
// No need to save the listener; ActionMenuItem does not support collapsing items.
return this;
}
-
- @Override
- public MenuItem setIconTintList(ColorStateList tintList) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintList = tintList;
- mIconTintInfo.mHasTintList = true;
- applyIconTint();
- return this;
- }
-
- @Override
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintMode = tintMode;
- mIconTintInfo.mHasTintMode = true;
- applyIconTint();
- return this;
- }
-
- private void applyIconTint() {
- final TintInfo tintInfo = mIconTintInfo;
- if (mIconDrawable != null && tintInfo != null) {
- if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
- mIconDrawable = mIconDrawable.mutate();
- if (tintInfo.mHasTintList) {
- mIconDrawable.setTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mIconDrawable.setTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index f75b139..8db363d 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -273,7 +273,8 @@ public class ActionMenuItemView extends TextView
Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
// Show along the top; follow action buttons
- cheatSheet.setGravity(Gravity.TOP | Gravity.END, referenceX, height);
+ cheatSheet.setGravity(Gravity.TOP | Gravity.END, referenceX,
+ screenPos[1] + height - displayFrame.top);
} else {
// Show along the bottom center
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index ef4e546..3b1f20d 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -21,8 +21,6 @@ import com.android.internal.view.menu.MenuView.ItemView;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.ActionProvider;
@@ -62,11 +60,6 @@ public final class MenuItemImpl implements MenuItem {
* needed).
*/
private int mIconResId = NO_ICON;
-
- /**
- * Tint info for the icon
- */
- private TintInfo mIconTintInfo;
/** The menu to which this item belongs */
private MenuBuilder mMenu;
@@ -392,10 +385,10 @@ public final class MenuItemImpl implements MenuItem {
}
if (mIconResId != NO_ICON) {
- mIconDrawable = mMenu.getContext().getDrawable(mIconResId);
+ Drawable icon = mMenu.getContext().getDrawable(mIconResId);
mIconResId = NO_ICON;
- applyIconTint();
- return mIconDrawable;
+ mIconDrawable = icon;
+ return icon;
}
return null;
@@ -404,7 +397,6 @@ public final class MenuItemImpl implements MenuItem {
public MenuItem setIcon(Drawable icon) {
mIconResId = NO_ICON;
mIconDrawable = icon;
- applyIconTint();
mMenu.onItemsChanged(false);
return this;
@@ -678,48 +670,4 @@ public final class MenuItemImpl implements MenuItem {
public boolean isActionViewExpanded() {
return mIsActionViewExpanded;
}
-
- @Override
- public MenuItem setIconTintList(ColorStateList tintList) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintList = tintList;
- mIconTintInfo.mHasTintList = true;
- applyIconTint();
- return this;
- }
-
- @Override
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintMode = tintMode;
- mIconTintInfo.mHasTintMode = true;
- applyIconTint();
- return this;
- }
-
- private void applyIconTint() {
- final TintInfo tintInfo = mIconTintInfo;
- if (mIconDrawable != null && tintInfo != null) {
- if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
- mIconDrawable = mIconDrawable.mutate();
- if (tintInfo.mHasTintList) {
- mIconDrawable.setTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mIconDrawable.setTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
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/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index c77d614..2d0989f 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -361,7 +361,7 @@ public final class FloatingToolbar {
mParent = Preconditions.checkNotNull(parent);
mContentContainer = createContentContainer(parent.getContext());
mPopupWindow = createPopupWindow(mContentContainer);
- mDismissAnimation = createShrinkFadeOutFromBottomAnimation(
+ mDismissAnimation = createExitAnimation(
mContentContainer,
150, // startDelay
new AnimatorListenerAdapter() {
@@ -371,7 +371,7 @@ public final class FloatingToolbar {
mContentContainer.removeAllViews();
}
});
- mHideAnimation = createShrinkFadeOutFromBottomAnimation(
+ mHideAnimation = createExitAnimation(
mContentContainer,
0, // startDelay
new AnimatorListenerAdapter() {
@@ -561,7 +561,7 @@ public final class FloatingToolbar {
* Performs the "show" animation on the floating popup.
*/
private void runShowAnimation() {
- createGrowFadeInFromBottom(mContentContainer).start();
+ createEnterAnimation(mContentContainer).start();
}
/**
@@ -1369,38 +1369,35 @@ public final class FloatingToolbar {
}
/**
- * Creates a "grow and fade in from the bottom" animation for the specified view.
+ * Creates an "appear" animation for the specified view.
*
* @param view The view to animate
*/
- private static AnimatorSet createGrowFadeInFromBottom(View view) {
- AnimatorSet growFadeInFromBottomAnimation = new AnimatorSet();
- growFadeInFromBottomAnimation.playTogether(
- ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125),
- ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125),
- ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75),
+ private static AnimatorSet createEnterAnimation(View view) {
+ AnimatorSet animation = new AnimatorSet();
+ animation.playTogether(
+ ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(200),
// Make sure that view.x is always fixed throughout the duration of this animation.
ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX()));
- growFadeInFromBottomAnimation.setStartDelay(50);
- return growFadeInFromBottomAnimation;
+ animation.setStartDelay(50);
+ return animation;
}
/**
- * Creates a "shrink and fade out from bottom" animation for the specified view.
+ * Creates a "disappear" animation for the specified view.
*
* @param view The view to animate
* @param startDelay The start delay of the animation
* @param listener The animation listener
*/
- private static AnimatorSet createShrinkFadeOutFromBottomAnimation(
+ private static AnimatorSet createExitAnimation(
View view, int startDelay, Animator.AnimatorListener listener) {
- AnimatorSet shrinkFadeOutFromBottomAnimation = new AnimatorSet();
- shrinkFadeOutFromBottomAnimation.playTogether(
- ObjectAnimator.ofFloat(view, View.SCALE_Y, 1, 0.5f).setDuration(125),
- ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(75));
- shrinkFadeOutFromBottomAnimation.setStartDelay(startDelay);
- shrinkFadeOutFromBottomAnimation.addListener(listener);
- return shrinkFadeOutFromBottomAnimation;
+ AnimatorSet animation = new AnimatorSet();
+ animation.playTogether(
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(200));
+ animation.setStartDelay(startDelay);
+ animation.addListener(listener);
+ return animation;
}
private static int getEstimatedToolbarHeight(Context context) {
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