diff --git a/api/current.xml b/api/current.xml index 47dc08ae48bf3..936e67e05ddb8 100644 --- a/api/current.xml +++ b/api/current.xml @@ -13804,6 +13804,8 @@ + + - + @@ -13917,8 +13919,10 @@ - + + + - + - + @@ -14399,7 +14403,7 @@ - + @@ -14568,7 +14572,7 @@ - + diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index ee6d748ac6862..0efeb1d36a91b 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -87,6 +87,9 @@ import android.Manifest; * the {@link AccountAuthenticatorResponse} as {@link AccountManager#KEY_ACCOUNT_MANAGER_RESPONSE}. * The activity must then call {@link AccountAuthenticatorResponse#onResult} or * {@link AccountAuthenticatorResponse#onError} when it is complete. + *
  • If the authenticator cannot synchronously process the request and return a result then it + * may choose to return null and then use the {@link AccountManagerResponse} to send the result + * when it has completed the request. * *

    * The following descriptions of each of the abstract authenticator methods will not describe the @@ -111,44 +114,35 @@ public abstract class AbstractAccountAuthenticator { String authTokenType, String[] requiredFeatures, Bundle options) throws RemoteException { checkBinderPermission(); - final Bundle result; try { - result = AbstractAccountAuthenticator.this.addAccount( + final Bundle result = AbstractAccountAuthenticator.this.addAccount( new AccountAuthenticatorResponse(response), accountType, authTokenType, requiredFeatures, options); + if (result != null) { + response.onResult(result); + } } catch (NetworkErrorException e) { response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage()); - return; } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, "addAccount not supported"); - return; - } - if (result != null) { - response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } public void confirmCredentials(IAccountAuthenticatorResponse response, Account account, Bundle options) throws RemoteException { checkBinderPermission(); - final Bundle result; try { - result = AbstractAccountAuthenticator.this.confirmCredentials( + final Bundle result = AbstractAccountAuthenticator.this.confirmCredentials( new AccountAuthenticatorResponse(response), account, options); + if (result != null) { + response.onResult(result); + } + } catch (NetworkErrorException e) { + response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage()); } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, "confirmCredentials not supported"); - return; - } - if (result != null) { - response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } @@ -180,9 +174,6 @@ public abstract class AbstractAccountAuthenticator { authTokenType, loginOptions); if (result != null) { response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, @@ -195,64 +186,50 @@ public abstract class AbstractAccountAuthenticator { public void updateCredentials(IAccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws RemoteException { checkBinderPermission(); - final Bundle result; try { - result = AbstractAccountAuthenticator.this.updateCredentials( + final Bundle result = AbstractAccountAuthenticator.this.updateCredentials( new AccountAuthenticatorResponse(response), account, authTokenType, loginOptions); + if (result != null) { + response.onResult(result); + } + } catch (NetworkErrorException e) { + response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage()); } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, "updateCredentials not supported"); - return; - } - if (result != null) { - response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } public void editProperties(IAccountAuthenticatorResponse response, String accountType) throws RemoteException { checkBinderPermission(); - final Bundle result; try { - result = AbstractAccountAuthenticator.this.editProperties( + final Bundle result = AbstractAccountAuthenticator.this.editProperties( new AccountAuthenticatorResponse(response), accountType); + if (result != null) { + response.onResult(result); + } } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, "editProperties not supported"); - return; - } - if (result != null) { - response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } public void hasFeatures(IAccountAuthenticatorResponse response, Account account, String[] features) throws RemoteException { checkBinderPermission(); - final Bundle result; try { - result = AbstractAccountAuthenticator.this.hasFeatures( + final Bundle result = AbstractAccountAuthenticator.this.hasFeatures( new AccountAuthenticatorResponse(response), account, features); + if (result != null) { + response.onResult(result); + } } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, "hasFeatures not supported"); - return; } catch (NetworkErrorException e) { response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage()); - return; - } - if (result != null) { - response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } @@ -264,9 +241,6 @@ public abstract class AbstractAccountAuthenticator { new AccountAuthenticatorResponse(response), account); if (result != null) { response.onResult(result); - } else { - response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, - "no response from the authenticator"); } } catch (UnsupportedOperationException e) { response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION, @@ -347,16 +321,18 @@ public abstract class AbstractAccountAuthenticator { *

  • {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to * indicate an error * + * @throws NetworkErrorException if the authenticator could not honor the request due to a + * network error */ public abstract Bundle confirmCredentials(AccountAuthenticatorResponse response, - Account account, Bundle options); - + Account account, Bundle options) + throws NetworkErrorException; /** * Gets the authtoken for an account. * @param response to send the result back to the AccountManager, will never be null * @param account the account whose credentials are to be retrieved, will never be null * @param authTokenType the type of auth token to retrieve, will never be null - * @param loginOptions a Bundle of authenticator-specific options, may be null + * @param options a Bundle of authenticator-specific options, may be null * @return a Bundle result or null if the result is to be returned via the response. The result * will contain either: *
      @@ -370,7 +346,7 @@ public abstract class AbstractAccountAuthenticator { * network error */ public abstract Bundle getAuthToken(AccountAuthenticatorResponse response, - Account account, String authTokenType, Bundle loginOptions) + Account account, String authTokenType, Bundle options) throws NetworkErrorException; /** @@ -386,7 +362,7 @@ public abstract class AbstractAccountAuthenticator { * @param account the account whose credentials are to be updated, will never be null * @param authTokenType the type of auth token to retrieve after updating the credentials, * may be null - * @param loginOptions a Bundle of authenticator-specific options, may be null + * @param options a Bundle of authenticator-specific options, may be null * @return a Bundle result or null if the result is to be returned via the response. The result * will contain either: *
        @@ -397,9 +373,11 @@ public abstract class AbstractAccountAuthenticator { *
      • {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to * indicate an error *
      + * @throws NetworkErrorException if the authenticator could not honor the request due to a + * network error */ public abstract Bundle updateCredentials(AccountAuthenticatorResponse response, - Account account, String authTokenType, Bundle loginOptions); + Account account, String authTokenType, Bundle options) throws NetworkErrorException; /** * Checks if the account supports all the specified authenticator specific features. diff --git a/core/java/android/accounts/AccountAuthenticatorActivity.java b/core/java/android/accounts/AccountAuthenticatorActivity.java index 3d7be481c75d6..5cce6da6d0ca6 100644 --- a/core/java/android/accounts/AccountAuthenticatorActivity.java +++ b/core/java/android/accounts/AccountAuthenticatorActivity.java @@ -56,30 +56,14 @@ public class AccountAuthenticatorActivity extends Activity { protected void onCreate(Bundle icicle) { super.onCreate(icicle); - if (icicle == null) { - Intent intent = getIntent(); - mAccountAuthenticatorResponse = - intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE); - } else { - mAccountAuthenticatorResponse = - icicle.getParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE); - } + mAccountAuthenticatorResponse = + getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE); if (mAccountAuthenticatorResponse != null) { mAccountAuthenticatorResponse.onRequestContinued(); } } - /** - * Saves the AccountAuthenticatorResponse in the instance state. - * @param outState where to store any instance data - */ - protected void onSaveInstanceState(Bundle outState) { - outState.putParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, - mAccountAuthenticatorResponse); - super.onSaveInstanceState(outState); - } - /** * Sends the result or a Constants.ERROR_CODE_CANCELED error if a result isn't present. */ @@ -89,7 +73,8 @@ public class AccountAuthenticatorActivity extends Activity { if (mResultBundle != null) { mAccountAuthenticatorResponse.onResult(mResultBundle); } else { - mAccountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled"); + mAccountAuthenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, + "canceled"); } mAccountAuthenticatorResponse = null; } diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 153d95f559b44..46dc895a826e8 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -237,13 +237,13 @@ public class AccountManager { * with the same UID as the Authenticator for the account. * @param account The account to add * @param password The password to associate with the account. May be null. - * @param extras A bundle of key/value pairs to set as the account's userdata. May be null. + * @param userdata A bundle of key/value pairs to set as the account's userdata. May be null. * @return true if the account was sucessfully added, false otherwise, for example, * if the account already exists or if the account is null */ - public boolean addAccountExplicitly(Account account, String password, Bundle extras) { + public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { try { - return mService.addAccount(account, password, extras); + return mService.addAccount(account, password, userdata); } catch (RemoteException e) { // won't ever happen throw new RuntimeException(e); @@ -320,6 +320,12 @@ public class AccountManager { * AccountManager, null otherwise. */ public String peekAuthToken(final Account account, final String authTokenType) { + if (account == null) { + throw new IllegalArgumentException("the account must not be null"); + } + if (authTokenType == null) { + return null; + } try { return mService.peekAuthToken(account, authTokenType); } catch (RemoteException e) { @@ -339,6 +345,9 @@ public class AccountManager { * @param password the password to set for the account. May be null. */ public void setPassword(final Account account, final String password) { + if (account == null) { + throw new IllegalArgumentException("the account must not be null"); + } try { mService.setPassword(account, password); } catch (RemoteException e) { @@ -355,6 +364,9 @@ public class AccountManager { * @param account the account whose password is to be cleared. Must not be null. */ public void clearPassword(final Account account) { + if (account == null) { + throw new IllegalArgumentException("the account must not be null"); + } try { mService.clearPassword(account); } catch (RemoteException e) { @@ -375,6 +387,12 @@ public class AccountManager { * @param value the value to set. May be null. */ public void setUserData(final Account account, final String key, final String value) { + if (account == null) { + throw new IllegalArgumentException("the account must not be null"); + } + if (key == null) { + throw new IllegalArgumentException("the key must not be null"); + } try { mService.setUserData(account, key, value); } catch (RemoteException e) { @@ -458,7 +476,7 @@ public class AccountManager { * @param account The account whose credentials are to be updated. * @param authTokenType the auth token to retrieve as part of updating the credentials. * May be null. - * @param loginOptions authenticator specific options for the request + * @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. @@ -474,7 +492,7 @@ public class AccountManager { * If the user presses "back" then the request will be canceled. */ public AccountManagerFuture getAuthToken( - final Account account, final String authTokenType, final Bundle loginOptions, + final Account account, final String authTokenType, final Bundle options, final Activity activity, AccountManagerCallback callback, Handler handler) { if (activity == null) throw new IllegalArgumentException("activity is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); @@ -482,7 +500,7 @@ public class AccountManager { public void doWork() throws RemoteException { mService.getAuthToken(mResponse, account, authTokenType, false /* notifyOnAuthFailure */, true /* expectActivityLaunch */, - loginOptions); + options); } }.start(); } @@ -584,6 +602,9 @@ public class AccountManager { final String authTokenType, final String[] requiredFeatures, final Bundle addAccountOptions, final Activity activity, AccountManagerCallback callback, Handler handler) { + if (accountType == null) { + throw new IllegalArgumentException(); + } return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { mService.addAcount(mResponse, accountType, authTokenType, @@ -683,7 +704,7 @@ public class AccountManager { * @param account The account whose credentials are to be updated. * @param authTokenType the auth token to retrieve as part of updating the credentials. * May be null. - * @param loginOptions authenticator specific options for the request + * @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. @@ -702,13 +723,13 @@ public class AccountManager { */ public AccountManagerFuture updateCredentials(final Account account, final String authTokenType, - final Bundle loginOptions, final Activity activity, + final Bundle options, final Activity activity, final AccountManagerCallback callback, final Handler handler) { return new AmsTask(activity, handler, callback) { public void doWork() throws RemoteException { mService.updateCredentials(mResponse, account, authTokenType, activity != null, - loginOptions); + options); } }.start(); } @@ -1214,7 +1235,7 @@ public class AccountManager { * @param activityForPrompting The activity used to start any account management * activities that are required to fulfill this request. This may be null. * @param addAccountOptions authenticator-specific options used if an account needs to be added - * @param loginOptions authenticator-specific options passed to getAuthToken + * @param getAuthTokenOptions authenticator-specific options passed to getAuthToken * @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 @@ -1232,13 +1253,13 @@ public class AccountManager { public AccountManagerFuture getAuthTokenByFeatures( final String accountType, final String authTokenType, final String[] features, final Activity activityForPrompting, final Bundle addAccountOptions, - final Bundle loginOptions, + final Bundle getAuthTokenOptions, final AccountManagerCallback callback, final Handler handler) { if (accountType == null) throw new IllegalArgumentException("account type is null"); if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); final GetAuthTokenByTypeAndFeaturesTask task = new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features, - activityForPrompting, addAccountOptions, loginOptions, callback, handler); + activityForPrompting, addAccountOptions, getAuthTokenOptions, callback, handler); task.start(); return task; } diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 3a11cb337b376..9c60141336e63 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -154,6 +154,7 @@ public class AccountManagerService private static final boolean isDebuggableMonkeyBuild = SystemProperties.getBoolean("ro.monkey", false) && SystemProperties.getBoolean("ro.debuggable", false); + private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{}; static { ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); @@ -268,6 +269,10 @@ public class AccountManagerService } private String readPasswordFromDatabase(Account account) { + if (account == null) { + return null; + } + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD}, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", @@ -293,6 +298,10 @@ public class AccountManagerService } private String readUserDataFromDatabase(Account account, String key) { + if (account == null) { + return null; + } + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE}, EXTRAS_ACCOUNTS_ID @@ -364,6 +373,9 @@ public class AccountManagerService SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { + if (account == null) { + return false; + } boolean noBroadcast = false; if (account.type.equals(GOOGLE_ACCOUNT_TYPE)) { // Look for the 'nobroadcast' flag and remove it since we don't want it to persist @@ -417,6 +429,14 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { + if (account == null) { + try { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "null account"); + } catch (RemoteException e) { + // it doesn't matter if we are unable to deliver this error + } + return; + } new RemoveAccountSession(response, account).bind(); } finally { restoreCallingIdentity(identityToken); @@ -513,6 +533,9 @@ public class AccountManagerService } private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) { + if (account == null || type == null) { + return false; + } cancelNotification(getSigninRequiredNotificationId(account)); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); @@ -539,6 +562,9 @@ public class AccountManagerService } public String readAuthTokenFromDatabase(Account account, String authTokenType) { + if (account == null || authTokenType == null) { + return null; + } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor cursor = db.query(TABLE_AUTHTOKENS, new String[]{AUTHTOKENS_AUTHTOKEN}, AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?) AND " @@ -586,6 +612,9 @@ public class AccountManagerService } private void setPasswordInDB(Account account, String password) { + if (account == null) { + return; + } ContentValues values = new ContentValues(); values.put(ACCOUNTS_PASSWORD, password); mOpenHelper.getWritableDatabase().update(TABLE_ACCOUNTS, values, @@ -608,23 +637,12 @@ public class AccountManagerService } } - private void sendResult(IAccountManagerResponse response, Bundle bundle) { - if (response != null) { - try { - response.onResult(bundle); - } catch (RemoteException e) { - // if the caller is dead then there is no one to care about remote - // exceptions - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "failure while notifying response", e); - } - } - } - } - public void setUserData(Account account, String key, String value) { checkAuthenticateAccountsPermission(account); long identityToken = clearCallingIdentity(); + if (account == null) { + return; + } if (account.type.equals(GOOGLE_ACCOUNT_TYPE) && key.equals("broadcast")) { sendAccountsChangedBroadcast(); return; @@ -637,6 +655,9 @@ public class AccountManagerService } private void writeUserdataIntoDatabase(Account account, String key, String value) { + if (account == null || key == null) { + return; + } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { @@ -685,6 +706,22 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { + try { + if (account == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "account is null"); + return; + } + if (authTokenType == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "authTokenType is null"); + return; + } + } catch (RemoteException e) { + // it doesn't matter if we can't deliver this error + return; + } + // if the caller has permission, do the peek. otherwise go the more expensive // route of starting a Session if (permissionGranted) { @@ -850,6 +887,16 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { + try { + if (authTokenType == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "authTokenType is null"); + return; + } + } catch (RemoteException e) { + // it doesn't matter if we can't deliver this error + return; + } new Session(response, accountType, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures, @@ -875,6 +922,16 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { + try { + if (account == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "account is null"); + return; + } + } catch (RemoteException e) { + // it doesn't matter if we can't deliver this error + return; + } new Session(response, account.type, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.confirmCredentials(this, account, options); @@ -895,6 +952,16 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { + try { + if (account == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "account is null"); + return; + } + } catch (RemoteException e) { + // it doesn't matter if we can't deliver this error + return; + } new Session(response, account.type, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions); @@ -917,6 +984,16 @@ public class AccountManagerService checkManageAccountsPermission(); long identityToken = clearCallingIdentity(); try { + try { + if (accountType == null) { + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, + "accountType is null"); + return; + } + } catch (RemoteException e) { + // it doesn't matter if we can't deliver this error + return; + } new Session(response, accountType, expectActivityLaunch) { public void run() throws RemoteException { mAuthenticator.editProperties(this, mAccountType); @@ -1565,8 +1642,10 @@ public class AccountManagerService } private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) { - final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid); - final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType); + final boolean fromAuthenticator = account != null + && hasAuthenticatorUid(account.type, callerUid); + final boolean hasExplicitGrants = account != null + && hasExplicitlyGrantedPermission(account, authTokenType); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid " + callerUid + ", account " + account @@ -1610,7 +1689,7 @@ public class AccountManagerService private void checkCallingUidAgainstAuthenticator(Account account) { final int uid = Binder.getCallingUid(); - if (!hasAuthenticatorUid(account.type, uid)) { + if (account == null || !hasAuthenticatorUid(account.type, uid)) { String msg = "caller uid " + uid + " is different than the authenticator's uid"; Log.w(TAG, msg); throw new SecurityException(msg); @@ -1641,6 +1720,9 @@ public class AccountManagerService * @hide */ public void grantAppPermission(Account account, String authTokenType, int uid) { + if (account == null || authTokenType == null) { + return; + } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { @@ -1668,6 +1750,9 @@ public class AccountManagerService * @hide */ public void revokeAppPermission(Account account, String authTokenType, int uid) { + if (account == null || authTokenType == null) { + return; + } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 9757ef68bdaaa..ba186159680d5 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -2294,8 +2294,8 @@ class SyncManager implements OnAccountsUpdateListener { } if (!mSyncStorageEngine.deleteFromPending(operationToRemove.pendingOperation)) { - throw new IllegalStateException("unable to find pending row for " - + operationToRemove); + final String errorMessage = "unable to find pending row for " + operationToRemove; + Log.e(TAG, errorMessage, new IllegalStateException(errorMessage)); } if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); @@ -2314,7 +2314,8 @@ class SyncManager implements OnAccountsUpdateListener { } if (!mSyncStorageEngine.deleteFromPending(operation.pendingOperation)) { - throw new IllegalStateException("unable to find pending row for " + operation); + final String errorMessage = "unable to find pending row for " + operation; + Log.e(TAG, errorMessage, new IllegalStateException(errorMessage)); } if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); @@ -2336,8 +2337,8 @@ class SyncManager implements OnAccountsUpdateListener { } if (!mSyncStorageEngine.deleteFromPending(syncOperation.pendingOperation)) { - throw new IllegalStateException("unable to find pending row for " - + syncOperation); + final String errorMessage = "unable to find pending row for " + syncOperation; + Log.e(TAG, errorMessage, new IllegalStateException(errorMessage)); } if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index ef90da71092cd..ced4f16a6ceb8 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -111,7 +111,7 @@ "Kunne ikke åpne filen." "Fant ikke den forespurte filen." "For mange forespørsler blir behandlet. Prøv igjen senere." - "Påloggingsfeil for %1$s" + "Innloggingsfeil for %1$s" "Synkronisering" "Synkronisering" "For mange slettinger av %s." @@ -147,8 +147,8 @@ "Overvåking av telefonens fysiske plassering" "Nettverkstilgang" "Gir applikasjoner tilgang til diverse nettverksfunksjoner." - "Dine kontoer" - "Gi tilgang til de tilgjengelige kontoene." + "Google-kontoer" + "Tilgang til tilgjengelige Google-kontoer." "Maskinvarekontroll" "Direkte tilgang til maskinvaren på telefonen." "Telefonsamtaler" @@ -195,7 +195,7 @@ "Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av." "forhindre applikasjonsbytte" "Lar applikasjonen forhindre brukeren fra å bytte til en annen applikasjon." - "Blokker popup-vinduer" + "overvåke og kontrollere all applikasjonsoppstart" "Lar applikasjonen overvåke og kontrollere hvordan systemet starter applikasjoner. Ondsinnede applikasjoner kan ta over systemet helt. Denne rettigheten behøves bare for utvikling, aldri for vanlig bruk av telefonen." "kringkaste melding om fjernet pakke" "Lar applikasjonen kringkaste en melding om at en applikasjonspakke er blitt fjernet. Ondsinnede applikasjoner kan bruke dette til å drepe vilkårlige andre kjørende applikasjoner." @@ -210,9 +210,9 @@ "endre batteristatistikk" "Lar applikasjonen endre på innsamlet batteristatistikk. Ikke ment for vanlige applikasjoner." "kontrollere backup og gjenoppretting" - "Gir programmet tillatelse til å kontrollere systemets mekanismer for sikkerhetskopiering og·gjenoppretting. Ikke beregnet på vanlige programmer." - "sikkerhetskopier og gjenopprett programmets data" - "Gir programmet tillatelse til å ta del i systemets mekanismer for sikkerhetskopiering og gjenoppretting." + "Lar applikasjonen kontrollere systemets backup- og gjenopprettingsmekanisme. Ikke ment for vanlige applikasjoner." + "foreta backup og gjenoppretting av applikasjonens data" + "Lar applikasjonen delta i systemets backup- og gjenopprettingsmekanisme." "vis uautoriserte vinduer" "Tillater at det opprettes vinduer ment for bruk av systemets interne brukergrensesnitt. Ikke ment for vanlige applikasjoner." "vise advarsler på systemnivå" @@ -258,7 +258,7 @@ "endre globale systeminnstillinger" "Lar applikasjonen endre systemets innstillingsdata. Ondsinnede applikasjoner kan skade systemets innstillinger." "endre sikre systeminnstillinger" - "Gir programmet tillatelse til å endre systemets data for sikkerhetsinnstilling. Ikke beregnet på vanlige programmer." + "Gir programmet tillatelse til å endre systemets data for sikkerhetsinnstilling. Ikke ment for vanlige programmer." "redigere Google-tjenestekartet" "Lar applikasjonen redigere Google-tjenestekartet. Ikke ment for bruk av vanlige applikasjoner." "starte automatisk sammen med systemet" @@ -315,8 +315,8 @@ "Lar applikasjonen ringe telefonnummer uten inngripen fra brukeren. Ondsinnede applikasjoner kan forårsake uventede oppringinger på telefonregningen. Merk at dette ikke gir applikasjonen lov til å ringe nødnummer." "ringe vilkårlige telefonnummer direkte" "Lar applikasjonen ringe hvilket som helst telefonnummer, inkludert nødnummer, uten inngripen fra brukeren. Ondsinnede applikasjoner kan forårsake unødvendige og ulovlige samtaler til nødtjenester." - "start CDMA-telefonoppsett direkte" - "Gir programmet tillatelse til å starte klargjøring av CDMA. Skadelige programmer kan starte klargjøring av CDMA uten grunn" + "begynne CDMA-telefonoppsett direkte" + "Lar applikasjonen begynne CDMA-oppsett. Ondsinnede applikasjoner kan bruke dette til å starte CDMA-oppsett uten grunn." "kontrollere varsling for plasseringsendring" "Lar applikasjonen slå av/på varsling om plasseringsendringer fra radioen. Ikke ment for vanlige applikasjoner." "få tilgang til egenskaper for innsjekking" @@ -432,56 +432,56 @@ "ICQ" "Jabber" - "Tilpasset" - "Privat" + "Egendefinert" + "Hjemme" "Mobil" "Arbeid" - "Send faks (arbeid)" - "Send faks (privat)" + "Faks arbeid" + "Faks hjemme" "Personsøker" "Annen" - "Tilbakeringing" + "Tilbakering" "Bil" - "Firma (sentralbord)" + "Firma hoved" "ISDN" "Hoved" - "Annen faks" + "Faks annen" "Radio" "Teleks" - "TTY/TDD" - "Mobil (arbeid)" - "Personsøker (arbeid)" + "Teksttelefon" + "Mobil arbeid" + "Personsøker arbeid" "Assistent" "MMS" - "Fødselsdag" - "Merkedag" - "Aktivitet" - "Tilpasset" - "Privat" + "Bursdag" + "Jubileum" + "Akivitet" + "Egendefinert" + "Hjemme" "Arbeid" "Annen" "Mobil" - "Tilpasset" - "Privat" + "Egendefinert" + "Hjemme" "Arbeid" "Annen" - "Tilpasset" - "Privat" + "Egendefinert" + "Hjemme" "Arbeid" "Annen" - "Tilpasset" + "Egendefinert" "AIM" "Windows Live" "Yahoo" "Skype" - "QQ" + "OQ" "Google Talk" "ICQ" "Jabber" "NetMeeting" "Arbeid" "Annen" - "Tilpasset" + "Egendefinert" "via %1$s" "%1$s via %2$s" "Skriv inn PIN-kode:" @@ -530,17 +530,17 @@ "Lader…" "Koble til en lader" "Batteriet er nesten tomt:" - "%d%% eller mindre gjenstår." + "mindre enn %d%% igjen." "Batteribruk" - "Factory test failed" + "Fabrikktesten feilet" "The FACTORY_TEST action is only supported for packages installed in /system/app." "No package was found that provides the FACTORY_TEST action." - "Reboot" + "Omstart" "Siden \'%s sier:" "JavaScript" "Naviger bort fra denne siden?"\n\n"%s"\n\n"Velg OK for å fortsette, eller Avbryt for å forbli på denne siden." "Bekreft" - "Tips: trykk to ganger for å zoome inn og ut." + "Dobbelttrykk for å zoome inn og ut." "lese nettleserens logg og bokmerker" "Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker." "skrive til nettleserens logg og bokmerker" @@ -623,7 +623,7 @@ "i morgen" "om %d d" - "den %s" + "%s" "kl. %s" "i %s" "dag" @@ -675,24 +675,24 @@ "Merk" "På" "Av" - "Complete action using" - "Use by default for this action." - "Clear default in Home Settings > Applications > Manage applications." - "Select an action" - "No applications can perform this action." - "Sorry!" - "The application %1$s (process %2$s) has stopped unexpectedly. Please try again." - "The process %1$s has stopped unexpectedly. Please try again." - "Sorry!" - "Activity %1$s (in application %2$s) is not responding." - "Activity %1$s (in process %2$s) is not responding." - "Application %1$s (in process %2$s) is not responding." - "Process %1$s is not responding." - "Force close" + "Fullfør med" + "Bruk som standardvalg." + "Fjern standardvalg i Innstillinger > Applikasjoner > Installerte applikasjoner." + "Velg en aktivitet" + "Ingen applikasjoner kan gjøre dette." + "Beklager!" + "Applikasjonen %1$s (prosess %2$s) stoppet uventet. Prøv igjen." + "Prosessen %1$s stoppet uventet. Prøv igjen." + "Beklager!" + "Aktiviteten %1$s (i applikasjonen %2$s) svarer ikke." + "Aktiviteten %1$s (i prosessen %2$s) svarer ikke." + "Applikasjonen %1$s (i prosessen %2$s) svarer ikke." + "Prosessen %1$s svarer ikke." + "Tving avslutning" "Rapportér" - "Wait" + "Vent" "Debug" - "Select an action for text" + "Velg mål for tekst" "Ringetonevolum" "Medievolum" "Spiller over Bluetooth" @@ -740,12 +740,12 @@ "Før du slår av USB-lagring, sjekk at du har avmontert enheten i USB-verten. Velg «slå av» for å slå av USB-lagring." "Slå av" "Avbryt" - "Det har oppstått et problem ved deaktiveringen av USB-lagring. Kontroller at du har frakoblet USB-verten, og prøv igjen." + "Det har oppstått et problem ved deaktiveringen av USB-lagring. Kontroller at du har demontert USB-verten, og prøv igjen." "Formatere minnekort" "Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt." - "Format" + "Formatér" "USB-debugging tilkoblet" - "Velg for å deaktivere USB-feilsøking" + "Velg for å deaktivere USB-debugging." "Velg inndatametode" " ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" @@ -777,19 +777,19 @@ "Lag kontakt"\n"med nummeret %s" "valgt" "ikke valgt" - "De·oppførte·programmene ber om tilgangstillatelse til påloggingsopplysningene for konto %1$s fra %2$s. Vil du gi denne tillatelsen? I·så·fall·lagres·svaret,·og·du·blir·ikke·spurt·flere·ganger." - "De·oppførte·programmene ber om tilgangstillatelse til %1$s-påloggingsopplysningene for konto %2$s fra %3$s. Vil du gi denne tillatelsen? I·så·fall·lagres·svaret,·og·du·blir·ikke·spurt·flere·ganger." + "Det nevnte programmet ber om tilgangstillatelse til påloggingsopplysningene for konto %1$s fra %2$s. Vil du gi denne tillatelsen? I så fall vil svaret ditt bli lagret, og du vil ikke bli spurt flere ganger." + "Det nevnte programmet ber om tilgangstillatelse til %1$s-påloggingsopplysningene for konto %2$s fra %3$s. Vil du gi denne tillatelsen? I så fall vil svaret ditt bli lagret, og du vil ikke bli spurt flere ganger." "Tillat" "Avslå" "Tillatelse forespurt" - "Tillatelse forespurt"\n"for konto %s" + "Trenger tillatelse"\n"for konto %s" "Inndatametode" "Synkronisering" "Tilgjengelighet" "Bakgrunnsbilde" - "Endre bakgrunnsbilde" - "PPTP·(point-to-point·tunneling·protocol)" - "Tunnelprotokoll for lag 2" - "Forhåndsdelt nøkkelbasert L2TP/IPSec VPN" - "Sertifikatbasert L2TP/IPSec VPN" + "Velg bakgrunnsbilde" + "Punkt-til-punkt-tunneleringsprotokoll" + "Lag 2-tunneleringsprotokoll" + "Passordbasert L2TP/IPSec-VPN" + "Sertifikatbasert L2TP/IPSec-VPN" diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index f4192845370d1..c5f5a4b609842 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -444,7 +444,7 @@ "Overig" "Terugbelnummer" "Auto" - "Hoofdkantoor" + "Bedrijf, algemeen" "ISDN" "Algemeen" "Andere fax" diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd index b3b6371d97370..083003236a25b 100644 --- a/docs/html/guide/appendix/api-levels.jd +++ b/docs/html/guide/appendix/api-levels.jd @@ -324,22 +324,24 @@ control to show documentation only for parts of the API that are actually accessible to your application, based on the API Level that it specifies in the android:minSdkVersion attribute of its manifest file.

      -

      To use filtering, set the control to the same API Level as that specified -by your application. Notice that APIs introduced in a later API Level are -then grayed out and their content is masked, since they would not be -accessible to your application.

      +

      To use filtering, select the checkbox to enable filtering, just below the +page search box. Then set the "Filter by API Level" control to the same API +Level as specified by your application. Notice that APIs introduced in a later +API Level are then grayed out and their content is masked, since they would not +be accessible to your application.

      Filtering by API Level in the documentation does not provide a view of what is new or introduced in each API Level — it simply provides a way to view the entire API associated with a given API Level, while excluding API elements introduced in later API Levels.

      -

      By default, API Level filtering is enabled and set to show the latest API -Level. If you do not want to use filtering reference documentation, -simply select the highest available API Level.

      +

      If you decide that you don't want to filter the API documentation, just +disable the feature using the checkbox. By default, API Level filtering is +disabled, so that you can view the full framework API, regardless of API Level. +

      Also note that the reference documentation for individual API elements -specifies the API Level at which the elements were introduced. The API Level +specifies the API Level at which each element was introduced. The API Level for packages and classes is specified as "Since <api level>" at the top-right corner of the content area on each documentation page. The API Level for class members is specified in their detailed description headers, diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd index 1d16d886f960c..88975f8c09283 100644 --- a/docs/html/guide/practices/screens_support.jd +++ b/docs/html/guide/practices/screens_support.jd @@ -1069,28 +1069,29 @@ not. Once you've tested your application and found that it displays properly on various screen sizes, you should make sure to add the corresponding size attribute(s) to your application's manifest. --> +

      + +

      Figure 3. + A typical set of AVDs for testing screens support.

      +
      +

      As a test environment for your applications, set up a series of AVDs that emulate the screen sizes and densities you want to support. The Android SDK -includes four emulator skins to get you started. You can use the Android AVD +includes six emulator skins to get you started. You can use the Android AVD Manager or the android tool to create AVDs that use the various emulator skins and you can also set up custom AVDs to test densities other than the defaults. For general information about working with AVDs, see Android Virtual Devices.

      -

      The Android 1.6 and higher platforms in the SDK include these emulator skins, -which represent the primary screen configurations that your should test:

      +

      The Android SDK provides a set of default emulator skins that you can use for +testing. The skins are included as part of each Android platform that you can +install in your SDK. The Android 1.6 platform offers these default skins:

      • QVGA (240x320, low density, small screen)
      • -
      • - WQVGA400 (240x400, low density, normal screen) -
      • -
      • - WQVGA432 (240x432, low density, normal screen) -
      • HVGA (320x480, medium density, normal screen)
      • @@ -1102,6 +1103,18 @@ which represent the primary screen configurations that your should test:

      +

      The Android 2.0 platform offers all of the Android 1.6 default skins, +above, plus:

      + +
        +
      • + WQVGA400 (240x400, low density, normal screen) +
      • +
      • + WQVGA432 (240x432, low density, normal screen) +
      • +
      +

      If you are using the android tool command line to create your AVDs, here's an example of how to specify the skin you want to use:

      @@ -1130,6 +1143,12 @@ monitor. Using the default densities, the emulator skins included in the Android
    • QVGA, low density: 3.3"
    • +
    • + WQVGA, low density: 3.9" +
    • +
    • + WQVGA432, low density: 4.1" +
    • HVGA, medium density: 3.6"
    • @@ -1141,6 +1160,12 @@ monitor. Using the default densities, the emulator skins included in the Android
    +
    + +

    Figure 4. + Resolution and density options that you can use, when creating an AVD using the AVD Manager.

    +
    +

    You should also make sure to test your application on different physical screen sizes within a single size-density configuration. For example, according to Table 1, the minimum supported diagonal of QVGA is 2.8". @@ -1150,21 +1175,35 @@ To display this is on a 30" monitor you will need to adjust the value passed to

    emulator -avd <name> -scale 0.6
    -

    If you would like to test your application on a screen not supported by the -built-in skins, you can either adjust an existing skin, or create a custom -resolution.

    +

    If you would like to test your application on a screen that uses a resolution +or density not supported by the built-in skins, you can either adjust an +existing skin, or create an AVD +that uses a custom resolution or density.

    -

    For example, to test on a large WVGA800 screen with medium density:

    +

    In the AVD Manager, you can specify a custom skin resolution or density in +the Create New AVD dialog, as shown in Figure 4, at right.

    + +

    In the android tool, follow these steps to create an AVD with a +custom resolution or density:

      -
    1. Create an AVD based on the WVGA800 skin (using the android -tool's command line.)
    2. -
    3. Answer "yes" when asked about using custom hardware
    4. -
    5. enter "160" when asked about the value for hw.lcd.density -(120-low, 160-medium, 240-high).
    6. +
    7. Use the create avd command to create a new AVD, specifying +the --skin option with a value that references either a default +skin name (such as "WVGA800") or a custom skin resolution (such as 240x432). +Here's an example: +
      android create avd -n <name> -t <targetID> --skin WVGA800
      +
    8. +
    9. To specify a custom density for the skin, answer "yes" when asked whether +you want to create a custom hardware profile for the new AVD.
    10. +
    11. Continue through the various profile settings until the tool asks you to +specify "Abstracted LCD density" (hw.lcd.density). Consult Table 1, earlier in this document, and enter the appropriate +value. For example, enter "160" to use medium density for the WVGA800 screen.
    12. +
    13. Set any other hardware options and complete the AVD creation.
    -

    When running this AVD, the emulator will emulate a 5.8" WVGA screen.

    +

    In the example above (WVGA medium density), the new AVD will emulate a 5.8" +WVGA screen.

    As an alternative to adjusting the emulator skin configuration, you can use the emulator skin's default density and add the -dpi-device option @@ -1172,25 +1211,6 @@ to the emulator command line when starting the AVD. For example,

    emulator -avd WVGA800 -scale 96dpi -dpi-device 160
    -

    If you would like to test your application with a resolution not supported by -the provided skins, you can use the desired resolution in place of the skin -name. For instance, for FWQVGA you would use:

    - -
    android create avd ... --skin 240x432
    - -

    Next, you would need to set the proper density for the screen. When asked by -the tool whether you want to create a custom hardware profile for the new AVD, -enter "yes". Continue through the various profile settings until the tools asks -you to specify "Abstracted LCD density". Consult Table 1, -earlier in this document, and enter the appropriate value. For the FWQVGA -screen, the density should be "160", or medium.

    - -
    - -

    Figure 3. - A typical set of AVDs for testing screens support.

    -
    -

    Screen-Compatibility Examples

    diff --git a/docs/html/images/screens_support/avd-density.png b/docs/html/images/screens_support/avd-density.png new file mode 100644 index 0000000000000..e3fc36ec5c692 Binary files /dev/null and b/docs/html/images/screens_support/avd-density.png differ diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/sdk/android-1.5.jd index 15d19383b7c73..46126820410e2 100644 --- a/docs/html/sdk/android-1.5.jd +++ b/docs/html/sdk/android-1.5.jd @@ -16,7 +16,6 @@ sdk.platform.deployableDate=May 2009
  • Built-in Applications
  • Locales
  • Emulator Skins
  • -
  • Other Notes
  • Framework API
    1. API level
    2. diff --git a/docs/html/sdk/android-1.6.jd b/docs/html/sdk/android-1.6.jd index 38112b547376e..4b659a1af62f5 100644 --- a/docs/html/sdk/android-1.6.jd +++ b/docs/html/sdk/android-1.6.jd @@ -16,7 +16,6 @@ sdk.platform.deployableDate=October 2009
    3. Built-in Applications
    4. Locales
    5. Emulator Skins
    6. -
    7. Other Notes
    8. Framework API
      1. API level
      2. diff --git a/docs/html/sdk/api_diff/3/changes.html b/docs/html/sdk/api_diff/3/changes.html index bc0f8791013c1..9bc67b987711d 100644 --- a/docs/html/sdk/api_diff/3/changes.html +++ b/docs/html/sdk/api_diff/3/changes.html @@ -26,12 +26,12 @@ body{overflow:auto;} body{background-image:url();padding:12px;} - - - - + + + + - + <H2> diff --git a/docs/html/sdk/api_diff/3/stylesheet-jdiff.css b/docs/html/sdk/api_diff/3/stylesheet-jdiff.css index b3c1b9af86b9a..abc4dd5eb80bf 100644 --- a/docs/html/sdk/api_diff/3/stylesheet-jdiff.css +++ b/docs/html/sdk/api_diff/3/stylesheet-jdiff.css @@ -3,6 +3,7 @@ div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;} table.diffspectable {border:1px;padding:0px;margin:0px;} +table.jdiffIndex {margin-bottom:.5em;} .diffspechead {background-color:#eee;} .diffspectable tr {border:0px;padding:0px;} .diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;} @@ -29,7 +30,7 @@ tt {font-size:11pt;font-family:monospace;} } .hiddenlink { font-size:96%; - line-height:.8em; +/* line-height:.8em; */ text-decoration:none;} a { text-decoration:none;} diff --git a/docs/html/sdk/api_diff/4/changes.html b/docs/html/sdk/api_diff/4/changes.html index c1b66a1ef24ff..9cfdc24173d64 100644 --- a/docs/html/sdk/api_diff/4/changes.html +++ b/docs/html/sdk/api_diff/4/changes.html @@ -25,12 +25,12 @@ body{overflow:auto;} <style type="text/css"> </style> </HEAD> -<FRAMESET COLS="242,**" frameborder="1" border="7" xframespacing="20" bordercolor="#e9e9e9"> -<frameset rows="164,**" frameborder="1" border="7" xframespacing="20" resizable="yes"> - <FRAME SRC="changes/jdiff_topleftframe.html" SCROLLING="no" NAME="topleftframe" xframeborder="1" xborder="6" xframespacing="0"> - <FRAME SRC="changes/alldiffs_index_all.html" SCROLLING="auto" NAME="bottomleftframe" xframeborder="1" xborder="1" xframespacing="0"> +<FRAMESET COLS="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> +<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> + <FRAME SRC="changes/jdiff_topleftframe.html" SCROLLING="no" NAME="topleftframe" frameborder="1"> + <FRAME SRC="changes/alldiffs_index_all.html" SCROLLING="auto" NAME="bottomleftframe" frameborder="1"> </FRAMESET> - <FRAME SRC="changes/changes-summary.html" SCROLLING="auto" NAME="rightframe" xframeborder="1" xborder="1" xframespacing="0"> + <FRAME SRC="changes/changes-summary.html" SCROLLING="auto" NAME="rightframe" frameborder="1"> </FRAMESET> <NOFRAMES> <H2> diff --git a/docs/html/sdk/api_diff/4/stylesheet-jdiff.css b/docs/html/sdk/api_diff/4/stylesheet-jdiff.css index b3c1b9af86b9a..824b3df4c1661 100644 --- a/docs/html/sdk/api_diff/4/stylesheet-jdiff.css +++ b/docs/html/sdk/api_diff/4/stylesheet-jdiff.css @@ -3,6 +3,7 @@ div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;} table.diffspectable {border:1px;padding:0px;margin:0px;} +table.jdiffIndex {margin-bottom:.5em;} .diffspechead {background-color:#eee;} .diffspectable tr {border:0px;padding:0px;} .diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;} @@ -29,7 +30,7 @@ tt {font-size:11pt;font-family:monospace;} } .hiddenlink { font-size:96%; - line-height:.8em; +/* line-height:.8em; */ text-decoration:none;} a { text-decoration:none;} diff --git a/docs/html/sdk/api_diff/5/changes.html b/docs/html/sdk/api_diff/5/changes.html index dc3f7cb515613..671e89069f54c 100644 --- a/docs/html/sdk/api_diff/5/changes.html +++ b/docs/html/sdk/api_diff/5/changes.html @@ -25,12 +25,12 @@ body{overflow:auto;} <style type="text/css"> </style> </HEAD> -<FRAMESET COLS="242,**" frameborder="1" border="7" xframespacing="20" bordercolor="#e9e9e9"> -<frameset rows="164,**" frameborder="1" border="7" xframespacing="20" resizable="yes"> - <FRAME SRC="changes/jdiff_topleftframe.html" SCROLLING="no" NAME="topleftframe" xframeborder="1" xborder="6" xframespacing="0"> - <FRAME SRC="changes/alldiffs_index_all.html" SCROLLING="auto" NAME="bottomleftframe" xframeborder="1" xborder="1" xframespacing="0"> +<FRAMESET COLS="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> +<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> + <FRAME SRC="changes/jdiff_topleftframe.html" SCROLLING="no" NAME="topleftframe" frameborder="1"> + <FRAME SRC="changes/alldiffs_index_all.html" SCROLLING="auto" NAME="bottomleftframe" frameborder="1"> </FRAMESET> - <FRAME SRC="changes/changes-summary.html" SCROLLING="auto" NAME="rightframe" xframeborder="1" xborder="1" xframespacing="0"> + <FRAME SRC="changes/changes-summary.html" SCROLLING="auto" NAME="rightframe" frameborder="1"> </FRAMESET> <NOFRAMES> <H2> diff --git a/docs/html/sdk/api_diff/5/stylesheet-jdiff.css b/docs/html/sdk/api_diff/5/stylesheet-jdiff.css index b3c1b9af86b9a..abc4dd5eb80bf 100644 --- a/docs/html/sdk/api_diff/5/stylesheet-jdiff.css +++ b/docs/html/sdk/api_diff/5/stylesheet-jdiff.css @@ -3,6 +3,7 @@ div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;} table.diffspectable {border:1px;padding:0px;margin:0px;} +table.jdiffIndex {margin-bottom:.5em;} .diffspechead {background-color:#eee;} .diffspectable tr {border:0px;padding:0px;} .diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;} @@ -29,7 +30,7 @@ tt {font-size:11pt;font-family:monospace;} } .hiddenlink { font-size:96%; - line-height:.8em; +/* line-height:.8em; */ text-decoration:none;} a { text-decoration:none;} diff --git a/docs/html/videos/index.jd b/docs/html/videos/index.jd index ddb9f861fae2e..4e53aac2991c9 100644 --- a/docs/html/videos/index.jd +++ b/docs/html/videos/index.jd @@ -37,12 +37,10 @@ var playlistsWithTitleInDescription = "734A052F802C96B9"; * Each playlist ID is paired with a custom video description. */ var featured = { -// Android 1.6 Release - 'MBRFkLKRwFw' : "The Android 1.6 release includes new features and improvements to the Android platform. Here's an introduction to what's new in Android 1.6.", +// Android 2.0 Release + 'opZ69P-0Jbc' : "The Android 2.0 platform adds exciting new user features and developer APIs. Here's an introduction to what's new.", // How to Make your Android UI Fast.. 'N6YdwzAvwOA' : "Make your user interface fast, with more efficient AdapterViews, better bitmap scaling, faster redrawing, ViewStub layouts, fewer Views, and more.", -// Coding for Life: Battery Life -// 'OUemfrKe65c' : "Learn what kinds of operations consume the most battery and how you can reduce your usage, with tips for parsing and zipping data, using wakelocks, and running a Service.", // How Do I Code Thee? 'GARMe7Km_gk' : "If you'd like to augment your Android applications with pieces written in JavaScript or native code, watch this video." }; diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp index 8ac9c26a2f37f..b7d1297feddf1 100644 --- a/libs/rs/rsAllocation.cpp +++ b/libs/rs/rsAllocation.cpp @@ -405,7 +405,7 @@ RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint3 const uint8_t * src = static_cast<const uint8_t *>(data); for (uint32_t y = 0; y < h; y++) { uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp]; - memcpy(&ydst[(w2 - w) >> 1], src, w * bpp); + memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp); src += w * bpp; } diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index 0c3d0eef5cdc6..4b9e59b7c885f 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -154,6 +154,8 @@ static bool copybit(GLint x, GLint y, int transform, ogles_context_t* c) { + status_t err = NO_ERROR; + // We assume checkContext has already been called and has already // returned true. @@ -200,6 +202,7 @@ static bool copybit(GLint x, GLint y, const uint32_t enables = c->rasterizer.state.enables; int planeAlpha = 255; + bool alphaPlaneWorkaround = false; static const int tmu = 0; texture_t& tev(c->rasterizer.state.texture[tmu]); int32_t opFormat = textureObject->surface.format; @@ -259,9 +262,10 @@ static bool copybit(GLint x, GLint y, if (c->currentColorClamped.r == c->currentColorClamped.a && c->currentColorClamped.g == c->currentColorClamped.a && c->currentColorClamped.b == c->currentColorClamped.a) { - // TODO: Need to emulate: RGBA source, color={a,a,a,a} / premult - // and RGBA source, color={1,1,1,a} / regular-blending - // (both are equivalent) + // TODO: RGBA source, color={1,1,1,a} / regular-blending + // is equivalent + alphaPlaneWorkaround = true; + break; } } LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE"); @@ -331,13 +335,13 @@ static bool copybit(GLint x, GLint y, tmp_w, tmp_h, src.format, GraphicBuffer::USAGE_HW_2D); - status_t err = tempBitmap->initCheck(); + err = tempBitmap->initCheck(); if (err == NO_ERROR) { copybit_image_t tmp_dst; copybit_rect_t tmp_rect; tmp_dst.w = tmp_w; tmp_dst.h = tmp_h; - tmp_dst.format = src.format; + tmp_dst.format = tempBitmap->format; tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle; tmp_rect.l = 0; tmp_rect.t = 0; @@ -359,13 +363,66 @@ static bool copybit(GLint x, GLint y, textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst); copybit_rect_t drect = {x, y, x+w, y+h}; - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); - clipRectRegion it(c); - status_t err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + /* and now the alpha-plane hack. This handles the "Fade" case of a + * texture with an alpha channel. + */ + if (alphaPlaneWorkaround) { + sp<GraphicBuffer> tempCb = new GraphicBuffer( + w, h, COPYBIT_FORMAT_RGB_565, + GraphicBuffer::USAGE_HW_2D); + + err = tempCb->initCheck(); + + copybit_image_t tmpCbImg; + copybit_rect_t tmpCbRect; + tmpCbImg.w = w; + tmpCbImg.h = h; + tmpCbImg.format = tempCb->format; + tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle; + tmpCbRect.l = 0; + tmpCbRect.t = 0; + tmpCbRect.r = w; + tmpCbRect.b = h; + + if (!err) { + // first make a copy of the destination buffer + region_iterator tmp_it(Region(Rect(w, h))); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); + err = copybit->stretch(copybit, + &tmpCbImg, &dst, &tmpCbRect, &drect, &tmp_it); + } + if (!err) { + // then proceed as usual, but without the alpha plane + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + copybit->set_parameter(copybit, COPYBIT_DITHER, + (enables & GGL_ENABLE_DITHER) ? + COPYBIT_ENABLE : COPYBIT_DISABLE); + clipRectRegion it(c); + err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + } + if (!err) { + // finally copy back the destination on top with 1-alphaplane + int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a); + clipRectRegion it(c); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + err = copybit->stretch(copybit, + &dst, &tmpCbImg, &drect, &tmpCbRect, &it); + } + } else { + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); + copybit->set_parameter(copybit, COPYBIT_DITHER, + (enables & GGL_ENABLE_DITHER) ? + COPYBIT_ENABLE : COPYBIT_DISABLE); + clipRectRegion it(c); + err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + } if (err != NO_ERROR) { c->textures.tmu[0].texture->try_copybit = false; } diff --git a/packages/SubscribedFeedsProvider/res/values-nb/strings.xml b/packages/SubscribedFeedsProvider/res/values-nb/strings.xml index 53bf3b57193e6..30a2c5ea96368 100644 --- a/packages/SubscribedFeedsProvider/res/values-nb/strings.xml +++ b/packages/SubscribedFeedsProvider/res/values-nb/strings.xml @@ -15,6 +15,6 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5400580392303600842">"Synkroniser·innmatinger"</string> + <string name="app_label" msgid="5400580392303600842">"Strømsynkronisering"</string> <string name="provider_label" msgid="3669714991966737047">"Push-abonnementer"</string> </resources> diff --git a/packages/VpnServices/res/values-nb/strings.xml b/packages/VpnServices/res/values-nb/strings.xml index 506f99926de0f..9aac82867b043 100644 --- a/packages/VpnServices/res/values-nb/strings.xml +++ b/packages/VpnServices/res/values-nb/strings.xml @@ -16,7 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4589592829302498102">"VPN-tjenester"</string> - <string name="vpn_notification_title_connected" msgid="8598654486956133580">"<xliff:g id="PROFILENAME">%s</xliff:g> er VPN-tilkoblet"</string> - <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"<xliff:g id="PROFILENAME">%s</xliff:g> er VPN-frakoblet"</string> + <string name="vpn_notification_title_connected" msgid="8598654486956133580">"Koblet til VPNet <xliff:g id="PROFILENAME">%s</xliff:g>"</string> + <string name="vpn_notification_title_disconnected" msgid="6216572264382192027">"Koblet fra VPNet <xliff:g id="PROFILENAME">%s</xliff:g>"</string> <string name="vpn_notification_hint_disconnected" msgid="1952209867082269429">"Trykk for å koble til et VPN på nytt"</string> </resources> diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index cd6a3712a8bf3..94667ebbac3ef 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -9303,6 +9303,15 @@ public class WindowManagerService extends IWindowManager.Stub & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { wallpaperMayChange = true; } + if (changed && !forceHiding + && (mCurrentFocus == null) + && (mFocusedApp != null)) { + // It's possible that the last focus recalculation left no + // current focused window even though the app has come to the + // foreground already. In this case, we make sure to recalculate + // focus when we show a window. + focusMayChange = true; + } } mPolicy.animatingWindowLw(w, attrs); @@ -9644,7 +9653,8 @@ public class WindowManagerService extends IWindowManager.Stub WindowState w = (WindowState)mWindows.get(i); if (w.mSurface != null) { final WindowManager.LayoutParams attrs = w.mAttrs; - if (mPolicy.doesForceHide(w, attrs)) { + if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { + if (DEBUG_FOCUS) Log.i(TAG, "win=" + w + " force hides other windows"); forceHiding = true; } else if (mPolicy.canBeForceHidden(w, attrs)) { if (!w.mAnimating) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index ad1926e20aa69..56270f48b45ab 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2705,13 +2705,31 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. - Configuration config = mWindowManager.updateOrientationFromAppTokens( - mConfiguration, - next.mayFreezeScreenLocked(next.app) ? next : null); - if (config != null) { - next.frozenBeforeDestroy = true; + boolean updated; + synchronized (this) { + Configuration config = mWindowManager.updateOrientationFromAppTokens( + mConfiguration, + next.mayFreezeScreenLocked(next.app) ? next : null); + if (config != null) { + /* + * Explicitly restore the locale to the one from the + * old configuration, since the one that comes back from + * the window manager has the default (boot) locale. + * + * It looks like previously the locale picker only worked + * by coincidence: usually it would do its setting of + * the locale after the activity transition, so it didn't + * matter that this lost it. With the synchronized + * block now keeping them from happening at the same time, + * this one always would happen second and undo what the + * locale picker had just done. + */ + config.locale = mConfiguration.locale; + next.frozenBeforeDestroy = true; + } + updated = updateConfigurationLocked(config, next); } - if (!updateConfigurationLocked(config, next)) { + if (!updated) { // The configuration update wasn't able to keep the existing // instance of the activity, and instead started a new one. // We should be all done, but let's just make sure our activity