diff options
Diffstat (limited to 'core')
85 files changed, 1472 insertions, 964 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 31e129b..993b53d 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -51,10 +51,7 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static android.Manifest.permission.AUTHENTICATE_ACCOUNTS; import static android.Manifest.permission.GET_ACCOUNTS; -import static android.Manifest.permission.MANAGE_ACCOUNTS; -import static android.Manifest.permission.USE_CREDENTIALS; /** * This class provides access to a centralized registry of the user's @@ -319,14 +316,12 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that owns the specified account. * - * @param account The account to query for a password + * @param account The account to query for a password. Must not be {@code null}. * @return The account's password, null if none or if the account doesn't exist */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public String getPassword(final Account account) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -345,14 +340,12 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that owns the specified account. * * @param account The account to query for user data * @return The user data, null if the account or key doesn't exist */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public String getUserData(final Account account, final String key) { if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); @@ -662,10 +655,8 @@ public class AccountManager { * wizards associated with authenticators, not directly by applications. * * <p>It is safe to call this method from the main thread. - * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the added account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that owns the specified account. * * @param account The {@link Account} to add * @param password The password to associate with the account, null for none @@ -673,7 +664,6 @@ public class AccountManager { * @return True if the account was successfully added, false if the account * already exists, the account is null, or another error occurs. */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -692,14 +682,13 @@ public class AccountManager { * <p> * It is not safe to call this method from the main thread. As such, call it * from another thread. - * <p> - * This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and should be - * called from the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that owns the specified account. * * @param account The {@link Account} to be updated. + * @return boolean {@code true} if the authentication of the account has been successfully + * acknowledged. Otherwise {@code false}. */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public boolean notifyAccountAuthenticated(Account account) { if (account == null) throw new IllegalArgumentException("account is null"); @@ -717,9 +706,8 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * * @param account The {@link Account} to rename * @param newName String name to be associated with the account. @@ -731,7 +719,6 @@ public class AccountManager { * after the name change. If successful the account's name will be the * specified new name. */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public AccountManagerFuture<Account> renameAccount( final Account account, @Size(min = 1) final String newName, @@ -783,11 +770,8 @@ public class AccountManager { * The authenticator may have its own policies preventing account * deletion, in which case the account will not be deleted. * - * <p>This method may be called from any thread, but the returned - * {@link AccountManagerFuture} must not be used on the main thread. - * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * * @param account The {@link Account} to remove * @param callback Callback to invoke when the request completes, @@ -800,15 +784,16 @@ public class AccountManager { * {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)} * instead */ - @RequiresPermission(MANAGE_ACCOUNTS) @Deprecated public AccountManagerFuture<Boolean> removeAccount(final Account account, AccountManagerCallback<Boolean> callback, Handler handler) { if (account == null) throw new IllegalArgumentException("account is null"); return new Future2Task<Boolean>(handler, callback) { + @Override public void doWork() throws RemoteException { mService.removeAccount(mResponse, account, false); } + @Override public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) { throw new AuthenticatorException("no result in response"); @@ -827,8 +812,8 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * * @param account The {@link Account} to remove * @param activity The {@link Activity} context to use for launching a new @@ -855,11 +840,11 @@ public class AccountManager { * adding accounts (of this type) has been disabled by policy * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> removeAccount(final Account account, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { if (account == null) throw new IllegalArgumentException("account is null"); return new AmsTask(activity, handler, callback) { + @Override public void doWork() throws RemoteException { mService.removeAccount(mResponse, account, activity != null); } @@ -880,9 +865,11 @@ public class AccountManager { if (account == null) throw new IllegalArgumentException("account is null"); if (userHandle == null) throw new IllegalArgumentException("userHandle is null"); return new Future2Task<Boolean>(handler, callback) { + @Override public void doWork() throws RemoteException { mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier()); } + @Override public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException { if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) { throw new AuthenticatorException("no result in response"); @@ -918,17 +905,14 @@ public class AccountManager { * in which case the account will not be deleted. * <p> * It is safe to call this method from the main thread. - * <p> - * This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and to have the - * same UID or signature as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * * @param account The {@link Account} to delete. * @return True if the account was successfully deleted, false if the * account did not exist, the account is null, or another error * occurs. */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public boolean removeAccountExplicitly(Account account) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -948,14 +932,9 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS} or - * {@link android.Manifest.permission#USE_CREDENTIALS} - * * @param accountType The account type of the auth token to invalidate, must not be null * @param authToken The auth token to invalidate, may be null */ - @RequiresPermission(anyOf = {MANAGE_ACCOUNTS, USE_CREDENTIALS}) public void invalidateAuthToken(final String accountType, final String authToken) { if (accountType == null) throw new IllegalArgumentException("accountType is null"); try { @@ -976,16 +955,15 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * - * @param account The account to fetch an auth token for - * @param authTokenType The type of auth token to fetch, see {#getAuthToken} + * @param account The account for which an auth token is to be fetched. Cannot be {@code null}. + * @param authTokenType The type of auth token to fetch. Cannot be {@code null}. * @return The cached auth token for this account and type, or null if * no auth token is cached or the account does not exist. + * @see #getAuthToken */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public String peekAuthToken(final Account account, final String authTokenType) { if (account == null) throw new IllegalArgumentException("account is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); @@ -1005,14 +983,12 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * - * @param account The account to set a password for + * @param account The account whose password is to be set. Cannot be {@code null}. * @param password The password to set, null to clear the password */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public void setPassword(final Account account, final String password) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -1030,14 +1006,14 @@ public class AccountManager { * permissions, and may be used by applications or management interfaces * to "sign out" from an account. * - * <p>It is safe to call this method from the main thread. + * <p>This method only successfully clear the account's password when the + * caller has the same signature as the authenticator that owns the + * specified account. Otherwise, this method will silently fail. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS} + * <p>It is safe to call this method from the main thread. * * @param account The account whose password to clear */ - @RequiresPermission(MANAGE_ACCOUNTS) public void clearPassword(final Account account) { if (account == null) throw new IllegalArgumentException("account is null"); try { @@ -1055,15 +1031,13 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * - * @param account The account to set the userdata for - * @param key The userdata key to set. Must not be null - * @param value The value to set, null to clear this userdata key + * @param account Account whose user data is to be set. Must not be {@code null}. + * @param key String user data key to set. Must not be null + * @param value String value to set, {@code null} to clear this user data key */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public void setUserData(final Account account, final String key, final String value) { if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); @@ -1083,15 +1057,13 @@ public class AccountManager { * * <p>It is safe to call this method from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} - * and to have the same UID as the account's authenticator. + * <p>This method requires the caller to have a signature match with the + * authenticator that manages the specified account. * * @param account The account to set an auth token for * @param authTokenType The type of the auth token, see {#getAuthToken} * @param authToken The auth token to add to the cache */ - @RequiresPermission(AUTHENTICATE_ACCOUNTS) public void setAuthToken(Account account, final String authTokenType, final String authToken) { if (account == null) throw new IllegalArgumentException("account is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); @@ -1110,9 +1082,6 @@ public class AccountManager { * <p>This method may block while a network request completes, and must * never be made from the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#USE_CREDENTIALS}. - * * @param account The account to fetch an auth token for * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()} * @param notifyAuthFailure If true, display a notification and return null @@ -1126,7 +1095,6 @@ public class AccountManager { * @throws java.io.IOException if the authenticator experienced an I/O problem * creating a new auth token, usually because of network trouble */ - @RequiresPermission(USE_CREDENTIALS) public String blockingGetAuthToken(Account account, String authTokenType, boolean notifyAuthFailure) throws OperationCanceledException, IOException, AuthenticatorException { @@ -1165,9 +1133,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#USE_CREDENTIALS}. - * * @param account The account to fetch an auth token for * @param authTokenType The auth token type, an authenticator-dependent * string token, must not be null @@ -1201,7 +1166,6 @@ public class AccountManager { * authenticator-dependent. The caller should verify the validity of the * account before requesting an auth token. */ - @RequiresPermission(USE_CREDENTIALS) public AccountManagerFuture<Bundle> getAuthToken( final Account account, final String authTokenType, final Bundle options, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { @@ -1253,9 +1217,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#USE_CREDENTIALS}. - * * @param account The account to fetch an auth token for * @param authTokenType The auth token type, an authenticator-dependent * string token, must not be null @@ -1292,7 +1253,6 @@ public class AccountManager { * boolean, AccountManagerCallback, android.os.Handler)} instead */ @Deprecated - @RequiresPermission(USE_CREDENTIALS) public AccountManagerFuture<Bundle> getAuthToken( final Account account, final String authTokenType, final boolean notifyAuthFailure, @@ -1333,9 +1293,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#USE_CREDENTIALS}. - * * @param account The account to fetch an auth token for * @param authTokenType The auth token type, an authenticator-dependent * string token, must not be null @@ -1371,7 +1328,6 @@ public class AccountManager { * authenticator-dependent. The caller should verify the validity of the * account before requesting an auth token. */ - @RequiresPermission(USE_CREDENTIALS) public AccountManagerFuture<Bundle> getAuthToken( final Account account, final String authTokenType, final Bundle options, final boolean notifyAuthFailure, @@ -1401,9 +1357,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. - * * @param accountType The type of account to add; must not be null * @param authTokenType The type of auth token (see {@link #getAuthToken}) * this account will need to be able to generate, null for none @@ -1441,7 +1394,6 @@ public class AccountManager { * creating a new account, usually because of network trouble * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> addAccount(final String accountType, final String authTokenType, final String[] requiredFeatures, final Bundle addAccountOptions, @@ -1586,9 +1538,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. - * * @param account The account to confirm password knowledge for * @param options Authenticator-specific options for the request; * if the {@link #KEY_PASSWORD} string field is present, the @@ -1615,11 +1564,11 @@ public class AccountManager { * If no activity or password was specified, the returned Bundle contains * {@link #KEY_INTENT} with the {@link Intent} needed to launch the * password prompt. - * + * * <p>Also the returning Bundle may contain {@link * #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the * credential was validated/created. - * + * * If an error occurred,{@link AccountManagerFuture#getResult()} throws: * <ul> * <li> {@link AuthenticatorException} if the authenticator failed to respond @@ -1629,7 +1578,6 @@ public class AccountManager { * verifying the password, usually because of network trouble * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> confirmCredentials(final Account account, final Bundle options, final Activity activity, @@ -1668,9 +1616,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. - * * @param account The account to update credentials for * @param authTokenType The credentials entered must allow an auth token * of this type to be created (but no actual auth token is returned); @@ -1706,7 +1651,6 @@ public class AccountManager { * verifying the password, usually because of network trouble * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> updateCredentials(final Account account, final String authTokenType, final Bundle options, final Activity activity, @@ -1729,8 +1673,8 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. + * <p>This method requires the caller to have the same signature as the + * authenticator associated with the specified account type. * * @param accountType The account type associated with the authenticator * to adjust @@ -1758,7 +1702,6 @@ public class AccountManager { * updating settings, usually because of network trouble * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> editProperties(final String accountType, final Activity activity, final AccountManagerCallback<Bundle> callback, final Handler handler) { @@ -2253,9 +2196,6 @@ public class AccountManager { * <p>This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. * - * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#MANAGE_ACCOUNTS}. - * * @param accountType The account type required * (see {@link #getAccountsByType}), must not be null * @param authTokenType The desired auth token type @@ -2292,7 +2232,6 @@ public class AccountManager { * updating settings, usually because of network trouble * </ul> */ - @RequiresPermission(MANAGE_ACCOUNTS) public AccountManagerFuture<Bundle> getAuthTokenByFeatures( final String accountType, final String authTokenType, final String[] features, final Activity activity, final Bundle addAccountOptions, diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index da345a6..b65593d 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2812,7 +2812,9 @@ public class ActivityManager { * continues running even if the process is killed and restarted. To remove the watch, * use {@link #clearWatchHeapLimit()}. * - * <p>This API only work if running on a debuggable (userdebug or eng) build.</p> + * <p>This API only work if the calling process has been marked as + * {@link ApplicationInfo#FLAG_DEBUGGABLE} or this is running on a debuggable + * (userdebug or eng) build.</p> * * <p>Callers can optionally implement {@link #ACTION_REPORT_HEAP_LIMIT} to directly * handle heap limit reports themselves.</p> diff --git a/core/java/android/app/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/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 bf44746..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. */ @@ -3975,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. @@ -4288,21 +4210,6 @@ public class DevicePolicyManager { } /** - * Called by device initializer to send a provisioning status update to the remote setup device. - * - * @param statusCode a custom status code value as defined by - * {@link DeviceInitializerStatus#FLAG_STATUS_CUSTOM}. - * @param description custom description of the status code sent - */ - public void sendDeviceInitializerStatus(int statusCode, String description) { - try { - mService.sendDeviceInitializerStatus(statusCode, description); - } catch (RemoteException re) { - Log.w(TAG, "Could not send device initializer status", re); - } - } - - /** * Called by device owners to set a local system update policy. When a new policy is set, * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted. * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index a700806..376a3d8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -220,7 +220,6 @@ interface IDevicePolicyManager { void setUserIcon(in ComponentName admin, in Bitmap icon); - void sendDeviceInitializerStatus(int statusCode, String description); void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy); SystemUpdatePolicy getSystemUpdatePolicy(); diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 58279d7..369b692 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -68,9 +68,15 @@ public final class UsageEvents implements Parcelable { public static final int CONFIGURATION_CHANGE = 5; /** - * An event type denoting that a package was interacted with in some way. + * An event type denoting that a package was interacted with in some way by the system. + * @hide */ - public static final int INTERACTION = 6; + public static final int SYSTEM_INTERACTION = 6; + + /** + * An event type denoting that a package was interacted with in some way by the user. + */ + public static final int USER_INTERACTION = 7; /** * {@hide} diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index 81c7422..0fce4e2 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -41,11 +41,19 @@ public final class UsageStats implements Parcelable { public long mEndTimeStamp; /** + * Last time used by the user with an explicit action (notification, activity launch). * {@hide} */ public long mLastTimeUsed; /** + * The last time the package was used via implicit, non-user initiated actions (service + * was bound, etc). + * {@hide} + */ + public long mLastTimeSystemUsed; + + /** * Last time the package was used and the beginning of the idle countdown. * This uses a different timebase that is about how much the device has been in use in general. * {@hide} @@ -82,6 +90,7 @@ public final class UsageStats implements Parcelable { mLaunchCount = stats.mLaunchCount; mLastEvent = stats.mLastEvent; mBeginIdleTime = stats.mBeginIdleTime; + mLastTimeSystemUsed = stats.mLastTimeSystemUsed; } public String getPackageName() { @@ -119,6 +128,16 @@ public final class UsageStats implements Parcelable { /** * @hide + * Get the last time this package was used by the system (not the user). This can be different + * from {@link #getLastTimeUsed()} when the system binds to one of this package's services. + * See {@link System#currentTimeMillis()}. + */ + public long getLastTimeSystemUsed() { + return mLastTimeSystemUsed; + } + + /** + * @hide * Get the last time this package was active, measured in milliseconds. This timestamp * uses a timebase that represents how much the device was used and not wallclock time. */ @@ -151,6 +170,7 @@ public final class UsageStats implements Parcelable { mEndTimeStamp = right.mEndTimeStamp; mLastTimeUsed = right.mLastTimeUsed; mBeginIdleTime = right.mBeginIdleTime; + mLastTimeSystemUsed = right.mLastTimeSystemUsed; } mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); mTotalTimeInForeground += right.mTotalTimeInForeground; @@ -172,6 +192,7 @@ public final class UsageStats implements Parcelable { dest.writeInt(mLaunchCount); dest.writeInt(mLastEvent); dest.writeLong(mBeginIdleTime); + dest.writeLong(mLastTimeSystemUsed); } public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() { @@ -186,6 +207,7 @@ public final class UsageStats implements Parcelable { stats.mLaunchCount = in.readInt(); stats.mLastEvent = in.readInt(); stats.mBeginIdleTime = in.readLong(); + stats.mLastTimeSystemUsed = in.readLong(); return stats; } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 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/ContentResolver.java b/core/java/android/content/ContentResolver.java index 96a80e7..057001c 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -17,6 +17,7 @@ package android.content; import android.accounts.Account; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManagerNative; import android.app.ActivityThread; @@ -47,6 +48,8 @@ import android.util.Log; import dalvik.system.CloseGuard; +import com.android.internal.util.Preconditions; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -320,7 +323,9 @@ public abstract class ContentResolver { * using the content:// scheme. * @return A MIME type for the content, or null if the URL is invalid or the type is unknown */ - public final String getType(Uri url) { + public final @Nullable String getType(@NonNull Uri url) { + Preconditions.checkNotNull(url, "url"); + // XXX would like to have an acquireExistingUnstableProvider for this. IContentProvider provider = acquireExistingProvider(url); if (provider != null) { @@ -371,7 +376,10 @@ public abstract class ContentResolver { * data streams that match the given mimeTypeFilter. If there are none, * null is returned. */ - public String[] getStreamTypes(Uri url, String mimeTypeFilter) { + public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) { + Preconditions.checkNotNull(url, "url"); + Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter"); + IContentProvider provider = acquireProvider(url); if (provider == null) { return null; @@ -418,8 +426,9 @@ public abstract class ContentResolver { * @return A Cursor object, which is positioned before the first entry, or null * @see Cursor */ - public final Cursor query(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder) { + public final @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection, + @Nullable String selection, @Nullable String[] selectionArgs, + @Nullable String sortOrder) { return query(uri, projection, selection, selectionArgs, sortOrder, null); } @@ -457,9 +466,10 @@ public abstract class ContentResolver { * @return A Cursor object, which is positioned before the first entry, or null * @see Cursor */ - public final Cursor query(final Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder, - CancellationSignal cancellationSignal) { + public final @Nullable Cursor query(final @NonNull Uri uri, @Nullable String[] projection, + @Nullable String selection, @Nullable String[] selectionArgs, + @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) { + Preconditions.checkNotNull(uri, "uri"); IContentProvider unstableProvider = acquireUnstableProvider(uri); if (unstableProvider == null) { return null; @@ -555,7 +565,8 @@ public abstract class ContentResolver { * * @see #uncanonicalize */ - public final Uri canonicalize(Uri url) { + public final @Nullable Uri canonicalize(@NonNull Uri url) { + Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { return null; @@ -590,7 +601,8 @@ public abstract class ContentResolver { * * @see #canonicalize */ - public final Uri uncanonicalize(Uri url) { + public final @Nullable Uri uncanonicalize(@NonNull Uri url) { + Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { return null; @@ -626,8 +638,9 @@ public abstract class ContentResolver { * @throws FileNotFoundException if the provided URI could not be opened. * @see #openAssetFileDescriptor(Uri, String) */ - public final InputStream openInputStream(Uri uri) + public final @Nullable InputStream openInputStream(@NonNull Uri uri) throws FileNotFoundException { + Preconditions.checkNotNull(uri, "uri"); String scheme = uri.getScheme(); if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { // Note: left here to avoid breaking compatibility. May be removed @@ -658,7 +671,7 @@ public abstract class ContentResolver { * openOutputStream(uri, "w")}. * @throws FileNotFoundException if the provided URI could not be opened. */ - public final OutputStream openOutputStream(Uri uri) + public final @Nullable OutputStream openOutputStream(@NonNull Uri uri) throws FileNotFoundException { return openOutputStream(uri, "w"); } @@ -682,7 +695,7 @@ public abstract class ContentResolver { * @throws FileNotFoundException if the provided URI could not be opened. * @see #openAssetFileDescriptor(Uri, String) */ - public final OutputStream openOutputStream(Uri uri, String mode) + public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null); try { @@ -729,8 +742,8 @@ public abstract class ContentResolver { * file exists under the URI or the mode is invalid. * @see #openAssetFileDescriptor(Uri, String) */ - public final ParcelFileDescriptor openFileDescriptor(Uri uri, String mode) - throws FileNotFoundException { + public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri, + @NonNull String mode) throws FileNotFoundException { return openFileDescriptor(uri, mode, null); } @@ -774,8 +787,9 @@ public abstract class ContentResolver { * file exists under the URI or the mode is invalid. * @see #openAssetFileDescriptor(Uri, String) */ - public final ParcelFileDescriptor openFileDescriptor(Uri uri, - String mode, CancellationSignal cancellationSignal) throws FileNotFoundException { + public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri, + @NonNull String mode, @Nullable CancellationSignal cancellationSignal) + throws FileNotFoundException { AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal); if (afd == null) { return null; @@ -844,8 +858,8 @@ public abstract class ContentResolver { * @throws FileNotFoundException Throws FileNotFoundException of no * file exists under the URI or the mode is invalid. */ - public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, String mode) - throws FileNotFoundException { + public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri, + @NonNull String mode) throws FileNotFoundException { return openAssetFileDescriptor(uri, mode, null); } @@ -900,8 +914,12 @@ public abstract class ContentResolver { * @throws FileNotFoundException Throws FileNotFoundException of no * file exists under the URI or the mode is invalid. */ - public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, - String mode, CancellationSignal cancellationSignal) throws FileNotFoundException { + public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri, + @NonNull String mode, @Nullable CancellationSignal cancellationSignal) + throws FileNotFoundException { + Preconditions.checkNotNull(uri, "uri"); + Preconditions.checkNotNull(mode, "mode"); + String scheme = uri.getScheme(); if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { if (!"r".equals(mode)) { @@ -1023,8 +1041,8 @@ public abstract class ContentResolver { * @throws FileNotFoundException Throws FileNotFoundException of no * data of the desired type exists under the URI. */ - public final AssetFileDescriptor openTypedAssetFileDescriptor( - Uri uri, String mimeType, Bundle opts) throws FileNotFoundException { + public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri, + @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException { return openTypedAssetFileDescriptor(uri, mimeType, opts, null); } @@ -1059,9 +1077,12 @@ public abstract class ContentResolver { * @throws FileNotFoundException Throws FileNotFoundException of no * data of the desired type exists under the URI. */ - public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri, - String mimeType, Bundle opts, CancellationSignal cancellationSignal) - throws FileNotFoundException { + public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri, + @NonNull String mimeType, @Nullable Bundle opts, + @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException { + Preconditions.checkNotNull(uri, "uri"); + Preconditions.checkNotNull(mimeType, "mimeType"); + IContentProvider unstableProvider = acquireUnstableProvider(uri); if (unstableProvider == null) { throw new FileNotFoundException("No content provider: " + uri); @@ -1197,8 +1218,8 @@ public abstract class ContentResolver { * the field. Passing an empty ContentValues will create an empty row. * @return the URL of the newly created row. */ - public final Uri insert(Uri url, ContentValues values) - { + public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) { + Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { throw new IllegalArgumentException("Unknown URL " + url); @@ -1234,9 +1255,11 @@ public abstract class ContentResolver { * @throws RemoteException thrown if a RemoteException is encountered while attempting * to communicate with a remote provider. */ - public ContentProviderResult[] applyBatch(String authority, - ArrayList<ContentProviderOperation> operations) - throws RemoteException, OperationApplicationException { + public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority, + @NonNull ArrayList<ContentProviderOperation> operations) + throws RemoteException, OperationApplicationException { + Preconditions.checkNotNull(authority, "authority"); + Preconditions.checkNotNull(operations, "operations"); ContentProviderClient provider = acquireContentProviderClient(authority); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + authority); @@ -1258,8 +1281,9 @@ public abstract class ContentResolver { * the field. Passing null will create an empty row. * @return the number of newly created rows. */ - public final int bulkInsert(Uri url, ContentValues[] values) - { + public final int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] values) { + Preconditions.checkNotNull(url, "url"); + Preconditions.checkNotNull(values, "values"); IContentProvider provider = acquireProvider(url); if (provider == null) { throw new IllegalArgumentException("Unknown URL " + url); @@ -1289,8 +1313,9 @@ public abstract class ContentResolver { (excluding the WHERE itself). * @return The number of rows deleted. */ - public final int delete(Uri url, String where, String[] selectionArgs) - { + public final int delete(@NonNull Uri url, @Nullable String where, + @Nullable String[] selectionArgs) { + Preconditions.checkNotNull(url, "url"); IContentProvider provider = acquireProvider(url); if (provider == null) { throw new IllegalArgumentException("Unknown URL " + url); @@ -1323,8 +1348,9 @@ public abstract class ContentResolver { * @return the number of rows updated. * @throws NullPointerException if uri or values are null */ - public final int update(Uri uri, ContentValues values, String where, - String[] selectionArgs) { + public final int update(@NonNull Uri uri, @Nullable ContentValues values, + @Nullable String where, @Nullable String[] selectionArgs) { + Preconditions.checkNotNull(uri, "uri"); IContentProvider provider = acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); @@ -1358,14 +1384,10 @@ public abstract class ContentResolver { * @throws NullPointerException if uri or method is null * @throws IllegalArgumentException if uri is not known */ - public final Bundle call( - Uri uri, String method, @Nullable String arg, @Nullable Bundle extras) { - if (uri == null) { - throw new NullPointerException("uri == null"); - } - if (method == null) { - throw new NullPointerException("method == null"); - } + public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method, + @Nullable String arg, @Nullable Bundle extras) { + Preconditions.checkNotNull(uri, "uri"); + Preconditions.checkNotNull(method, "method"); IContentProvider provider = acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); @@ -1467,12 +1489,12 @@ public abstract class ContentResolver { * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider} * that services the content at uri or null if there isn't one. */ - public final ContentProviderClient acquireContentProviderClient(Uri uri) { + public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) { + Preconditions.checkNotNull(uri, "uri"); IContentProvider provider = acquireProvider(uri); if (provider != null) { return new ContentProviderClient(this, provider, true); } - return null; } @@ -1487,7 +1509,9 @@ public abstract class ContentResolver { * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider} * with the authority of name or null if there isn't one. */ - public final ContentProviderClient acquireContentProviderClient(String name) { + public final @Nullable ContentProviderClient acquireContentProviderClient( + @NonNull String name) { + Preconditions.checkNotNull(name, "name"); IContentProvider provider = acquireProvider(name); if (provider != null) { return new ContentProviderClient(this, provider, true); @@ -1512,7 +1536,9 @@ public abstract class ContentResolver { * can acquire a new one if you would like to try to restart the provider * and perform new operations on it. */ - public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) { + public final @Nullable ContentProviderClient acquireUnstableContentProviderClient( + @NonNull Uri uri) { + Preconditions.checkNotNull(uri, "uri"); IContentProvider provider = acquireUnstableProvider(uri); if (provider != null) { return new ContentProviderClient(this, provider, false); @@ -1537,7 +1563,9 @@ public abstract class ContentResolver { * can acquire a new one if you would like to try to restart the provider * and perform new operations on it. */ - public final ContentProviderClient acquireUnstableContentProviderClient(String name) { + public final @Nullable ContentProviderClient acquireUnstableContentProviderClient( + @NonNull String name) { + Preconditions.checkNotNull(name, "name"); IContentProvider provider = acquireUnstableProvider(name); if (provider != null) { return new ContentProviderClient(this, provider, false); @@ -1559,8 +1587,10 @@ public abstract class ContentResolver { * @param observer The object that receives callbacks when changes occur. * @see #unregisterContentObserver */ - public final void registerContentObserver(Uri uri, boolean notifyForDescendents, - ContentObserver observer) { + public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendents, + @NonNull ContentObserver observer) { + Preconditions.checkNotNull(uri, "uri"); + Preconditions.checkNotNull(observer, "observer"); registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId()); } @@ -1580,7 +1610,8 @@ public abstract class ContentResolver { * @param observer The previously registered observer that is no longer needed. * @see #registerContentObserver */ - public final void unregisterContentObserver(ContentObserver observer) { + public final void unregisterContentObserver(@NonNull ContentObserver observer) { + Preconditions.checkNotNull(observer, "observer"); try { IContentObserver contentObserver = observer.releaseContentObserver(); if (contentObserver != null) { @@ -1603,7 +1634,7 @@ public abstract class ContentResolver { * has requested to receive self-change notifications by implementing * {@link ContentObserver#deliverSelfNotifications()} to return true. */ - public void notifyChange(Uri uri, ContentObserver observer) { + public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) { notifyChange(uri, observer, true /* sync to network */); } @@ -1623,7 +1654,9 @@ public abstract class ContentResolver { * @param syncToNetwork If true, attempt to sync the change to the network. * @see #requestSync(android.accounts.Account, String, android.os.Bundle) */ - public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { + public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, + boolean syncToNetwork) { + Preconditions.checkNotNull(uri, "uri"); notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId()); } @@ -1653,7 +1686,9 @@ public abstract class ContentResolver { * * @see #getPersistedUriPermissions() */ - public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) { + public void takePersistableUriPermission(@NonNull Uri uri, + @Intent.AccessUriMode int modeFlags) { + Preconditions.checkNotNull(uri, "uri"); try { ActivityManagerNative.getDefault().takePersistableUriPermission( ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); @@ -1669,7 +1704,9 @@ public abstract class ContentResolver { * * @see #getPersistedUriPermissions() */ - public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) { + public void releasePersistableUriPermission(@NonNull Uri uri, + @Intent.AccessUriMode int modeFlags) { + Preconditions.checkNotNull(uri, "uri"); try { ActivityManagerNative.getDefault().releasePersistableUriPermission( ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); @@ -1686,7 +1723,7 @@ public abstract class ContentResolver { * @see #takePersistableUriPermission(Uri, int) * @see #releasePersistableUriPermission(Uri, int) */ - public List<UriPermission> getPersistedUriPermissions() { + public @NonNull List<UriPermission> getPersistedUriPermissions() { try { return ActivityManagerNative.getDefault() .getPersistedUriPermissions(mPackageName, true).getList(); @@ -1701,7 +1738,7 @@ public abstract class ContentResolver { * <em>from</em> the calling app. Only grants taken with * {@link #takePersistableUriPermission(Uri, int)} are returned. */ - public List<UriPermission> getOutgoingPersistedUriPermissions() { + public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() { try { return ActivityManagerNative.getDefault() .getPersistedUriPermissions(mPackageName, false).getList(); diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 33c0b87..08c5236 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -254,12 +254,14 @@ public class IntentFilter implements Parcelable { * HTTP scheme. * * @see #addDataScheme(String) + * @hide */ public static final String SCHEME_HTTP = "http"; /** * HTTPS scheme. * * @see #addDataScheme(String) + * @hide */ public static final String SCHEME_HTTPS = "https"; diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 83b0140..c92c256 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -36,6 +36,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.os.Build; import android.os.Bundle; +import android.os.FileUtils; import android.os.PatternMatcher; import android.os.UserHandle; import android.text.TextUtils; @@ -1194,7 +1195,8 @@ public class PackageParser { } } - private static String validateName(String name, boolean requiresSeparator) { + private static String validateName(String name, boolean requireSeparator, + boolean requireFilename) { final int N = name.length(); boolean hasSep = false; boolean front = true; @@ -1216,7 +1218,10 @@ public class PackageParser { } return "bad character '" + c + "'"; } - return hasSep || !requiresSeparator + if (requireFilename && !FileUtils.isValidExtFilename(name)) { + return "Invalid filename"; + } + return hasSep || !requireSeparator ? null : "must have at least one '.' separator"; } @@ -1240,7 +1245,7 @@ public class PackageParser { final String packageName = attrs.getAttributeValue(null, "package"); if (!"android".equals(packageName)) { - final String error = validateName(packageName, true); + final String error = validateName(packageName, true, true); if (error != null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Invalid manifest package: " + error); @@ -1252,7 +1257,7 @@ public class PackageParser { if (splitName.length() == 0) { splitName = null; } else { - final String error = validateName(splitName, false); + final String error = validateName(splitName, false, false); if (error != null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, "Invalid manifest split: " + error); @@ -1391,7 +1396,7 @@ public class PackageParser { String str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); if (str != null && str.length() > 0) { - String nameError = validateName(str, true); + String nameError = validateName(str, true, false); if (nameError != null && !"android".equals(pkgName)) { outError[0] = "<manifest> specifies bad sharedUserId name \"" + str + "\": " + nameError; @@ -1973,7 +1978,7 @@ public class PackageParser { return null; } String subName = proc.substring(1); - String nameError = validateName(subName, false); + String nameError = validateName(subName, false, false); if (nameError != null) { outError[0] = "Invalid " + type + " name " + proc + " in package " + pkg + ": " + nameError; @@ -1981,7 +1986,7 @@ public class PackageParser { } return (pkg + proc).intern(); } - String nameError = validateName(proc, true); + String nameError = validateName(proc, true, false); if (nameError != null && !"system".equals(proc)) { outError[0] = "Invalid " + type + " name " + proc + " in package " + pkg + ": " + nameError; diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index ed167f0..8512b23 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -52,6 +52,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -79,7 +80,7 @@ public class CameraDeviceImpl extends CameraDevice { private volatile StateCallbackKK mSessionStateCallback; private final Handler mDeviceHandler; - private volatile boolean mClosing = false; + private final AtomicBoolean mClosing = new AtomicBoolean(); private boolean mInError = false; private boolean mIdle = true; @@ -906,6 +907,10 @@ public class CameraDeviceImpl extends CameraDevice { @Override public void close() { synchronized (mInterfaceLock) { + if (mClosing.getAndSet(true)) { + return; + } + try { if (mRemoteDevice != null) { mRemoteDevice.disconnect(); @@ -1917,7 +1922,7 @@ public class CameraDeviceImpl extends CameraDevice { /** Whether the camera device has started to close (may not yet have finished) */ private boolean isClosed() { - return mClosing; + return mClosing.get(); } private CameraCharacteristics getCharacteristics() { diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java index a3a998e..cc95c0e 100644 --- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java +++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java @@ -87,6 +87,9 @@ public class LegacyCameraDevice implements AutoCloseable { public static final int MAX_DIMEN_FOR_ROUNDING = 1080; // 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) { return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, @@ -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..348b14a 100644 --- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java +++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java @@ -384,6 +384,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 +414,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 +424,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 +438,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 +459,6 @@ public class RequestThreadManager { } } - Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs, - callbackOutputSizes, mParams); if (smallestSupportedJpegSize != null) { /* * Set takePicture size to the smallest supported JPEG size large enough diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java index 45f1889..a5490ef 100644 --- a/core/java/android/inputmethodservice/Keyboard.java +++ b/core/java/android/inputmethodservice/Keyboard.java @@ -400,16 +400,27 @@ public class Keyboard { public void onPressed() { pressed = !pressed; } - + /** - * Changes the pressed state of the key. If it is a sticky key, it will also change the - * toggled state of the key if the finger was release inside. - * @param inside whether the finger was released inside the key + * Changes the pressed state of the key. + * + * <p>Toggled state of the key will be flipped when all the following conditions are + * fulfilled:</p> + * + * <ul> + * <li>This is a sticky key, that is, {@link #sticky} is {@code true}. + * <li>The parameter {@code inside} is {@code true}. + * <li>{@link android.os.Build.VERSION#SDK_INT} is greater than + * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}. + * </ul> + * + * @param inside whether the finger was released inside the key. Works only on Android M and + * later. See the method document for details. * @see #onPressed() */ public void onReleased(boolean inside) { pressed = !pressed; - if (sticky) { + if (sticky && inside) { on = !on; } } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index a6efc58..f76192e 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" }; /** diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 917271d..864225a 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -24,6 +24,8 @@ import android.util.Log; import android.util.Slog; import android.webkit.MimeTypeMap; +import com.android.internal.annotations.VisibleForTesting; + import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -34,6 +36,7 @@ import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Comparator; import java.util.Objects; @@ -456,6 +459,7 @@ public class FileUtils { res.append('_'); } } + trimFilename(res, 255); return res.toString(); } @@ -504,9 +508,31 @@ public class FileUtils { res.append('_'); } } + // Even though vfat allows 255 UCS-2 chars, we might eventually write to + // ext4 through a FUSE layer, so use that limit. + trimFilename(res, 255); + return res.toString(); + } + + @VisibleForTesting + public static String trimFilename(String str, int maxBytes) { + final StringBuilder res = new StringBuilder(str); + trimFilename(res, maxBytes); return res.toString(); } + private static void trimFilename(StringBuilder res, int maxBytes) { + byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8); + if (raw.length > maxBytes) { + maxBytes -= 3; + while (raw.length > maxBytes) { + res.deleteCharAt(res.length() / 2); + raw = res.toString().getBytes(StandardCharsets.UTF_8); + } + res.insert(res.length() / 2, "..."); + } + } + public static String rewriteAfterRename(File beforeDir, File afterDir, String path) { if (path == null) return null; final File result = rewriteAfterRename(beforeDir, afterDir, new File(path)); diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 1c9c713..135f369 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -621,6 +621,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { final int fd = getFd(); Parcel.clearFileDescriptor(mFd); writeCommStatusAndClose(Status.DETACHED, null); + mClosed = true; + mGuard.close(); + releaseResources(); return fd; } } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 8b18f32..7a1aa1e 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -878,7 +878,10 @@ public final class PowerManager { * off network access to apps. You can monitor for changes to this state with * {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}. * - * @return Returns true if currently in low power mode, else false. + * @return Returns true if currently in active device idle mode, else false. This is + * when idle mode restrictions are being actively applied; it will return false if the + * device is in a long-term idle mode but currently running a maintenance window where + * restrictions have been lifted. */ public boolean isDeviceIdleMode() { try { diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index 04e54aa..5bc45d5 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -80,6 +80,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/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index d9c412b..aebe7f1 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -8931,157 +8931,4 @@ public final class ContactsContract { public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET"; } } - - /** - * @hide - */ - protected interface MetadataSyncColumns { - - /** - * The raw contact backup id. - * A reference to the {@link ContactsContract.RawContacts#BACKUP_ID} that save the - * persistent unique id for each raw contact within its source system. - * - * @hide - */ - public static final String RAW_CONTACT_BACKUP_ID = "raw_contact_backup_id"; - - /** - * The account type to which the raw_contact of this item is associated. See - * {@link RawContacts#ACCOUNT_TYPE} - * - * @hide - */ - public static final String ACCOUNT_TYPE = "account_type"; - - /** - * The account name to which the raw_contact of this item is associated. See - * {@link RawContacts#ACCOUNT_NAME} - * - * @hide - */ - public static final String ACCOUNT_NAME = "account_name"; - - /** - * The data set within the account that the raw_contact of this row belongs to. This allows - * multiple sync adapters for the same account type to distinguish between - * each others' data. - * {@link RawContacts#DATA_SET} - * - * @hide - */ - public static final String DATA_SET = "data_set"; - - /** - * A text column contains the Json string got from People API. The Json string contains - * all the metadata related to the raw contact, i.e., all the data fields and - * aggregation exceptions. - * - * Here is an example of the Json string got from the actual schema. - * <pre> - * { - * "unique_contact_id": { - * "account_type": "CUSTOM_ACCOUNT", - * "custom_account_type": "facebook", - * "account_name": "android-test", - * "contact_id": "1111111", - * "data_set": "FOCUS" - * }, - * "contact_prefs": { - * "send_to_voicemail": true, - * "starred": false, - * "pinned": 2 - * }, - * "aggregation_data": [ - * { - * "type": "TOGETHER", - * "contact_ids": [ - * { - * "account_type": "GOOGLE_ACCOUNT", - * "account_name": "android-test2", - * "contact_id": "2222222", - * "data_set": "GOOGLE_PLUS" - * }, - * { - * "account_type": "GOOGLE_ACCOUNT", - * "account_name": "android-test3", - * "contact_id": "3333333", - * "data_set": "CUSTOM", - * "custom_data_set": "custom type" - * } - * ] - * } - * ], - * "field_data": [ - * { - * "field_data_id": "1001", - * "field_data_prefs": { - * "is_primary": true, - * "is_super_primary": true - * }, - * "usage_stats": [ - * { - * "usage_type": "CALL", - * "last_time_used": 10000001, - * "usage_count": 10 - * } - * ] - * } - * ] - * } - * </pre> - * - * @hide - */ - public static final String DATA = "data"; - - /** - * The "deleted" flag: "0" by default, "1" if the row has been marked - * for deletion. When {@link android.content.ContentResolver#delete} is - * called on a raw contact, updating MetadataSync table to set the flag of the raw contact - * as "1", then metadata sync adapter deletes the raw contact metadata on the server. - * <P>Type: INTEGER</P> - * - * @hide - */ - public static final String DELETED = "deleted"; - } - - /** - * Constants for the metadata sync table. This table is used to cache the metadata_sync data - * from server before it is merged into other CP2 tables. - * - * @hide - */ - public static final class MetadataSync implements BaseColumns, MetadataSyncColumns { - - /** The authority for the contacts metadata */ - public static final String METADATA_AUTHORITY = "com.android.contacts.metadata"; - - /** A content:// style uri to the authority for the contacts metadata */ - public static final Uri METADATA_AUTHORITY_URI = Uri.parse( - "content://" + METADATA_AUTHORITY); - - /** - * This utility class cannot be instantiated - */ - private MetadataSync() { - } - - /** - * The content:// style URI for this table. - */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI, - "metadata_sync"); - - /** - * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata - */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata"; - - /** - * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata. - */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata"; - } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 167d8e5..f2d3e71 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7087,6 +7087,36 @@ 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"; + + /** * Get the key that retrieves a bluetooth headset's priority. * @hide */ diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java index 9eb22ef..890ea3d 100644 --- a/core/java/android/speech/tts/UtteranceProgressListener.java +++ b/core/java/android/speech/tts/UtteranceProgressListener.java @@ -61,16 +61,16 @@ public abstract class UtteranceProgressListener { /** * Called when an utterance has been stopped while in progress or flushed from the - * synthesis queue. This can happen if client calls {@link TextToSpeech#stop()} - * or use {@link TextToSpeech#QUEUE_FLUSH} as an argument in + * synthesis queue. This can happen if a client calls {@link TextToSpeech#stop()} + * or uses {@link TextToSpeech#QUEUE_FLUSH} as an argument with the * {@link TextToSpeech#speak} or {@link TextToSpeech#synthesizeToFile} methods. * * @param utteranceId the utterance ID of the utterance. - * @param isStarted If true, then utterance was interrupted while being synthesized - * and it's output is incomplete. If it's false, then utterance was flushed + * @param interrupted If true, then the utterance was interrupted while being synthesized + * and its output is incomplete. If false, then the utterance was flushed * before the synthesis started. */ - public void onStop(String utteranceId, boolean isStarted) { + public void onStop(String utteranceId, boolean interrupted) { } /** @@ -99,7 +99,7 @@ public abstract class UtteranceProgressListener { } @Override - public void onStop(String utteranceId, boolean isStarted) { + public void onStop(String utteranceId, boolean interrupted) { listener.onUtteranceCompleted(utteranceId); } }; diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 6c4d8fd..d51aa79 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -1790,6 +1790,15 @@ public class TextUtils { } } + /** + * Return localized string representing the given number of selected items. + * + * @hide + */ + public static CharSequence formatSelectedCount(int count) { + return Resources.getSystem().getQuantityString(R.plurals.selected_count, count, count); + } + private static Object sLock = new Object(); private static char[] sTemp = null; diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java index 6ed3885..4ee9807 100644 --- a/core/java/android/util/ArrayMap.java +++ b/core/java/android/util/ArrayMap.java @@ -266,7 +266,7 @@ public final class ArrayMap<K, V> implements Map<K, V> { /** * Create a new ArrayMap with the mappings from the given ArrayMap. */ - public ArrayMap(ArrayMap map) { + public ArrayMap(ArrayMap<K, V> map) { this(); if (map != null) { putAll(map); @@ -843,7 +843,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { * in the array map. * * <p><b>Note:</b> this is a very inefficient way to access the array contents, it - * requires generating a number of temporary objects.</p> + * requires generating a number of temporary objects and allocates additional state + * information associated with the container that will remain for the life of the container.</p> * * <p><b>Note:</b></p> the semantics of this * Set are subtly different than that of a {@link java.util.HashMap}: most important, @@ -861,7 +862,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { * in the array map. * * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it - * requires generating a number of temporary objects.</p> + * requires generating a number of temporary objects and allocates additional state + * information associated with the container that will remain for the life of the container.</p> */ @Override public Set<K> keySet() { @@ -873,7 +875,8 @@ public final class ArrayMap<K, V> implements Map<K, V> { * in the array map. * * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it - * requires generating a number of temporary objects.</p> + * requires generating a number of temporary objects and allocates additional state + * information associated with the container that will remain for the life of the container.</p> */ @Override public Collection<V> values() { diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index 7da3941..b7a3c42 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -42,8 +42,6 @@ import java.util.Set; * you have no control over this shrinking -- if you set a capacity and then remove an * item, it may reduce the capacity to better match the current size. In the future an * explicit call to set the capacity should turn off this aggressive shrinking behavior.</p> - * - * @hide */ public final class ArraySet<E> implements Collection<E>, Set<E> { private static final boolean DEBUG = false; @@ -660,11 +658,24 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { return mCollections; } + /** + * Return an {@link java.util.Iterator} over all values in the set. + * + * <p><b>Note:</b> this is a fairly inefficient way to access the array contents, it + * requires generating a number of temporary objects and allocates additional state + * information associated with the container that will remain for the life of the container.</p> + */ @Override public Iterator<E> iterator() { return getCollection().getKeySet().iterator(); } + /** + * Determine if the array set contains all of the values in the given collection. + * @param collection The collection whose contents are to be checked against. + * @return Returns true if this array set contains a value for every entry + * in <var>collection</var>, else returns false. + */ @Override public boolean containsAll(Collection<?> collection) { Iterator<?> it = collection.iterator(); @@ -676,6 +687,10 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { return true; } + /** + * Perform an {@link #add(Object)} of all values in <var>collection</var> + * @param collection The collection whose contents are to be retrieved. + */ @Override public boolean addAll(Collection<? extends E> collection) { ensureCapacity(mSize + collection.size()); @@ -686,6 +701,11 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { return added; } + /** + * Remove all values in the array set that exist in the given collection. + * @param collection The collection whose contents are to be used to remove values. + * @return Returns true if any values were removed from the array set, else false. + */ @Override public boolean removeAll(Collection<?> collection) { boolean removed = false; @@ -695,6 +715,12 @@ public final class ArraySet<E> implements Collection<E>, Set<E> { return removed; } + /** + * Remove all values in the array set that do <b>not</b> exist in the given collection. + * @param collection The collection whose contents are to be used to determine which + * values to keep. + * @return Returns true if any values were removed from the array set, else false. + */ @Override public boolean retainAll(Collection<?> collection) { boolean removed = false; diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java new file mode 100644 index 0000000..4abdde0 --- /dev/null +++ b/core/java/android/util/KeyValueListParser.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.util; + +import android.text.TextUtils; + +/** + * Parses a list of key=value pairs, separated by some delimiter, and puts the results in + * an internal Map. Values can be then queried by key, or if not found, a default value + * can be used. + * @hide + */ +public class KeyValueListParser { + private final ArrayMap<String, String> mValues = new ArrayMap<>(); + private final TextUtils.StringSplitter mSplitter; + + /** + * Constructs a new KeyValueListParser. This can be reused for different strings + * by calling {@link #setString(String)}. + * @param delim The delimiter that separates key=value pairs. + */ + public KeyValueListParser(char delim) { + mSplitter = new TextUtils.SimpleStringSplitter(delim); + } + + /** + * Resets the parser with a new string to parse. The string is expected to be in the following + * format: + * <pre>key1=value,key2=value,key3=value</pre> + * + * where the delimiter is a comma. + * + * @param str the string to parse. + * @throws IllegalArgumentException if the string is malformed. + */ + public void setString(String str) throws IllegalArgumentException { + mValues.clear(); + if (str != null) { + mSplitter.setString(str); + for (String pair : mSplitter) { + int sep = pair.indexOf('='); + if (sep < 0) { + mValues.clear(); + throw new IllegalArgumentException( + "'" + pair + "' in '" + str + "' is not a valid key-value pair"); + } + mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim()); + } + } + } + + /** + * Get the value for key as a long. + * @param key The key to lookup. + * @param def The value to return if the key was not found, or the value was not a long. + * @return the long value associated with the key. + */ + public long getLong(String key, long def) { + String value = mValues.get(key); + if (value != null) { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + // fallthrough + } + } + return def; + } + + /** + * Get the value for key as a float. + * @param key The key to lookup. + * @param def The value to return if the key was not found, or the value was not a float. + * @return the float value associated with the key. + */ + public float getFloat(String key, float def) { + String value = mValues.get(key); + if (value != null) { + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + // fallthrough + } + } + return def; + } + + /** + * Get the value for key as a string. + * @param key The key to lookup. + * @param def The value to return if the key was not found. + * @return the string value associated with the key. + */ + public String getString(String key, String def) { + String value = mValues.get(key); + if (value != null) { + return value; + } + return def; + } +} diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index d2b6533..a865307 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -22,6 +22,7 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.Trace; import android.util.Log; import android.util.TimeUtils; @@ -160,6 +161,14 @@ public final class Choreographer { FrameInfo mFrameInfo = new FrameInfo(); /** + * Must be kept in sync with CALLBACK_* ints below, used to index into this array. + * @hide + */ + private static final String[] CALLBACK_TRACE_TITLES = { + "input", "animation", "traversal", "commit" + }; + + /** * Callback type: Input callback. Runs first. * @hide */ @@ -584,16 +593,22 @@ public final class Choreographer { mLastFrameTimeNanos = frameTimeNanos; } - mFrameInfo.markInputHandlingStart(); - doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); + try { + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame"); + + mFrameInfo.markInputHandlingStart(); + doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); - mFrameInfo.markAnimationsStart(); - doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); + mFrameInfo.markAnimationsStart(); + doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); - mFrameInfo.markPerformTraversalsStart(); - doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); + mFrameInfo.markPerformTraversalsStart(); + doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); - doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); + doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } if (DEBUG_FRAMES) { final long endNanos = System.nanoTime(); @@ -627,6 +642,7 @@ public final class Choreographer { // safe by ensuring the commit time is always at least one frame behind. if (callbackType == Choreographer.CALLBACK_COMMIT) { final long jitterNanos = now - frameTimeNanos; + Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos); if (jitterNanos >= 2 * mFrameIntervalNanos) { final long lastFrameOffset = jitterNanos % mFrameIntervalNanos + mFrameIntervalNanos; @@ -644,6 +660,7 @@ public final class Choreographer { } } try { + Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]); for (CallbackRecord c = callbacks; c != null; c = c.next) { if (DEBUG_FRAMES) { Log.d(TAG, "RunCallback: type=" + callbackType @@ -661,6 +678,7 @@ public final class Choreographer { callbacks = next; } while (callbacks != null); } + Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index be372d0..0df8ea9 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -741,6 +741,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static boolean sUseBrokenMakeMeasureSpec = false; /** + * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED + */ + static boolean sUseZeroUnspecifiedMeasureSpec = false; + + /** * Ignore any optimizations using the measure cache. */ private static boolean sIgnoreMeasureCache = false; @@ -3796,6 +3801,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Canvas.sCompatibilityRestore = targetSdkVersion < MNC; + // In MNC and newer, our widgets can pass a "hint" value in the size + // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers + // know what the expected parent size is going to be, so e.g. list items can size + // themselves at 1/3 the size of their container. It breaks older apps though, + // specifically apps that use some popular open source libraries. + sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < MNC; + sCompatibilityDone = true; } } @@ -17163,21 +17175,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * If the view has a ColorDrawable background, returns the color of that - * drawable. - * - * @return The color of the ColorDrawable background, if set, otherwise 0. - * @hide - */ - @ColorInt - public int getBackgroundColor() { - if (mBackground instanceof ColorDrawable) { - return ((ColorDrawable) mBackground).getColor(); - } - return 0; - } - - /** * Set the background to a given resource. The resource should refer to * a Drawable object or 0 to remove the background. * @param resid The identifier of the resource. @@ -21032,6 +21029,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED + * will automatically get a size of 0. Older apps expect this. + * + * @hide internal use only for compatibility with system widgets and older apps + */ + public static int makeSafeMeasureSpec(int size, int mode) { + if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) { + return 0; + } + return makeMeasureSpec(size, mode); + } + + /** * Extracts the mode from the supplied measure specification. * * @param measureSpec the measure specification to extract the mode from diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index dd32f85..89743e5 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -5963,12 +5963,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be - resultSize = size; + resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be - resultSize = size; + resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e1e0154..8b57d96 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -663,6 +663,10 @@ public final class ViewRootImpl implements ViewParent, return mWindowAttributes.flags; } + public int getDisplayId() { + return mDisplay.getDisplayId(); + } + public CharSequence getTitle() { return mWindowAttributes.getTitle(); } @@ -1105,12 +1109,7 @@ public final class ViewRootImpl implements ViewParent, Debug.startMethodTracing("ViewAncestor"); } - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals"); - try { - performTraversals(); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } + performTraversals(); if (mProfile) { Debug.stopMethodTracing(); diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index 8ceb166..d06cd83 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -201,6 +201,17 @@ public abstract class ViewStructure { public abstract void setChildCount(int num); /** + * Add to this view's child count. This increases the current child count by + * <var>num</var> children beyond what was last set by {@link #setChildCount} + * or {@link #addChildCount}. The index at which the new child starts in the child + * array is returned. + * + * @param num The number of new children to add. + * @return Returns the index in the child array at which the new children start. + */ + public abstract int addChildCount(int num); + + /** * Return the child count as set by {@link #setChildCount}. */ public abstract int getChildCount(); diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index b7d529e..b4ef58a 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -333,8 +333,8 @@ public final class WebViewFactory { newVmSize = Math.max(newVmSize, f.length()); continue; } - if (path.contains("!")) { - String[] split = TextUtils.split(path, "!"); + if (path.contains("!/")) { + String[] split = TextUtils.split(path, "!/"); if (split.length == 2) { try { ZipFile z = new ZipFile(split[0]); @@ -384,7 +384,7 @@ public final class WebViewFactory { ZipEntry e = z.getEntry(entry); if (e != null && e.getMethod() == ZipEntry.STORED) { // Return a path formatted for dlopen() load from APK. - return apkPath + "!" + entry; + return apkPath + "!/" + entry; } } } catch (IOException e) { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index e43237a..cf6a018 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1162,6 +1162,10 @@ public class Editor { // We do not hide the span controllers, since they can be added when a new text is // inserted into the text view (voice IME). hideCursorControllers(); + // Reset drag accelerator. + if (mSelectionModifierCursorController != null) { + mSelectionModifierCursorController.resetTouchOffsets(); + } stopTextActionMode(); } diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index f06f3c2..11d7026 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -662,7 +662,7 @@ class FastScroller { final int adjMaxWidth = maxWidth - marginLeft - marginRight; final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST); - final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(), + final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(), MeasureSpec.UNSPECIFIED); view.measure(widthMeasureSpec, heightMeasureSpec); @@ -702,7 +702,7 @@ class FastScroller { final int containerWidth = container.width(); final int adjMaxWidth = containerWidth - marginLeft - marginRight; final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST); - final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(), + final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(), MeasureSpec.UNSPECIFIED); preview.measure(widthMeasureSpec, heightMeasureSpec); @@ -768,7 +768,7 @@ class FastScroller { final Rect container = mContainerRect; final int maxWidth = container.width(); final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST); - final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(), + final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(), MeasureSpec.UNSPECIFIED); track.measure(widthMeasureSpec, heightMeasureSpec); diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index dcaafa5..f994d4a 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -1073,7 +1073,7 @@ public class GridView extends AbsListView { p.forceAdd = true; int childHeightSpec = getChildMeasureSpec( - MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), + MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED), 0, p.height); int childWidthSpec = getChildMeasureSpec( MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width); diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index 9d14254..056323d 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -1062,9 +1062,9 @@ public class LinearLayout extends ViewGroup { // use as much space as it wants because we can shrink things // later (and re-measure). if (baselineAligned) { - final int freeWidthSpec = MeasureSpec.makeMeasureSpec( + final int freeWidthSpec = MeasureSpec.makeSafeMeasureSpec( MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.UNSPECIFIED); - final int freeHeightSpec = MeasureSpec.makeMeasureSpec( + final int freeHeightSpec = MeasureSpec.makeSafeMeasureSpec( MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED); child.measure(freeWidthSpec, freeHeightSpec); } else { diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index f8b965f..fd0395a 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -1206,7 +1206,7 @@ public class ListView extends AbsListView { if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED); + childHeightSpec = MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); } @@ -1943,7 +1943,7 @@ public class ListView extends AbsListView { if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), + childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); @@ -2698,7 +2698,7 @@ public class ListView extends AbsListView { if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), + childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 11904e1..58a94b9 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -1263,7 +1263,7 @@ public class ScrollView extends FrameLayout { childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); - childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec( MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); @@ -1277,7 +1277,7 @@ public class ScrollView extends FrameLayout { final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width); - final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec( MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 6fe34dd..fdabe91 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -812,9 +812,9 @@ public class Spinner extends AbsSpinner implements OnClickListener { View itemView = null; int itemType = 0; final int widthMeasureSpec = - MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED); + MeasureSpec.makeSafeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED); final int heightMeasureSpec = - MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED); + MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED); // Make sure the number of items we'll measure is capped. If it's a huge data set // with wildly varying sizes, oh well. diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index aa7168c..d9cff4e 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -174,7 +174,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { // First, measure with no constraint final int width = MeasureSpec.getSize(widthMeasureSpec); - final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED); + final int unspecifiedWidth = MeasureSpec.makeSafeMeasureSpec(width, + MeasureSpec.UNSPECIFIED); mImposedTabsHeight = -1; super.measureHorizontal(unspecifiedWidth, heightMeasureSpec); diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java index d4288d6..f7f9c91 100644 --- a/core/java/android/widget/TableRow.java +++ b/core/java/android/widget/TableRow.java @@ -303,7 +303,7 @@ public class TableRow extends LinearLayout { spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT); break; case LayoutParams.MATCH_PARENT: - spec = MeasureSpec.makeMeasureSpec( + spec = MeasureSpec.makeSafeMeasureSpec( MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED); break; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 353901c..78b5d5d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8790,7 +8790,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void onProvideStructure(ViewStructure structure) { super.onProvideStructure(structure); - final boolean isPassword = hasPasswordTransformationMethod(); + final boolean isPassword = hasPasswordTransformationMethod() + || isPasswordInputType(getInputType()); if (!isPassword) { structure.setText(getText(), getSelectionStart(), getSelectionEnd()); @@ -9244,25 +9245,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * If provided, this ActionMode.Callback will be used to create the ActionMode when text * insertion is initiated in this View. - * * The standard implementation populates the menu with a subset of Select All, * Paste and Replace actions, depending on what this View supports. * - * A custom implementation can add new entries in the default menu in its - * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The - * default actions can also be removed from the menu using + * <p>A custom implementation can add new entries in the default menu in its + * {@link android.view.ActionMode.Callback#onPrepareActionMode(android.view.ActionMode, + * android.view.Menu)} method. The default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, - * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters. + * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.</p> * - * Returning false from - * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent - * the action mode from being started. + * <p>Returning false from + * {@link android.view.ActionMode.Callback#onCreateActionMode(android.view.ActionMode, + * android.view.Menu)} will prevent the action mode from being started.</p> * - * Action click events should be handled by the custom implementation of - * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}. + * <p>Action click events should be handled by the custom implementation of + * {@link android.view.ActionMode.Callback#onActionItemClicked(android.view.ActionMode, + * android.view.MenuItem)}.</p> * - * Note that text insertion mode is not started when a TextView receives focus and the - * {@link android.R.attr#selectAllOnFocus} flag has been set. + * <p>Note that text insertion mode is not started when a TextView receives focus and the + * {@link android.R.attr#selectAllOnFocus} flag has been set.</p> */ public void setCustomInsertionActionModeCallback(ActionMode.Callback actionModeCallback) { createEditorIfNeeded(); diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 42668f1..585cdf1 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -45,7 +45,7 @@ import java.util.Map; class ResolverComparator implements Comparator<ResolvedComponentInfo> { private static final String TAG = "ResolverComparator"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; // Two weeks private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 087db78..07d1fc8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4634,7 +4634,7 @@ public final class BatteryStatsImpl extends BatteryStats { @Override public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) { int bin = 0; - while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) { + while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS-1) { csph = csph >> 3; bin++; } diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 106272b..c5d3290 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -367,7 +367,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(); 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/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index d0f7591..ad3a5e2 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -84,7 +84,11 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap, jint tileModeX, jint tileModeY) { SkBitmap bitmap; - GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + if (jbitmap) { + // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise, + // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility. + GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); + } SkShader* s = SkShader::CreateBitmapShader(bitmap, (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY); diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp index 08d61d5..b9e48a0 100644 --- a/core/jni/android/graphics/SurfaceTexture.cpp +++ b/core/jni/android/graphics/SurfaceTexture.cpp @@ -49,6 +49,12 @@ struct fields_t { }; static fields_t fields; +// Get an ID that's unique within this process. +static int32_t createProcessUniqueId() { + static volatile int32_t globalCounter = 0; + return android_atomic_inc(&globalCounter); +} + // ---------------------------------------------------------------------------- static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz, @@ -253,6 +259,11 @@ static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached, "Unable to create native SurfaceTexture"); return; } + surfaceTexture->setName(String8::format("SurfaceTexture-%d-%d-%d", + (isDetached ? 0 : texName), + getpid(), + createProcessUniqueId())); + SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture); SurfaceTexture_setProducer(env, thiz, producer); diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp index afdfd8f..5bef653 100644 --- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp +++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp @@ -689,6 +689,23 @@ static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, return NO_ERROR; } +static jint LegacyCameraDevice_nativeSetScalingMode(JNIEnv* env, jobject thiz, jobject surface, + jint mode) { + ALOGV("nativeSetScalingMode"); + sp<ANativeWindow> anw; + if ((anw = getNativeWindow(env, surface)) == NULL) { + ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); + return BAD_VALUE; + } + status_t err = NO_ERROR; + if ((err = native_window_set_scaling_mode(anw.get(), static_cast<int>(mode))) != NO_ERROR) { + ALOGE("%s: Unable to set surface scaling mode, error %s (%d)", __FUNCTION__, + strerror(-err), err); + return err; + } + return NO_ERROR; +} + static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) { ALOGV("nativeGetJpegFooterSize"); return static_cast<jint>(sizeof(struct camera3_jpeg_blob)); @@ -733,6 +750,9 @@ static JNINativeMethod gCameraDeviceMethods[] = { { "nativeDetectSurfaceUsageFlags", "(Landroid/view/Surface;)I", (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags }, + { "nativeSetScalingMode", + "(Landroid/view/Surface;I)I", + (void *)LegacyCameraDevice_nativeSetScalingMode }, }; // Get all the required offsets in java class and register native functions diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 0911d42..8a79f5a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -90,7 +90,6 @@ <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" /> <protected-broadcast android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" /> - <protected-broadcast android:name="android.app.action.SEND_DEVICE_INITIALIZER_STATUS" /> <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" /> <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" /> @@ -454,6 +453,63 @@ android:description="@string/permdesc_readCellBroadcasts" android:protectionLevel="dangerous" /> + <!-- ====================================================================== --> + <!-- Permissions for accessing external storage --> + <!-- ====================================================================== --> + <eat-comment /> + + <!-- Used for runtime permissions related to the shared external storage. --> + <permission-group android:name="android.permission-group.STORAGE" + android:icon="@drawable/perm_group_storage" + android:label="@string/permgrouplab_storage" + android:description="@string/permgroupdesc_storage" + android:priority="900" /> + + <!-- Allows an application to read from external storage. + <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly + granted this permission.</p> + <p>This permission is enforced starting in API level 19. Before API level 19, this + permission is not enforced and all apps still have access to read from external storage. + You can test your app with the permission enforced by enabling <em>Protect USB + storage</em> under Developer options in the Settings app on a device running Android 4.1 or + higher.</p> + <p>Also starting in API level 19, this permission is <em>not</em> required to + read/write files in your application-specific directories returned by + {@link android.content.Context#getExternalFilesDir} and + {@link android.content.Context#getExternalCacheDir}. + <p class="note"><strong>Note:</strong> If <em>both</em> your <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code + minSdkVersion}</a> and <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code + targetSdkVersion}</a> values are set to 3 or lower, the system implicitly + grants your app this permission. If you don't need this permission, be sure your <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code + targetSdkVersion}</a> is 4 or higher.--> + <permission android:name="android.permission.READ_EXTERNAL_STORAGE" + android:permissionGroup="android.permission-group.STORAGE" + android:label="@string/permlab_sdcardRead" + android:description="@string/permdesc_sdcardRead" + android:protectionLevel="normal" /> + + <!-- Allows an application to write to external storage. + <p class="note"><strong>Note:</strong> If <em>both</em> your <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code + minSdkVersion}</a> and <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code + targetSdkVersion}</a> values are set to 3 or lower, the system implicitly + grants your app this permission. If you don't need this permission, be sure your <a + href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code + targetSdkVersion}</a> is 4 or higher. + <p>Starting in API level 19, this permission is <em>not</em> required to + read/write files in your application-specific directories returned by + {@link android.content.Context#getExternalFilesDir} and + {@link android.content.Context#getExternalCacheDir}. --> + <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" + android:permissionGroup="android.permission-group.STORAGE" + android:label="@string/permlab_sdcardWrite" + android:description="@string/permdesc_sdcardWrite" + android:protectionLevel="dangerous" /> + <!-- =============================================================== --> <!-- Permissions for accessing social info --> <!-- =============================================================== --> @@ -866,7 +922,7 @@ <permission android:name="android.permission.CHANGE_WIFI_STATE" android:description="@string/permdesc_changeWifiState" android:label="@string/permlab_changeWifiState" - android:protectionLevel="dangerous" /> + android:protectionLevel="normal" /> <!-- @SystemApi @hide Allows applications to read Wi-Fi credential. <p>Not for use by third-party applications. --> @@ -896,7 +952,7 @@ <permission android:name="android.permission.CHANGE_WIMAX_STATE" android:description="@string/permdesc_changeWimaxState" android:label="@string/permlab_changeWimaxState" - android:protectionLevel="dangerous" /> + android:protectionLevel="normal" /> <!--@SystemApi Allows applications to the the local WiFi and Bluetooth MAC address. @hide @@ -913,13 +969,13 @@ <permission android:name="android.permission.BLUETOOTH" android:description="@string/permdesc_bluetooth" android:label="@string/permlab_bluetooth" - android:protectionLevel="dangerous" /> + android:protectionLevel="normal" /> <!-- Allows applications to discover and pair bluetooth devices --> <permission android:name="android.permission.BLUETOOTH_ADMIN" android:description="@string/permdesc_bluetoothAdmin" android:label="@string/permlab_bluetoothAdmin" - android:protectionLevel="dangerous" /> + android:protectionLevel="normal" /> <!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to allow or disallow phonebook access or message access. @@ -981,33 +1037,11 @@ <!-- Allows access to the list of accounts in the Accounts Service --> <permission android:name="android.permission.GET_ACCOUNTS" - android:permissionGroup="android.permission-group.ACCOUNTS" + android:permissionGroup="android.permission-group.CONTACTS" android:protectionLevel="normal" android:description="@string/permdesc_getAccounts" android:label="@string/permlab_getAccounts" /> - <!-- Allows an application to act as an AccountAuthenticator for - the AccountManager --> - <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" - android:permissionGroup="android.permission-group.ACCOUNTS" - android:protectionLevel="dangerous" - android:label="@string/permlab_authenticateAccounts" - android:description="@string/permdesc_authenticateAccounts" /> - - <!-- Allows an application to request authtokens from the AccountManager --> - <permission android:name="android.permission.USE_CREDENTIALS" - android:permissionGroup="android.permission-group.ACCOUNTS" - android:protectionLevel="dangerous" - android:label="@string/permlab_useCredentials" - android:description="@string/permdesc_useCredentials" /> - - <!-- Allows an application to manage the list of accounts in the AccountManager --> - <permission android:name="android.permission.MANAGE_ACCOUNTS" - android:permissionGroup="android.permission-group.ACCOUNTS" - android:protectionLevel="dangerous" - android:label="@string/permlab_manageAccounts" - android:description="@string/permdesc_manageAccounts" /> - <!-- @SystemApi Allows applications to call into AccountAuthenticators. <p>Not for use by third-party applications. --> <permission android:name="android.permission.ACCOUNT_MANAGER" @@ -1023,7 +1057,7 @@ <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" android:description="@string/permdesc_changeWifiMulticastState" android:label="@string/permlab_changeWifiMulticastState" - android:protectionLevel="dangerous" /> + android:protectionLevel="normal" /> <!-- Allows access to the vibrator --> <permission android:name="android.permission.VIBRATE" @@ -1205,60 +1239,21 @@ <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" android:protectionLevel="system|signature" /> - <!-- @SystemApi Allows an application to control the in-call experience. @hide --> <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" android:protectionLevel="system|signature" /> + <!-- Allows an application to receive STK related commands. + @hide --> + <permission android:name="android.permission.RECEIVE_STK_COMMANDS" + android:protectionLevel="system|signature" /> + <!-- ================================== --> <!-- Permissions for sdcard interaction --> <!-- ================================== --> <eat-comment /> - <!-- Allows an application to read from external storage. - <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly - granted this permission.</p> - <p>This permission is enforced starting in API level 19. Before API level 19, this - permission is not enforced and all apps still have access to read from external storage. - You can test your app with the permission enforced by enabling <em>Protect USB - storage</em> under Developer options in the Settings app on a device running Android 4.1 or - higher.</p> - <p>Also starting in API level 19, this permission is <em>not</em> required to - read/write files in your application-specific directories returned by - {@link android.content.Context#getExternalFilesDir} and - {@link android.content.Context#getExternalCacheDir}. - <p class="note"><strong>Note:</strong> If <em>both</em> your <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code - minSdkVersion}</a> and <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code - targetSdkVersion}</a> values are set to 3 or lower, the system implicitly - grants your app this permission. If you don't need this permission, be sure your <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code - targetSdkVersion}</a> is 4 or higher.--> - <permission android:name="android.permission.READ_EXTERNAL_STORAGE" - android:label="@string/permlab_sdcardRead" - android:description="@string/permdesc_sdcardRead" - android:protectionLevel="normal" /> - - <!-- Allows an application to write to external storage. - <p class="note"><strong>Note:</strong> If <em>both</em> your <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code - minSdkVersion}</a> and <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code - targetSdkVersion}</a> values are set to 3 or lower, the system implicitly - grants your app this permission. If you don't need this permission, be sure your <a - href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code - targetSdkVersion}</a> is 4 or higher. - <p>Starting in API level 19, this permission is <em>not</em> required to - read/write files in your application-specific directories returned by - {@link android.content.Context#getExternalFilesDir} and - {@link android.content.Context#getExternalCacheDir}. --> - <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" - android:label="@string/permlab_sdcardWrite" - android:description="@string/permdesc_sdcardWrite" - android:protectionLevel="normal" /> - <!-- @SystemApi Allows an application to write to internal media storage @hide --> <permission android:name="android.permission.WRITE_MEDIA_STORAGE" @@ -1496,7 +1491,7 @@ <permission android:name="android.permission.WRITE_SETTINGS" android:label="@string/permlab_writeSettings" android:description="@string/permdesc_writeSettings" - android:protectionLevel="normal" /> + android:protectionLevel="dangerous" /> <!-- @SystemApi Allows an application to modify the Google service map. <p>Not for use by third-party applications. --> @@ -1603,24 +1598,6 @@ <permission android:name="android.permission.WRITE_APN_SETTINGS" android:protectionLevel="signature|system" /> - <!-- Allows an application to allow access the subscribed feeds ContentProvider. - @hide - @removed - --> - <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ" - android:label="@string/permlab_subscribedFeedsRead" - android:description="@string/permdesc_subscribedFeedsRead" - android:protectionLevel="normal" /> - - <!-- - @hide - @removed - --> - <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE" - android:label="@string/permlab_subscribedFeedsWrite" - android:description="@string/permdesc_subscribedFeedsWrite" - android:protectionLevel="dangerous" /> - <!-- Allows applications to change network connectivity state --> <permission android:name="android.permission.CHANGE_NETWORK_STATE" android:description="@string/permdesc_changeNetworkState" @@ -1630,7 +1607,7 @@ <!-- Allows an application to clear the caches of all installed applications on the device. --> <permission android:name="android.permission.CLEAR_APP_CACHE" - android:protectionLevel="dangerous" /> + android:protectionLevel="signatureOrSystem" /> <!-- @SystemApi Allows an application to use any media decoder when decoding for playback @hide --> @@ -2450,11 +2427,6 @@ <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" android:protectionLevel="signature" /> - <!-- Allows receiving status updates from a device initializer. - @hide Not for use by third-party applications. --> - <permission android:name="android.permission.RECEIVE_DEVICE_INITIALIZER_STATUS" - android:protectionLevel="signature" /> - <!-- The system process that is allowed to bind to services in carrier apps will have this permission. Carrier apps should use this permission to protect their services that only the system is allowed to bind to. --> diff --git a/core/res/res/drawable/floating_popup_background_dark.xml b/core/res/res/drawable/floating_popup_background_dark.xml new file mode 100644 index 0000000..ded1137 --- /dev/null +++ b/core/res/res/drawable/floating_popup_background_dark.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* Copyright 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. +*/ +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/background_floating_material_dark" /> + <corners android:radius="2dp" /> +</shape> + diff --git a/core/res/res/drawable/floating_popup_background.xml b/core/res/res/drawable/floating_popup_background_light.xml index b6700b3..9c7a886 100644 --- a/core/res/res/drawable/floating_popup_background.xml +++ b/core/res/res/drawable/floating_popup_background_light.xml @@ -17,7 +17,7 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <solid android:color="?attr/colorBackgroundFloating" /> + <solid android:color="@color/background_floating_material_light" /> <corners android:radius="2dp" /> </shape> diff --git a/core/res/res/drawable/ic_ab_back_material_dark.xml b/core/res/res/drawable/ic_ab_back_material_dark.xml new file mode 100644 index 0000000..7cdd139 --- /dev/null +++ b/core/res/res/drawable/ic_ab_back_material_dark.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:autoMirrored="true" + android:tint="@color/secondary_text_material_dark"> + <path + android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z" + android:fillColor="@color/white"/> +</vector> diff --git a/core/res/res/drawable/ic_ab_back_material_light.xml b/core/res/res/drawable/ic_ab_back_material_light.xml new file mode 100644 index 0000000..65dab81 --- /dev/null +++ b/core/res/res/drawable/ic_ab_back_material_light.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:autoMirrored="true" + android:tint="@color/secondary_text_material_light"> + <path + android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z" + android:fillColor="@color/white"/> +</vector> diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material.xml b/core/res/res/drawable/ic_menu_moreoverflow_material.xml index 502ad69..3f53451 100644 --- a/core/res/res/drawable/ic_menu_moreoverflow_material.xml +++ b/core/res/res/drawable/ic_menu_moreoverflow_material.xml @@ -1,3 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2014 The Android Open Source Project diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml b/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml new file mode 100644 index 0000000..fa350a6 --- /dev/null +++ b/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="@color/secondary_text_material_dark"> + <path + android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z" + android:fillColor="@color/white"/> +</vector> diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml b/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml new file mode 100644 index 0000000..7af234f --- /dev/null +++ b/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="@color/secondary_text_material_light"> + <path + android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z" + android:fillColor="@color/white"/> +</vector> diff --git a/core/res/res/drawable/item_background_borderless_material_dark.xml b/core/res/res/drawable/item_background_borderless_material_dark.xml new file mode 100644 index 0000000..685c52a --- /dev/null +++ b/core/res/res/drawable/item_background_borderless_material_dark.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/ripple_material_dark" /> diff --git a/core/res/res/drawable/item_background_borderless_material_light.xml b/core/res/res/drawable/item_background_borderless_material_light.xml new file mode 100644 index 0000000..3ef6674 --- /dev/null +++ b/core/res/res/drawable/item_background_borderless_material_light.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/ripple_material_light" /> diff --git a/core/res/res/drawable/item_background_material_dark.xml b/core/res/res/drawable/item_background_material_dark.xml new file mode 100644 index 0000000..06eb531 --- /dev/null +++ b/core/res/res/drawable/item_background_material_dark.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/ripple_material_dark"> + <item android:id="@id/mask"> + <color android:color="@color/white" /> + </item> +</ripple> diff --git a/core/res/res/drawable/item_background_material_light.xml b/core/res/res/drawable/item_background_material_light.xml new file mode 100644 index 0000000..2f3d157 --- /dev/null +++ b/core/res/res/drawable/item_background_material_light.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/ripple_material_light"> + <item android:id="@id/mask"> + <color android:color="@color/white" /> + </item> +</ripple> diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml new file mode 100644 index 0000000..11078d3 --- /dev/null +++ b/core/res/res/drawable/perm_group_storage.xml @@ -0,0 +1,24 @@ +<!-- +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="48dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:pathData="M20,8H8c-2.2,0 -4,1.8 -4,4l0,24c0,2.2 1.8,4 4,4h32c2.2,0 4,-1.8 4,-4V16c0,-2.2 -1.8,-4 -4,-4H24L20,8z" + android:fillColor="#FFFFFF"/> +</vector> diff --git a/core/res/res/layout/floating_popup_close_overflow_button.xml b/core/res/res/layout/floating_popup_close_overflow_button.xml index 0dbf7f7..4dae1ae 100644 --- a/core/res/res/layout/floating_popup_close_overflow_button.xml +++ b/core/res/res/layout/floating_popup_close_overflow_button.xml @@ -20,6 +20,6 @@ android:layout_height="match_parent" android:minWidth="@dimen/floating_toolbar_menu_button_minimum_width" android:minHeight="@dimen/floating_toolbar_height" - android:src="?android:attr/actionModeCloseDrawable" + android:src="?attr/floatingToolbarCloseDrawable" android:contentDescription="@string/floating_toolbar_close_overflow_description" - android:background="?attr/selectableItemBackgroundBorderless" /> + android:background="?attr/floatingToolbarItemBackgroundBorderlessDrawable" /> diff --git a/core/res/res/layout/floating_popup_container.xml b/core/res/res/layout/floating_popup_container.xml index f37aee1..63dae44 100644 --- a/core/res/res/layout/floating_popup_container.xml +++ b/core/res/res/layout/floating_popup_container.xml @@ -24,4 +24,4 @@ android:elevation="2dp" android:focusable="true" android:focusableInTouchMode="true" - android:background="@drawable/floating_popup_background"/> + android:background="?attr/floatingToolbarPopupBackgroundDrawable"/> diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml index b549198..1b58ce5 100644 --- a/core/res/res/layout/floating_popup_menu_button.xml +++ b/core/res/res/layout/floating_popup_menu_button.xml @@ -30,5 +30,5 @@ android:fontFamily="sans-serif-medium" android:textSize="@dimen/floating_toolbar_text_size" android:textAllCaps="true" - android:textColor="?attr/colorForeground" - android:background="?attr/selectableItemBackground" /> + android:textColor="?attr/floatingToolbarForegroundColor" + android:background="?attr/floatingToolbarItemBackgroundDrawable" /> diff --git a/core/res/res/layout/floating_popup_menu_image_button.xml b/core/res/res/layout/floating_popup_menu_image_button.xml index 07eb7a3..1ba7848 100644 --- a/core/res/res/layout/floating_popup_menu_image_button.xml +++ b/core/res/res/layout/floating_popup_menu_image_button.xml @@ -32,5 +32,5 @@ android:paddingEnd="@dimen/floating_toolbar_menu_button_side_padding" android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding" android:scaleType="centerInside" - android:background="?attr/selectableItemBackground" /> + android:background="?attr/floatingToolbarItemBackgroundDrawable" /> </LinearLayout> diff --git a/core/res/res/layout/floating_popup_open_overflow_button.xml b/core/res/res/layout/floating_popup_open_overflow_button.xml index 3027565..f6a3e8d 100644 --- a/core/res/res/layout/floating_popup_open_overflow_button.xml +++ b/core/res/res/layout/floating_popup_open_overflow_button.xml @@ -24,6 +24,6 @@ android:paddingTop="0dp" android:paddingBottom="0dp" android:paddingEnd="4dp" - android:src="@drawable/ic_menu_moreoverflow_material" + android:src="?attr/floatingToolbarOpenDrawable" android:contentDescription="@string/floating_toolbar_open_overflow_description" - android:background="?attr/selectableItemBackgroundBorderless" /> + android:background="?attr/floatingToolbarItemBackgroundBorderlessDrawable" /> diff --git a/core/res/res/layout/floating_popup_overflow_list_item.xml b/core/res/res/layout/floating_popup_overflow_list_item.xml index 2ff45bb..22f4e68 100644 --- a/core/res/res/layout/floating_popup_overflow_list_item.xml +++ b/core/res/res/layout/floating_popup_overflow_list_item.xml @@ -31,6 +31,6 @@ android:ellipsize="end" android:fontFamily="sans-serif-medium" android:textSize="@dimen/floating_toolbar_text_size" - android:textColor="?attr/colorForeground" + android:textColor="?attr/floatingToolbarForegroundColor" android:textAllCaps="true" /> diff --git a/core/res/res/layout/media_route_controller_dialog.xml b/core/res/res/layout/media_route_controller_dialog.xml index 78287e0..0bf70da 100644 --- a/core/res/res/layout/media_route_controller_dialog.xml +++ b/core/res/res/layout/media_route_controller_dialog.xml @@ -14,47 +14,50 @@ limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:divider="?android:attr/dividerHorizontal" - android:showDividers="middle"> - <!-- Optional volume slider section. --> - <LinearLayout android:id="@+id/media_route_volume_layout" - android:layout_width="match_parent" - android:layout_height="64dp" - android:gravity="center_vertical" - android:padding="8dp" - android:visibility="gone"> - <ImageView android:layout_width="48dp" - android:layout_height="48dp" - android:src="@drawable/ic_audio_vol" - android:gravity="center" - android:scaleType="center" /> - <SeekBar android:id="@+id/media_route_volume_slider" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" /> - </LinearLayout> - - <!-- Optional content view section. --> - <FrameLayout android:id="@+id/media_route_control_frame" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:visibility="gone" /> - - <!-- Disconnect button. --> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - style="?attr/buttonBarStyle"> - <Button android:id="@+id/media_route_disconnect_button" - android:layout_width="match_parent" - android:layout_height="match_parent" - style="?attr/buttonBarButtonStyle" - android:gravity="center" - android:text="@string/media_route_controller_disconnect" /> + android:orientation="vertical" + android:divider="?android:attr/dividerHorizontal" + android:showDividers="middle"> + <!-- Optional volume slider section. --> + <LinearLayout android:id="@+id/media_route_volume_layout" + android:layout_width="match_parent" + android:layout_height="64dp" + android:gravity="center_vertical" + android:padding="8dp" + android:visibility="gone"> + <ImageView android:layout_width="48dp" + android:layout_height="48dp" + android:src="@drawable/ic_audio_vol" + android:gravity="center" + android:scaleType="center" /> + <SeekBar android:id="@+id/media_route_volume_slider" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" /> + </LinearLayout> + + <!-- Optional content view section. --> + <FrameLayout android:id="@+id/media_route_control_frame" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> + + <!-- Disconnect button. --> + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?attr/buttonBarStyle"> + <Button android:id="@+id/media_route_disconnect_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + style="?attr/buttonBarButtonStyle" + android:gravity="center" + android:text="@string/media_route_controller_disconnect" /> + </LinearLayout> </LinearLayout> -</LinearLayout> +</ScrollView>
\ No newline at end of file diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index d5c2d19..a3cc4ae 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -310,7 +310,11 @@ <item>@drawable/fastscroll_label_right_material</item> <item>@drawable/fastscroll_thumb_material</item> <item>@drawable/fastscroll_track_material</item> + <item>@drawable/floating_popup_background_dark</item> + <item>@drawable/floating_popup_background_light</item> <item>@drawable/ic_ab_back_material</item> + <item>@drawable/ic_ab_back_material_dark</item> + <item>@drawable/ic_ab_back_material_light</item> <item>@drawable/ic_clear_material</item> <item>@drawable/ic_commit_search_api_material</item> <item>@drawable/ic_dialog_alert_material</item> @@ -330,7 +334,11 @@ <item>@drawable/ic_search_api_material</item> <item>@drawable/ic_voice_search_api_material</item> <item>@drawable/item_background_borderless_material</item> + <item>@drawable/item_background_borderless_material_dark</item> + <item>@drawable/item_background_borderless_material_light</item> <item>@drawable/item_background_material</item> + <item>@drawable/item_background_material_dark</item> + <item>@drawable/item_background_material_light</item> <item>@drawable/list_divider_material</item> <item>@drawable/list_section_divider_material</item> <item>@drawable/notification_material_action_background</item> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 52e2cf0..c08d511 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -550,6 +550,17 @@ <attr name="windowTransitionBackgroundFadeDuration" format="integer"/> <!-- ============ --> + <!-- Floating toolbar styles --> + <!-- ============ --> + <eat-comment /> + <attr name="floatingToolbarCloseDrawable" format="reference" /> + <attr name="floatingToolbarForegroundColor" format="reference|color" /> + <attr name="floatingToolbarItemBackgroundBorderlessDrawable" format="reference" /> + <attr name="floatingToolbarItemBackgroundDrawable" format="reference" /> + <attr name="floatingToolbarOpenDrawable" format="reference" /> + <attr name="floatingToolbarPopupBackgroundDrawable" format="reference" /> + + <!-- ============ --> <!-- Alert Dialog styles --> <!-- ============ --> <eat-comment /> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 470e345..f31c1d6 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1058,18 +1058,20 @@ lockTask mode is disabled. <p>While in lockTask mode with multiple permitted tasks running, each launched task is permitted to finish, transitioning to the previous locked task, until there is only one - task remaining. At that point the last task running is not permitted to finish. --> + task remaining. At that point the last task running is not permitted to finish, unless it + uses the value always. --> <attr name="lockTaskMode"> <!-- This is the default value. Tasks will not launch into lockTask mode but can be placed there by calling {@link android.app.Activity#startLockTask}. If a task with this mode has been whitelisted using {@link - android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling startLockTask - will enter lockTask mode immediately, otherwise the user will be presented with a - dialog to approve entering lockTask mode. + android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling + {@link android.app.Activity#startLockTask} will enter lockTask mode immediately, + otherwise the user will be presented with a dialog to approve entering pinned mode. <p>If the system is already in lockTask mode when a new task rooted at this activity is launched that task will or will not start depending on whether the package of this activity has been whitelisted. - <p>Tasks rooted at this activity can only exit lockTask mode using stopLockTask(). --> + <p>Tasks rooted at this activity can only exit lockTask mode using + {@link android.app.Activity#stopLockTask}. --> <enum name="normal" value="0"/> <!-- Tasks will not launch into lockTask mode and cannot be placed there using {@link android.app.Activity#startLockTask} or be pinned from the Overview screen. @@ -1082,16 +1084,17 @@ <!-- Tasks rooted at this activity will always launch into lockTask mode. If the system is already in lockTask mode when this task is launched then the new task will be launched on top of the current task. Tasks launched in this mode are capable of exiting - lockTask mode using finish(), whereas tasks entering lockTask mode using - startLockTask() must use stopLockTask() to exit. + lockTask mode using {@link android.app.Activity#finish()}. <p>Note: This mode is only available to system and privileged applications. Non-privileged apps with this value will be treated as normal. --> <enum name="always" value="2"/> <!-- If the DevicePolicyManager (DPM) authorizes this package ({@link android.app.admin.DevicePolicyManager#setLockTaskPackages}) then this mode is - identical to always. If the DPM does not authorize this package then this - mode is identical to normal. --> + identical to always, except that the activity needs to call + {@link android.app.Activity#stopLockTask} before being able to finish if it is the last + locked task. + If the DPM does not authorize this package then this mode is identical to normal. --> <enum name="if_whitelisted" value="3"/> </attr> <!-- When set installer will extract native libraries. If set to false diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index db1ac44..e7811df 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -572,6 +572,43 @@ true here reverses that logic. --> <bool name="config_reverseDefaultRotation">false</bool> + <!-- Sets the minimum and maximum tilt tolerance for each possible rotation. + This array consists of 4 pairs of values which specify the minimum and maximum + tilt angle at which the device will transition into each rotation. + + The tilt angle represents the direction in which the plane of the screen is facing; + it is also known as the angle of elevation. + + -90 degree tilt means that the screen is facing straight down + (the device is being held overhead upside-down) + 0 degree tilt means that the screen is facing outwards + (the device is being held vertically) + 90 degree tilt means that the screen is facing straight up + (the device is resting on a flat table) + + The default tolerances are set conservatively such that the device is more + likely to remain in its natural orientation than rotate into a counterclockwise, + clockwise, or reversed posture (with an especially strong bias against the latter) + to prevent accidental rotation while carrying the device in hand. + + These thresholds may need to be tuned when the device is intended to be + mounted into a dock with a particularly shallow profile wherein rotation + would ordinarily have been suppressed. + + It is helpful to consider the desired behavior both when the device is being + held at a positive tilt (typical case) vs. a negative tilt (reading overhead in + bed) since they are quite different. In the overhead case, we typically want + the device to more strongly prefer to retain its current configuration (in absence + of a clear indication that a rotation is desired) since the user's head and neck may + be held at an unusual angle. + --> + <integer-array name="config_autoRotationTiltTolerance"> + <!-- rotation: 0 (natural) --> <item>-25</item> <item>70</item> + <!-- rotation: 90 (rotate CCW) --> <item>-25</item> <item>65</item> + <!-- rotation: 180 (reverse) --> <item>-25</item> <item>60</item> + <!-- rotation: 270 (rotate CW) --> <item>-25</item> <item>65</item> + </integer-array> + <!-- Lid switch behavior --> <!-- The number of degrees to rotate the display when the keyboard is open. diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 28274ae..a6b7e35 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -566,7 +566,12 @@ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_sms">SMS</string> <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgroupdesc_sms">view and manage SMS messages</string> + <string name="permgroupdesc_sms">send and view SMS messages</string> + + <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permgrouplab_storage">Storage</string> + <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permgroupdesc_storage">access photos, media, and files on your device</string> <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_dictionary">User Dictionary</string> @@ -596,7 +601,7 @@ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_sensors">Sensors</string> <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgroupdesc_sensors">access data from sensors and wearable devices</string> + <string name="permgroupdesc_sensors">access information about your vital signs and physical activity</string> <!-- Title for the capability of an accessibility service to retrieve window content. --> <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string> @@ -1113,27 +1118,6 @@ the list of accounts known by the phone. This may include any accounts created by applications you have installed.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_authenticateAccounts">create accounts and set passwords</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_authenticateAccounts">Allows the app - to use the account authenticator capabilities of the - AccountManager, including creating accounts and getting and - setting their passwords.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_manageAccounts">add or remove accounts</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_manageAccounts">Allows the app to - perform operations like adding and removing accounts, and deleting - their password.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_useCredentials">use accounts on the device</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_useCredentials">Allows the app to request authentication tokens.</string> - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_accessNetworkState">view network connections</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> @@ -1302,12 +1286,6 @@ <string name="permdesc_readSyncStats">Allows an app to read the sync stats for an account, including the history of sync events and how much data is synced. </string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_subscribedFeedsWrite">write subscribed feeds</string> - <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_subscribedFeedsWrite">Allows the app to modify - your currently synced feeds. Malicious apps may change your synced feeds.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readDictionary">read terms you added to the dictionary</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_readDictionary">Allows the app to read all words, @@ -4207,4 +4185,9 @@ notification_template_material_inbox.xml. DO NOT TRANSLATE --> <string name="notification_inbox_ellipsis">\u2026</string> + + <!-- Label describing the number of selected items [CHAR LIMIT=48] --> + <plurals name="selected_count"> + <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item> + </plurals> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8900688..361c0bd 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1451,6 +1451,7 @@ <java-symbol type="anim" name="voice_activity_open_exit" /> <java-symbol type="anim" name="voice_activity_open_enter" /> + <java-symbol type="array" name="config_autoRotationTiltTolerance" /> <java-symbol type="array" name="config_keyboardTapVibePattern" /> <java-symbol type="array" name="config_longPressVibePattern" /> <java-symbol type="array" name="config_safeModeDisabledVibePattern" /> @@ -2306,5 +2307,6 @@ <java-symbol type="string" name="ext_media_status_missing" /> <java-symbol type="string" name="ext_media_unsupported_notification_message" /> <java-symbol type="string" name="ext_media_unsupported_notification_title" /> + <java-symbol type="plurals" name="selected_count" /> </resources> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index ecf00f0..b7acdd4 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -389,6 +389,14 @@ please see themes_device_defaults.xml. <item name="segmentedButtonStyle">@style/SegmentedButton</item> <item name="fingerprintAuthDrawable">@drawable/ic_fingerprint</item> + <!-- Floating toolbar styles --> + <item name="floatingToolbarCloseDrawable">@drawable/ic_ab_back_material_dark</item> + <item name="floatingToolbarForegroundColor">@color/foreground_material_dark</item> + <item name="floatingToolbarItemBackgroundBorderlessDrawable">@drawable/item_background_borderless_material_dark</item> + <item name="floatingToolbarItemBackgroundDrawable">@drawable/item_background_material_dark</item> + <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_dark</item> + <item name="floatingToolbarPopupBackgroundDrawable">@drawable/floating_popup_background_dark</item> + <!-- SearchView attributes --> <item name="searchViewStyle">@style/Widget.Holo.SearchView</item> <item name="searchDialogTheme">@style/Theme.SearchBar</item> @@ -538,6 +546,14 @@ please see themes_device_defaults.xml. <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.Light.MediaRouteButton</item> <item name="findOnPageNextDrawable">@drawable/ic_find_next_holo_light</item> <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_holo_light</item> + + <!-- Floating toolbar styles --> + <item name="floatingToolbarCloseDrawable">@drawable/ic_ab_back_material_light</item> + <item name="floatingToolbarForegroundColor">@color/foreground_material_light</item> + <item name="floatingToolbarItemBackgroundBorderlessDrawable">@drawable/item_background_borderless_material_light</item> + <item name="floatingToolbarItemBackgroundDrawable">@drawable/item_background_material_light</item> + <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_light</item> + <item name="floatingToolbarPopupBackgroundDrawable">@drawable/floating_popup_background_light</item> </style> <!-- Variant of {@link #Theme_Light} with no title bar --> diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index ee9e2e4..ac5abad 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -232,6 +232,18 @@ public class FileUtilsTest extends AndroidTestCase { assertEquals("foo_bar__baz", FileUtils.buildValidFatFilename("foo?bar**baz")); } + public void testTrimFilename() throws Exception { + assertEquals("short.txt", FileUtils.trimFilename("short.txt", 16)); + assertEquals("extrem...eme.txt", FileUtils.trimFilename("extremelylongfilename.txt", 16)); + + final String unicode = "a\u03C0\u03C0\u03C0\u03C0z"; + assertEquals("a\u03C0\u03C0\u03C0\u03C0z", FileUtils.trimFilename(unicode, 10)); + assertEquals("a\u03C0...\u03C0z", FileUtils.trimFilename(unicode, 9)); + assertEquals("a...\u03C0z", FileUtils.trimFilename(unicode, 8)); + assertEquals("a...\u03C0z", FileUtils.trimFilename(unicode, 7)); + assertEquals("a...z", FileUtils.trimFilename(unicode, 6)); + } + public void testBuildUniqueFile_normal() throws Exception { assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test")); assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg")); |
