diff options
Diffstat (limited to 'core/java')
42 files changed, 1032 insertions, 261 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 4761f98..bf9e07d 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -66,10 +66,10 @@ public class AccessibilityServiceInfo implements Parcelable { * The event types an {@link AccessibilityService} is interested in. * * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED - * @see android.view.accessibility.AccessibilityEvent#TYPE_ACTIVITY_STARTED * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED */ @@ -115,7 +115,7 @@ public class AccessibilityServiceInfo implements Parcelable { return 0; } - public void writeToParcel(Parcel parcel, int flags) { + public void writeToParcel(Parcel parcel, int flagz) { parcel.writeInt(eventTypes); parcel.writeStringArray(packageNames); parcel.writeInt(feedbackType); diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index be2bdbe..8bc7428 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -296,8 +296,7 @@ public abstract class AbstractAccountAuthenticator { * <ul> * <li> {@link AccountManager#KEY_INTENT}, or * <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of - * the account that was added, plus {@link AccountManager#KEY_AUTHTOKEN} if an authTokenType - * was supplied, or + * the account that was added, or * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to * indicate an error * </ul> @@ -368,8 +367,7 @@ public abstract class AbstractAccountAuthenticator { * <ul> * <li> {@link AccountManager#KEY_INTENT}, or * <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of - * the account that was added, plus {@link AccountManager#KEY_AUTHTOKEN} if an authTokenType - * was supplied, or + * the account that was added, or * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to * indicate an error * </ul> @@ -378,7 +376,7 @@ public abstract class AbstractAccountAuthenticator { */ public abstract Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException; - + /** * Checks if the account supports all the specified authenticator specific features. * @param response to send the result back to the AccountManager, will never be null diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index be15ac9..43a0f30 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -67,6 +67,8 @@ import com.google.android.collect.Maps; * cause the running thread to block until the result is returned. Keep in mind that one * should not block the main thread in this way. Instead one should either use a callback, * thus making the call asynchronous, or make the blocking call on a separate thread. + * getResult() will throw an {@link IllegalStateException} if you call it from the main thread + * before the request has completed, i.e. before the callback has been invoked. * <p> * If one wants to ensure that the callback is invoked from a specific handler then they should * pass the handler to the request. This makes it easier to ensure thread-safety by running @@ -149,6 +151,8 @@ public class AccountManager { * Get the password that is associated with the account. Returns null if the account does * not exist. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -166,6 +170,8 @@ public class AccountManager { * Get the user data named by "key" that is associated with the account. * Returns null if the account does not exist or if it does not have a value for key. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -185,6 +191,8 @@ public class AccountManager { * @return an array that contains all the authenticators known to the AccountManager service. * This array will be empty if there are no authenticators and will never return null. * <p> + * It is safe to call this method from the main thread. + * <p> * No permission is required to make this call. */ public AuthenticatorDescription[] getAuthenticatorTypes() { @@ -201,6 +209,8 @@ public class AccountManager { * @return an array that contains all the accounts known to the AccountManager service. * This array will be empty if there are no accounts and will never return null. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS} */ public Account[] getAccounts() { @@ -219,6 +229,8 @@ public class AccountManager { * @return an array that contains the accounts that match the specified type. This array * will be empty if no accounts match. It will never return null. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS} */ public Account[] getAccountsByType(String type) { @@ -243,6 +255,22 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Boolean result = hasFeatures(account, features, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * hasFeatures(account, features, new AccountManagerCallback<Boolean>() { + * public void run(AccountManagerFuture<Boolean> future) { + * Boolean result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}. * * @param account The {@link Account} to test @@ -274,6 +302,8 @@ public class AccountManager { /** * Add an account to the AccountManager's set of known accounts. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -304,6 +334,22 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Boolean result = removeAccount(account, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * removeAccount(account, new AccountManagerCallback<Boolean>() { + * public void run(AccountManagerFuture<Boolean> future) { + * Boolean result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * * @param account The {@link Account} to remove @@ -334,6 +380,8 @@ public class AccountManager { * Removes the given authtoken. If this authtoken does not exist for the given account type * then this call has no effect. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * @param accountType the account type of the authtoken to invalidate * @param authToken the authtoken to invalidate @@ -353,6 +401,8 @@ public class AccountManager { * asking the authenticaticor to generate one. If the account or the * authtoken do not exist then null is returned. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -381,6 +431,8 @@ public class AccountManager { * Sets the password for the account. The password may be null. If the account does not exist * then this call has no affect. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -404,6 +456,8 @@ public class AccountManager { * Sets the password for account to null. If the account does not exist then this call * has no effect. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * @param account the account whose password is to be cleared. Must not be null. */ @@ -424,6 +478,8 @@ public class AccountManager { * Sets account's userdata named "key" to the specified value. If the account does not * exist then this call has no effect. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -452,6 +508,8 @@ public class AccountManager { * Sets the authtoken named by "authTokenType" to the value specified by authToken. * If the account does not exist then this call has no effect. * <p> + * It is safe to call this method from the main thread. + * <p> * Requires that the caller has permission * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and is running * with the same UID as the Authenticator for the account. @@ -473,6 +531,8 @@ public class AccountManager { * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, Handler)} * then extracts and returns the value of {@link #KEY_AUTHTOKEN} from its result. * <p> + * It is not safe to call this method from the main thread. See {@link #getAuthToken}. + * <p> * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. * @param account the account whose authtoken is to be retrieved, must not be null * @param authTokenType the type of authtoken to retrieve @@ -505,9 +565,8 @@ public class AccountManager { * in the result. * <p> * If the authenticator needs to prompt the user for credentials it will return an intent to - * the activity that will do the prompting. If an activity is supplied then that activity - * will be used to launch the intent and the result will come from it. Otherwise a result will - * be returned that contains the intent. + * an activity that will do the prompting. The supplied activity will be used to launch the + * intent and the result will come from the launched activity. * <p> * This call returns immediately but runs asynchronously and the result is accessed via the * {@link AccountManagerFuture} that is returned. This future is also passed as the sole @@ -518,6 +577,23 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = getAuthToken( + * account, authTokenType, options, activity, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * getAuthToken(account, authTokenType, options, activity, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. * * @param account The account whose credentials are to be updated. @@ -525,8 +601,9 @@ public class AccountManager { * May be null. * @param options authenticator specific options for the request * @param activity If the authenticator returns a {@link #KEY_INTENT} in the result then - * the intent will be started with this activity. If activity is null then the result will - * be returned as-is. + * the intent will be started with this activity. If you do not with to have the intent + * started automatically then use the other form, + * {@link #getAuthToken(Account, String, boolean, AccountManagerCallback, android.os.Handler)} * @param callback A callback to invoke when the request completes. If null then * no callback is invoked. * @param handler The {@link Handler} to use to invoke the callback. If null then the @@ -578,6 +655,23 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = getAuthToken( + * account, authTokenType, notifyAuthFailure, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * getAuthToken(account, authTokenType, notifyAuthFailure, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#USE_CREDENTIALS}. * * @param account The account whose credentials are to be updated. @@ -625,6 +719,23 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = addAccount( + * account, authTokenType, features, options, activity, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * addAccount(account, authTokenType, features, options, activity, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * * @param accountType The type of account to add. This must not be null. @@ -646,7 +757,6 @@ public class AccountManager { * <ul> * <li> {@link #KEY_INTENT}, or * <li> {@link #KEY_ACCOUNT_NAME}, {@link #KEY_ACCOUNT_TYPE} - * and {@link #KEY_AUTHTOKEN} (if an authTokenType was specified). * </ul> */ public AccountManagerFuture<Bundle> addAccount(final String accountType, @@ -667,6 +777,51 @@ public class AccountManager { }.start(); } + /** + * Queries for accounts that match the given account type and feature set. + * <p> + * This call returns immediately but runs asynchronously and the result is accessed via the + * {@link AccountManagerFuture} that is returned. This future is also passed as the sole + * parameter to the {@link AccountManagerCallback}. If the caller wished to use this + * method asynchronously then they will generally pass in a callback object that will get + * invoked with the {@link AccountManagerFuture}. If they wish to use it synchronously then + * they will generally pass null for the callback and instead call + * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, + * which will then block until the request completes. + * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Account[] result = + * getAccountsByTypeAndFeatures(accountType, features, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * getAccountsByTypeAndFeatures(accountType, features, new AccountManagerCallback<Account[]>() { + * public void run(AccountManagerFuture<Account[]> future) { + * Account[] result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> + * Requires that the caller has permission {@link android.Manifest.permission#GET_ACCOUNTS}. + * + * @param type The type of {@link Account} to return. If null is passed in then an empty + * array will be returned. + * @param features the features with which to filter the accounts list. Each returned account + * will have all specified features. This may be null, which will mean the account list will + * not be filtered by features, making this functionally identical to + * {@link #getAccountsByType(String)}. + * @param callback A callback to invoke when the request completes. If null then + * no callback is invoked. + * @param handler The {@link Handler} to use to invoke the callback. If null then the + * main thread's {@link Handler} is used. + * @return an {@link AccountManagerFuture} that represents the future result of the call. + * The future result is a an {@link Account} array that contains accounts of the specified + * type that match all the requested features. + */ public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( final String type, final String[] features, AccountManagerCallback<Account[]> callback, Handler handler) { @@ -709,6 +864,23 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = confirmCredentials( + * account, options, activity, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * confirmCredentials(account, options, activity, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * * @param account The account whose credentials are to be checked @@ -757,6 +929,23 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = updateCredentials( + * account, authTokenType, options, activity, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * updateCredentials(account, authTokenType, options, activity, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * * @param account The account whose credentials are to be updated. @@ -775,7 +964,7 @@ public class AccountManager { * <ul> * <li> {@link #KEY_INTENT}, which is to be used to prompt the user for the credentials * <li> {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE} if the user enters the correct - * credentials, and optionally a {@link #KEY_AUTHTOKEN} if an authTokenType was provided. + * credentials. * </ul> * If the user presses "back" then the request will be canceled. */ @@ -807,6 +996,22 @@ public class AccountManager { * {@link android.accounts.AccountManagerFuture#getResult()} on this method's return value, * which will then block until the request completes. * <p> + * Do not block the main thread waiting this method's result. + * <p> + * Not allowed from main thread (but allowed from other threads): + * <pre> + * Bundle result = editProperties(accountType, activity, callback, handler).getResult(); + * </pre> + * Allowed from main thread: + * <pre> + * editProperties(accountType, activity, new AccountManagerCallback<Bundle>() { + * public void run(AccountManagerFuture<Bundle> future) { + * Bundle result = future.getResult(); + * // use result + * } + * }, handler); + * </pre> + * <p> * Requires that the caller has permission {@link android.Manifest.permission#MANAGE_ACCOUNTS}. * * @param accountType The account type of the authenticator whose properties are to be edited. diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 7850124..770554e 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -466,7 +466,8 @@ public class AccountManagerService public TestFeaturesSession(IAccountManagerResponse response, Account account, String[] features) { - super(response, account.type, false /* expectActivityLaunch */); + super(response, account.type, false /* expectActivityLaunch */, + true /* stripAuthTokenFromResult */); mFeatures = features; mAccount = account; } @@ -520,7 +521,8 @@ public class AccountManagerService private class RemoveAccountSession extends Session { final Account mAccount; public RemoveAccountSession(IAccountManagerResponse response, Account account) { - super(response, account.type, false /* expectActivityLaunch */); + super(response, account.type, false /* expectActivityLaunch */, + true /* stripAuthTokenFromResult */); mAccount = account; } @@ -794,7 +796,8 @@ public class AccountManagerService } } - new Session(response, account.type, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch, + false /* stripAuthTokenFromResult */) { protected String toDebugString(long now) { if (loginOptions != null) loginOptions.keySet(); return super.toDebugString(now) + ", getAuthToken" @@ -945,7 +948,8 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, accountType, expectActivityLaunch) { + new Session(response, accountType, expectActivityLaunch, + true /* stripAuthTokenFromResult */) { public void run() throws RemoteException { mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures, options); @@ -970,7 +974,8 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, account.type, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch, + true /* stripAuthTokenFromResult */) { public void run() throws RemoteException { mAuthenticator.confirmCredentials(this, account, options); } @@ -990,7 +995,8 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, account.type, expectActivityLaunch) { + new Session(response, account.type, expectActivityLaunch, + true /* stripAuthTokenFromResult */) { public void run() throws RemoteException { mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions); } @@ -1012,7 +1018,8 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { - new Session(response, accountType, expectActivityLaunch) { + new Session(response, accountType, expectActivityLaunch, + true /* stripAuthTokenFromResult */) { public void run() throws RemoteException { mAuthenticator.editProperties(this, mAccountType); } @@ -1034,7 +1041,8 @@ public class AccountManagerService public GetAccountsByTypeAndFeatureSession(IAccountManagerResponse response, String type, String[] features) { - super(response, type, false /* expectActivityLaunch */); + super(response, type, false /* expectActivityLaunch */, + true /* stripAuthTokenFromResult */); mFeatures = features; } @@ -1176,11 +1184,14 @@ public class AccountManagerService IAccountAuthenticator mAuthenticator = null; + private final boolean mStripAuthTokenFromResult; + public Session(IAccountManagerResponse response, String accountType, - boolean expectActivityLaunch) { + boolean expectActivityLaunch, boolean stripAuthTokenFromResult) { super(); if (response == null) throw new IllegalArgumentException("response is null"); if (accountType == null) throw new IllegalArgumentException("accountType is null"); + mStripAuthTokenFromResult = stripAuthTokenFromResult; mResponse = response; mAccountType = accountType; mExpectActivityLaunch = expectActivityLaunch; @@ -1319,6 +1330,9 @@ public class AccountManagerService response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle returned"); } else { + if (mStripAuthTokenFromResult) { + result.remove(AccountManager.KEY_AUTHTOKEN); + } response.onResult(result); } } catch (RemoteException e) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 56e44c8..13cc3ba 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1392,7 +1392,7 @@ public final class ActivityThread { r.startsNotResumed = notResumed; r.createdConfig = config; - synchronized (mRelaunchingActivities) { + synchronized (mPackages) { mRelaunchingActivities.add(r); } @@ -1523,8 +1523,11 @@ public final class ActivityThread { } public void scheduleConfigurationChanged(Configuration config) { - synchronized (mRelaunchingActivities) { - mPendingConfiguration = config; + synchronized (mPackages) { + if (mPendingConfiguration == null || + mPendingConfiguration.isOtherSeqNewer(config)) { + mPendingConfiguration = config; + } } queueOrSendMessage(H.CONFIGURATION_CHANGED, config); } @@ -2060,6 +2063,7 @@ public final class ActivityThread { = new HashMap<IBinder, Service>(); AppBindData mBoundApplication; Configuration mConfiguration; + Configuration mResConfiguration; Application mInitialApplication; final ArrayList<Application> mAllApplications = new ArrayList<Application>(); @@ -2073,14 +2077,6 @@ public final class ActivityThread { boolean mSystemThread = false; boolean mJitEnabled = false; - /** - * Activities that are enqueued to be relaunched. This list is accessed - * by multiple threads, so you must synchronize on it when accessing it. - */ - final ArrayList<ActivityRecord> mRelaunchingActivities - = new ArrayList<ActivityRecord>(); - Configuration mPendingConfiguration = null; - // These can be accessed by multiple threads; mPackages is the lock. // XXX For now we keep around information about all packages we have // seen, not removing entries from this map. @@ -2092,6 +2088,9 @@ public final class ActivityThread { DisplayMetrics mDisplayMetrics = null; HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources = new HashMap<ResourcesKey, WeakReference<Resources> >(); + final ArrayList<ActivityRecord> mRelaunchingActivities + = new ArrayList<ActivityRecord>(); + Configuration mPendingConfiguration = null; // The lock of mProviderMap protects the following variables. final HashMap<String, ProviderRecord> mProviderMap @@ -3555,7 +3554,7 @@ public final class ActivityThread { // First: make sure we have the most recent configuration and most // recent version of the activity, or skip it if some previous call // had taken a more recent version. - synchronized (mRelaunchingActivities) { + synchronized (mPackages) { int N = mRelaunchingActivities.size(); IBinder token = tmp.token; tmp = null; @@ -3585,8 +3584,12 @@ public final class ActivityThread { // assume that is really what we want regardless of what we // may have pending. if (mConfiguration == null - || mConfiguration.diff(tmp.createdConfig) != 0) { - changedConfig = tmp.createdConfig; + || (tmp.createdConfig.isOtherSeqNewer(mConfiguration) + && mConfiguration.diff(tmp.createdConfig) != 0)) { + if (changedConfig == null + || tmp.createdConfig.isOtherSeqNewer(changedConfig)) { + changedConfig = tmp.createdConfig; + } } } @@ -3761,62 +3764,81 @@ public final class ActivityThread { } } + final void applyConfigurationToResourcesLocked(Configuration config) { + if (mResConfiguration == null) { + mResConfiguration = new Configuration(); + } + if (!mResConfiguration.isOtherSeqNewer(config)) { + return; + } + mResConfiguration.updateFrom(config); + DisplayMetrics dm = getDisplayMetricsLocked(true); + + // set it for java, this also affects newly created Resources + if (config.locale != null) { + Locale.setDefault(config.locale); + } + + Resources.updateSystemConfiguration(config, dm); + + ContextImpl.ApplicationPackageManager.configurationChanged(); + //Log.i(TAG, "Configuration changed in " + currentPackageName()); + + Iterator<WeakReference<Resources>> it = + mActiveResources.values().iterator(); + //Iterator<Map.Entry<String, WeakReference<Resources>>> it = + // mActiveResources.entrySet().iterator(); + while (it.hasNext()) { + WeakReference<Resources> v = it.next(); + Resources r = v.get(); + if (r != null) { + r.updateConfiguration(config, dm); + //Log.i(TAG, "Updated app resources " + v.getKey() + // + " " + r + ": " + r.getConfiguration()); + } else { + //Log.i(TAG, "Removing old resources " + v.getKey()); + it.remove(); + } + } + } + final void handleConfigurationChanged(Configuration config) { - synchronized (mRelaunchingActivities) { + ArrayList<ComponentCallbacks> callbacks = null; + + synchronized (mPackages) { if (mPendingConfiguration != null) { - config = mPendingConfiguration; + if (!mPendingConfiguration.isOtherSeqNewer(config)) { + config = mPendingConfiguration; + } mPendingConfiguration = null; } - } - - ArrayList<ComponentCallbacks> callbacks - = new ArrayList<ComponentCallbacks>(); - if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: " - + config); + if (config == null) { + return; + } + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: " + + config); - synchronized(mPackages) { + applyConfigurationToResourcesLocked(config); + if (mConfiguration == null) { mConfiguration = new Configuration(); } - mConfiguration.updateFrom(config); - DisplayMetrics dm = getDisplayMetricsLocked(true); - - // set it for java, this also affects newly created Resources - if (config.locale != null) { - Locale.setDefault(config.locale); - } - - Resources.updateSystemConfiguration(config, dm); - - ContextImpl.ApplicationPackageManager.configurationChanged(); - //Log.i(TAG, "Configuration changed in " + currentPackageName()); - { - Iterator<WeakReference<Resources>> it = - mActiveResources.values().iterator(); - //Iterator<Map.Entry<String, WeakReference<Resources>>> it = - // mActiveResources.entrySet().iterator(); - while (it.hasNext()) { - WeakReference<Resources> v = it.next(); - Resources r = v.get(); - if (r != null) { - r.updateConfiguration(config, dm); - //Log.i(TAG, "Updated app resources " + v.getKey() - // + " " + r + ": " + r.getConfiguration()); - } else { - //Log.i(TAG, "Removing old resources " + v.getKey()); - it.remove(); - } - } + if (!mConfiguration.isOtherSeqNewer(config)) { + return; } + mConfiguration.updateFrom(config); callbacks = collectComponentCallbacksLocked(false, config); } - final int N = callbacks.size(); - for (int i=0; i<N; i++) { - performConfigurationChanged(callbacks.get(i), config); + if (callbacks != null) { + final int N = callbacks.size(); + for (int i=0; i<N; i++) { + performConfigurationChanged(callbacks.get(i), config); + } } } @@ -3856,7 +3878,7 @@ public final class ActivityThread { ArrayList<ComponentCallbacks> callbacks = new ArrayList<ComponentCallbacks>(); - synchronized(mPackages) { + synchronized (mPackages) { callbacks = collectComponentCallbacksLocked(true, null); } @@ -4348,6 +4370,25 @@ public final class ActivityThread { "Unable to instantiate Application():" + e.toString(), e); } } + + ViewRoot.addConfigCallback(new ComponentCallbacks() { + public void onConfigurationChanged(Configuration newConfig) { + synchronized (mPackages) { + if (mPendingConfiguration == null || + mPendingConfiguration.isOtherSeqNewer(newConfig)) { + mPendingConfiguration = newConfig; + + // We need to apply this change to the resources + // immediately, because upon returning the view + // hierarchy will be informed about it. + applyConfigurationToResourcesLocked(newConfig); + } + } + queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig); + } + public void onLowMemory() { + } + }); } private final void detach() diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 52cdc74..ce5f1bf 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1690,6 +1690,25 @@ public class SearchManager } /** + * Gets the name of the web search activity. + * + * @return The name of the default activity for web searches. This activity + * can be used to get web search suggestions. Returns {@code null} if + * there is no default web search activity. + * + * @hide + */ + public ComponentName getWebSearchActivity() { + ComponentName globalSearch = getGlobalSearchActivity(); + if (globalSearch == null) { + return null; + } + Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); + intent.setPackage(globalSearch.getPackageName()); + return intent.resolveActivity(mContext.getPackageManager()); + } + + /** * Similar to {@link #startSearch} but actually fires off the search query after invoking * the search dialog. Made available for testing purposes. * diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 8ec5bd4..6767332 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -56,6 +56,8 @@ import java.io.PrintWriter; * <li><a href="#ServiceLifecycle">Service Lifecycle</a> * <li><a href="#Permissions">Permissions</a> * <li><a href="#ProcessLifecycle">Process Lifecycle</a> + * <li><a href="#LocalServiceSample">Local Service Sample</a> + * <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a> * </ol> * * <a name="ServiceLifecycle"></a> @@ -166,6 +168,64 @@ import java.io.PrintWriter; * (such as an {@link android.app.Activity}) can, of course, increase the * importance of the overall * process beyond just the importance of the service itself. + * + * <a name="LocalServiceSample"></a> + * <h3>Local Service Sample</h3> + * + * <p>One of the most common uses of a Service is as a secondary component + * running alongside other parts of an application, in the same process as + * the rest of the components. All components of an .apk run in the same + * process unless explicitly stated otherwise, so this is a typical situation. + * + * <p>When used in this way, by assuming the + * components are in the same process, you can greatly simplify the interaction + * between them: clients of the service can simply cast the IBinder they + * receive from it to a concrete class published by the service. + * + * <p>An example of this use of a Service is shown here. First is the Service + * itself, publishing a custom class when bound: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java + * service} + * + * <p>With that done, one can now write client code that directly accesses the + * running service, such as: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java + * bind} + * + * <a name="RemoteMessengerServiceSample"></a> + * <h3>Remote Messenger Service Sample</h3> + * + * <p>If you need to be able to write a Service that can perform complicated + * communication with clients in remote processes (beyond simply the use of + * {@link Context#startService(Intent) Context.startService} to send + * commands to it), then you can use the {@link android.os.Messenger} class + * instead of writing full AIDL files. + * + * <p>An example of a Service that uses Messenger as its client interface + * is shown here. First is the Service itself, publishing a Messenger to + * an internal Handler when bound: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java + * service} + * + * <p>If we want to make this service run in a remote process (instead of the + * standard one for its .apk), we can use <code>android:process</code> in its + * manifest tag to specify one: + * + * {@sample development/samples/ApiDemos/AndroidManifest.xml remote_service_declaration} + * + * <p>Note that the name "remote" chosen here is arbitrary, and you can use + * other names if you want additional processes. The ':' prefix appends the + * name to your package's standard process name. + * + * <p>With that done, clients can now bind to the service and send messages + * to it. Note that this allows clients to register with it to receive + * messages back as well: + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java + * bind} */ public abstract class Service extends ContextWrapper implements ComponentCallbacks { private static final String TAG = "Service"; diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index b792965..251813e 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -112,11 +112,9 @@ public final class BluetoothHeadset { /** Default priority when not set or when the device is unpaired */ public static final int PRIORITY_UNDEFINED = -1; - /** The voice dialer 'works' but the user experience is poor. The voice - * recognizer has trouble dealing with the 8kHz SCO signal, and it still - * requires visual confirmation. Disable for cupcake. - */ - public static final boolean DISABLE_BT_VOICE_DIALING = true; + /** Set this to true to prevent the bluetooth headset from + * activating the VoiceDialer. */ + public static final boolean DISABLE_BT_VOICE_DIALING = false; /** * An interface for notifying BluetoothHeadset IPC clients when they have diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index d31b25b..1b0437c 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1815,11 +1815,18 @@ public class Intent implements Parcelable, Cloneable { /** * Broadcast Action: A sticky broadcast indicating the phone was docked - * or undocked. Includes the extra - * field {@link #EXTRA_DOCK_STATE}, containing the current dock state. It also - * includes the boolean extra field {@link #EXTRA_CAR_MODE_ENABLED}, indicating - * the state of the car mode. - * This is intended for monitoring the current dock state. + * or undocked. + * + * <p>The intent will have the following extra values: + * <ul> + * <li><em>{@link #EXTRA_DOCK_STATE}</em> - the current dock + * state, which depends on the state of the car mode.</li> + * <li><em>{@link #EXTRA_PHYSICAL_DOCK_STATE}</em> - the physical dock + * state.</li> + * <li><em>{@link #EXTRA_CAR_MODE_ENABLED}</em> - a boolean indicating the + * state of the car mode.</li> + * </ul> + * <p>This is intended for monitoring the current dock state. * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK} * or {@link #CATEGORY_DESK_DOCK} instead. */ @@ -2154,6 +2161,16 @@ public class Intent implements Parcelable, Cloneable { public static final int EXTRA_DOCK_STATE_CAR = 2; /** + * Used as an int extra field in {@link android.content.Intent#ACTION_DOCK_EVENT} + * intents to request the physical dock state. Possible values are + * {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED}, + * {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or + * {@link android.content.Intent#EXTRA_DOCK_STATE_CAR}. + */ + public static final String EXTRA_PHYSICAL_DOCK_STATE = + "android.intent.extra.PHYSICAL_DOCK_STATE"; + + /** * Used as an boolean extra field in {@link android.content.Intent#ACTION_DOCK_EVENT} * intents to indicate that the car mode is enabled or not. */ diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 4ddb819..317e5a9 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -115,6 +115,11 @@ public class SyncManager implements OnAccountsUpdateListener { private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour /** + * How long to wait before retrying a sync that failed due to one already being in progress. + */ + private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10; + + /** * An error notification is sent if sync of any of the providers has been failing for this long. */ private static final long ERROR_NOTIFICATION_DELAY_MS = 1000 * 60 * 10; // 10 minutes @@ -807,6 +812,14 @@ public class SyncManager implements OnAccountsUpdateListener { + "it achieved some success"); } scheduleSyncOperation(operation); + } else if (syncResult.syncAlreadyInProgress) { + if (isLoggable) { + Log.d(TAG, "retrying sync operation that failed because there was already a " + + "sync in progress: " + operation); + } + scheduleSyncOperation(new SyncOperation(operation.account, operation.syncSource, + operation.authority, operation.extras, + DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS)); } else if (syncResult.hasSoftError()) { if (isLoggable) { Log.d(TAG, "retrying sync operation because it encountered a soft error: " diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index ff2ed3d..8576de2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1153,7 +1153,9 @@ public abstract class PackageManager { * * @return Returns a ResolveInfo containing the final activity intent that * was determined to be the best action. Returns null if no - * matching activity was found. + * matching activity was found. If multiple matching activities are + * found and there is no default set, returns a ResolveInfo + * containing something else, such as the activity resolver. * * @see #MATCH_DEFAULT_ONLY * @see #GET_INTENT_FILTERS diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index aa5f128..6490b65 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -193,6 +193,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration public int uiMode; /** + * @hide Internal book-keeping. + */ + public int seq; + + /** * Construct an invalid Configuration. You must call {@link #setToDefaults} * for this object to be valid. {@more} */ @@ -220,6 +225,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration orientation = o.orientation; screenLayout = o.screenLayout; uiMode = o.uiMode; + seq = o.seq; } public String toString() { @@ -250,6 +256,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration sb.append(screenLayout); sb.append(" uiMode="); sb.append(uiMode); + if (seq != 0) { + sb.append(" seq="); + sb.append(seq); + } sb.append('}'); return sb.toString(); } @@ -260,7 +270,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration public void setToDefaults() { fontScale = 1; mcc = mnc = 0; - locale = Locale.getDefault(); + locale = null; userSetLocale = false; touchscreen = TOUCHSCREEN_UNDEFINED; keyboard = KEYBOARD_UNDEFINED; @@ -271,6 +281,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration orientation = ORIENTATION_UNDEFINED; screenLayout = SCREENLAYOUT_SIZE_UNDEFINED; uiMode = UI_MODE_TYPE_NORMAL; + seq = 0; } /** {@hide} */ @@ -357,6 +368,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration uiMode = delta.uiMode; } + if (delta.seq != 0) { + seq = delta.seq; + } + return changed; } @@ -456,6 +471,35 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** + * @hide Return true if the sequence of 'other' is better than this. Assumes + * that 'this' is your current sequence and 'other' is a new one you have + * received some how and want to compare with what you have. + */ + public boolean isOtherSeqNewer(Configuration other) { + if (other == null) { + // Sanity check. + return false; + } + if (other.seq == 0) { + // If the other sequence is not specified, then we must assume + // it is newer since we don't know any better. + return true; + } + if (seq == 0) { + // If this sequence is not specified, then we also consider the + // other is better. Yes we have a preference for other. Sue us. + return true; + } + int diff = other.seq - seq; + if (diff > 0x10000) { + // If there has been a sufficiently large jump, assume the + // sequence has wrapped around. + return false; + } + return diff > 0; + } + + /** * Parcelable methods */ public int describeContents() { @@ -488,6 +532,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(orientation); dest.writeInt(screenLayout); dest.writeInt(uiMode); + dest.writeInt(seq); } public static final Parcelable.Creator<Configuration> CREATOR @@ -522,6 +567,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration orientation = source.readInt(); screenLayout = source.readInt(); uiMode = source.readInt(); + seq = source.readInt(); } public int compareTo(Configuration that) { diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index ae8e297..a5e39d4 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -39,6 +39,7 @@ import android.view.Display; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; +import java.util.Locale; /** * Class for accessing an application's resources. This sits on top of the @@ -1259,6 +1260,9 @@ public class Resources { if (config != null) { configChanges = mConfiguration.updateFrom(config); } + if (mConfiguration.locale == null) { + mConfiguration.locale = Locale.getDefault(); + } if (metrics != null) { mMetrics.setTo(metrics); mMetrics.updateMetrics(mCompatibilityInfo, diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java index 7776520..e589f34 100644 --- a/core/java/android/database/sqlite/SQLiteClosable.java +++ b/core/java/android/database/sqlite/SQLiteClosable.java @@ -16,6 +16,8 @@ package android.database.sqlite; +import android.database.CursorWindow; + /** * An object create from a SQLiteDatabase that can be closed. */ @@ -29,9 +31,9 @@ public abstract class SQLiteClosable { synchronized(mLock) { if (mReferenceCount <= 0) { throw new IllegalStateException( - "attempt to acquire a reference on an already-closed SQLiteClosable obj."); + "attempt to acquire a reference on an already-closed " + getObjInfo()); } - mReferenceCount++; + mReferenceCount++; } } @@ -52,4 +54,24 @@ public abstract class SQLiteClosable { } } } + + private String getObjInfo() { + StringBuilder buff = new StringBuilder(); + buff.append(this.getClass().getName()); + buff.append(" Obj"); + buff.append(" ("); + if (this instanceof SQLiteDatabase) { + buff.append("database = "); + buff.append(((SQLiteDatabase)this).getPath()); + } else if (this instanceof SQLiteProgram || this instanceof SQLiteStatement || + this instanceof SQLiteQuery) { + buff.append("mSql = "); + buff.append(((SQLiteProgram)this).mSql); + } else if (this instanceof CursorWindow) { + buff.append("mStartPos = "); + buff.append(((CursorWindow)this).getStartPosition()); + } + buff.append(") "); + return buff.toString(); + } } diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java index 79527b4..eb85822 100644 --- a/core/java/android/database/sqlite/SQLiteCompiledSql.java +++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java @@ -44,6 +44,9 @@ import android.util.Log; */ /* package */ int nStatement = 0; + /** when in cache and is in use, this member is set */ + private boolean mInUse = false; + /* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) { mDatabase = db; this.nHandle = db.mNativeHandle; @@ -92,6 +95,18 @@ import android.util.Log; } } + /* package */ synchronized boolean isInUse() { + return mInUse; + } + + /* package */ synchronized void acquire() { + mInUse = true; + } + + /* package */ synchronized void release() { + mInUse = false; + } + /** * Make sure that the native resource is cleaned up. */ diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java index 2d0aa39..2bb2f5d 100644 --- a/core/java/android/database/sqlite/SQLiteProgram.java +++ b/core/java/android/database/sqlite/SQLiteProgram.java @@ -58,32 +58,51 @@ public abstract class SQLiteProgram extends SQLiteClosable { // add it to the cache of compiled-sqls db.addToCompiledQueries(sql, mCompiledSql); + mCompiledSql.acquire(); + } else { + // it is already in compiled-sql cache. + if (mCompiledSql.isInUse()) { + // but the CompiledSql in cache is in use by some other SQLiteProgram object. + // we can't have two different SQLiteProgam objects can't share the same + // CompiledSql object. create a new one. + // finalize it when I am done with it in "this" object. + mCompiledSql = new SQLiteCompiledSql(db, sql); + } else { + // the CompiledSql in cache is NOT in use by any other SQLiteProgram object. + // it is safe to give it to this SQLIteProgram Object. + mCompiledSql.acquire(); + } } nStatement = mCompiledSql.nStatement; } @Override protected void onAllReferencesReleased() { - releaseCompiledSqlIfInCache(); + releaseCompiledSqlIfNotInCache(); mDatabase.releaseReference(); mDatabase.removeSQLiteClosable(this); } @Override protected void onAllReferencesReleasedFromContainer() { - releaseCompiledSqlIfInCache(); + releaseCompiledSqlIfNotInCache(); mDatabase.releaseReference(); } - private void releaseCompiledSqlIfInCache() { + private void releaseCompiledSqlIfNotInCache() { if (mCompiledSql == null) { return; } synchronized(mDatabase.mCompiledQueries) { if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) { + // it is NOT in compiled-sql cache. i.e., responsibility of + // release this statement is on me. mCompiledSql.releaseSqlStatement(); mCompiledSql = null; // so that GC doesn't call finalize() on it nStatement = 0; + } else { + // it is in compiled-sql cache. reset its CompiledSql#mInUse flag + mCompiledSql.release(); } } } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index c0bff66..6dba94d 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -26,7 +26,7 @@ import java.io.IOException; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; -import android.graphics.PixelFormat; +import android.graphics.ImageFormat; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -192,7 +192,7 @@ public class Camera { * The callback that delivers the preview frames. * * @param data The contents of the preview frame in the format defined - * by {@link android.graphics.PixelFormat}, which can be queried + * by {@link android.graphics.ImageFormat}, which can be queried * with {@link android.hardware.Camera.Parameters#getPreviewFormat()}. * If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)} * is never called, the default will be the YCbCr_420_SP @@ -276,7 +276,7 @@ public class Camera { * Adds a pre-allocated buffer to the callback buffer queue. * Preview width and height can be determined from getPreviewSize, and bitsPerPixel can be * found from from {@link android.hardware.Camera.Parameters#getPreviewFormat()} and - * {@link android.graphics.PixelFormat#getPixelFormatInfo(int, PixelFormat)} + * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} * * Alternatively, a buffer from a previous callback may be passed in or used * to determine the size of new preview frame buffers. @@ -1086,15 +1086,15 @@ public class Camera { /** * Sets the image format for preview pictures. * <p>If this is never called, the default format will be - * {@link android.graphics.PixelFormat#YCbCr_420_SP}, which + * {@link android.graphics.ImageFormat#NV21}, which * uses the NV21 encoding format.</p> * * @param pixel_format the desired preview picture format, defined - * by one of the {@link android.graphics.PixelFormat} constants. - * (E.g., <var>PixelFormat.YCbCr_420_SP</var> (default), - * <var>PixelFormat.RGB_565</var>, or - * <var>PixelFormat.JPEG</var>) - * @see android.graphics.PixelFormat + * by one of the {@link android.graphics.ImageFormat} constants. + * (E.g., <var>ImageFormat.NV21</var> (default), + * <var>ImageFormat.RGB_565</var>, or + * <var>ImageFormat.JPEG</var>) + * @see android.graphics.ImageFormat */ public void setPreviewFormat(int pixel_format) { String s = cameraFormatForPixelFormat(pixel_format); @@ -1110,7 +1110,7 @@ public class Camera { * Returns the image format for preview pictures got from * {@link PreviewCallback}. * - * @return the {@link android.graphics.PixelFormat} int representing + * @return the {@link android.graphics.ImageFormat} int representing * the preview picture format. */ public int getPreviewFormat() { @@ -1128,7 +1128,7 @@ public class Camera { ArrayList<Integer> formats = new ArrayList<Integer>(); for (String s : split(str)) { int f = pixelFormatForCameraFormat(s); - if (f == PixelFormat.UNKNOWN) continue; + if (f == ImageFormat.UNKNOWN) continue; formats.add(f); } return formats; @@ -1171,10 +1171,10 @@ public class Camera { * Sets the image format for pictures. * * @param pixel_format the desired picture format - * (<var>PixelFormat.YCbCr_420_SP (NV21)</var>, - * <var>PixelFormat.RGB_565</var>, or - * <var>PixelFormat.JPEG</var>) - * @see android.graphics.PixelFormat + * (<var>ImageFormat.NV21</var>, + * <var>ImageFormat.RGB_565</var>, or + * <var>ImageFormat.JPEG</var>) + * @see android.graphics.ImageFormat */ public void setPictureFormat(int pixel_format) { String s = cameraFormatForPixelFormat(pixel_format); @@ -1189,7 +1189,7 @@ public class Camera { /** * Returns the image format for pictures. * - * @return the PixelFormat int representing the picture format + * @return the ImageFormat int representing the picture format */ public int getPictureFormat() { return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT)); @@ -1198,7 +1198,7 @@ public class Camera { /** * Gets the supported picture formats. * - * @return a List of Integer objects (values are PixelFormat.XXX). This + * @return a List of Integer objects (values are ImageFormat.XXX). This * method will always return a list with at least one element. */ public List<Integer> getSupportedPictureFormats() { @@ -1206,7 +1206,7 @@ public class Camera { ArrayList<Integer> formats = new ArrayList<Integer>(); for (String s : split(str)) { int f = pixelFormatForCameraFormat(s); - if (f == PixelFormat.UNKNOWN) continue; + if (f == ImageFormat.UNKNOWN) continue; formats.add(f); } return formats; @@ -1214,35 +1214,35 @@ public class Camera { private String cameraFormatForPixelFormat(int pixel_format) { switch(pixel_format) { - case PixelFormat.YCbCr_422_SP: return PIXEL_FORMAT_YUV422SP; - case PixelFormat.YCbCr_420_SP: return PIXEL_FORMAT_YUV420SP; - case PixelFormat.YCbCr_422_I: return PIXEL_FORMAT_YUV422I; - case PixelFormat.RGB_565: return PIXEL_FORMAT_RGB565; - case PixelFormat.JPEG: return PIXEL_FORMAT_JPEG; - default: return null; + case ImageFormat.NV16: return PIXEL_FORMAT_YUV422SP; + case ImageFormat.NV21: return PIXEL_FORMAT_YUV420SP; + case ImageFormat.YUY2: return PIXEL_FORMAT_YUV422I; + case ImageFormat.RGB_565: return PIXEL_FORMAT_RGB565; + case ImageFormat.JPEG: return PIXEL_FORMAT_JPEG; + default: return null; } } private int pixelFormatForCameraFormat(String format) { if (format == null) - return PixelFormat.UNKNOWN; + return ImageFormat.UNKNOWN; if (format.equals(PIXEL_FORMAT_YUV422SP)) - return PixelFormat.YCbCr_422_SP; + return ImageFormat.NV16; if (format.equals(PIXEL_FORMAT_YUV420SP)) - return PixelFormat.YCbCr_420_SP; + return ImageFormat.NV21; if (format.equals(PIXEL_FORMAT_YUV422I)) - return PixelFormat.YCbCr_422_I; + return ImageFormat.YUY2; if (format.equals(PIXEL_FORMAT_RGB565)) - return PixelFormat.RGB_565; + return ImageFormat.RGB_565; if (format.equals(PIXEL_FORMAT_JPEG)) - return PixelFormat.JPEG; + return ImageFormat.JPEG; - return PixelFormat.UNKNOWN; + return ImageFormat.UNKNOWN; } /** diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java index 65301e4..911439a 100644 --- a/core/java/android/os/HandlerThread.java +++ b/core/java/android/os/HandlerThread.java @@ -53,9 +53,9 @@ public class HandlerThread extends Thread { Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); - Process.setThreadPriority(mPriority); notifyAll(); } + Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f48f45f..92041d8 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -148,4 +148,18 @@ interface INetworkManagementService */ void detachPppd(String tty); + /** + * Turn on USB RNDIS support - this will turn off thinks like adb/mass-storage + */ + void startUsbRNDIS(); + + /** + * Turn off USB RNDIS support + */ + void stopUsbRNDIS(); + + /** + * Check the status of USB RNDIS support + */ + boolean isUsbRNDISStarted(); } diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index 4130109..476da1d 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -40,20 +40,36 @@ public final class Message implements Parcelable { */ public int what; - // Use these fields instead of using the class's Bundle if you can. - /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()} - if you only need to store a few integer values. */ + /** + * arg1 and arg2 are lower-cost alternatives to using + * {@link #setData(Bundle) setData()} if you only need to store a + * few integer values. + */ public int arg1; - /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()} - if you only need to store a few integer values.*/ + /** + * arg1 and arg2 are lower-cost alternatives to using + * {@link #setData(Bundle) setData()} if you only need to store a + * few integer values. + */ public int arg2; - /** An arbitrary object to send to the recipient. This must be null when - * sending messages across processes. */ + /** + * An arbitrary object to send to the recipient. When using + * {@link Messenger} to send the message across processes this can only + * be non-null if it contains a Parcelable of a framework class (not one + * implemented by the application). For other data transfer use + * {@link #setData}. + * + * <p>Note that Parcelable objects here are not supported prior to + * the {@link android.os.Build.VERSION_CODES#FROYO} release. + */ public Object obj; - /** Optional Messenger where replies to this message can be sent. + /** + * Optional Messenger where replies to this message can be sent. The + * semantics of exactly how this is used are up to the sender and + * receiver. */ public Messenger replyTo; @@ -278,14 +294,22 @@ public final class Message implements Parcelable { * the <em>target</em> {@link Handler} that is receiving this Message to * dispatch it. If * not set, the message will be dispatched to the receiving Handler's - * {@link Handler#handleMessage(Message Handler.handleMessage())}. */ + * {@link Handler#handleMessage(Message Handler.handleMessage())}. + */ public Runnable getCallback() { return callback; } /** * Obtains a Bundle of arbitrary data associated with this - * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}. + * event, lazily creating it if necessary. Set this value by calling + * {@link #setData(Bundle)}. Note that when transferring data across + * processes via {@link Messenger}, you will need to set your ClassLoader + * on the Bundle via {@link Bundle#setClassLoader(ClassLoader) + * Bundle.setClassLoader()} so that it can instantiate your objects when + * you retrieve them. + * @see #peekData() + * @see #setData(Bundle) */ public Bundle getData() { if (data == null) { @@ -297,14 +321,21 @@ public final class Message implements Parcelable { /** * Like getData(), but does not lazily create the Bundle. A null - * is returned if the Bundle does not already exist. + * is returned if the Bundle does not already exist. See + * {@link #getData} for further information on this. + * @see #getData() + * @see #setData(Bundle) */ public Bundle peekData() { return data; } - /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members - * as a lower cost way to send a few simple integer values, if you can. */ + /** + * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members + * as a lower cost way to send a few simple integer values, if you can. + * @see #getData() + * @see #peekData() + */ public void setData(Bundle data) { this.data = data; } @@ -381,13 +412,25 @@ public final class Message implements Parcelable { } public void writeToParcel(Parcel dest, int flags) { - if (obj != null || callback != null) { + if (callback != null) { throw new RuntimeException( - "Can't marshal objects across processes."); + "Can't marshal callbacks across processes."); } dest.writeInt(what); dest.writeInt(arg1); dest.writeInt(arg2); + if (obj != null) { + try { + Parcelable p = (Parcelable)obj; + dest.writeInt(1); + dest.writeParcelable(p, flags); + } catch (ClassCastException e) { + throw new RuntimeException( + "Can't marshal non-Parcelable objects across processes."); + } + } else { + dest.writeInt(0); + } dest.writeLong(when); dest.writeBundle(data); Messenger.writeMessengerOrNullToParcel(replyTo, dest); @@ -397,6 +440,9 @@ public final class Message implements Parcelable { what = source.readInt(); arg1 = source.readInt(); arg2 = source.readInt(); + if (source.readInt() != 0) { + obj = source.readParcelable(getClass().getClassLoader()); + } when = source.readLong(); data = source.readBundle(); replyTo = Messenger.readMessengerOrNullFromParcel(source); diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index 816baf3..79a6cfe 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -63,7 +63,7 @@ interface IMountService * Safely unmount external storage at given mount point. * Returns an int consistent with MountServiceResultCode */ - int unmountVolume(String mountPoint); + int unmountVolume(String mountPoint, boolean force); /** * Format external storage given a mount point. @@ -100,7 +100,7 @@ interface IMountService * NOTE: Ensure all references are released prior to deleting. * Returns an int consistent with MountServiceResultCode */ - int destroySecureContainer(String id); + int destroySecureContainer(String id, boolean force); /* * Mount a secure container with the specified key and owner UID. @@ -112,7 +112,7 @@ interface IMountService * Unount a secure container. * Returns an int consistent with MountServiceResultCode */ - int unmountSecureContainer(String id); + int unmountSecureContainer(String id, boolean force); /* * Returns true if the specified container is mounted diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java index 249bacf..07d95df 100644 --- a/core/java/android/os/storage/StorageResultCode.java +++ b/core/java/android/os/storage/StorageResultCode.java @@ -64,4 +64,10 @@ public class StorageResultCode */ public static final int OperationFailedStorageMounted = -6; + /** + * Operation failed: Storage is busy. + * @see android.os.storage.StorageManager + */ + public static final int OperationFailedStorageBusy = -7; + } diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java index bd7924a..5d09fb5 100644 --- a/core/java/android/pim/RecurrenceSet.java +++ b/core/java/android/pim/RecurrenceSet.java @@ -48,7 +48,8 @@ public class RecurrenceSet { * events table in the CalendarProvider. * @param values The values retrieved from the Events table. */ - public RecurrenceSet(ContentValues values) { + public RecurrenceSet(ContentValues values) + throws EventRecurrence.InvalidFormatException { String rruleStr = values.getAsString(Calendar.Events.RRULE); String rdateStr = values.getAsString(Calendar.Events.RDATE); String exruleStr = values.getAsString(Calendar.Events.EXRULE); @@ -65,7 +66,8 @@ public class RecurrenceSet { * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE * columns. */ - public RecurrenceSet(Cursor cursor) { + public RecurrenceSet(Cursor cursor) + throws EventRecurrence.InvalidFormatException { int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE); int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE); int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE); @@ -78,12 +80,14 @@ public class RecurrenceSet { } public RecurrenceSet(String rruleStr, String rdateStr, - String exruleStr, String exdateStr) { + String exruleStr, String exdateStr) + throws EventRecurrence.InvalidFormatException { init(rruleStr, rdateStr, exruleStr, exdateStr); } private void init(String rruleStr, String rdateStr, - String exruleStr, String exdateStr) { + String exruleStr, String exdateStr) + throws EventRecurrence.InvalidFormatException { if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) { if (!TextUtils.isEmpty(rruleStr)) { diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index eb48a0c..52de64c 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -28,6 +28,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; @@ -226,7 +227,7 @@ public abstract class WallpaperService extends Service { @Override public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { + Rect visibleInsets, boolean reportDraw, Configuration newConfig) { Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0); mCaller.sendMessage(msg); diff --git a/core/java/android/speech/RecognitionManager.java b/core/java/android/speech/RecognitionManager.java index 7f55ad6..16b1f89 100644 --- a/core/java/android/speech/RecognitionManager.java +++ b/core/java/android/speech/RecognitionManager.java @@ -98,6 +98,9 @@ public class RecognitionManager { /** Context with which the manager was created */ private final Context mContext; + + /** Component to direct service intent to */ + private final ComponentName mServiceComponent; /** Handler that will execute the main tasks */ private Handler mHandler = new Handler() { @@ -133,8 +136,9 @@ public class RecognitionManager { * The right way to create a {@code RecognitionManager} is by using * {@link #createRecognitionManager} static factory method */ - private RecognitionManager(final Context context) { + private RecognitionManager(final Context context, final ComponentName serviceComponent) { mContext = context; + mServiceComponent = serviceComponent; } /** @@ -184,11 +188,31 @@ public class RecognitionManager { * @return a new {@code RecognitionManager} */ public static RecognitionManager createRecognitionManager(final Context context) { + return createRecognitionManager(context, null); + } + + /** + * Factory method to create a new {@code RecognitionManager}, please note that + * {@link #setRecognitionListener(RecognitionListener)} must be called before dispatching any + * command to the created {@code RecognitionManager}. + * + * Use this version of the method to specify a specific service to direct this + * {@link RecognitionManager} to. Normally you would not use this; use + * {@link #createRecognitionManager(Context)} instead to use the system default + * recognition service. + * + * @param context in which to create {@code RecognitionManager} + * @param serviceComponent the {@link ComponentName} of a specific service to direct this + * {@code RecognitionManager} to + * @return a new {@code RecognitionManager} + */ + public static RecognitionManager createRecognitionManager(final Context context, + final ComponentName serviceComponent) { if (context == null) { throw new IllegalArgumentException("Context cannot be null)"); } checkIsCalledFromMainThread(); - return new RecognitionManager(context); + return new RecognitionManager(context, serviceComponent); } /** @@ -222,17 +246,22 @@ public class RecognitionManager { mConnection = new Connection(); Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE); - String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(), - Settings.Secure.VOICE_RECOGNITION_SERVICE); - if (TextUtils.isEmpty(serviceComponent)) { - Log.e(TAG, "no selected voice recognition service"); - mListener.onError(ERROR_CLIENT); - return; + if (mServiceComponent == null) { + String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.VOICE_RECOGNITION_SERVICE); + + if (TextUtils.isEmpty(serviceComponent)) { + Log.e(TAG, "no selected voice recognition service"); + mListener.onError(ERROR_CLIENT); + return; + } + + serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); + } else { + serviceIntent.setComponent(mServiceComponent); } - serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent)); - if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) { Log.e(TAG, "bind to recognition service failed"); mConnection = null; diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java index 5f651e1..7c15cec 100644 --- a/core/java/android/speech/RecognizerIntent.java +++ b/core/java/android/speech/RecognizerIntent.java @@ -16,9 +16,17 @@ package android.speech; +import java.util.ArrayList; + import android.app.Activity; import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; /** * Constants for supporting speech recognition through starting an {@link Intent} @@ -208,4 +216,92 @@ public class RecognizerIntent { * an activity result. In a PendingIntent, the lack of this extra indicates failure. */ public static final String EXTRA_RESULTS = "android.speech.extra.RESULTS"; + + /** + * Returns the broadcast intent to fire with + * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)} + * to receive details from the package that implements voice search. + * <p> + * This is based on the value specified by the voice search {@link Activity} in + * {@link #DETAILS_META_DATA}, and if this is not specified, will return null. Also if there + * is no chosen default to resolve for {@link #ACTION_WEB_SEARCH}, this will return null. + * <p> + * If an intent is returned and is fired, a {@link Bundle} of extras will be returned to the + * provided result receiver, and should ideally contain values for + * {@link #EXTRA_LANGUAGE_PREFERENCE} and {@link #EXTRA_SUPPORTED_LANGUAGES}. + * <p> + * (Whether these are actually provided is up to the particular implementation. It is + * recommended that {@link Activity}s implementing {@link #ACTION_WEB_SEARCH} provide this + * information, but it is not required.) + * + * @param context a context object + * @return the broadcast intent to fire or null if not available + */ + public static final Intent getVoiceDetailsIntent(Context context) { + Intent voiceSearchIntent = new Intent(ACTION_WEB_SEARCH); + ResolveInfo ri = context.getPackageManager().resolveActivity( + voiceSearchIntent, PackageManager.GET_META_DATA); + if (ri == null || ri.activityInfo == null || ri.activityInfo.metaData == null) return null; + + String className = ri.activityInfo.metaData.getString(DETAILS_META_DATA); + if (className == null) return null; + + Intent detailsIntent = new Intent(ACTION_GET_LANGUAGE_DETAILS); + detailsIntent.setComponent(new ComponentName(ri.activityInfo.packageName, className)); + return detailsIntent; + } + + /** + * Meta-data name under which an {@link Activity} implementing {@link #ACTION_WEB_SEARCH} can + * use to expose the class name of a {@link BroadcastReceiver} which can respond to request for + * more information, from any of the broadcast intents specified in this class. + * <p> + * Broadcast intents can be directed to the class name specified in the meta-data by creating + * an {@link Intent}, setting the component with + * {@link Intent#setComponent(android.content.ComponentName)}, and using + * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle)} + * with another {@link BroadcastReceiver} which can receive the results. + * <p> + * The {@link #getVoiceDetailsIntent(Context)} method is provided as a convenience to create + * a broadcast intent based on the value of this meta-data, if available. + * <p> + * This is optional and not all {@link Activity}s which implement {@link #ACTION_WEB_SEARCH} + * are required to implement this. Thus retrieving this meta-data may be null. + */ + public static final String DETAILS_META_DATA = "android.speech.DETAILS"; + + /** + * A broadcast intent which can be fired to the {@link BroadcastReceiver} component specified + * in the meta-data defined in the {@link #DETAILS_META_DATA} meta-data of an + * {@link Activity} satisfying {@link #ACTION_WEB_SEARCH}. + * <p> + * When fired with + * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle)}, + * a {@link Bundle} of extras will be returned to the provided result receiver, and should + * ideally contain values for {@link #EXTRA_LANGUAGE_PREFERENCE} and + * {@link #EXTRA_SUPPORTED_LANGUAGES}. + * <p> + * (Whether these are actually provided is up to the particular implementation. It is + * recommended that {@link Activity}s implementing {@link #ACTION_WEB_SEARCH} provide this + * information, but it is not required.) + */ + public static final String ACTION_GET_LANGUAGE_DETAILS = + "android.speech.action.GET_LANGUAGE_DETAILS"; + + /** + * The key to the extra in the {@link Bundle} returned by {@link #ACTION_GET_LANGUAGE_DETAILS} + * which is a {@link String} that represents the current language preference this user has + * specified - a locale string like "en-US". + */ + public static final String EXTRA_LANGUAGE_PREFERENCE = + "android.speech.extra.LANGUAGE_PREFERENCE"; + + /** + * The key to the extra in the {@link Bundle} returned by {@link #ACTION_GET_LANGUAGE_DETAILS} + * which is an {@link ArrayList} of {@link String}s that represents the languages supported by + * this implementation of voice recognition - a list of strings like "en-US", "cmn-Hans-CN", + * etc. + */ + public static final String EXTRA_SUPPORTED_LANGUAGES = + "android.speech.extra.SUPPORTED_LANGUAGES"; } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 71302cb..3b09808 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -17,6 +17,7 @@ package android.view; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -44,7 +45,7 @@ oneway interface IWindow { void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor); void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets, - boolean reportDraw); + boolean reportDraw, in Configuration newConfig); void dispatchKey(in KeyEvent event); void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone); void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 0ebe360..9b7b2f4 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -64,8 +64,6 @@ interface IWindowManager void addAppToken(int addPos, IApplicationToken token, int groupId, int requestedOrientation, boolean fullscreen); void setAppGroupId(IBinder token, int groupId); - Configuration updateOrientationFromAppTokens(in Configuration currentConfig, - IBinder freezeThisOneIfNeeded); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); void setFocusedApp(IBinder token, boolean moveFocusNow); @@ -85,6 +83,13 @@ interface IWindowManager void moveAppTokensToTop(in List<IBinder> tokens); void moveAppTokensToBottom(in List<IBinder> tokens); + // Re-evaluate the current orientation from the caller's state. + // If there is a change, the new Configuration is returned and the + // caller must call setNewConfiguration() sometime later. + Configuration updateOrientationFromAppTokens(in Configuration currentConfig, + IBinder freezeThisOneIfNeeded); + void setNewConfiguration(in Configuration config); + // these require DISABLE_KEYGUARD permission void disableKeyguard(IBinder token, String tag); void reenableKeyguard(IBinder token); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index ca5e1de..d7f2539 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -19,6 +19,7 @@ package android.view; import com.android.internal.view.BaseIWindow; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; @@ -504,7 +505,7 @@ public class SurfaceView extends View { } public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { + Rect visibleInsets, boolean reportDraw, Configuration newConfig) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (localLOGV) Log.v( diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bc49439..2eb633f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -20,6 +20,7 @@ import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -3933,6 +3934,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * Dispatch a notification about a resource configuration change down + * the view hierarchy. + * ViewGroups should override to route to their children. + * + * @param newConfig The new resource configuration. + * + * @see #onConfigurationChanged + */ + public void dispatchConfigurationChanged(Configuration newConfig) { + onConfigurationChanged(newConfig); + } + + /** + * Called when the current configuration of the resources being used + * by the application have changed. You can use this to decide when + * to reload resources that can changed based on orientation and other + * configuration characterstics. You only need to use this if you are + * not relying on the normal {@link android.app.Activity} mechanism of + * recreating the activity instance upon a configuration change. + * + * @param newConfig The new resource configuration. + */ + protected void onConfigurationChanged(Configuration newConfig) { + } + + /** * Private function to aggregate all per-view attributes in to the view * root. */ diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 2ed623d..0663215 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -19,6 +19,7 @@ package android.view; import com.android.internal.R; import android.content.Context; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -722,6 +723,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * {@inheritDoc} */ + @Override + public void dispatchConfigurationChanged(Configuration newConfig) { + super.dispatchConfigurationChanged(newConfig); + final int count = mChildrenCount; + final View[] children = mChildren; + for (int i = 0; i < count; i++) { + children[i].dispatchConfigurationChanged(newConfig); + } + } + + /** + * {@inheritDoc} + */ public void recomputeViewAttributes(View child) { ViewParent parent = mParent; if (parent != null) parent.recomputeViewAttributes(this); diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 07b2d1c..264b8c9 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -41,7 +41,9 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; import android.content.res.Resources; +import android.content.ComponentCallbacks; import android.content.Context; import android.app.ActivityManagerNative; import android.Manifest; @@ -101,6 +103,9 @@ public final class ViewRoot extends Handler implements ViewParent, static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>(); static boolean sFirstDrawComplete = false; + static final ArrayList<ComponentCallbacks> sConfigCallbacks + = new ArrayList<ComponentCallbacks>(); + private static int sDrawTime; long mLastTrackballTime = 0; @@ -171,6 +176,12 @@ public final class ViewRoot extends Handler implements ViewParent, final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets = new ViewTreeObserver.InternalInsetsInfo(); + class ResizedInfo { + Rect coveredInsets; + Rect visibleInsets; + Configuration newConfig; + } + boolean mScrollMayChange; int mSoftInputMode; View mLastScrolledFocus; @@ -265,6 +276,12 @@ public final class ViewRoot extends Handler implements ViewParent, } } + public static void addConfigCallback(ComponentCallbacks callback) { + synchronized (sConfigCallbacks) { + sConfigCallbacks.add(callback); + } + } + // FIXME for perf testing only private boolean mProfile = false; @@ -1782,23 +1799,33 @@ public final class ViewRoot extends Handler implements ViewParent, handleGetNewSurface(); break; case RESIZED: - Rect coveredInsets = ((Rect[])msg.obj)[0]; - Rect visibleInsets = ((Rect[])msg.obj)[1]; + ResizedInfo ri = (ResizedInfo)msg.obj; if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2 - && mPendingContentInsets.equals(coveredInsets) - && mPendingVisibleInsets.equals(visibleInsets)) { + && mPendingContentInsets.equals(ri.coveredInsets) + && mPendingVisibleInsets.equals(ri.visibleInsets)) { break; } // fall through... case RESIZED_REPORT: if (mAdded) { + Configuration config = ((ResizedInfo)msg.obj).newConfig; + if (config != null) { + synchronized (sConfigCallbacks) { + for (int i=sConfigCallbacks.size()-1; i>=0; i--) { + sConfigCallbacks.get(i).onConfigurationChanged(config); + } + } + if (mView != null) { + mView.dispatchConfigurationChanged(config); + } + } mWinFrame.left = 0; mWinFrame.right = msg.arg1; mWinFrame.top = 0; mWinFrame.bottom = msg.arg2; - mPendingContentInsets.set(((Rect[])msg.obj)[0]); - mPendingVisibleInsets.set(((Rect[])msg.obj)[1]); + mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets); + mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets); if (msg.what == RESIZED_REPORT) { mReportNextDraw = true; } @@ -2587,7 +2614,7 @@ public final class ViewRoot extends Handler implements ViewParent, } public void dispatchResized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { + Rect visibleInsets, boolean reportDraw, Configuration newConfig) { if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w + " h=" + h + " coveredInsets=" + coveredInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -2601,7 +2628,11 @@ public final class ViewRoot extends Handler implements ViewParent, } msg.arg1 = w; msg.arg2 = h; - msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) }; + ResizedInfo ri = new ResizedInfo(); + ri.coveredInsets = new Rect(coveredInsets); + ri.visibleInsets = new Rect(visibleInsets); + ri.newConfig = newConfig; + msg.obj = ri; sendMessage(msg); } @@ -2802,11 +2833,11 @@ public final class ViewRoot extends Handler implements ViewParent, } public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { + Rect visibleInsets, boolean reportDraw, Configuration newConfig) { final ViewRoot viewRoot = mViewRoot.get(); if (viewRoot != null) { viewRoot.dispatchResized(w, h, coveredInsets, - visibleInsets, reportDraw); + visibleInsets, reportDraw, newConfig); } } diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java index 16feaa9..bc13504 100644 --- a/core/java/android/webkit/DateSorter.java +++ b/core/java/android/webkit/DateSorter.java @@ -26,7 +26,7 @@ import java.util.Date; * Sorts dates into the following groups: * Today * Yesterday - * five days ago + * seven days ago * one month ago * older than a month ago */ @@ -41,7 +41,7 @@ public class DateSorter { private long [] mBins = new long[DAY_COUNT-1]; private String [] mLabels = new String[DAY_COUNT]; - private static final int NUM_DAYS_AGO = 5; + private static final int NUM_DAYS_AGO = 7; /** * @param context Application context diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java index d12d828..4565b75 100755 --- a/core/java/android/webkit/GeolocationPermissions.java +++ b/core/java/android/webkit/GeolocationPermissions.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.Vector; /** @@ -61,11 +62,8 @@ public final class GeolocationPermissions { private Handler mHandler; private Handler mUIHandler; - // Members used to transfer the origins and permissions between threads. - private Set<String> mOrigins; - private boolean mAllowed; - private Set<String> mOriginsToClear; - private Set<String> mOriginsToAllow; + // A queue to store messages until the handler is ready. + private Vector<Message> mQueuedMessages; // Message ids static final int GET_ORIGINS = 0; @@ -126,7 +124,7 @@ public final class GeolocationPermissions { * Creates the message handler. Must be called on the WebKit thread. * @hide */ - public void createHandler() { + public synchronized void createHandler() { if (mHandler == null) { mHandler = new Handler() { @Override @@ -134,21 +132,21 @@ public final class GeolocationPermissions { // Runs on the WebKit thread. switch (msg.what) { case GET_ORIGINS: { - getOriginsImpl(); + Set origins = nativeGetOrigins(); ValueCallback callback = (ValueCallback) msg.obj; Map values = new HashMap<String, Object>(); values.put(CALLBACK, callback); - values.put(ORIGINS, mOrigins); + values.put(ORIGINS, origins); postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); } break; case GET_ALLOWED: { Map values = (Map) msg.obj; String origin = (String) values.get(ORIGIN); ValueCallback callback = (ValueCallback) values.get(CALLBACK); - getAllowedImpl(origin); + boolean allowed = nativeGetAllowed(origin); Map retValues = new HashMap<String, Object>(); retValues.put(CALLBACK, callback); - retValues.put(ALLOWED, new Boolean(mAllowed)); + retValues.put(ALLOWED, new Boolean(allowed)); postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues)); } break; case CLEAR: @@ -164,15 +162,12 @@ public final class GeolocationPermissions { } }; - if (mOriginsToClear != null) { - for (String origin : mOriginsToClear) { - nativeClear(origin); - } - } - if (mOriginsToAllow != null) { - for (String origin : mOriginsToAllow) { - nativeAllow(origin); + // Handle the queued messages + if (mQueuedMessages != null) { + while (!mQueuedMessages.isEmpty()) { + mHandler.sendMessage(mQueuedMessages.remove(0)); } + mQueuedMessages = null; } } } @@ -180,9 +175,15 @@ public final class GeolocationPermissions { /** * Utility function to send a message to our handler. */ - private void postMessage(Message msg) { - assert(mHandler != null); - mHandler.sendMessage(msg); + private synchronized void postMessage(Message msg) { + if (mHandler == null) { + if (mQueuedMessages == null) { + mQueuedMessages = new Vector<Message>(); + } + mQueuedMessages.add(msg); + } else { + mHandler.sendMessage(msg); + } } /** @@ -207,8 +208,8 @@ public final class GeolocationPermissions { public void getOrigins(ValueCallback<Set<String> > callback) { if (callback != null) { if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - getOriginsImpl(); - callback.onReceiveValue(mOrigins); + Set origins = nativeGetOrigins(); + callback.onReceiveValue(origins); } else { postMessage(Message.obtain(null, GET_ORIGINS, callback)); } @@ -216,14 +217,6 @@ public final class GeolocationPermissions { } /** - * Helper method to get the set of origins. - */ - private void getOriginsImpl() { - // Called on the WebKit thread. - mOrigins = nativeGetOrigins(); - } - - /** * Gets the permission state for the specified origin. * * Callback is a ValueCallback object whose onReceiveValue method will be @@ -238,8 +231,8 @@ public final class GeolocationPermissions { return; } if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { - getAllowedImpl(origin); - callback.onReceiveValue(new Boolean(mAllowed)); + boolean allowed = nativeGetAllowed(origin); + callback.onReceiveValue(new Boolean(allowed)); } else { Map values = new HashMap<String, Object>(); values.put(ORIGIN, origin); @@ -249,31 +242,13 @@ public final class GeolocationPermissions { } /** - * Helper method to get the permission state for the specified origin. - */ - private void getAllowedImpl(String origin) { - // Called on the WebKit thread. - mAllowed = nativeGetAllowed(origin); - } - - /** * Clears the permission state for the specified origin. This method may be * called before the WebKit thread has intialized the message handler. * Messages will be queued until this time. */ public void clear(String origin) { // Called on the UI thread. - if (mHandler == null) { - if (mOriginsToClear == null) { - mOriginsToClear = new HashSet<String>(); - } - mOriginsToClear.add(origin); - if (mOriginsToAllow != null) { - mOriginsToAllow.remove(origin); - } - } else { - postMessage(Message.obtain(null, CLEAR, origin)); - } + postMessage(Message.obtain(null, CLEAR, origin)); } /** @@ -283,17 +258,7 @@ public final class GeolocationPermissions { */ public void allow(String origin) { // Called on the UI thread. - if (mHandler == null) { - if (mOriginsToAllow == null) { - mOriginsToAllow = new HashSet<String>(); - } - mOriginsToAllow.add(origin); - if (mOriginsToClear != null) { - mOriginsToClear.remove(origin); - } - } else { - postMessage(Message.obtain(null, ALLOW, origin)); - } + postMessage(Message.obtain(null, ALLOW, origin)); } /** diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 39e5275..662be95 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -916,9 +916,12 @@ public class WebSettings { } /** - * Tell the WebView to block network image. This is only checked when - * getLoadsImagesAutomatically() is true. - * @param flag True if the WebView should block network image + * Tell the WebView to block network images. This is only checked when + * {@link #getLoadsImagesAutomatically} is true. If you set the value to + * false, images will automatically be loaded. Use this api to reduce + * bandwidth only. Use {@link #setBlockNetworkLoads} if possible. + * @param flag True if the WebView should block network images. + * @see #setBlockNetworkLoads */ public synchronized void setBlockNetworkImage(boolean flag) { if (mBlockNetworkImage != flag) { @@ -928,17 +931,21 @@ public class WebSettings { } /** - * Return true if the WebView will block network image. The default is false. - * @return True if the WebView blocks network image. + * Return true if the WebView will block network images. The default is + * false. + * @return True if the WebView blocks network images. */ public synchronized boolean getBlockNetworkImage() { return mBlockNetworkImage; } /** - * @hide - * Tell the WebView to block all network load requests. - * @param flag True if the WebView should block all network loads + * Tell the WebView to block all network load requests. If you set the + * value to false, you must call {@link android.webkit.WebView#reload} to + * fetch remote resources. This flag supercedes the value passed to + * {@link #setBlockNetworkImage}. + * @param flag True if the WebView should block all network loads. + * @see android.webkit.WebView#reload */ public synchronized void setBlockNetworkLoads(boolean flag) { if (mBlockNetworkLoads != flag) { @@ -948,9 +955,8 @@ public class WebSettings { } /** - * @hide - * Return true if the WebView will block all network loads. - * The default is false. + * Return true if the WebView will block all network loads. The default is + * false. * @return True if the WebView blocks all network loads. */ public synchronized boolean getBlockNetworkLoads() { diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java index cf71a84..9314d7b 100644 --- a/core/java/android/webkit/WebStorage.java +++ b/core/java/android/webkit/WebStorage.java @@ -146,7 +146,7 @@ public final class WebStorage { * @hide * Message handler, webcore side */ - public void createHandler() { + public synchronized void createHandler() { if (mHandler == null) { mHandler = new Handler() { @Override @@ -342,7 +342,7 @@ public final class WebStorage { /** * Utility function to send a message to our handler */ - private void postMessage(Message msg) { + private synchronized void postMessage(Message msg) { if (mHandler != null) { mHandler.sendMessage(msg); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 5f5df56..adae0cb 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -4436,6 +4436,7 @@ public class WebView extends AbsoluteLayout ted.mX = viewToContentX((int) x + mScrollX); ted.mY = viewToContentY((int) y + mScrollY); ted.mEventTime = eventTime; + ted.mMetaState = ev.getMetaState(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; } @@ -4699,6 +4700,7 @@ public class WebView extends AbsoluteLayout ted.mX = viewToContentX((int) x + mScrollX); ted.mY = viewToContentY((int) y + mScrollY); ted.mEventTime = eventTime; + ted.mMetaState = ev.getMetaState(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mFullScreenHolder == null) { doDoubleTap(); @@ -5735,6 +5737,11 @@ public class WebView extends AbsoluteLayout ted.mX = viewToContentX((int) mLastTouchX + mScrollX); ted.mY = viewToContentY((int) mLastTouchY + mScrollY); ted.mEventTime = SystemClock.uptimeMillis(); + // metaState for long press is tricky. Should it be the state + // when the press started or when the press was released? Or + // some intermediary key state? For simplicity for now, we + // don't set it. + ted.mMetaState = 0; mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDrag == PREVENT_DRAG_NO) { mTouchMode = TOUCH_DONE_MODE; diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 3a3e445..361ec56 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -515,7 +515,7 @@ final class WebViewCore { private native void nativeTouchUp(int touchGeneration, int framePtr, int nodePtr, int x, int y); - private native int nativeHandleTouchEvent(int action, int x, int y, long time); + private native int nativeHandleTouchEvent(int action, int x, int y, long time, int metaState); private native void nativeUpdateFrameCache(); @@ -735,6 +735,7 @@ final class WebViewCore { int mX; int mY; long mEventTime; + int mMetaState; } static class GeolocationPermissionsData { @@ -1198,7 +1199,7 @@ final class WebViewCore { mWebView.mPrivateHandler, WebView.PREVENT_TOUCH_ID, ted.mAction, nativeHandleTouchEvent(ted.mAction, ted.mX, - ted.mY, ted.mEventTime)).sendToTarget(); + ted.mY, ted.mEventTime, ted.mMetaState)).sendToTarget(); break; } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 5308725..2feed03 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -3092,9 +3092,9 @@ public class ListView extends AbsListView { previouslyFocusedRect.offset(mScrollX, mScrollY); final ListAdapter adapter = mAdapter; - final int firstPosition = mFirstPosition; - // Don't cache the result of getChildCount here, it could change in layoutChildren. - if (adapter.getCount() < getChildCount() + firstPosition) { + // Don't cache the result of getChildCount or mFirstPosition here, + // it could change in layoutChildren. + if (adapter.getCount() < getChildCount() + mFirstPosition) { mLayoutMode = LAYOUT_NORMAL; layoutChildren(); } @@ -3104,6 +3104,7 @@ public class ListView extends AbsListView { Rect otherRect = mTempRect; int minDistance = Integer.MAX_VALUE; final int childCount = getChildCount(); + final int firstPosition = mFirstPosition; for (int i = 0; i < childCount; i++) { // only consider selectable views diff --git a/core/java/com/android/internal/app/DisableCarModeActivity.java b/core/java/com/android/internal/app/DisableCarModeActivity.java new file mode 100644 index 0000000..95dc1f9 --- /dev/null +++ b/core/java/com/android/internal/app/DisableCarModeActivity.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.app.Activity; +import android.app.IUiModeManager; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +public class DisableCarModeActivity extends Activity { + private static final String TAG = "DisableCarModeActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + IUiModeManager uiModeManager = IUiModeManager.Stub.asInterface( + ServiceManager.getService("uimode")); + uiModeManager.disableCarMode(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to disable car mode", e); + } + finish(); + } + +} diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index c5b869b..bc7dbf4 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -93,7 +93,7 @@ public class PackageHelper { public static boolean unMountSdDir(String cid) { try { - int rc = getMountService().unmountSecureContainer(cid); + int rc = getMountService().unmountSecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc); return false; @@ -148,7 +148,7 @@ public class PackageHelper { public static boolean destroySdDir(String cid) { try { - int rc = getMountService().destroySecureContainer(cid); + int rc = getMountService().destroySecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to destroy container " + cid); return false; diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 15dcbd6..22c6e79 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -1,5 +1,6 @@ package com.android.internal.view; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -17,7 +18,7 @@ public class BaseIWindow extends IWindow.Stub { } public void resized(int w, int h, Rect coveredInsets, - Rect visibleInsets, boolean reportDraw) { + Rect visibleInsets, boolean reportDraw, Configuration newConfig) { if (reportDraw) { try { mSession.finishDrawing(this); |