summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/accounts/AccountManagerService.java797
-rw-r--r--core/java/android/app/Activity.java9
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/DialogFragment.java6
-rw-r--r--core/java/android/app/FragmentManager.java7
-rw-r--r--core/java/android/app/backup/WallpaperBackupHelper.java9
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/pm/PackageManager.java15
-rw-r--r--core/java/android/hardware/IUsbManager.aidl31
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl64
-rw-r--r--core/java/android/hardware/usb/UsbAccessory.aidl (renamed from core/java/android/hardware/UsbAccessory.aidl)2
-rw-r--r--core/java/android/hardware/usb/UsbAccessory.java (renamed from core/java/android/hardware/UsbAccessory.java)33
-rw-r--r--core/java/android/hardware/usb/UsbConstants.java (renamed from core/java/android/hardware/UsbConstants.java)2
-rw-r--r--core/java/android/hardware/usb/UsbDevice.aidl (renamed from core/java/android/hardware/UsbDevice.aidl)2
-rw-r--r--core/java/android/hardware/usb/UsbDevice.java (renamed from core/java/android/hardware/UsbDevice.java)25
-rw-r--r--core/java/android/hardware/usb/UsbEndpoint.aidl (renamed from core/java/android/hardware/UsbEndpoint.aidl)2
-rw-r--r--core/java/android/hardware/usb/UsbEndpoint.java (renamed from core/java/android/hardware/UsbEndpoint.java)20
-rw-r--r--core/java/android/hardware/usb/UsbInterface.aidl (renamed from core/java/android/hardware/UsbInterface.aidl)2
-rw-r--r--core/java/android/hardware/usb/UsbInterface.java (renamed from core/java/android/hardware/UsbInterface.java)14
-rw-r--r--core/java/android/hardware/usb/UsbManager.java (renamed from core/java/android/hardware/UsbManager.java)31
-rw-r--r--core/java/android/hardware/usb/UsbRequest.java (renamed from core/java/android/hardware/UsbRequest.java)12
-rw-r--r--core/java/android/os/Parcel.java1
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java34
-rw-r--r--core/java/android/view/ViewGroup.java36
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java63
-rw-r--r--core/java/android/view/ViewRoot.java103
-rw-r--r--core/java/android/view/WindowManagerImpl.java14
-rw-r--r--core/java/android/webkit/CookieManager.java88
-rw-r--r--core/java/android/webkit/HTML5VideoViewProxy.java5
-rw-r--r--core/java/android/webkit/WebTextView.java2
-rw-r--r--core/java/android/webkit/WebView.java37
-rw-r--r--core/java/android/webkit/ZoomManager.java7
-rw-r--r--core/java/android/widget/AbsListView.java100
-rw-r--r--core/java/android/widget/ExpandableListView.java3
-rw-r--r--core/java/android/widget/HorizontalScrollView.java8
-rw-r--r--core/java/android/widget/ScrollView.java8
-rw-r--r--core/java/android/widget/StackView.java36
-rw-r--r--core/java/android/widget/TabHost.java8
-rw-r--r--core/java/android/widget/TabWidget.java9
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java21
-rw-r--r--core/jni/android_hardware_UsbDevice.cpp8
-rw-r--r--core/jni/android_hardware_UsbEndpoint.cpp124
-rw-r--r--core/jni/android_hardware_UsbRequest.cpp8
-rw-r--r--core/jni/android_os_ParcelFileDescriptor.cpp15
-rw-r--r--core/jni/android_util_Binder.cpp9
-rw-r--r--core/res/AndroidManifest.xml28
-rw-r--r--core/res/res/values-es/strings.xml78
-rw-r--r--core/res/res/values-in/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml18
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values/config.xml3
-rwxr-xr-xcore/res/res/values/strings.xml6
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java42
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java24
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java2
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java30
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java11
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java136
59 files changed, 1314 insertions, 909 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 2e70a56..894e196 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -52,7 +52,6 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -81,8 +80,6 @@ import java.util.concurrent.atomic.AtomicReference;
public class AccountManagerService
extends IAccountManager.Stub
implements RegisteredServicesCacheListener<AuthenticatorDescription> {
- private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
-
private static final String TAG = "AccountManagerService";
private static final int TIMEOUT_DELAY_MS = 1000 * 60;
@@ -101,7 +98,6 @@ public class AccountManagerService
private final IAccountAuthenticatorCache mAuthenticatorCache;
private final DatabaseHelper mOpenHelper;
- private final SimWatcher mSimWatcher;
private static final String TABLE_ACCOUNTS = "accounts";
private static final String ACCOUNTS_ID = "_id";
@@ -199,7 +195,9 @@ public class AccountManagerService
mContext = context;
mPackageManager = packageManager;
- mOpenHelper = new DatabaseHelper(mContext);
+ synchronized (mCacheLock) {
+ mOpenHelper = new DatabaseHelper(mContext);
+ }
mMessageThread = new HandlerThread("AccountManagerService");
mMessageThread.start();
@@ -208,20 +206,54 @@ public class AccountManagerService
mAuthenticatorCache = authenticatorCache;
mAuthenticatorCache.setListener(this, null /* Handler */);
- mSimWatcher = new SimWatcher(mContext);
sThis.set(this);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ intentFilter.addDataScheme("package");
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context1, Intent intent) {
+ purgeOldGrants();
+ }
+ }, intentFilter);
+ purgeOldGrants();
+
validateAccountsAndPopulateCache();
}
+ private void purgeOldGrants() {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ final Cursor cursor = db.query(TABLE_GRANTS,
+ new String[]{GRANTS_GRANTEE_UID},
+ null, null, GRANTS_GRANTEE_UID, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ final int uid = cursor.getInt(0);
+ final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
+ if (packageExists) {
+ continue;
+ }
+ Log.d(TAG, "deleting grants for UID " + uid
+ + " because its package is no longer installed");
+ db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
+ new String[]{Integer.toString(uid)});
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
private void validateAccountsAndPopulateCache() {
- boolean accountDeleted = false;
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Cursor cursor = db.query(TABLE_ACCOUNTS,
- new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
- null, null, null, null, null);
- try {
- synchronized (mCacheLock) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ boolean accountDeleted = false;
+ Cursor cursor = db.query(TABLE_ACCOUNTS,
+ new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
+ null, null, null, null, null);
+ try {
mAccountCache.clear();
final HashMap<String, ArrayList<String>> accountNamesByType =
new HashMap<String, ArrayList<String>>();
@@ -247,7 +279,8 @@ public class AccountManagerService
accountNames.add(accountName);
}
}
- for (HashMap.Entry<String, ArrayList<String>> cur : accountNamesByType.entrySet()) {
+ for (HashMap.Entry<String, ArrayList<String>> cur
+ : accountNamesByType.entrySet()) {
final String accountType = cur.getKey();
final ArrayList<String> accountNames = cur.getValue();
final Account[] accountsForType = new Account[accountNames.size()];
@@ -258,11 +291,11 @@ public class AccountManagerService
}
mAccountCache.put(accountType, accountsForType);
}
- }
- } finally {
- cursor.close();
- if (accountDeleted) {
- sendAccountsChangedBroadcast();
+ } finally {
+ cursor.close();
+ if (accountDeleted) {
+ sendAccountsChangedBroadcast();
+ }
}
}
}
@@ -282,28 +315,30 @@ public class AccountManagerService
long identityToken = clearCallingIdentity();
try {
- return readPasswordFromDatabase(account);
+ return readPasswordInternal(account);
} finally {
restoreCallingIdentity(identityToken);
}
}
- private String readPasswordFromDatabase(Account account) {
+ private String readPasswordInternal(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+ "=?",
- new String[]{account.name, account.type}, null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type}, null, null, null);
+ try {
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
+ }
+ return null;
+ } finally {
+ cursor.close();
}
- return null;
- } finally {
- cursor.close();
}
}
@@ -319,7 +354,7 @@ public class AccountManagerService
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- return readUserDataFromCache(account, key);
+ return readUserDataInternal(account, key);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -361,58 +396,60 @@ public class AccountManagerService
// fails if the account already exists
long identityToken = clearCallingIdentity();
try {
- return insertAccountIntoDatabase(account, password, extras);
+ return addAccountInternal(account, password, extras);
} finally {
restoreCallingIdentity(identityToken);
}
}
- private boolean insertAccountIntoDatabase(Account account, String password, Bundle extras) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ private boolean addAccountInternal(Account account, String password, Bundle extras) {
if (account == null) {
return false;
}
- db.beginTransaction();
- try {
- long numMatches = DatabaseUtils.longForQuery(db,
- "select count(*) from " + TABLE_ACCOUNTS
- + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.name, account.type});
- if (numMatches > 0) {
- Log.w(TAG, "insertAccountIntoDatabase: " + account
- + ", skipping since the account already exists");
- return false;
- }
- ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, account.name);
- values.put(ACCOUNTS_TYPE, account.type);
- values.put(ACCOUNTS_PASSWORD, password);
- long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
- if (accountId < 0) {
- Log.w(TAG, "insertAccountIntoDatabase: " + account
- + ", skipping the DB insert failed");
- return false;
- }
- if (extras != null) {
- for (String key : extras.keySet()) {
- final String value = extras.getString(key);
- if (insertExtra(db, accountId, key, value) < 0) {
- Log.w(TAG, "insertAccountIntoDatabase: " + account
- + ", skipping since insertExtra failed for key " + key);
- return false;
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long numMatches = DatabaseUtils.longForQuery(db,
+ "select count(*) from " + TABLE_ACCOUNTS
+ + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type});
+ if (numMatches > 0) {
+ Log.w(TAG, "insertAccountIntoDatabase: " + account
+ + ", skipping since the account already exists");
+ return false;
+ }
+ ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, account.name);
+ values.put(ACCOUNTS_TYPE, account.type);
+ values.put(ACCOUNTS_PASSWORD, password);
+ long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
+ if (accountId < 0) {
+ Log.w(TAG, "insertAccountIntoDatabase: " + account
+ + ", skipping the DB insert failed");
+ return false;
+ }
+ if (extras != null) {
+ for (String key : extras.keySet()) {
+ final String value = extras.getString(key);
+ if (insertExtraLocked(db, accountId, key, value) < 0) {
+ Log.w(TAG, "insertAccountIntoDatabase: " + account
+ + ", skipping since insertExtra failed for key " + key);
+ return false;
+ }
}
}
+ db.setTransactionSuccessful();
+ insertAccountIntoCacheLocked(account);
+ } finally {
+ db.endTransaction();
}
- db.setTransactionSuccessful();
- insertAccountIntoCache(account);
- } finally {
- db.endTransaction();
+ sendAccountsChangedBroadcast();
+ return true;
}
- sendAccountsChangedBroadcast();
- return true;
}
- private long insertExtra(SQLiteDatabase db, long accountId, String key, String value) {
+ private long insertExtraLocked(SQLiteDatabase db, long accountId, String key, String value) {
ContentValues values = new ContentValues();
values.put(EXTRAS_KEY, key);
values.put(EXTRAS_ACCOUNTS_ID, accountId);
@@ -545,7 +582,7 @@ public class AccountManagerService
&& !result.containsKey(AccountManager.KEY_INTENT)) {
final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
if (removalAllowed) {
- removeAccount(mAccount);
+ removeAccountInternal(mAccount);
}
IAccountManagerResponse response = getResponseAndClose();
if (response != null) {
@@ -566,12 +603,14 @@ public class AccountManagerService
}
}
- protected void removeAccount(Account account) {
- final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.name, account.type});
- removeAccountFromCache(account);
- sendAccountsChangedBroadcast();
+ protected void removeAccountInternal(Account account) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type});
+ removeAccountFromCacheLocked(account);
+ sendAccountsChangedBroadcast();
+ }
}
public void invalidateAuthToken(String accountType, String authToken) {
@@ -585,20 +624,22 @@ public class AccountManagerService
checkManageAccountsOrUseCredentialsPermissions();
long identityToken = clearCallingIdentity();
try {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- invalidateAuthToken(db, accountType, authToken);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ invalidateAuthTokenLocked(db, accountType, authToken);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
}
} finally {
restoreCallingIdentity(identityToken);
}
}
- private void invalidateAuthToken(SQLiteDatabase db, String accountType, String authToken) {
+ private void invalidateAuthTokenLocked(SQLiteDatabase db, String accountType, String authToken) {
if (authToken == null || accountType == null) {
return;
}
@@ -619,7 +660,8 @@ public class AccountManagerService
String accountName = cursor.getString(1);
String authTokenType = cursor.getString(2);
db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null);
- writeAuthTokenIntoCache(new Account(accountName, accountType), authTokenType, null);
+ writeAuthTokenIntoCacheLocked(db, new Account(accountName, accountType),
+ authTokenType, null);
}
} finally {
cursor.close();
@@ -631,28 +673,30 @@ public class AccountManagerService
return false;
}
cancelNotification(getSigninRequiredNotificationId(account));
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountIdLocked(db, account);
+ if (accountId < 0) {
+ return false;
+ }
+ db.delete(TABLE_AUTHTOKENS,
+ AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
+ new String[]{type});
+ ContentValues values = new ContentValues();
+ values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
+ values.put(AUTHTOKENS_TYPE, type);
+ values.put(AUTHTOKENS_AUTHTOKEN, authToken);
+ if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) {
+ db.setTransactionSuccessful();
+ writeAuthTokenIntoCacheLocked(db, account, type, authToken);
+ return true;
+ }
return false;
+ } finally {
+ db.endTransaction();
}
- db.delete(TABLE_AUTHTOKENS,
- AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
- new String[]{type});
- ContentValues values = new ContentValues();
- values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
- values.put(AUTHTOKENS_TYPE, type);
- values.put(AUTHTOKENS_AUTHTOKEN, authToken);
- if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) {
- db.setTransactionSuccessful();
- writeAuthTokenIntoCache(account, type, authToken);
- return true;
- }
- return false;
- } finally {
- db.endTransaction();
}
}
@@ -668,7 +712,7 @@ public class AccountManagerService
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- return readAuthTokenFromCache(account, authTokenType);
+ return readAuthTokenInternal(account, authTokenType);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -702,35 +746,35 @@ public class AccountManagerService
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- setPasswordInDB(account, password);
+ setPasswordInternal(account, password);
} finally {
restoreCallingIdentity(identityToken);
}
}
- private void setPasswordInDB(Account account, String password) {
+ private void setPasswordInternal(Account account, String password) {
if (account == null) {
return;
}
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_PASSWORD, password);
- final long accountId = getAccountId(db, account);
- if (accountId >= 0) {
- final String[] argsAccountId = {String.valueOf(accountId)};
- db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
- db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
- synchronized (mCacheLock) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_PASSWORD, password);
+ final long accountId = getAccountIdLocked(db, account);
+ if (accountId >= 0) {
+ final String[] argsAccountId = {String.valueOf(accountId)};
+ db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
+ db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
mAuthTokenCache.remove(account);
+ db.setTransactionSuccessful();
}
- db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
}
- } finally {
- db.endTransaction();
+ sendAccountsChangedBroadcast();
}
- sendAccountsChangedBroadcast();
}
private void sendAccountsChangedBroadcast() {
@@ -749,7 +793,7 @@ public class AccountManagerService
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- setPasswordInDB(account, null);
+ setPasswordInternal(account, null);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -767,41 +811,43 @@ public class AccountManagerService
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- writeUserdataIntoDatabase(account, key, value);
+ setUserdataInternal(account, key, value);
} finally {
restoreCallingIdentity(identityToken);
}
}
- private void writeUserdataIntoDatabase(Account account, String key, String value) {
+ private void setUserdataInternal(Account account, String key, String value) {
if (account == null || key == null) {
return;
}
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
- return;
- }
- long extrasId = getExtrasId(db, accountId, key);
- if (extrasId < 0 ) {
- extrasId = insertExtra(db, accountId, key, value);
- if (extrasId < 0) {
- return;
- }
- } else {
- ContentValues values = new ContentValues();
- values.put(EXTRAS_VALUE, value);
- if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountIdLocked(db, account);
+ if (accountId < 0) {
return;
}
+ long extrasId = getExtrasIdLocked(db, accountId, key);
+ if (extrasId < 0 ) {
+ extrasId = insertExtraLocked(db, accountId, key, value);
+ if (extrasId < 0) {
+ return;
+ }
+ } else {
+ ContentValues values = new ContentValues();
+ values.put(EXTRAS_VALUE, value);
+ if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
+ return;
+ }
+ }
+ writeUserDataIntoCacheLocked(db, account, key, value);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
}
- db.setTransactionSuccessful();
- writeUserDataIntoCache(account, key, value);
- } finally {
- db.endTransaction();
}
}
@@ -907,7 +953,7 @@ public class AccountManagerService
// if the caller has permission, do the peek. otherwise go the more expensive
// route of starting a Session
if (!customTokens && permissionGranted) {
- String authToken = readAuthTokenFromCache(account, authTokenType);
+ String authToken = readAuthTokenInternal(account, authTokenType);
if (authToken != null) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
@@ -1213,7 +1259,9 @@ public class AccountManagerService
}
public void run() throws RemoteException {
- mAccountsOfType = getAccountsByTypeFromCache(mAccountType);
+ synchronized (mCacheLock) {
+ mAccountsOfType = getAccountsFromCacheLocked(mAccountType);
+ }
// check whether each account matches the requested features
mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
mCurrentAccount = 0;
@@ -1299,7 +1347,9 @@ public class AccountManagerService
checkReadAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- return getAccountsByTypeFromCache(type);
+ synchronized (mCacheLock) {
+ return getAccountsFromCacheLocked(type);
+ }
} finally {
restoreCallingIdentity(identityToken);
}
@@ -1320,7 +1370,10 @@ public class AccountManagerService
long identityToken = clearCallingIdentity();
try {
if (features == null || features.length == 0) {
- Account[] accounts = getAccountsByTypeFromCache(type);
+ Account[] accounts;
+ synchronized (mCacheLock) {
+ accounts = getAccountsFromCacheLocked(type);
+ }
Bundle result = new Bundle();
result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
onResult(response, result);
@@ -1332,7 +1385,7 @@ public class AccountManagerService
}
}
- private long getAccountId(SQLiteDatabase db, Account account) {
+ private long getAccountIdLocked(SQLiteDatabase db, Account account) {
Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
"name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
try {
@@ -1345,7 +1398,7 @@ public class AccountManagerService
}
}
- private long getExtrasId(SQLiteDatabase db, long accountId, String key) {
+ private long getExtrasIdLocked(SQLiteDatabase db, long accountId, String key) {
Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_ID},
EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
new String[]{key}, null, null, null);
@@ -1635,6 +1688,11 @@ public class AccountManagerService
super(context, AccountManagerService.getDatabaseName(), null, DATABASE_VERSION);
}
+ /**
+ * This call needs to be made while the mCacheLock is held. The way to
+ * ensure this is to get the lock any time a method is called ont the DatabaseHelper
+ * @param db The database.
+ */
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " ( "
@@ -1723,113 +1781,24 @@ public class AccountManagerService
ContentValues values = new ContentValues();
values.put(META_KEY, key);
values.put(META_VALUE, value);
- mOpenHelper.getWritableDatabase().replace(TABLE_META, META_KEY, values);
- }
-
- private String getMetaValue(String key) {
- Cursor c = mOpenHelper.getReadableDatabase().query(TABLE_META,
- new String[]{META_VALUE}, META_KEY + "=?", new String[]{key}, null, null, null);
- try {
- if (c.moveToNext()) {
- return c.getString(0);
- }
- return null;
- } finally {
- c.close();
+ synchronized (mCacheLock) {
+ mOpenHelper.getWritableDatabase().replace(TABLE_META, META_KEY, values);
}
}
- private class SimWatcher extends BroadcastReceiver {
- public SimWatcher(Context context) {
- // Re-scan the SIM card when the SIM state changes, and also if
- // the disk recovers from a full state (we may have failed to handle
- // things properly while the disk was full).
- final IntentFilter filter = new IntentFilter();
- filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
- context.registerReceiver(this, filter);
- }
-
- /**
- * Compare the IMSI to the one stored in the login service's
- * database. If they differ, erase all passwords and
- * authtokens (and store the new IMSI).
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- // Check IMSI on every update; nothing happens if the IMSI
- // is missing or unchanged.
- TelephonyManager telephonyManager =
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- if (telephonyManager == null) {
- Log.w(TAG, "failed to get TelephonyManager");
- return;
- }
- String imsi = telephonyManager.getSubscriberId();
-
- // If the subscriber ID is an empty string, don't do anything.
- if (TextUtils.isEmpty(imsi)) return;
-
- // If the current IMSI matches what's stored, don't do anything.
- String storedImsi = getMetaValue("imsi");
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "current IMSI=" + imsi + "; stored IMSI=" + storedImsi);
- }
- if (imsi.equals(storedImsi)) return;
-
- // If a CDMA phone is unprovisioned, getSubscriberId()
- // will return a different value, but we *don't* erase the
- // passwords. We only erase them if it has a different
- // subscriber ID once it's provisioned.
- if (telephonyManager.getCurrentPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
- IBinder service = ServiceManager.checkService(Context.TELEPHONY_SERVICE);
- if (service == null) {
- Log.w(TAG, "call to checkService(TELEPHONY_SERVICE) failed");
- return;
- }
- ITelephony telephony = ITelephony.Stub.asInterface(service);
- if (telephony == null) {
- Log.w(TAG, "failed to get ITelephony interface");
- return;
- }
- boolean needsProvisioning;
- try {
- needsProvisioning = telephony.needsOtaServiceProvisioning();
- } catch (RemoteException e) {
- Log.w(TAG, "exception while checking provisioning", e);
- // default to NOT wiping out the passwords
- needsProvisioning = true;
- }
- if (needsProvisioning) {
- // if the phone needs re-provisioning, don't do anything.
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "current IMSI=" + imsi + " (needs provisioning); stored IMSI=" +
- storedImsi);
- }
- return;
- }
- }
-
- if (!imsi.equals(storedImsi) && !TextUtils.isEmpty(storedImsi)) {
- Log.w(TAG, "wiping all passwords and authtokens because IMSI changed ("
- + "stored=" + storedImsi + ", current=" + imsi + ")");
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- db.execSQL("DELETE from " + TABLE_AUTHTOKENS);
- db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_PASSWORD + " = ''");
-
- synchronized (mCacheLock) {
- mAuthTokenCache = new HashMap<Account, HashMap<String, String>>();
- }
-
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
+ private String getMetaValue(String key) {
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = db.query(TABLE_META,
+ new String[]{META_VALUE}, META_KEY + "=?", new String[]{key}, null, null, null);
+ try {
+ if (c.moveToNext()) {
+ return c.getString(0);
}
- sendAccountsChangedBroadcast();
+ return null;
+ } finally {
+ c.close();
}
- setMetaValue("imsi", imsi);
}
}
@@ -1855,42 +1824,44 @@ public class AccountManagerService
}
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- if (isCheckinRequest) {
- // This is a checkin request. *Only* upload the account types and the count of each.
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
- Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
- null, null, ACCOUNTS_TYPE, null, null);
- try {
- while (cursor.moveToNext()) {
- // print type,count
- fout.println(cursor.getString(0) + "," + cursor.getString(1));
+ if (isCheckinRequest) {
+ // This is a checkin request. *Only* upload the account types and the count of each.
+ Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
+ null, null, ACCOUNTS_TYPE, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ // print type,count
+ fout.println(cursor.getString(0) + "," + cursor.getString(1));
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
- } finally {
- if (cursor != null) {
- cursor.close();
+ } else {
+ Account[] accounts = getAccountsFromCacheLocked(null /* type */);
+ fout.println("Accounts: " + accounts.length);
+ for (Account account : accounts) {
+ fout.println(" " + account);
}
- }
- } else {
- Account[] accounts = getAccountsByTypeFromCache(null /* type */);
- fout.println("Accounts: " + accounts.length);
- for (Account account : accounts) {
- fout.println(" " + account);
- }
- fout.println();
- synchronized (mSessions) {
- final long now = SystemClock.elapsedRealtime();
- fout.println("Active Sessions: " + mSessions.size());
- for (Session session : mSessions.values()) {
- fout.println(" " + session.toDebugString(now));
+ fout.println();
+ synchronized (mSessions) {
+ final long now = SystemClock.elapsedRealtime();
+ fout.println("Active Sessions: " + mSessions.size());
+ for (Session session : mSessions.values()) {
+ fout.println(" " + session.toDebugString(now));
+ }
}
- }
- fout.println();
- mAuthenticatorCache.dump(fd, fout, args);
+ fout.println();
+ mAuthenticatorCache.dump(fd, fout, args);
+ }
}
}
@@ -2003,20 +1974,22 @@ public class AccountManagerService
if (Binder.getCallingUid() == android.os.Process.SYSTEM_UID) {
return true;
}
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType,
- account.name, account.type};
- final boolean permissionGranted =
- DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
- if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
- // TODO: Skip this check when running automated tests. Replace this
- // with a more general solution.
- Log.d(TAG, "no credentials permission for usage of " + account + ", "
- + authTokenType + " by uid " + Binder.getCallingUid()
- + " but ignoring since device is in test harness.");
- return true;
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType,
+ account.name, account.type};
+ final boolean permissionGranted =
+ DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
+ if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
+ // TODO: Skip this check when running automated tests. Replace this
+ // with a more general solution.
+ Log.d(TAG, "no credentials permission for usage of " + account + ", "
+ + authTokenType + " by uid " + Binder.getCallingUid()
+ + " but ignoring since device is in test harness.");
+ return true;
+ }
+ return permissionGranted;
}
- return permissionGranted;
}
private void checkCallingUidAgainstAuthenticator(Account account) {
@@ -2061,22 +2034,24 @@ public class AccountManagerService
Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
return;
}
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId >= 0) {
- ContentValues values = new ContentValues();
- values.put(GRANTS_ACCOUNTS_ID, accountId);
- values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
- values.put(GRANTS_GRANTEE_UID, uid);
- db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
- db.setTransactionSuccessful();
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountIdLocked(db, account);
+ if (accountId >= 0) {
+ ContentValues values = new ContentValues();
+ values.put(GRANTS_ACCOUNTS_ID, accountId);
+ values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
+ values.put(GRANTS_GRANTEE_UID, uid);
+ db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
+ db.setTransactionSuccessful();
+ }
+ } finally {
+ db.endTransaction();
}
- } finally {
- db.endTransaction();
+ cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
}
- cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
}
/**
@@ -2092,153 +2067,149 @@ public class AccountManagerService
Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
return;
}
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId >= 0) {
- db.delete(TABLE_GRANTS,
- GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
- + GRANTS_GRANTEE_UID + "=?",
- new String[]{String.valueOf(accountId), authTokenType,
- String.valueOf(uid)});
- db.setTransactionSuccessful();
+ synchronized (mCacheLock) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountIdLocked(db, account);
+ if (accountId >= 0) {
+ db.delete(TABLE_GRANTS,
+ GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
+ + GRANTS_GRANTEE_UID + "=?",
+ new String[]{String.valueOf(accountId), authTokenType,
+ String.valueOf(uid)});
+ db.setTransactionSuccessful();
+ }
+ } finally {
+ db.endTransaction();
}
- } finally {
- db.endTransaction();
+ cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
}
- cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid));
}
static final private String stringArrayToString(String[] value) {
return value != null ? ("[" + TextUtils.join(",", value) + "]") : null;
}
- private void removeAccountFromCache(Account account) {
- synchronized (mCacheLock) {
- final Account[] oldAccountsForType = mAccountCache.get(account.type);
- if (oldAccountsForType != null) {
- ArrayList<Account> newAccountsList = new ArrayList<Account>();
- for (Account curAccount : oldAccountsForType) {
- if (!curAccount.equals(account)) {
- newAccountsList.add(curAccount);
- }
- }
- if (newAccountsList.isEmpty()) {
- mAccountCache.remove(account.type);
- } else {
- Account[] newAccountsForType = new Account[newAccountsList.size()];
- newAccountsForType = newAccountsList.toArray(newAccountsForType);
- mAccountCache.put(account.type, newAccountsForType);
+ private void removeAccountFromCacheLocked(Account account) {
+ final Account[] oldAccountsForType = mAccountCache.get(account.type);
+ if (oldAccountsForType != null) {
+ ArrayList<Account> newAccountsList = new ArrayList<Account>();
+ for (Account curAccount : oldAccountsForType) {
+ if (!curAccount.equals(account)) {
+ newAccountsList.add(curAccount);
}
}
- mUserDataCache.remove(account);
- mAuthTokenCache.remove(account);
+ if (newAccountsList.isEmpty()) {
+ mAccountCache.remove(account.type);
+ } else {
+ Account[] newAccountsForType = new Account[newAccountsList.size()];
+ newAccountsForType = newAccountsList.toArray(newAccountsForType);
+ mAccountCache.put(account.type, newAccountsForType);
+ }
}
+ mUserDataCache.remove(account);
+ mAuthTokenCache.remove(account);
}
/**
* This assumes that the caller has already checked that the account is not already present.
*/
- private void insertAccountIntoCache(Account account) {
- synchronized (mCacheLock) {
- Account[] accountsForType = mAccountCache.get(account.type);
- int oldLength = (accountsForType != null) ? accountsForType.length : 0;
- Account[] newAccountsForType = new Account[oldLength + 1];
- if (accountsForType != null) {
- System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
- }
- newAccountsForType[oldLength] = account;
- mAccountCache.put(account.type, newAccountsForType);
- }
- }
-
- protected Account[] getAccountsByTypeFromCache(String accountType) {
- synchronized (mCacheLock) {
- if (accountType != null) {
- final Account[] accounts = mAccountCache.get(accountType);
- if (accounts == null) {
- return EMPTY_ACCOUNT_ARRAY;
- } else {
- return Arrays.copyOf(accounts, accounts.length);
- }
+ private void insertAccountIntoCacheLocked(Account account) {
+ Account[] accountsForType = mAccountCache.get(account.type);
+ int oldLength = (accountsForType != null) ? accountsForType.length : 0;
+ Account[] newAccountsForType = new Account[oldLength + 1];
+ if (accountsForType != null) {
+ System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
+ }
+ newAccountsForType[oldLength] = account;
+ mAccountCache.put(account.type, newAccountsForType);
+ }
+
+ protected Account[] getAccountsFromCacheLocked(String accountType) {
+ if (accountType != null) {
+ final Account[] accounts = mAccountCache.get(accountType);
+ if (accounts == null) {
+ return EMPTY_ACCOUNT_ARRAY;
} else {
- int totalLength = 0;
- for (Account[] accounts : mAccountCache.values()) {
- totalLength += accounts.length;
- }
- if (totalLength == 0) {
- return EMPTY_ACCOUNT_ARRAY;
- }
- Account[] accounts = new Account[totalLength];
- totalLength = 0;
- for (Account[] accountsOfType : mAccountCache.values()) {
- System.arraycopy(accountsOfType, 0, accounts, totalLength,
- accountsOfType.length);
- totalLength += accountsOfType.length;
- }
- return accounts;
+ return Arrays.copyOf(accounts, accounts.length);
}
+ } else {
+ int totalLength = 0;
+ for (Account[] accounts : mAccountCache.values()) {
+ totalLength += accounts.length;
+ }
+ if (totalLength == 0) {
+ return EMPTY_ACCOUNT_ARRAY;
+ }
+ Account[] accounts = new Account[totalLength];
+ totalLength = 0;
+ for (Account[] accountsOfType : mAccountCache.values()) {
+ System.arraycopy(accountsOfType, 0, accounts, totalLength,
+ accountsOfType.length);
+ totalLength += accountsOfType.length;
+ }
+ return accounts;
}
}
- protected void writeUserDataIntoCache(Account account, String key, String value) {
- synchronized (mCacheLock) {
- HashMap<String, String> userDataForAccount = mUserDataCache.get(account);
- if (userDataForAccount == null) {
- userDataForAccount = readUserDataForAccountFromDatabase(account);
- mUserDataCache.put(account, userDataForAccount);
- }
- if (value == null) {
- userDataForAccount.remove(key);
- } else {
- userDataForAccount.put(key, value);
- }
+ protected void writeUserDataIntoCacheLocked(final SQLiteDatabase db, Account account,
+ String key, String value) {
+ HashMap<String, String> userDataForAccount = mUserDataCache.get(account);
+ if (userDataForAccount == null) {
+ userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
+ mUserDataCache.put(account, userDataForAccount);
+ }
+ if (value == null) {
+ userDataForAccount.remove(key);
+ } else {
+ userDataForAccount.put(key, value);
}
}
- protected void writeAuthTokenIntoCache(Account account, String key, String value) {
- synchronized (mCacheLock) {
- HashMap<String, String> authTokensForAccount = mAuthTokenCache.get(account);
- if (authTokensForAccount == null) {
- authTokensForAccount = readAuthTokensForAccountFromDatabase(account);
- mAuthTokenCache.put(account, authTokensForAccount);
- }
- if (value == null) {
- authTokensForAccount.remove(key);
- } else {
- authTokensForAccount.put(key, value);
- }
+ protected void writeAuthTokenIntoCacheLocked(final SQLiteDatabase db, Account account,
+ String key, String value) {
+ HashMap<String, String> authTokensForAccount = mAuthTokenCache.get(account);
+ if (authTokensForAccount == null) {
+ authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
+ mAuthTokenCache.put(account, authTokensForAccount);
+ }
+ if (value == null) {
+ authTokensForAccount.remove(key);
+ } else {
+ authTokensForAccount.put(key, value);
}
}
- protected String readAuthTokenFromCache(Account account, String authTokenType) {
+ protected String readAuthTokenInternal(Account account, String authTokenType) {
synchronized (mCacheLock) {
HashMap<String, String> authTokensForAccount = mAuthTokenCache.get(account);
if (authTokensForAccount == null) {
// need to populate the cache for this account
- authTokensForAccount = readAuthTokensForAccountFromDatabase(account);
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
mAuthTokenCache.put(account, authTokensForAccount);
}
return authTokensForAccount.get(authTokenType);
}
}
- protected String readUserDataFromCache(Account account, String key) {
+ protected String readUserDataInternal(Account account, String key) {
synchronized (mCacheLock) {
HashMap<String, String> userDataForAccount = mUserDataCache.get(account);
if (userDataForAccount == null) {
// need to populate the cache for this account
- userDataForAccount = readUserDataForAccountFromDatabase(account);
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
mUserDataCache.put(account, userDataForAccount);
}
return userDataForAccount.get(key);
}
}
- protected HashMap<String, String> readUserDataForAccountFromDatabase(Account account) {
+ protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
+ final SQLiteDatabase db, Account account) {
HashMap<String, String> userDataForAccount = new HashMap<String, String>();
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor cursor = db.query(TABLE_EXTRAS,
COLUMNS_EXTRAS_KEY_AND_VALUE,
SELECTION_USERDATA_BY_ACCOUNT,
@@ -2256,9 +2227,9 @@ public class AccountManagerService
return userDataForAccount;
}
- protected HashMap<String, String> readAuthTokensForAccountFromDatabase(Account account) {
+ protected HashMap<String, String> readAuthTokensForAccountFromDatabaseLocked(
+ final SQLiteDatabase db, Account account) {
HashMap<String, String> authTokensForAccount = new HashMap<String, String>();
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor cursor = db.query(TABLE_AUTHTOKENS,
COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
SELECTION_AUTHTOKENS_BY_ACCOUNT,
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9e72c1b..3a82c78 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -66,6 +66,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
+import android.view.WindowManagerImpl;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
@@ -2417,6 +2418,7 @@ public class Activity extends ContextThemeWrapper
*/
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_ACTION_BAR) {
+ initActionBar();
if (mActionBar != null) {
mActionBar.dispatchMenuVisibilityChanged(true);
} else {
@@ -4401,6 +4403,9 @@ public class Activity extends ContextThemeWrapper
if (mStopped) {
mStopped = false;
mCalled = false;
+ if (mToken != null && mParent == null) {
+ WindowManagerImpl.getDefault().setStoppedState(mToken, false);
+ }
mInstrumentation.callActivityOnRestart(this);
if (!mCalled) {
throw new SuperNotCalledException(
@@ -4477,6 +4482,10 @@ public class Activity extends ContextThemeWrapper
mWindow.closeAllPanels();
}
+ if (mToken != null && mParent == null) {
+ WindowManagerImpl.getDefault().setStoppedState(mToken, true);
+ }
+
mFragments.dispatchStop();
mCalled = false;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8737e93..539e946 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -41,9 +41,9 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.hardware.IUsbManager;
import android.hardware.SensorManager;
-import android.hardware.UsbManager;
+import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbManager;
import android.location.CountryDetector;
import android.location.ICountryDetector;
import android.location.ILocationManager;
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 3d99055..dee1ef3 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -396,7 +396,11 @@ public class DialogFragment extends Fragment
case STYLE_NO_TITLE:
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
- return (LayoutInflater)mDialog.getContext().getSystemService(
+ if (mDialog != null) {
+ return (LayoutInflater)mDialog.getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ }
+ return (LayoutInflater)mActivity.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 52b3108..d8d0a5b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -167,10 +167,9 @@ public abstract class FragmentManager {
public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
/**
- * Pop the top state off the back stack. Returns true if there was one
- * to pop, else false. This function is asynchronous -- it enqueues the
- * request to pop, but the action will not be performed until the application
- * returns to its event loop.
+ * Pop the top state off the back stack. This function is asynchronous -- it
+ * enqueues the request to pop, but the action will not be performed until the
+ * application returns to its event loop.
*/
public abstract void popBackStack();
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index d70b3d3..6539711 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -21,6 +21,8 @@ import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
+import android.view.Display;
+import android.view.WindowManager;
import java.io.File;
@@ -65,6 +67,13 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu
mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth();
mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight();
+ if (mDesiredMinWidth <= 0 || mDesiredMinHeight <= 0) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display d = wm.getDefaultDisplay();
+ mDesiredMinWidth = d.getWidth();
+ mDesiredMinHeight = d.getHeight();
+ }
+
if (DEBUG) {
Slog.d(TAG, "dmW=" + mDesiredMinWidth + " dmH=" + mDesiredMinHeight);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 051ae9e..4c7d87f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1664,11 +1664,11 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.hardware.UsbManager} for access to USB devices (as a USB host)
+ * android.hardware.usb.UsbManager} for access to USB devices (as a USB host)
* and for controlling this device's behavior as a USB device.
*
* @see #getSystemService
- * @see android.harware.UsbManager
+ * @see android.harware.usb.UsbManager
*/
public static final String USB_SERVICE = "usb";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a589216..7525749 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -785,6 +785,21 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports connecting to USB devices
+ * as the USB host.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_USB_HOST = "android.hardware.usb.host";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports connecting to USB accessories.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The SIP API is enabled on the device.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/hardware/IUsbManager.aidl b/core/java/android/hardware/IUsbManager.aidl
deleted file mode 100644
index 6c99ab3..0000000
--- a/core/java/android/hardware/IUsbManager.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 android.hardware;
-
-import android.hardware.UsbAccessory;
-import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-
-/** @hide */
-interface IUsbManager
-{
- /* Returns a list of all currently attached USB devices */
- void getDeviceList(out Bundle devices);
- ParcelFileDescriptor openDevice(String deviceName);
- UsbAccessory getCurrentAccessory();
- ParcelFileDescriptor openAccessory();
-}
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
new file mode 100644
index 0000000..be65bdb
--- /dev/null
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -0,0 +1,64 @@
+/*
+ * 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 android.hardware.usb;
+
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+
+/** @hide */
+interface IUsbManager
+{
+ /* Returns a list of all currently attached USB devices */
+ void getDeviceList(out Bundle devices);
+
+ /* Returns a file descriptor for communicating with the USB device.
+ * The native fd can be passed to usb_device_new() in libusbhost.
+ */
+ ParcelFileDescriptor openDevice(String deviceName);
+
+ /* Returns the currently attached USB accessory */
+ UsbAccessory getCurrentAccessory();
+
+ /* Returns a file descriptor for communicating with the USB accessory.
+ * This file descriptor can be used with standard Java file operations.
+ */
+ ParcelFileDescriptor openAccessory(in UsbAccessory accessory);
+
+ /* Sets the default package for a USB device
+ * (or clears it if the package name is null)
+ */
+ oneway void setDevicePackage(in UsbDevice device, String packageName);
+
+ /* Sets the default package for a USB device
+ * (or clears it if the package name is null)
+ */
+ void setAccessoryPackage(in UsbAccessory accessory, String packageName);
+
+ /* Grants permission for the given UID to access the device */
+ void grantDevicePermission(in UsbDevice device, int uid);
+
+ /* Grants permission for the given UID to access the accessory */
+ void grantAccessoryPermission(in UsbAccessory accessory, int uid);
+
+ /* Returns true if the USB manager has default preferences or permissions for the package */
+ boolean hasDefaults(String packageName, int uid);
+
+ /* Clears default preferences and permissions for the package */
+ oneway void clearDefaults(String packageName, int uid);
+}
diff --git a/core/java/android/hardware/UsbAccessory.aidl b/core/java/android/hardware/usb/UsbAccessory.aidl
index 97a777b..1c15f1c 100644
--- a/core/java/android/hardware/UsbAccessory.aidl
+++ b/core/java/android/hardware/usb/UsbAccessory.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
parcelable UsbAccessory;
diff --git a/core/java/android/hardware/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java
index 71672fa..6cd9178 100644
--- a/core/java/android/hardware/UsbAccessory.java
+++ b/core/java/android/hardware/usb/UsbAccessory.java
@@ -14,28 +14,24 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
import android.util.Log;
/**
* A class representing a USB accessory.
*/
-public final class UsbAccessory implements Parcelable {
+public class UsbAccessory implements Parcelable {
private static final String TAG = "UsbAccessory";
- private String mManufacturer;
- private String mModel;
- private String mType;
- private String mVersion;
-
- private UsbAccessory() {
- }
+ private final String mManufacturer;
+ private final String mModel;
+ private final String mType;
+ private final String mVersion;
/**
* UsbAccessory should only be instantiated by UsbService implementation
@@ -95,6 +91,23 @@ public final class UsbAccessory implements Parcelable {
return mVersion;
}
+ private static boolean compare(String s1, String s2) {
+ if (s1 == null) return (s2 == null);
+ return s1.equals(s2);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof UsbAccessory) {
+ UsbAccessory accessory = (UsbAccessory)obj;
+ return (compare(mManufacturer, accessory.getManufacturer()) &&
+ compare(mModel, accessory.getModel()) &&
+ compare(mType, accessory.getType()) &&
+ compare(mVersion, accessory.getVersion()));
+ }
+ return false;
+ }
+
@Override
public String toString() {
return "UsbAccessory[mManufacturer=" + mManufacturer +
diff --git a/core/java/android/hardware/UsbConstants.java b/core/java/android/hardware/usb/UsbConstants.java
index 4c8c4d4..6626c9f 100644
--- a/core/java/android/hardware/UsbConstants.java
+++ b/core/java/android/hardware/usb/UsbConstants.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
/**
* Contains constants for the USB protocol.
diff --git a/core/java/android/hardware/UsbDevice.aidl b/core/java/android/hardware/usb/UsbDevice.aidl
index 6dfd43f..6030ad1 100644
--- a/core/java/android/hardware/UsbDevice.aidl
+++ b/core/java/android/hardware/usb/UsbDevice.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
parcelable UsbDevice;
diff --git a/core/java/android/hardware/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index ca7dae3..37bd82b 100644
--- a/core/java/android/hardware/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
import android.os.Bundle;
import android.os.Parcel;
@@ -106,7 +106,7 @@ public final class UsbDevice implements Parcelable {
/**
* Returns the devices's class field.
* Some useful constants for USB device classes can be found in
- * {@link android.hardware.UsbConstants}
+ * {@link android.hardware.usb.UsbConstants}
*
* @return the devices's class
*/
@@ -133,7 +133,7 @@ public final class UsbDevice implements Parcelable {
}
/**
- * Returns the number of {@link android.hardware.UsbInterface}s this device contains.
+ * Returns the number of {@link android.hardware.usb.UsbInterface}s this device contains.
*
* @return the number of interfaces
*/
@@ -142,7 +142,7 @@ public final class UsbDevice implements Parcelable {
}
/**
- * Returns the {@link android.hardware.UsbInterface} at the given index.
+ * Returns the {@link android.hardware.usb.UsbInterface} at the given index.
*
* @return the interface
*/
@@ -171,9 +171,9 @@ public final class UsbDevice implements Parcelable {
}
/**
- * Claims exclusive access to a {@link android.hardware.UsbInterface}.
+ * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
* This must be done before sending or receiving data on any
- * {@link android.hardware.UsbEndpoint}s belonging to the interface
+ * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface
* @param intf the interface to claim
* @param force true to disconnect kernel driver if necessary
* @return true if the interface was successfully claimed
@@ -183,7 +183,7 @@ public final class UsbDevice implements Parcelable {
}
/**
- * Releases exclusive access to a {@link android.hardware.UsbInterface}.
+ * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}.
*
* @return true if the interface was successfully released
*/
@@ -231,11 +231,12 @@ public final class UsbDevice implements Parcelable {
}
/**
- * Waits for the result of a {@link android.hardware.UsbRequest#queue} operation
- * Note that this may return requests queued on multiple {@link android.hardware.UsbEndpoint}s.
- * When multiple endpoints are in use, {@link android.hardware.UsbRequest#getEndpoint} and
- * {@link android.hardware.UsbRequest#getClientData} can be useful in determining how to process
- * the result of this function.
+ * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
+ * Note that this may return requests queued on multiple
+ * {@link android.hardware.usb.UsbEndpoint}s.
+ * When multiple endpoints are in use, {@link android.hardware.usb.UsbRequest#getEndpoint} and
+ * {@link android.hardware.usb.UsbRequest#getClientData} can be useful in determining
+ * how to process the result of this function.
*
* @return a completed USB request, or null if an error occurred
*/
diff --git a/core/java/android/hardware/UsbEndpoint.aidl b/core/java/android/hardware/usb/UsbEndpoint.aidl
index 51fc67b..a75cd7e 100644
--- a/core/java/android/hardware/UsbEndpoint.aidl
+++ b/core/java/android/hardware/usb/UsbEndpoint.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
parcelable UsbEndpoint;
diff --git a/core/java/android/hardware/UsbEndpoint.java b/core/java/android/hardware/usb/UsbEndpoint.java
index 8d4099d..a48d88f 100644
--- a/core/java/android/hardware/UsbEndpoint.java
+++ b/core/java/android/hardware/usb/UsbEndpoint.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
/**
- * A class representing an endpoint on a {@link android.hardware.UsbInterface}.
+ * A class representing an endpoint on a {@link android.hardware.usb.UsbInterface}.
*/
public final class UsbEndpoint implements Parcelable {
@@ -65,9 +65,9 @@ public final class UsbEndpoint implements Parcelable {
/**
* Returns the endpoint's direction.
- * Returns {@link android.hardware.UsbConstants#USB_DIR_OUT}
+ * Returns {@link android.hardware.usb.UsbConstants#USB_DIR_OUT}
* if the direction is host to device, and
- * {@link android.hardware.UsbConstants#USB_DIR_IN} if the
+ * {@link android.hardware.usb.UsbConstants#USB_DIR_IN} if the
* direction is device to host.
*
* @return the endpoint's direction
@@ -89,10 +89,10 @@ public final class UsbEndpoint implements Parcelable {
* Returns the endpoint's type.
* Possible results are:
* <ul>
- * <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_CONTROL} (endpoint zero)
- * <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_ISOC} (isochronous endpoint)
- * <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_BULK} (bulk endpoint)
- * <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_INT} (interrupt endpoint)
+ * <li>{@link android.hardware.usb.UsbConstants#USB_ENDPOINT_XFER_CONTROL} (endpoint zero)
+ * <li>{@link android.hardware.usb.UsbConstants#USB_ENDPOINT_XFER_ISOC} (isochronous endpoint)
+ * <li>{@link android.hardware.usb.UsbConstants#USB_ENDPOINT_XFER_BULK} (bulk endpoint)
+ * <li>{@link android.hardware.usb.UsbConstants#USB_ENDPOINT_XFER_INT} (interrupt endpoint)
* </ul>
*
* @return the endpoint's type
@@ -120,7 +120,7 @@ public final class UsbEndpoint implements Parcelable {
}
/**
- * Returns the {@link android.hardware.UsbInterface} this endpoint belongs to.
+ * Returns the {@link android.hardware.usb.UsbInterface} this endpoint belongs to.
*
* @return the endpoint's interface
*/
@@ -129,7 +129,7 @@ public final class UsbEndpoint implements Parcelable {
}
/**
- * Returns the {@link android.hardware.UsbDevice} this endpoint belongs to.
+ * Returns the {@link android.hardware.usb.UsbDevice} this endpoint belongs to.
*
* @return the endpoint's device
*/
diff --git a/core/java/android/hardware/UsbInterface.aidl b/core/java/android/hardware/usb/UsbInterface.aidl
index a715ccd..32b8c64 100644
--- a/core/java/android/hardware/UsbInterface.aidl
+++ b/core/java/android/hardware/usb/UsbInterface.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
parcelable UsbInterface;
diff --git a/core/java/android/hardware/UsbInterface.java b/core/java/android/hardware/usb/UsbInterface.java
index deef81f..b3b0e81 100644
--- a/core/java/android/hardware/UsbInterface.java
+++ b/core/java/android/hardware/usb/UsbInterface.java
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
/**
- * A class representing an interface on a {@link android.hardware.UsbDevice}.
+ * A class representing an interface on a {@link android.hardware.usb.UsbDevice}.
*/
-public final class UsbInterface implements Parcelable {
+public class UsbInterface implements Parcelable {
private int mId;
private int mClass;
@@ -60,7 +60,7 @@ public final class UsbInterface implements Parcelable {
/**
* Returns the interface's class field.
* Some useful constants for USB classes can be found in
- * {@link android.hardware.UsbConstants}
+ * {@link android.hardware.usb.UsbConstants}
*
* @return the interface's class
*/
@@ -87,7 +87,7 @@ public final class UsbInterface implements Parcelable {
}
/**
- * Returns the number of {@link android.hardware.UsbEndpoint}s this interface contains.
+ * Returns the number of {@link android.hardware.usb.UsbEndpoint}s this interface contains.
*
* @return the number of endpoints
*/
@@ -96,7 +96,7 @@ public final class UsbInterface implements Parcelable {
}
/**
- * Returns the {@link android.hardware.UsbEndpoint} at the given index.
+ * Returns the {@link android.hardware.usb.UsbEndpoint} at the given index.
*
* @return the endpoint
*/
@@ -105,7 +105,7 @@ public final class UsbInterface implements Parcelable {
}
/**
- * Returns the {@link android.hardware.UsbDevice} this interface belongs to.
+ * Returns the {@link android.hardware.usb.UsbDevice} this interface belongs to.
*
* @return the interface's device
*/
diff --git a/core/java/android/hardware/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index dcfdcf4..6683179 100644
--- a/core/java/android/hardware/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -15,7 +15,7 @@
*/
-package android.hardware;
+package android.hardware.usb;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -55,55 +55,55 @@ public class UsbManager {
* </ul>
*/
public static final String ACTION_USB_STATE =
- "android.hardware.action.USB_STATE";
+ "android.hardware.usb.action.USB_STATE";
/**
* Broadcast Action: A broadcast for USB device attached event.
*
* This intent is sent when a USB device is attached to the USB bus when in host mode.
* <ul>
- * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.UsbDevice}
+ * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
* for the attached device
* </ul>
*/
public static final String ACTION_USB_DEVICE_ATTACHED =
- "android.hardware.action.USB_DEVICE_ATTACHED";
+ "android.hardware.usb.action.USB_DEVICE_ATTACHED";
/**
* Broadcast Action: A broadcast for USB device detached event.
*
* This intent is sent when a USB device is detached from the USB bus when in host mode.
* <ul>
- * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.UsbDevice}
+ * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
* for the detached device
* </ul>
*/
public static final String ACTION_USB_DEVICE_DETACHED =
- "android.hardware.action.USB_DEVICE_DETACHED";
+ "android.hardware.usb.action.USB_DEVICE_DETACHED";
/**
* Broadcast Action: A broadcast for USB accessory attached event.
*
* This intent is sent when a USB accessory is attached.
* <ul>
- * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
+ * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory}
* for the attached accessory
* </ul>
*/
public static final String ACTION_USB_ACCESSORY_ATTACHED =
- "android.hardware.action.USB_ACCESSORY_ATTACHED";
+ "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
/**
* Broadcast Action: A broadcast for USB accessory detached event.
*
* This intent is sent when a USB accessory is detached.
* <ul>
- * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
+ * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory}
* for the attached accessory that was detached
* </ul>
*/
public static final String ACTION_USB_ACCESSORY_DETACHED =
- "android.hardware.action.USB_ACCESSORY_DETACHED";
+ "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
/**
* Boolean extra indicating whether USB is connected or disconnected.
@@ -163,14 +163,15 @@ public class UsbManager {
/**
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and
- * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts.
+ * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts
* containing the UsbDevice object for the device.
*/
public static final String EXTRA_DEVICE = "device";
/**
- * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+ * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and
+ * {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts
* containing the UsbAccessory object for the accessory.
*/
public static final String EXTRA_ACCESSORY = "accessory";
@@ -209,7 +210,7 @@ public class UsbManager {
/**
* Opens the device so it can be used to send and receive
- * data using {@link android.hardware.UsbRequest}.
+ * data using {@link android.hardware.usb.UsbRequest}.
*
* @param device the device to open
* @return true if we successfully opened the device
@@ -244,7 +245,7 @@ public class UsbManager {
return new UsbAccessory[] { accessory };
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openAccessory" , e);
+ Log.e(TAG, "RemoteException in getAccessoryList" , e);
return null;
}
}
@@ -257,7 +258,7 @@ public class UsbManager {
*/
public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
try {
- return mService.openAccessory();
+ return mService.openAccessory(accessory);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in openAccessory" , e);
return null;
diff --git a/core/java/android/hardware/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index ae3a289..80085c1 100644
--- a/core/java/android/hardware/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware;
+package android.hardware.usb;
import android.util.Log;
@@ -23,9 +23,9 @@ import java.nio.ByteBuffer;
/**
* A class representing USB request packet.
* This can be used for both reading and writing data to or from a
- * {@link android.hardware.UsbDevice}.
+ * {@link android.hardware.usb.UsbDevice}.
* UsbRequests are sent asynchronously via {@link #queue} and the results
- * are read by {@link android.hardware.UsbDevice#requestWait}.
+ * are read by {@link android.hardware.usb.UsbDevice#requestWait}.
*/
public class UsbRequest {
@@ -94,7 +94,7 @@ public class UsbRequest {
* This can be used in conjunction with {@link #setClientData}
* to associate another object with this request, which can be useful for
* maintaining state between calls to {@link #queue} and
- * {@link android.hardware.UsbDevice#requestWait}
+ * {@link android.hardware.usb.UsbDevice#requestWait}
*
* @return the client data for the request
*/
@@ -107,7 +107,7 @@ public class UsbRequest {
* This can be used in conjunction with {@link #getClientData}
* to associate another object with this request, which can be useful for
* maintaining state between calls to {@link #queue} and
- * {@link android.hardware.UsbDevice#requestWait}
+ * {@link android.hardware.usb.UsbDevice#requestWait}
*
* @param data the client data for the request
*/
@@ -121,7 +121,7 @@ public class UsbRequest {
* For IN endpoints, the endpoint will attempt to read the given number of bytes
* into the specified buffer.
* If the queueing operation is successful, we return true and the result will be
- * returned via {@link android.hardware.UsbDevice#requestWait}
+ * returned via {@link android.hardware.usb.UsbDevice#requestWait}
*
* @param buffer the buffer containing the bytes to write, or location to store
* the results of a read
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 8944f12..eca3484 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1385,6 +1385,7 @@ public final class Parcel {
int mode) throws FileNotFoundException;
/*package*/ static native void closeFileDescriptor(FileDescriptor desc)
throws IOException;
+ /*package*/ static native void clearFileDescriptor(FileDescriptor desc);
/**
* Read a byte value from the parcel at the current dataPosition().
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3a5d26b..5bd129f 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -197,6 +197,40 @@ public class ParcelFileDescriptor implements Parcelable {
public native long seekTo(long pos);
/**
+ * Return the native fd int for this ParcelFileDescriptor. The
+ * ParcelFileDescriptor still owns the fd, and it still must be closed
+ * through this API.
+ */
+ public int getFd() {
+ if (mClosed) {
+ throw new IllegalStateException("Already closed");
+ }
+ return getFdNative();
+ }
+
+ private native int getFdNative();
+
+ /**
+ * Return the native fd int for this ParcelFileDescriptor and detach it
+ * from the object here. You are now responsible for closing the fd in
+ * native code.
+ */
+ public int detachFd() {
+ if (mClosed) {
+ throw new IllegalStateException("Already closed");
+ }
+ if (mParcelDescriptor != null) {
+ int fd = mParcelDescriptor.detachFd();
+ mClosed = true;
+ return fd;
+ }
+ int fd = getFd();
+ mClosed = true;
+ Parcel.clearFileDescriptor(mFileDescriptor);
+ return fd;
+ }
+
+ /**
* Close the ParcelFileDescriptor. This implementation closes the underlying
* OS resources allocated to represent this stream.
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 5c06151..af4c221 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2447,21 +2447,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
cache = child.getDrawingCache(true);
} else {
- if (layerType == LAYER_TYPE_SOFTWARE) {
- child.buildDrawingCache(true);
- cache = child.getDrawingCache(true);
- } else if (layerType == LAYER_TYPE_NONE) {
- // Delay getting the display list until animation-driven alpha values are
- // set up and possibly passed on to the view
- hasDisplayList = child.canHaveDisplayList();
+ switch (layerType) {
+ case LAYER_TYPE_SOFTWARE:
+ child.buildDrawingCache(true);
+ cache = child.getDrawingCache(true);
+ break;
+ case LAYER_TYPE_NONE:
+ // Delay getting the display list until animation-driven alpha values are
+ // set up and possibly passed on to the view
+ hasDisplayList = child.canHaveDisplayList();
+ break;
}
}
}
final boolean hasNoCache = cache == null || hasDisplayList;
+ final boolean offsetForScroll = cache == null && !hasDisplayList &&
+ layerType != LAYER_TYPE_HARDWARE;
final int restoreTo = canvas.save();
- if (cache == null && !hasDisplayList) {
+ if (offsetForScroll) {
canvas.translate(cl - sx, ct - sy);
} else {
canvas.translate(cl, ct);
@@ -2477,7 +2482,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
int transX = 0;
int transY = 0;
- if (cache == null && !hasDisplayList) {
+ if (offsetForScroll) {
transX = -sx;
transY = -sy;
}
@@ -2517,8 +2522,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
if (layerType == LAYER_TYPE_NONE) {
- canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct,
- multipliedAlpha, layerFlags);
+ final int scrollX = hasDisplayList ? 0 : sx;
+ final int scrollY = hasDisplayList ? 0 : sy;
+ canvas.saveLayerAlpha(scrollX, scrollY, scrollX + cr - cl,
+ scrollY + cb - ct, multipliedAlpha, layerFlags);
}
} else {
// Alpha is handled by the child directly, clobber the layer's alpha
@@ -2532,7 +2539,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
- if (cache == null && !hasDisplayList) {
+ if (offsetForScroll) {
canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct));
} else {
if (!scalingRequired || cache == null) {
@@ -2556,7 +2563,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
layerRendered = true;
} else {
- canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, child.mLayerPaint,
+ final int scrollX = hasDisplayList ? 0 : sx;
+ final int scrollY = hasDisplayList ? 0 : sy;
+ canvas.saveLayer(scrollX, scrollY,
+ scrollX + cr - cl, scrollY + cb - ct, child.mLayerPaint,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
}
}
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 27e7db1..1d56e9d 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2011 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.
@@ -33,11 +33,11 @@ import java.util.Set;
* more convenient syntax to animate a specific property, then ViewPropertyAnimator might be
* more well-suited to the task.
*
- * <p>This class could provide better performance for several simultaneous animations, because
- * it will optimize invalidatesionto take place only once for several properties instead of each
- * aniamted property independently causing its own invalidation. Also, the syntax of using this
+ * <p>This class may provide better performance for several simultaneous animations, because
+ * it will optimize invalidate calls to take place only once for several properties instead of each
+ * animated property independently causing its own invalidation. Also, the syntax of using this
* class could be easier to use because the caller need only tell the View object which
- * property to animate, and the value to animate either to or by, and this calss handles the
+ * property to animate, and the value to animate either to or by, and this class handles the
* details of configuring the underlying Animator class and starting it.</p>
*
* <p>This class is not constructed by the caller, but rather by the View whose properties
@@ -103,7 +103,7 @@ public class ViewPropertyAnimator {
/**
* Constants used to associate a property being requested and the mechanism used to set
- * the property (this calss calls directly into View to set the properties in question).
+ * the property (this class calls directly into View to set the properties in question).
*/
private static final int NONE = 0x0000;
private static final int TRANSLATION_X = 0x0001;
@@ -260,7 +260,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>x</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setX(float)
@@ -273,7 +273,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>x</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setX(float)
@@ -286,7 +286,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>y</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setY(float)
@@ -299,7 +299,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>y</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setY(float)
@@ -312,7 +312,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotation</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotation(float)
@@ -325,7 +325,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotation</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotation(float)
@@ -338,7 +338,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotationX</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotationX(float)
@@ -351,7 +351,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotationX</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotationX(float)
@@ -364,7 +364,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotationY</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setRotationY(float)
@@ -377,7 +377,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>rotationY</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setRotationY(float)
@@ -390,7 +390,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>translationX</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setTranslationX(float)
@@ -403,7 +403,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>translationX</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setTranslationX(float)
@@ -416,7 +416,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>translationY</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setTranslationY(float)
@@ -429,7 +429,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>translationY</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setTranslationY(float)
@@ -442,7 +442,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>scaleX</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setScaleX(float)
@@ -455,7 +455,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>scaleX</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setScaleX(float)
@@ -468,7 +468,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>scaleY</code> property to be animated to the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setScaleY(float)
@@ -481,7 +481,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>scaleY</code> property to be animated by the
- * specifed value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setScaleY(float)
@@ -494,7 +494,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>alpha</code> property to be animated to the
- * specified value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setAlpha(float)
@@ -507,7 +507,7 @@ public class ViewPropertyAnimator {
/**
* This method will cause the View's <code>alpha</code> property to be animated by the
- * specified value.
+ * specified value. Animations already running on the property will be canceled.
*
* @param value The amount to be animated by, as an offset from the current value.
* @see View#setAlpha(float)
@@ -548,7 +548,7 @@ public class ViewPropertyAnimator {
/**
* Utility function, called by the various x(), y(), etc. methods. This stores the
- * constnat name for the property along with the from/delta values that will be used to
+ * constant name for the property along with the from/delta values that will be used to
* calculate and set the property during the animation. This structure is added to the
* pending animations, awaiting the eventual start() of the underlying animator. A
* Runnable is posted to start the animation, and any pending such Runnable is canceled
@@ -578,14 +578,14 @@ public class ViewPropertyAnimator {
}
/**
- * Utility function, called by animatePropert() and animatePropertyBy(), which handles the
+ * Utility function, called by animateProperty() and animatePropertyBy(), which handles the
* details of adding a pending animation and posting the request to start the animation.
*
* @param constantName The specifier for the property being animated
- * @param fromValue The starting value of the property
+ * @param startValue The starting value of the property
* @param byValue The amount by which the property will change
*/
- private void animatePropertyBy(int constantName, float fromValue, float byValue) {
+ private void animatePropertyBy(int constantName, float startValue, float byValue) {
// First, cancel any existing animations on this property
if (mAnimatorMap.size() > 0) {
Animator animatorToCancel = null;
@@ -598,7 +598,7 @@ public class ViewPropertyAnimator {
// on a property will cancel a previous animation on that property, so
// there can only ever be one such animation running.
if (bundle.mPropertyMask == NONE) {
- // the animation is not longer changing animthing - cancel it
+ // the animation is not longer changing anything - cancel it
animatorToCancel = runningAnim;
break;
}
@@ -609,7 +609,6 @@ public class ViewPropertyAnimator {
}
}
- float startValue = getValue(constantName);
NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
mPendingAnimations.add(nameValuePair);
mView.getHandler().removeCallbacks(mAnimationStarter);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index c7b1955..965c959 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -155,6 +155,10 @@ public final class ViewRoot extends Handler implements ViewParent,
int mViewVisibility;
boolean mAppVisible = true;
+ // Set to true if the owner of this window is in the stopped state,
+ // so the window should no longer be active.
+ boolean mStopped = false;
+
SurfaceHolder.Callback2 mSurfaceHolderCallback;
BaseSurfaceHolder mSurfaceHolder;
boolean mIsCreating;
@@ -618,6 +622,15 @@ public final class ViewRoot extends Handler implements ViewParent,
scheduleTraversals();
}
+ void setStopped(boolean stopped) {
+ if (mStopped != stopped) {
+ mStopped = stopped;
+ if (!stopped) {
+ scheduleTraversals();
+ }
+ }
+ }
+
public ViewParent getParent() {
return null;
}
@@ -760,7 +773,7 @@ public final class ViewRoot extends Handler implements ViewParent,
boolean insetsChanged = false;
- if (mLayoutRequested) {
+ if (mLayoutRequested && !mStopped) {
// Execute enqueued actions on every layout in case a view that was detached
// enqueued an action after being detached
getRunQueue().executeActions(attachInfo.mHandler);
@@ -1143,54 +1156,56 @@ public final class ViewRoot extends Handler implements ViewParent,
mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
}
- boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
- (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
- if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
- || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
- childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
-
- if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth="
- + mWidth + " measuredWidth=" + host.getMeasuredWidth()
- + " mHeight=" + mHeight
- + " measuredHeight=" + host.getMeasuredHeight()
- + " coveredInsetsChanged=" + contentInsetsChanged);
-
- // Ask host how big it wants to be
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- // Implementation of weights from WindowManager.LayoutParams
- // We just grow the dimensions as needed and re-measure if
- // needs be
- int width = host.getMeasuredWidth();
- int height = host.getMeasuredHeight();
- boolean measureAgain = false;
-
- if (lp.horizontalWeight > 0.0f) {
- width += (int) ((mWidth - width) * lp.horizontalWeight);
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
- MeasureSpec.EXACTLY);
- measureAgain = true;
- }
- if (lp.verticalWeight > 0.0f) {
- height += (int) ((mHeight - height) * lp.verticalWeight);
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
- MeasureSpec.EXACTLY);
- measureAgain = true;
- }
-
- if (measureAgain) {
- if (DEBUG_LAYOUT) Log.v(TAG,
- "And hey let's measure once more: width=" + width
- + " height=" + height);
+ if (!mStopped) {
+ boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
+ (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
+ if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
+ || mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
+ childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
+ childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
+
+ if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth="
+ + mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ + " mHeight=" + mHeight
+ + " measuredHeight=" + host.getMeasuredHeight()
+ + " coveredInsetsChanged=" + contentInsetsChanged);
+
+ // Ask host how big it wants to be
host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
+ // Implementation of weights from WindowManager.LayoutParams
+ // We just grow the dimensions as needed and re-measure if
+ // needs be
+ int width = host.getMeasuredWidth();
+ int height = host.getMeasuredHeight();
+ boolean measureAgain = false;
+
+ if (lp.horizontalWeight > 0.0f) {
+ width += (int) ((mWidth - width) * lp.horizontalWeight);
+ childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
+ MeasureSpec.EXACTLY);
+ measureAgain = true;
+ }
+ if (lp.verticalWeight > 0.0f) {
+ height += (int) ((mHeight - height) * lp.verticalWeight);
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
+ MeasureSpec.EXACTLY);
+ measureAgain = true;
+ }
+
+ if (measureAgain) {
+ if (DEBUG_LAYOUT) Log.v(TAG,
+ "And hey let's measure once more: width=" + width
+ + " height=" + height);
+ host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ mLayoutRequested = true;
}
-
- mLayoutRequested = true;
}
}
- final boolean didLayout = mLayoutRequested;
+ final boolean didLayout = mLayoutRequested && !mStopped;
boolean triggerGlobalLayoutListener = didLayout
|| attachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 07953d6..a4c4544 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -302,6 +302,20 @@ public class WindowManagerImpl implements WindowManager {
}
}
+ public void setStoppedState(IBinder token, boolean stopped) {
+ synchronized (this) {
+ if (mViews == null)
+ return;
+ int count = mViews.length;
+ for (int i=0; i<count; i++) {
+ if (token == null || mParams[i].token == token) {
+ ViewRoot root = mRoots[i];
+ root.setStopped(stopped);
+ }
+ }
+ }
+ }
+
public WindowManager.LayoutParams getRootViewLayoutParameter(View view) {
ViewParent vp = view.getParent();
while (vp != null && !(vp instanceof ViewRoot)) {
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 40877e7..e44e2e7 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -293,6 +293,10 @@ public final class CookieManager {
* @param value The value for set-cookie: in http response header
*/
public void setCookie(String url, String value) {
+ if (JniUtil.useChromiumHttpStack()) {
+ setCookie(url, value, false);
+ }
+
WebAddress uri;
try {
uri = new WebAddress(url);
@@ -301,11 +305,33 @@ public final class CookieManager {
return;
}
- if (JniUtil.useChromiumHttpStack()) {
- nativeSetCookie(uri.toString(), value);
- } else {
- setCookie(uri, value);
+ setCookie(uri, value);
+ }
+
+ /**
+ * Set cookie for a given url. The old cookie with same host/path/name will
+ * be removed. The new cookie will be added if it is not expired or it does
+ * not have expiration which implies it is session cookie.
+ * @param url The url which cookie is set for
+ * @param value The value for set-cookie: in http response header
+ * @param privateBrowsing cookie jar to use
+ * @hide hiding private browsing
+ */
+ public void setCookie(String url, String value, boolean privateBrowsing) {
+ if (!JniUtil.useChromiumHttpStack()) {
+ setCookie(url, value);
+ return;
}
+
+ WebAddress uri;
+ try {
+ uri = new WebAddress(url);
+ } catch (ParseException ex) {
+ Log.e(LOGTAG, "Bad address: " + url);
+ return;
+ }
+
+ nativeSetCookie(uri.toString(), value, privateBrowsing);
}
/**
@@ -424,6 +450,10 @@ public final class CookieManager {
* @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
*/
public String getCookie(String url) {
+ if (JniUtil.useChromiumHttpStack()) {
+ return getCookie(url, false);
+ }
+
WebAddress uri;
try {
uri = new WebAddress(url);
@@ -432,11 +462,32 @@ public final class CookieManager {
return null;
}
- if (JniUtil.useChromiumHttpStack()) {
- return nativeGetCookie(uri.toString());
- } else {
- return getCookie(uri);
+ return getCookie(uri);
+ }
+
+ /**
+ * Get cookie(s) for a given url so that it can be set to "cookie:" in http
+ * request header.
+ * @param url The url needs cookie
+ * @param privateBrowsing cookie jar to use
+ * @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
+ * @hide Private mode is not very well exposed for now
+ */
+ public String getCookie(String url, boolean privateBrowsing) {
+ if (!JniUtil.useChromiumHttpStack()) {
+ // Just redirect to regular get cookie for android stack
+ return getCookie(url);
+ }
+
+ WebAddress uri;
+ try {
+ uri = new WebAddress(url);
+ } catch (ParseException ex) {
+ Log.e(LOGTAG, "Bad address: " + url);
+ return null;
}
+
+ return nativeGetCookie(uri.toString(), privateBrowsing);
}
/**
@@ -605,13 +656,26 @@ public final class CookieManager {
*/
public synchronized boolean hasCookies() {
if (JniUtil.useChromiumHttpStack()) {
- return nativeHasCookies();
+ return hasCookies(false);
}
return CookieSyncManager.getInstance().hasCookies();
}
/**
+ * Return true if there are stored cookies.
+ * @param privateBrowsing cookie jar to use
+ * @hide Hiding private mode
+ */
+ public synchronized boolean hasCookies(boolean privateBrowsing) {
+ if (!JniUtil.useChromiumHttpStack()) {
+ return hasCookies();
+ }
+
+ return nativeHasCookies(privateBrowsing);
+ }
+
+ /**
* Remove all expired cookies
*/
public void removeExpiredCookie() {
@@ -1132,13 +1196,13 @@ public final class CookieManager {
// Native functions
private static native boolean nativeAcceptCookie();
- private static native String nativeGetCookie(String url);
- private static native boolean nativeHasCookies();
+ private static native String nativeGetCookie(String url, boolean privateBrowsing);
+ private static native boolean nativeHasCookies(boolean privateBrowsing);
private static native void nativeRemoveAllCookie();
private static native void nativeRemoveExpiredCookie();
private static native void nativeRemoveSessionCookie();
private static native void nativeSetAcceptCookie(boolean accept);
- private static native void nativeSetCookie(String url, String value);
+ private static native void nativeSetCookie(String url, String value, boolean privateBrowsing);
private static native void nativeFlushCookieStore();
private static native boolean nativeAcceptFileSchemeCookies();
private static native void nativeSetAcceptFileSchemeCookies(boolean accept);
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 2cc3881..85763da 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -184,12 +184,13 @@ class HTML5VideoViewProxy extends Handler
mVideoView.setWillNotDraw(false);
mVideoView.setMediaController(new MediaController(proxy.getContext()));
- String cookieValue = CookieManager.getInstance().getCookie(url);
+ boolean isPrivate = mCurrentProxy.getWebView().isPrivateBrowsingEnabled();
+ String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate);
Map<String, String> headers = new HashMap<String, String>();
if (cookieValue != null) {
headers.put(COOKIE, cookieValue);
}
- if (mCurrentProxy.getWebView().isPrivateBrowsingEnabled()) {
+ if (isPrivate) {
headers.put(HIDE_URL_LOGS, "true");
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 492cb80..47c69be 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -947,6 +947,8 @@ import junit.framework.Assert;
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
+ bottom--;
+ right -= 2;
// Top line
mLines[0] = left;
mLines[1] = top + 1;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f877fc8..43f8790 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5043,15 +5043,13 @@ public class WebView extends AbsoluteLayout
super.onAttachedToWindow();
if (hasWindowFocus()) setActive(true);
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- if (mGlobalLayoutListener == null) {
- mGlobalLayoutListener = new InnerGlobalLayoutListener();
- treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
- }
- if (mScrollChangedListener == null) {
- mScrollChangedListener = new InnerScrollChangedListener();
- treeObserver.addOnScrollChangedListener(mScrollChangedListener);
- }
+ if (mGlobalLayoutListener == null) {
+ mGlobalLayoutListener = new InnerGlobalLayoutListener();
+ treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
+ }
+ if (mScrollChangedListener == null) {
+ mScrollChangedListener = new InnerScrollChangedListener();
+ treeObserver.addOnScrollChangedListener(mScrollChangedListener);
}
addAccessibilityApisToJavaScript();
@@ -5064,15 +5062,13 @@ public class WebView extends AbsoluteLayout
if (hasWindowFocus()) setActive(false);
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- if (mGlobalLayoutListener != null) {
- treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
- mGlobalLayoutListener = null;
- }
- if (mScrollChangedListener != null) {
- treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
- mScrollChangedListener = null;
- }
+ if (mGlobalLayoutListener != null) {
+ treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
+ mGlobalLayoutListener = null;
+ }
+ if (mScrollChangedListener != null) {
+ treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
+ mScrollChangedListener = null;
}
removeAccessibilityApisFromJavaScript();
@@ -5106,8 +5102,7 @@ public class WebView extends AbsoluteLayout
/**
* @deprecated WebView should not have implemented
- * ViewTreeObserver.OnGlobalFocusChangeListener. This method
- * does nothing now.
+ * ViewTreeObserver.OnGlobalFocusChangeListener. This method does nothing now.
*/
@Deprecated
public void onGlobalFocusChanged(View oldFocus, View newFocus) {
@@ -7758,6 +7753,7 @@ public class WebView extends AbsoluteLayout
int mEnabled;
int mId;
+ @Override
public String toString() {
return mString;
}
@@ -8222,6 +8218,7 @@ public class WebView extends AbsoluteLayout
* zero to make the view transparent.
* @param color the ARGB color described by Color.java
*/
+ @Override
public void setBackgroundColor(int color) {
mBackgroundColor = color;
mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 6303850..ee0d122 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -704,9 +704,10 @@ class ZoomManager {
* false otherwise.
*/
public boolean isPreventingWebkitUpdates() {
- // currently only animating a multi-touch zoom prevents updates, but
- // others can add their own conditions to this method if necessary.
- return mPinchToZoomAnimating;
+ // currently only animating a multi-touch zoom and fixed length
+ // animations prevent updates, but others can add their own conditions
+ // to this method if necessary.
+ return isZoomAnimating();
}
public ScaleGestureDetector getMultiTouchGestureDetector() {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1d05d0b..2925632 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1251,6 +1251,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
}
+ onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
}
/**
@@ -2268,11 +2269,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
super.onAttachedToWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.addOnTouchModeChangeListener(this);
- if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
- treeObserver.addOnGlobalLayoutListener(this);
- }
+ treeObserver.addOnTouchModeChangeListener(this);
+ if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
+ treeObserver.addOnGlobalLayoutListener(this);
}
if (mAdapter != null && mDataSetObserver == null) {
@@ -2297,12 +2296,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mRecycler.clear();
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.removeOnTouchModeChangeListener(this);
- if (mTextFilterEnabled && mPopup != null) {
- treeObserver.removeGlobalOnLayoutListener(this);
- mGlobalLayoutListenerAddedFilter = false;
- }
+ treeObserver.removeOnTouchModeChangeListener(this);
+ if (mTextFilterEnabled && mPopup != null) {
+ treeObserver.removeGlobalOnLayoutListener(this);
+ mGlobalLayoutListenerAddedFilter = false;
}
if (mAdapter != null) {
@@ -2793,8 +2790,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (!mDataChanged) {
if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
&& (getAdapter().isEnabled(motionPosition))) {
- // User clicked on an actual view (and was not stopping a fling). It might be a
- // click or a scroll. Assume it is a click until proven otherwise
+ // User clicked on an actual view (and was not stopping a fling).
+ // It might be a click or a scroll. Assume it is a click until
+ // proven otherwise
mTouchMode = TOUCH_MODE_DOWN;
// FIXME Debounce
if (mPendingCheckForTap == null) {
@@ -2803,9 +2801,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
- // If we couldn't find a view to click on, but the down event was touching
- // the edge, we will bail out and try again. This allows the edge correcting
- // code in ViewRoot to try to find a nearby view to select
+ // If we couldn't find a view to click on, but the down event
+ // was touching the edge, we will bail out and try again.
+ // This allows the edge correcting code in ViewRoot to try to
+ // find a nearby view to select
return false;
}
@@ -3019,7 +3018,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
case TOUCH_MODE_DONE_WAITING:
final int motionPosition = mMotionPosition;
final View child = getChildAt(motionPosition - mFirstPosition);
- if (child != null && !child.hasFocusable()) {
+
+ final float x = ev.getX();
+ final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
+
+ if (child != null && !child.hasFocusable() && inList) {
if (mTouchMode != TOUCH_MODE_DOWN) {
child.setPressed(false);
}
@@ -3241,24 +3244,47 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLastY = y;
break;
}
+
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ // New pointers take over dragging duties
+ final int index = ev.getActionIndex();
+ final int id = ev.getPointerId(index);
+ final int x = (int) ev.getX(index);
+ final int y = (int) ev.getY(index);
+ mMotionCorrection = 0;
+ mActivePointerId = id;
+ mMotionX = x;
+ mMotionY = y;
+ final int motionPosition = pointToPosition(x, y);
+ if (motionPosition >= 0) {
+ // Remember where the motion event started
+ v = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = v.getTop();
+ mMotionPosition = motionPosition;
+ }
+ mLastY = y;
+ break;
+ }
}
return true;
}
@Override
- protected void onOverScrolled(int scrollX, int scrollY,
- boolean clampedX, boolean clampedY) {
- mScrollY = scrollY;
- invalidateParentIfNeeded();
-
- if (clampedY) {
- // Velocity is broken by hitting the limit; don't start a fling off of this.
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
+ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
+ if (mScrollY != scrollY) {
+ onScrollChanged(mScrollX, scrollY, mScrollX, mScrollY);
+ mScrollY = scrollY;
+ invalidateParentIfNeeded();
+
+ if (clampedY) {
+ // Velocity is broken by hitting the limit; don't start a fling off of this.
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
}
+ awakenScrollBars();
}
- awakenScrollBars();
}
@Override
@@ -3270,7 +3296,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vscroll != 0) {
final int delta = (int) (vscroll * getVerticalScrollFactor());
- if (trackMotionScroll(delta, delta)) {
+ if (!trackMotionScroll(delta, delta)) {
return true;
}
}
@@ -3412,9 +3438,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mMotionY = (int) ev.getY(newPointerIndex);
mMotionCorrection = 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
- }
}
}
@@ -4279,17 +4302,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLastPositionDistanceGuess += incrementalDeltaY;
}
- if (firstPosition == 0 && firstTop >= listPadding.top && incrementalDeltaY >= 0) {
- // Don't need to move views down if the top of the first position
- // is already visible
- return incrementalDeltaY != 0;
- }
+ final boolean cannotScrollDown = (firstPosition == 0 &&
+ firstTop >= listPadding.top && incrementalDeltaY >= 0);
+ final boolean cannotScrollUp = (firstPosition + childCount == mItemCount &&
+ lastBottom <= getHeight() - listPadding.bottom && incrementalDeltaY <= 0);
- if (firstPosition + childCount == mItemCount &&
- lastBottom <= getHeight() - listPadding.bottom &&
- incrementalDeltaY <= 0) {
- // Don't need to move views up if the bottom of the last position
- // is already visible
+ if (cannotScrollDown || cannotScrollUp) {
return incrementalDeltaY != 0;
}
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 8279ee5..f862368 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -299,6 +299,9 @@ public class ExpandableListView extends ListView {
indicatorRect.right = mIndicatorRight;
}
+ indicatorRect.left += mPaddingLeft;
+ indicatorRect.right += mPaddingLeft;
+
lastItemType = pos.position.type;
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 3255f6f..d92588c 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -475,8 +475,16 @@ public class HorizontalScrollView extends FrameLayout {
invalidate();
}
break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ final float x = ev.getX(index);
+ mLastMotionX = x;
+ mActivePointerId = ev.getPointerId(index);
+ break;
+ }
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
+ mLastMotionX = ev.getX(ev.findPointerIndex(mActivePointerId));
break;
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 7aca0db..4b4f5f2 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -607,8 +607,16 @@ public class ScrollView extends FrameLayout {
endDrag();
}
break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ final float y = ev.getY(index);
+ mLastMotionY = y;
+ mActivePointerId = ev.getPointerId(index);
+ break;
+ }
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
+ mLastMotionY = ev.getY(ev.findPointerIndex(mActivePointerId));
break;
}
return true;
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index e6cf31e..bab469b 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -33,6 +33,7 @@ import android.graphics.Region;
import android.graphics.TableMaskFilter;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -114,6 +115,8 @@ public class StackView extends AdapterViewAnimator {
private static final int MIN_TIME_BETWEEN_INTERACTION_AND_AUTOADVANCE = 5000;
+ private static long MIN_TIME_BETWEEN_SCROLLS = 100;
+
/**
* These variables are all related to the current state of touch interaction
* with the stack
@@ -137,6 +140,7 @@ public class StackView extends AdapterViewAnimator {
private StackSlider mStackSlider;
private boolean mFirstLayoutHappened = false;
private long mLastInteractionTime = 0;
+ private long mLastScrollTime;
private int mStackMode;
private int mFramePadding;
private final Rect stackInvalidateRect = new Rect();
@@ -565,6 +569,38 @@ public class StackView extends AdapterViewAnimator {
}
}
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_SCROLL: {
+ final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+ if (vscroll < 0) {
+ pacedScroll(false);
+ return true;
+ } else if (vscroll > 0) {
+ pacedScroll(true);
+ return true;
+ }
+ }
+ }
+ }
+ return super.onGenericMotionEvent(event);
+ }
+
+ // This ensures that the frequency of stack flips caused by scrolls is capped
+ private void pacedScroll(boolean up) {
+ long timeSinceLastScroll = System.currentTimeMillis() - mLastScrollTime;
+ if (timeSinceLastScroll > MIN_TIME_BETWEEN_SCROLLS) {
+ if (up) {
+ showPrevious();
+ } else {
+ showNext();
+ }
+ mLastScrollTime = System.currentTimeMillis();
+ }
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 03eea66..57a8531 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -183,18 +183,14 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
protected void onAttachedToWindow() {
super.onAttachedToWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.addOnTouchModeChangeListener(this);
- }
+ treeObserver.addOnTouchModeChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.removeOnTouchModeChangeListener(this);
- }
+ treeObserver.removeOnTouchModeChangeListener(this);
}
/**
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index d74ef24..6f76dd0 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -172,6 +172,11 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
@Override
void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
+ if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED) {
+ super.measureHorizontal(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+
// First, measure with no constraint
final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
mImposedTabsHeight = -1;
@@ -208,9 +213,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
}
// Measure again, this time with imposed tab widths and respecting initial spec request
- if (mImposedTabsHeight >= 0 || unspecifiedWidth != widthMeasureSpec) {
- super.measureHorizontal(widthMeasureSpec, heightMeasureSpec);
- }
+ super.measureHorizontal(widthMeasureSpec, heightMeasureSpec);
}
/**
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 841de06..fb2a72b 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -68,7 +68,7 @@ public class ResolverActivity extends AlertActivity implements
protected void onCreate(Bundle savedInstanceState, Intent intent,
CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList,
- boolean alwaysUseOption) {
+ boolean alwaysUseOption, boolean alwaysChoose) {
super.onCreate(savedInstanceState);
mPm = getPackageManager();
intent.setComponent(null);
@@ -90,9 +90,10 @@ public class ResolverActivity extends AlertActivity implements
mClearDefaultHint.setVisibility(View.GONE);
}
mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList);
- if (mAdapter.getCount() > 1) {
+ int count = mAdapter.getCount();
+ if (count > 1 || (count == 1 && alwaysChoose)) {
ap.mAdapter = mAdapter;
- } else if (mAdapter.getCount() == 1) {
+ } else if (count == 1) {
startActivity(mAdapter.intentForPosition(0));
finish();
return;
@@ -103,11 +104,22 @@ public class ResolverActivity extends AlertActivity implements
setupAlert();
}
+ protected void onCreate(Bundle savedInstanceState, Intent intent,
+ CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList,
+ boolean alwaysUseOption) {
+ onCreate(savedInstanceState, intent, title, initialIntents, rList, alwaysUseOption, false);
+ }
+
public void onClick(DialogInterface dialog, int which) {
ResolveInfo ri = mAdapter.resolveInfoForPosition(which);
Intent intent = mAdapter.intentForPosition(which);
+ boolean alwaysCheck = (mAlwaysCheck != null && mAlwaysCheck.isChecked());
+ onIntentSelected(ri, intent, alwaysCheck);
+ finish();
+ }
- if ((mAlwaysCheck != null) && mAlwaysCheck.isChecked()) {
+ protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
+ if (alwaysCheck) {
// Build a reasonable intent filter, based on what matched.
IntentFilter filter = new IntentFilter();
@@ -190,7 +202,6 @@ public class ResolverActivity extends AlertActivity implements
if (intent != null) {
startActivity(intent);
}
- finish();
}
private final class DisplayResolveInfo {
diff --git a/core/jni/android_hardware_UsbDevice.cpp b/core/jni/android_hardware_UsbDevice.cpp
index 9014450..b01820c 100644
--- a/core/jni/android_hardware_UsbDevice.cpp
+++ b/core/jni/android_hardware_UsbDevice.cpp
@@ -237,7 +237,7 @@ static JNINativeMethod method_table[] = {
(void *)android_hardware_UsbDevice_control_request},
{"native_bulk_request", "(I[BII)I",
(void *)android_hardware_UsbDevice_bulk_request},
- {"native_request_wait", "()Landroid/hardware/UsbRequest;",
+ {"native_request_wait", "()Landroid/hardware/usb/UsbRequest;",
(void *)android_hardware_UsbDevice_request_wait},
{ "native_get_serial", "()Ljava/lang/String;",
(void*)android_hardware_UsbDevice_get_serial },
@@ -251,9 +251,9 @@ static JNINativeMethod method_table[] = {
int register_android_hardware_UsbDevice(JNIEnv *env)
{
- jclass clazz = env->FindClass("android/hardware/UsbDevice");
+ jclass clazz = env->FindClass("android/hardware/usb/UsbDevice");
if (clazz == NULL) {
- LOGE("Can't find android/hardware/UsbDevice");
+ LOGE("Can't find android/hardware/usb/UsbDevice");
return -1;
}
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
@@ -262,7 +262,7 @@ int register_android_hardware_UsbDevice(JNIEnv *env)
return -1;
}
- return AndroidRuntime::registerNativeMethods(env, "android/hardware/UsbDevice",
+ return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbDevice",
method_table, NELEM(method_table));
}
diff --git a/core/jni/android_hardware_UsbEndpoint.cpp b/core/jni/android_hardware_UsbEndpoint.cpp
deleted file mode 100644
index 00c8235..0000000
--- a/core/jni/android_hardware_UsbEndpoint.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "UsbEndpoint"
-
-#include "utils/Log.h"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-
-#include <usbhost/usbhost.h>
-
-#include <stdio.h>
-
-using namespace android;
-
-static jfieldID field_context;
-static jfieldID field_address;
-static jfieldID field_attributes;
-static jfieldID field_max_packet_size;
-static jfieldID field_interval;
-
-struct usb_endpoint* get_endpoint_from_object(JNIEnv* env, jobject javaEndpoint)
-{
- return (struct usb_endpoint*)env->GetIntField(javaEndpoint, field_context);
-}
-
-// in android_hardware_UsbDevice.cpp
-extern struct usb_device* get_device_from_object(JNIEnv* env, jobject javaDevice);
-
-static jboolean
-android_hardware_UsbEndpoint_init(JNIEnv *env, jobject thiz, jobject javaDevice)
-{
- LOGD("open\n");
-
- struct usb_device* device = get_device_from_object(env, javaDevice);
- if (!device) {
- LOGE("device null in native_init");
- return false;
- }
-
- // construct an endpoint descriptor from the Java object fields
- struct usb_endpoint_descriptor desc;
- desc.bLength = USB_DT_ENDPOINT_SIZE;
- desc.bDescriptorType = USB_DT_ENDPOINT;
- desc.bEndpointAddress = env->GetIntField(thiz, field_address);
- desc.bmAttributes = env->GetIntField(thiz, field_attributes);
- desc.wMaxPacketSize = env->GetIntField(thiz, field_max_packet_size);
- desc.bInterval = env->GetIntField(thiz, field_interval);
-
- struct usb_endpoint* endpoint = usb_endpoint_init(device, &desc);
- if (endpoint)
- env->SetIntField(thiz, field_context, (int)device);
- return (endpoint != NULL);
-}
-
-static void
-android_hardware_UsbEndpoint_close(JNIEnv *env, jobject thiz)
-{
- LOGD("close\n");
- struct usb_endpoint* endpoint = get_endpoint_from_object(env, thiz);
- if (endpoint) {
- usb_endpoint_close(endpoint);
- env->SetIntField(thiz, field_context, 0);
- }
-}
-
-static JNINativeMethod method_table[] = {
- {"native_init", "(Landroid/hardware/UsbDevice;)Z",
- (void *)android_hardware_UsbEndpoint_init},
- {"native_close", "()V", (void *)android_hardware_UsbEndpoint_close},
-};
-
-int register_android_hardware_UsbEndpoint(JNIEnv *env)
-{
- jclass clazz = env->FindClass("android/hardware/UsbEndpoint");
- if (clazz == NULL) {
- LOGE("Can't find android/hardware/UsbEndpoint");
- return -1;
- }
- field_context = env->GetFieldID(clazz, "mNativeContext", "I");
- if (field_context == NULL) {
- LOGE("Can't find UsbEndpoint.mNativeContext");
- return -1;
- }
- field_address = env->GetFieldID(clazz, "mAddress", "I");
- if (field_address == NULL) {
- LOGE("Can't find UsbEndpoint.mAddress");
- return -1;
- }
- field_attributes = env->GetFieldID(clazz, "mAttributes", "I");
- if (field_attributes == NULL) {
- LOGE("Can't find UsbEndpoint.mAttributes");
- return -1;
- }
- field_max_packet_size = env->GetFieldID(clazz, "mMaxPacketSize", "I");
- if (field_max_packet_size == NULL) {
- LOGE("Can't find UsbEndpoint.mMaxPacketSize");
- return -1;
- }
- field_interval = env->GetFieldID(clazz, "mInterval", "I");
- if (field_interval == NULL) {
- LOGE("Can't find UsbEndpoint.mInterval");
- return -1;
- }
-
- return AndroidRuntime::registerNativeMethods(env, "android/hardware/UsbEndpoint",
- method_table, NELEM(method_table));
-}
-
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 710afae..b497adb 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -187,7 +187,7 @@ android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
}
static JNINativeMethod method_table[] = {
- {"native_init", "(Landroid/hardware/UsbDevice;IIII)Z",
+ {"native_init", "(Landroid/hardware/usb/UsbDevice;IIII)Z",
(void *)android_hardware_UsbRequest_init},
{"native_close", "()V", (void *)android_hardware_UsbRequest_close},
{"native_queue_array", "([BIZ)Z", (void *)android_hardware_UsbRequest_queue_array},
@@ -200,9 +200,9 @@ static JNINativeMethod method_table[] = {
int register_android_hardware_UsbRequest(JNIEnv *env)
{
- jclass clazz = env->FindClass("android/hardware/UsbRequest");
+ jclass clazz = env->FindClass("android/hardware/usb/UsbRequest");
if (clazz == NULL) {
- LOGE("Can't find android/hardware/UsbRequest");
+ LOGE("Can't find android/hardware/usb/UsbRequest");
return -1;
}
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
@@ -211,7 +211,7 @@ int register_android_hardware_UsbRequest(JNIEnv *env)
return -1;
}
- return AndroidRuntime::registerNativeMethods(env, "android/hardware/UsbRequest",
+ return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbRequest",
method_table, NELEM(method_table));
}
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
index eceef1c..1f737f9 100644
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ b/core/jni/android_os_ParcelFileDescriptor.cpp
@@ -126,6 +126,17 @@ static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
return lseek(fd, pos, SEEK_SET);
}
+static jlong android_os_ParcelFileDescriptor_getFdNative(JNIEnv* env, jobject clazz)
+{
+ jint fd = getFd(env, clazz);
+ if (fd < 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
+ return -1;
+ }
+
+ return fd;
+}
+
static const JNINativeMethod gParcelFileDescriptorMethods[] = {
{"getFileDescriptorFromSocket", "(Ljava/net/Socket;)Ljava/io/FileDescriptor;",
(void*)android_os_ParcelFileDescriptor_getFileDescriptorFromSocket},
@@ -134,7 +145,9 @@ static const JNINativeMethod gParcelFileDescriptorMethods[] = {
{"getStatSize", "()J",
(void*)android_os_ParcelFileDescriptor_getStatSize},
{"seekTo", "(J)J",
- (void*)android_os_ParcelFileDescriptor_seekTo}
+ (void*)android_os_ParcelFileDescriptor_seekTo},
+ {"getFdNative", "()I",
+ (void*)android_os_ParcelFileDescriptor_getFdNative}
};
const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 7226e31..15362eb 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -1520,6 +1520,14 @@ static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jo
}
}
+static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
+{
+ int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
+ if (fd >= 0) {
+ env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
+ }
+}
+
static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
{
int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
@@ -1719,6 +1727,7 @@ static const JNINativeMethod gParcelMethods[] = {
{"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
{"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
{"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
+ {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
{"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
{"init", "(I)V", (void*)android_os_Parcel_init},
{"destroy", "()V", (void*)android_os_Parcel_destroy},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index beb824c..0ad174f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -84,11 +84,11 @@
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
- <protected-broadcast android:name="android.hardware.action.USB_STATE" />
- <protected-broadcast android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" />
- <protected-broadcast android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" />
- <protected-broadcast android:name="android.hardware.action.USB_DEVICE_ATTACHED" />
- <protected-broadcast android:name="android.hardware.action.USB_DEVICE_DETACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
@@ -466,12 +466,13 @@
android:label="@string/permlab_flashlight"
android:description="@string/permdesc_flashlight" />
- <!-- Allows an application to access USB devices -->
- <permission android:name="android.permission.ACCESS_USB"
+ <!-- Allows an application to manage preferences and permissions for USB devices
+ @hide -->
+ <permission android:name="android.permission.MANAGE_USB"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
- android:protectionLevel="normal"
- android:label="@string/permlab_accessUsb"
- android:description="@string/permdesc_accessUsb" />
+ android:protectionLevel="signatureOrSystem"
+ android:label="@string/permlab_manageUsb"
+ android:description="@string/permdesc_manageUsb" />
<!-- Allows an application to access the MTP USB kernel driver.
For use only by the device side MTP implementation.
@@ -1372,11 +1373,18 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+
<activity android:name="com.android.internal.app.NetInitiatedActivity"
android:theme="@style/Theme.Holo.Dialog.Alert"
android:excludeFromRecents="true">
</activity>
+ <activity android:name="com.android.server.usb.UsbResolverActivity"
+ android:theme="@style/Theme.Holo.Dialog.Alert"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true">
+ </activity>
+
<service android:name="com.android.server.LoadAverageService"
android:exported="true" />
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 4f74846..41fa758 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -125,10 +125,10 @@
<string name="contentServiceSync" msgid="8353523060269335667">"Sincronización"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronización"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
- <string name="low_memory" product="tablet" msgid="2292820184396262278">"Se ha agotado el espacio de almacenamiento de la tableta. Elimina algunos archivos para liberar espacio."</string>
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Se ha agotado el espacio de almacenamiento del tablet. Elimina algunos archivos para liberar espacio."</string>
<string name="low_memory" product="default" msgid="6632412458436461203">"Se ha agotado el espacio de almacenamiento del teléfono. Elimina algunos archivos para liberar espacio."</string>
<string name="me" msgid="6545696007631404292">"Yo"</string>
- <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opciones de tableta"</string>
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opciones del tablet"</string>
<string name="power_dialog" product="default" msgid="1319919075463988638">"Opciones del teléfono"</string>
<string name="silent_mode" msgid="7167703389802618663">"Modo silencio"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Activar conexión inalámbrica"</string>
@@ -136,12 +136,12 @@
<string name="screen_lock" msgid="799094655496098153">"Bloqueo de pantalla"</string>
<string name="power_off" msgid="4266614107412865048">"Apagar"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Apagando..."</string>
- <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"La tableta se apagará."</string>
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"El tablet se apagará."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"El teléfono se apagará."</string>
<string name="shutdown_confirm_question" msgid="6656441286856415014">"¿Quieres apagar el teléfono?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"No hay aplicaciones recientes"</string>
- <string name="global_actions" product="tablet" msgid="408477140088053665">"Opciones de tableta"</string>
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Opciones del tablet"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Opciones del teléfono"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Bloqueo de pantalla"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Apagar"</string>
@@ -159,7 +159,7 @@
<string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Leer y escribir SMS, mensajes de correo electrónico y otros mensajes"</string>
<string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Tu información personal"</string>
- <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accede directamente al calendario y a los contactos almacenados en la tableta."</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accede directamente al calendario y a los contactos almacenados en el tablet."</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acceso directo al calendario y a los contactos almacenados en el teléfono"</string>
<string name="permgrouplab_location" msgid="635149742436692049">"Tu ubicación"</string>
<string name="permgroupdesc_location" msgid="2430258821648348660">"Controlar su ubicación física"</string>
@@ -193,10 +193,10 @@
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar mensajes SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permite que la aplicación envíe mensajes SMS. Es posible que tengas que pagar si las aplicaciones malintencionadas envían mensajes sin tu confirmación."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"leer SMS o MMS"</string>
- <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permite que la aplicación lea mensajes SMS almacenados en la tableta o en la tarjeta SIM. Las aplicaciones malintencionadas pueden leer los mensajes confidenciales."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permite que la aplicación lea mensajes SMS almacenados en el tablet o en la tarjeta SIM. Las aplicaciones malintencionadas pueden leer los mensajes confidenciales."</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Permite que la aplicación lea mensajes SMS almacenados en el teléfono o en la tarjeta SIM. Las aplicaciones malintencionadas pueden leer los mensajes confidenciales."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"editar SMS o MMS"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permite que la aplicación escriba en mensajes SMS almacenados en la tableta o en la tarjeta SIM. Las aplicaciones malintencionadas pueden borrar los mensajes."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permite que la aplicación escriba en mensajes SMS almacenados en el tablet o en la tarjeta SIM. Las aplicaciones malintencionadas pueden borrar los mensajes."</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Permite que la aplicación escriba en mensajes SMS almacenados en el teléfono o en la tarjeta SIM. Las aplicaciones malintencionadas pueden borrar los mensajes."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"recibir WAP"</string>
<string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Permite que la aplicación reciba y procese mensajes WAP. Las aplicaciones malintencionadas pueden controlar los mensajes o eliminarlos sin mostrarlos al usuario."</string>
@@ -247,7 +247,7 @@
<string name="permlab_manageAppTokens" msgid="17124341698093865">"administrar tokens de aplicación"</string>
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Permite que las aplicaciones creen y administren sus propios tokens, ignorando su orden z normal. Nunca debería ser necesario para las aplicaciones normales."</string>
<string name="permlab_injectEvents" msgid="1378746584023586600">"pulsar teclas y botones de control"</string>
- <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permite que la aplicación proporcione sus propios eventos de entrada (pulsación de teclas, etc.) a otras aplicaciones. Las aplicaciones malintencionadas pueden utilizar este permiso para controlar la tableta."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permite que la aplicación proporcione sus propios eventos de entrada (pulsación de teclas, etc.) a otras aplicaciones. Las aplicaciones malintencionadas pueden utilizar este permiso para controlar el tablet."</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Permite que la aplicación proporcione sus propios eventos de entrada (pulsación de teclas, etc.) a otras aplicaciones. Las aplicaciones malintencionadas pueden utilizar este permiso para controlar el teléfono."</string>
<string name="permlab_readInputState" msgid="469428900041249234">"registrar lo que se escribe y las acciones que se realizan"</string>
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permite que las aplicaciones observen las teclas que pulsas incluso cuando interactúas con otra aplicación (como, por ejemplo, al introducir una contraseña). No debería ser necesario nunca para las aplicaciones normales."</string>
@@ -276,17 +276,17 @@
<string name="permlab_installPackages" msgid="335800214119051089">"instalar aplicaciones directamente"</string>
<string name="permdesc_installPackages" msgid="526669220850066132">"Permite que una aplicación instale paquetes Android nuevos o actualizados. Las aplicaciones malintencionadas pueden utilizar este permiso para añadir aplicaciones nuevas con permisos arbitrariamente potentes."</string>
<string name="permlab_clearAppCache" msgid="4747698311163766540">"eliminar todos los datos de caché de la aplicación"</string>
- <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite que una aplicación libere espacio de almacenamiento en la tableta mediante la eliminación de archivos del directorio de caché de la aplicación. El acceso está muy restringido (limitado normalmente al proceso del sistema)."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite que una aplicación libere espacio de almacenamiento en el tablet mediante la eliminación de archivos del directorio de caché de la aplicación. El acceso está muy restringido (limitado normalmente al proceso del sistema)."</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Permite que una aplicación libere espacio de almacenamiento en el teléfono mediante la eliminación de archivos en el directorio de caché de la aplicación. El acceso al proceso del sistema suele estar muy restringido."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Mover recursos de aplicaciones"</string>
<string name="permdesc_movePackage" msgid="6323049291923925277">"Permite que una aplicación mueva los recursos de aplicaciones de un medio interno a otro externo y viceversa."</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"leer datos de registro personales"</string>
- <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite que una aplicación lea diversos archivos de registro del sistema. Con este permiso, la aplicación puede ver información general sobre las acciones que se realizan con la tableta (que puede incluir datos personales o privados)."</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite que una aplicación lea diversos archivos de registro del sistema. Con este permiso, la aplicación puede ver información general sobre las acciones que se realizan con el tablet (que puede incluir datos personales o privados)."</string>
<string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permite que una aplicación lea distintos archivos de registro del sistema. Con este permiso, la aplicación puede ver información general sobre las acciones que realizas con el teléfono, que puede incluir datos personales o privados."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"leer/escribir en los recursos propiedad del grupo de diagnóstico"</string>
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Permite que una aplicación lea y escriba en cualquier recurso propiedad del grupo de diagnóstico como, por ejemplo, archivos in/dev. Este permiso podría afectar a la seguridad y estabilidad del sistema. SÓLO se debe utilizar para diagnósticos específicos de hardware realizados por el fabricante o el operador."</string>
<string name="permlab_changeComponentState" msgid="79425198834329406">"habilitar o inhabilitar componentes de la aplicación"</string>
- <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permite que una aplicación cambie si un componente de otra aplicación está habilitado o inhabilitado. Las aplicaciones malintencionadas pueden utilizar este permiso para inhabilitar funciones importantes de la tableta. Este permiso se debe utilizar con precaución, ya que es posible que los componentes se vuelvan inservibles, inconsistentes o inestables."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permite que una aplicación cambie si un componente de otra aplicación está habilitado o inhabilitado. Las aplicaciones malintencionadas pueden utilizar este permiso para inhabilitar funciones importantes del tablet. Este permiso se debe utilizar con precaución, ya que es posible que los componentes se vuelvan inservibles, inconsistentes o inestables."</string>
<string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Permite que una aplicación cambie si un componente de otra aplicación está habilitado o inhabilitado. Las aplicaciones malintencionadas pueden utilizar este permiso para inhabilitar funciones importantes del teléfono. Este permiso se debe utilizar con precaución, ya que es posible que los componentes se vuelvan inservibles, inconsistentes o inestables."</string>
<string name="permlab_setPreferredApplications" msgid="3393305202145172005">"establecer aplicaciones preferidas"</string>
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Permite que una aplicación modifique las aplicaciones preferidas del usuario. De esta forma, las aplicaciones malintencionadas pueden cambiar de forma silenciosa las aplicaciones que se están ejecutando, falsificando las aplicaciones existentes para recopilar datos privados del usuario."</string>
@@ -297,19 +297,19 @@
<string name="permlab_writeGservices" msgid="2149426664226152185">"modificar la asignación de servicios de Google"</string>
<string name="permdesc_writeGservices" msgid="6602362746516676175">"Permite que una aplicación modifique la asignación de servicios de Google. No está destinado al uso por parte de aplicaciones normales."</string>
<string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"ejecutar automáticamente al iniciar"</string>
- <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite que una aplicación se ejecute automáticamente en cuanto se haya terminado de iniciar el sistema. Esto puede hacer que la tableta tarde más en iniciarse y permite que la aplicación ralentice el funcionamiento global de la tableta al ejecutarse continuamente."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite que una aplicación se ejecute automáticamente en cuanto se haya terminado de iniciar el sistema. Esto puede hacer que el tablet tarde más en iniciarse y permite que la aplicación ralentice el funcionamiento global del tablet al ejecutarse continuamente."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Permite que una aplicación se ejecute automáticamente en cuanto se haya terminado de iniciar el sistema. Esto puede provocar que el teléfono tarde más en iniciarse y permite que la aplicación ralentice el funcionamiento global del teléfono al ejecutarse continuamente."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar emisión persistente"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite que una aplicación envíe emisiones persistentes que permanecen en el teléfono una vez que la emisión finaliza. Las aplicaciones malintencionadas pueden ralentizar la tableta o volverla inestable al hacer que emplee demasiada memoria."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite que una aplicación envíe emisiones persistentes que permanecen en el tablet una vez que la emisión finaliza. Las aplicaciones malintencionadas pueden ralentizar el tablet o volverlo inestable al hacer que emplee demasiada memoria."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Permite que una aplicación envíe emisiones persistentes, que permanecen en el teléfono una vez que la emisión finaliza. Las aplicaciones malintencionadas pueden ralentizar el teléfono o volverlo inestable al hacer que emplee demasiada memoria."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"leer los datos de contacto"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite que una aplicación lea todos los datos de contacto (direcciones) almacenados en la tableta. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus datos a otras personas."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite que una aplicación lea todos los datos de contacto (direcciones) almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus datos a otras personas."</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Permite que una aplicación lea todos los datos de contacto (direcciones) almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus datos a otras personas."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en la tableta. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos de contacto."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos de contacto."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar tus datos de contacto."</string>
<string name="permlab_readCalendar" msgid="6898987798303840534">"leer eventos de calendario"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en la tableta. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite que una aplicación lea todos los eventos de calendario almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"añadir o modificar eventos de calendario y enviar mensajes de correo electrónico a los invitados"</string>
<string name="permdesc_writeCalendar" msgid="2988871373544154221">"Permite que una aplicación añada o modifique los eventos de tu calendario, que puede enviar mensajes de correo electrónico a los invitados. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar tus eventos de calendario o para enviar mensajes a los invitados."</string>
@@ -320,10 +320,10 @@
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permiso para instalar un proveedor de ubicación"</string>
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Crear fuentes de origen simuladas para realizar pruebas. Las aplicaciones malintencionadas pueden utilizar este permiso para sobrescribir la ubicación o el estado devueltos por orígenes de ubicación reales, tales como los proveedores de red o GPS, o para controlar y notificar tu ubicación a una fuente externa."</string>
<string name="permlab_accessFineLocation" msgid="8116127007541369477">"precisar la ubicación (GPS)"</string>
- <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Permite acceder a fuentes de ubicación precisas como, por ejemplo, el sistema de posicionamiento global, en la tableta, si hay alguna disponible. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar la ubicación del usuario y pueden consumir batería adicional."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Permite acceder a fuentes de ubicación precisas como, por ejemplo, el sistema de posicionamiento global, en el tablet, si hay alguna disponible. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar la ubicación del usuario y pueden consumir batería adicional."</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Permite precisar las fuentes de ubicación como, por ejemplo, el sistema de posicionamiento global, en el teléfono, en los casos en que estén disponibles. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar dónde se encuentra el usuario y pueden consumir batería adicional."</string>
<string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"ubicación común (basada en red)"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Permite acceder a fuentes de ubicación comunes como, por ejemplo, la base de datos de la red de telefonía móvil, para determinar la ubicación aproximada de una tableta, si hay alguna disponible. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar tu ubicación aproximada."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Permite acceder a fuentes de ubicación comunes como, por ejemplo, la base de datos de la red de telefonía móvil, para determinar la ubicación aproximada de un tablet, si hay alguna disponible. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar tu ubicación aproximada."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Acceder a fuentes de ubicación comunes como, por ejemplo, la base de datos de red de un teléfono móvil, para determinar una ubicación telefónica aproximada, en los casos en que esté disponible. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar dónde te encuentras aproximadamente."</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"acceder a SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Permite que la aplicación utilice funciones de SurfaceFlinger de nivel inferior."</string>
@@ -335,13 +335,13 @@
<string name="permdesc_recordAudio" msgid="6493228261176552356">"Permite que la aplicación acceda a la ruta de grabación de audio."</string>
<string name="permlab_camera" msgid="3616391919559751192">"realizar fotografías y vídeos"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"Permite que la aplicación realice fotografías y vídeos con la cámara. De este modo, puede recopilar en cualquier momento las imágenes que ve la cámara."</string>
- <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"inhabilitar tableta de forma permanente"</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"inhabilitar tablet de forma permanente"</string>
<string name="permlab_brick" product="default" msgid="8337817093326370537">"inhabilitar el teléfono de forma permanente"</string>
- <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite que la aplicación inhabilite todas las funciones de la tableta de forma permanente. Este permiso es muy peligroso."</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite que la aplicación inhabilite todas las funciones del tablet de forma permanente. Este permiso es muy peligroso."</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"Permite que la aplicación inhabilite todas las funciones del teléfono de forma permanente. Este permiso es muy peligroso."</string>
- <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forzar reinicio de la tableta"</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forzar reinicio del tablet"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"forzar reinicio del teléfono"</string>
- <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite que la aplicación fuerce a la tableta a reiniciarse."</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite que la aplicación fuerce al tablet a reiniciarse."</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permite que la aplicación fuerce al teléfono a reiniciarse."</string>
<string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"activar y desactivar sistemas de archivos"</string>
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permite que las aplicaciones activen y desactiven sistemas de archivos para un almacenamiento extraíble."</string>
@@ -371,7 +371,7 @@
<string name="permdesc_callPhone" msgid="3369867353692722456">"Permite que la aplicación llame a números de teléfono sin la intervención del usuario. Las aplicaciones malintencionadas pueden originar llamadas inesperadas en la factura telefónica. Ten en cuenta que con este permiso la aplicación no puede realizar llamadas a números de emergencia."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"llamar directamente a cualquier número de teléfono"</string>
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Permite que la aplicación llame a cualquier número de teléfono, incluidos los números de emergencia, sin que el usuario intervenga. Las aplicaciones malintencionadas pueden realizar llamadas innecesarias e ilícitas a los servicios de emergencias."</string>
- <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente el método de acceso CDMA de la tableta"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directamente el método de acceso CDMA del tablet"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente el método de acceso CDMA del teléfono"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Permite que la aplicación inicie el método de acceso CDMA. Las aplicaciones malintencionadas pueden iniciar el método CDMA de forma innecesaria."</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar las notificaciones de actualización de la ubicación"</string>
@@ -384,16 +384,16 @@
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, activar y desactivar la señal móvil, etc., sin necesidad de notificar al usuario."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"leer la identidad y el estado del teléfono"</string>
<string name="permdesc_readPhoneState" msgid="188877305147626781">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. Una aplicación con este permiso puede determinar el número de teléfono y el número de serie de este teléfono, si una llamada está activa, el número al que está vinculada esa llamada, etc."</string>
- <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que la tableta entre en modo de suspensión"</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que el tablet entre en modo de suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el teléfono entre en modo de suspensión"</string>
- <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permite que una aplicación impida que la tableta entre en modo de suspensión."</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permite que una aplicación impida que el tablet entre en modo de suspensión."</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Permite que una aplicación impida que el teléfono entre en modo de suspensión."</string>
- <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"encender o apagar la tableta"</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"encender o apagar el tablet"</string>
<string name="permlab_devicePower" product="default" msgid="4928622470980943206">"encender o apagar el teléfono"</string>
- <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permite que la aplicación active o desactive la tableta."</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permite que la aplicación active o desactive el tablet."</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Permite que la aplicación active o desactive el teléfono."</string>
<string name="permlab_factoryTest" msgid="3715225492696416187">"ejecutar en modo de prueba de fábrica"</string>
- <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Permite la ejecución como prueba de fabricante de nivel inferior, lo que posibilita un acceso completo al hardware de la tableta. Sólo está disponible cuando una tableta se está ejecutando en modo de prueba."</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Permite la ejecución como prueba de fabricante de nivel inferior, lo que posibilita un acceso completo al hardware del tablet. Solo está disponible cuando un tablet se está ejecutando en modo de prueba."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Ejecutar como prueba de fabricante de nivel inferior, permitiendo un acceso íntegro al hardware del teléfono. Sólo está disponible cuando un teléfono se está ejecutando en modo de prueba."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"establecer fondo de pantalla"</string>
<string name="permdesc_setWallpaper" msgid="6417041752170585837">"Permite que la aplicación establezca el fondo de pantalla del sistema."</string>
@@ -402,15 +402,15 @@
<string name="permlab_masterClear" msgid="2315750423139697397">"restablecer el sistema a los valores predeterminados de fábrica"</string>
<string name="permdesc_masterClear" msgid="5033465107545174514">"Permite que una aplicación restablezca por completo el sistema a su configuración de fábrica, borrando todos los datos, la configuración y las aplicaciones instaladas."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"establecer hora"</string>
- <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Permite que una aplicación cambie la hora del reloj de la tableta."</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Permite que una aplicación cambie la hora del reloj del tablet."</string>
<string name="permdesc_setTime" product="default" msgid="667294309287080045">"Permite que una aplicación cambie la hora del reloj del teléfono."</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"establecer zona horaria"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permite que una aplicación cambie la zona horaria de la tableta."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permite que una aplicación cambie la zona horaria del tablet."</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Permite que una aplicación cambie la zona horaria del teléfono."</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"actuar como servicio de administrador de cuentas"</string>
<string name="permdesc_accountManagerService" msgid="6056903274106394752">"Permite que una aplicación realice llamadas a los autenticadores de cuentas."</string>
<string name="permlab_getAccounts" msgid="4549918644233460103">"ver cuentas reconocidas"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permite que una aplicación obtenga una lista de cuentas reconocidas por la tableta."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permite que una aplicación obtenga una lista de cuentas reconocidas por el tablet."</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Permite que una aplicación obtenga una lista de cuentas reconocidas por el teléfono."</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"actuar como autenticador de cuentas"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Permite que una aplicación utilice las funciones de autenticador de cuentas del administrador de cuentas, incluida la creación de cuentas y la obtención y el establecimiento de sus contraseñas."</string>
@@ -437,10 +437,10 @@
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitir recepción multidifusión Wi-Fi"</string>
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite que una aplicación reciba paquetes no dirigidos directamente a tu dispositivo. Esta función puede resultar útil para descubrir servicios cercanos. Utiliza más energía que el modo de no multidifusión."</string>
<string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"administración de Bluetooth"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permite que una aplicación configure la tableta Bluetooth local, vea dispositivos remotos y sincronice el teléfono con ellos."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permite que una aplicación configure el tablet Bluetooth local, vea dispositivos remotos y sincronice el tablet con ellos."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Permite que una aplicación configure el teléfono Bluetooth local, y vea dispositivos remotos y sincronice el teléfono con ellos."</string>
<string name="permlab_bluetooth" msgid="8361038707857018732">"crear conexiones de Bluetooth"</string>
- <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permite que una aplicación vea la configuración de la tableta Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permite que una aplicación vea la configuración del tablet Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permite que una aplicación vea la configuración del teléfono Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicación de campo cercano (NFC)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
@@ -473,14 +473,14 @@
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Control de la longitud y de los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla, bloquea la tableta o borra todos los datos de la tableta si se introducen demasiadas contraseñas incorrectas."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla, bloquea el tablet o borra todos los datos del tablet si se introducen demasiadas contraseñas incorrectas."</string>
<string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Control del número de contraseñas incorrectas introducidas al desbloquear la pantalla, así como bloqueo del teléfono o borrado de todos los datos si se introducen demasiadas contraseñas incorrectas"</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"Modificación de contraseña de bloqueo de pantalla"</string>
<string name="policydesc_resetPassword" msgid="5391240616981297361">"Modificación de contraseña de bloqueo de pantalla"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueo de pantalla"</string>
<string name="policydesc_forceLock" msgid="5696964126226028442">"Control de la forma en que se bloquea la pantalla y del momento en que se bloquea"</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Borrar todos los datos"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Borrado de los datos de la tableta sin avisar restableciendo datos de fábrica"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Borrado de los datos del tablet sin avisar restableciendo datos de fábrica"</string>
<string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Borrado de los datos del teléfono sin avisar restableciendo datos de fábrica"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Definir el servidor proxy global"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Define el servidor proxy global que se debe utilizar mientras la política esté habilitada. Solo el primer administrador de dispositivos define el servidor proxy global efectivo."</string>
@@ -623,7 +623,7 @@
<string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string>
<string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Falta la tarjeta SIM"</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en la tableta."</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Solo llamadas de emergencia"</string>
@@ -635,7 +635,7 @@
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Has introducido una contraseña incorrecta <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Has introducido un PIN incorrecto <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación del patrón de desbloqueo. Si realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos fallidos más, se te pedirá que desbloquees la tableta con tus credenciales de acceso de Google."\n\n" Espera <xliff:g id="NUMBER_2">%d</xliff:g> segundos e inténtalo de nuevo."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación del patrón de desbloqueo. Si realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos fallidos más, se te pedirá que desbloquees el tablet con tus credenciales de acceso de Google."\n\n" Espera <xliff:g id="NUMBER_2">%d</xliff:g> segundos e inténtalo de nuevo."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación del patrón de desbloqueo. Si realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos fallidos más, se te pedirá que desbloquees el teléfono con tus credenciales de acceso de Google."\n\n" Espera <xliff:g id="NUMBER_2">%d</xliff:g> segundos e inténtalo de nuevo."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Espera <xliff:g id="NUMBER">%d</xliff:g> segundos y vuelve a intentarlo."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"¿Has olvidado el patrón?"</string>
@@ -674,7 +674,7 @@
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer información de marcadores y del historial del navegador"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir en marcadores y en el historial del navegador"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en la tableta. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"establecer alarma en un reloj"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite a la aplicación establecer una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
@@ -800,7 +800,7 @@
<string name="inputMethod" msgid="1653630062304567879">"Método de introducción de texto"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
<string name="low_internal_storage_view_title" msgid="1399732408701697546">"Poco espacio"</string>
- <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Se está agotando el espacio de almacenamiento de la tableta."</string>
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Se está agotando el espacio de almacenamiento del tablet."</string>
<string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Se está agotando el espacio de almacenamiento del teléfono."</string>
<string name="ok" msgid="5970060430562524910">"Aceptar"</string>
<string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5d897e3..eb14169 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -130,7 +130,7 @@
<string name="me" msgid="6545696007631404292">"Saya"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsi tablet"</string>
<string name="power_dialog" product="default" msgid="1319919075463988638">"Opsi telepon"</string>
- <string name="silent_mode" msgid="7167703389802618663">"Mode senyap"</string>
+ <string name="silent_mode" msgid="7167703389802618663">"Modus senyap"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Hidupkan nirkabel"</string>
<string name="turn_off_radio" msgid="8198784949987062346">"Matikan nirkabel"</string>
<string name="screen_lock" msgid="799094655496098153">"Kunci layar"</string>
@@ -683,7 +683,7 @@
<string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Tidak sekarang"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
- <string name="save_password_never" msgid="8274330296785855105">"Tidak pernah"</string>
+ <string name="save_password_never" msgid="8274330296785855105">"Jangan"</string>
<string name="open_permission_deny" msgid="5661861460947222274">"Anda tidak memiliki izin untuk membuka laman ini."</string>
<string name="text_copied" msgid="4985729524670131385">"Teks disalin ke clipboard."</string>
<string name="more_item_label" msgid="4650918923083320495">"Lainnya"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index e9acf14..7aa7b30 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -489,7 +489,7 @@
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"הגדר הצפנת אחסון"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"דורש שנתוני היישום המאוחסנים יהיו מוצפנים"</string>
<string-array name="phoneTypes">
- <item msgid="8901098336658710359">"דף הבית"</item>
+ <item msgid="8901098336658710359">"בית"</item>
<item msgid="869923650527136615">"נייד"</item>
<item msgid="7897544654242874543">"עבודה"</item>
<item msgid="1103601433382158155">"פקס בעבודה"</item>
@@ -499,19 +499,19 @@
<item msgid="9192514806975898961">"מותאם אישית"</item>
</string-array>
<string-array name="emailAddressTypes">
- <item msgid="8073994352956129127">"דף הבית"</item>
+ <item msgid="8073994352956129127">"בית"</item>
<item msgid="7084237356602625604">"עבודה"</item>
<item msgid="1112044410659011023">"אחר"</item>
<item msgid="2374913952870110618">"מותאם אישית"</item>
</string-array>
<string-array name="postalAddressTypes">
- <item msgid="6880257626740047286">"דף הבית"</item>
+ <item msgid="6880257626740047286">"בית"</item>
<item msgid="5629153956045109251">"עבודה"</item>
<item msgid="4966604264500343469">"אחר"</item>
<item msgid="4932682847595299369">"מותאם אישית"</item>
</string-array>
<string-array name="imAddressTypes">
- <item msgid="1738585194601476694">"דף הבית"</item>
+ <item msgid="1738585194601476694">"בית"</item>
<item msgid="1359644565647383708">"עבודה"</item>
<item msgid="7868549401053615677">"אחר"</item>
<item msgid="3145118944639869809">"מותאם אישית"</item>
@@ -532,7 +532,7 @@
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
<string name="phoneTypeCustom" msgid="1644738059053355820">"מותאם אישית"</string>
- <string name="phoneTypeHome" msgid="2570923463033985887">"דף הבית"</string>
+ <string name="phoneTypeHome" msgid="2570923463033985887">"בית"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"נייד"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"עבודה"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"פקס בעבודה"</string>
@@ -557,16 +557,16 @@
<string name="eventTypeAnniversary" msgid="3876779744518284000">"יום השנה"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"אחר"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"מותאם אישית"</string>
- <string name="emailTypeHome" msgid="449227236140433919">"דף הבית"</string>
+ <string name="emailTypeHome" msgid="449227236140433919">"בית"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"עבודה"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"אחר"</string>
<string name="emailTypeMobile" msgid="119919005321166205">"סלולרי"</string>
<string name="postalTypeCustom" msgid="8903206903060479902">"מותאם אישית"</string>
- <string name="postalTypeHome" msgid="8165756977184483097">"דף הבית"</string>
+ <string name="postalTypeHome" msgid="8165756977184483097">"בית"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"עבודה"</string>
<string name="postalTypeOther" msgid="2726111966623584341">"אחר"</string>
<string name="imTypeCustom" msgid="2074028755527826046">"מותאם אישית"</string>
- <string name="imTypeHome" msgid="6241181032954263892">"דף הבית"</string>
+ <string name="imTypeHome" msgid="6241181032954263892">"בית"</string>
<string name="imTypeWork" msgid="1371489290242433090">"עבודה"</string>
<string name="imTypeOther" msgid="5377007495735915478">"אחר"</string>
<string name="imProtocolCustom" msgid="6919453836618749992">"מותאם אישית"</string>
@@ -598,7 +598,7 @@
<string name="relationTypeSister" msgid="1735983554479076481">"אחות"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"בן/בת זוג"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"מותאם אישית"</string>
- <string name="sipAddressTypeHome" msgid="6093598181069359295">"דף הבית"</string>
+ <string name="sipAddressTypeHome" msgid="6093598181069359295">"בית"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"עבודה"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"אחר"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"הזן קוד PIN"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index aa43fe9..1c234c2 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -823,7 +823,7 @@
<string name="anr_activity_process" msgid="5420826626009561014">"Aktiviteten <xliff:g id="ACTIVITY">%1$s</xliff:g> (i processen <xliff:g id="PROCESS">%2$s</xliff:g>) svarar inte."</string>
<string name="anr_application_process" msgid="4185842666452210193">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (i processen <xliff:g id="PROCESS">%2$s</xliff:g>) svarar inte."</string>
<string name="anr_process" msgid="1246866008169975783">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarar inte."</string>
- <string name="force_close" msgid="3653416315450806396">"Tvinga fram en stängning"</string>
+ <string name="force_close" msgid="3653416315450806396">"Tvinga stängning"</string>
<string name="report" msgid="4060218260984795706">"Rapportera"</string>
<string name="wait" msgid="7147118217226317732">"Vänta"</string>
<string name="launch_warning_title" msgid="8323761616052121936">"Programmet omdirigerades"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cb44a3a..c815758 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -296,9 +296,6 @@
<!-- Indicate whether the SD card is accessible without removing the battery. -->
<bool name="config_batterySdCardAccessibility">false</bool>
- <!-- Indicate whether the device has USB host support. -->
- <bool name="config_hasUsbHostSupport">false</bool>
-
<!-- List of file paths for USB host busses to exclude from USB host support.
For example, if the first USB bus on the device is used to communicate
with the modem or some other restricted hardware, add "/dev/bus/usb/001/"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 28690f5..8ef9a3b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1031,9 +1031,9 @@
the flashlight.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_accessUsb">access USB devices</string>
+ <string name="permlab_manageUsb">manage preferences and permissions for USB devices</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessUsb">Allows the application to access USB devices.</string>
+ <string name="permdesc_manageUsb">Allows the application to manage preferences and permissions for USB devices.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessMtp">implement MTP protocol</string>
@@ -2302,6 +2302,8 @@
<string name="clearDefaultHintMsg">Clear default in Home Settings &gt; Applications &gt; Manage applications.</string>
<!-- Default title for the activity chooser, when one is not given. Android allows multiple activities to perform an action. for example, there may be many ringtone pickers installed. A dialog is shown to the user allowing him to pick which activity should be used. This is the title. -->
<string name="chooseActivity">Select an action</string>
+ <!-- title for the USB activity chooser. -->
+ <string name="chooseUsbActivity">Select an application for the USB device</string>
<!-- Text to display when there are no activities found to display in the
activity chooser. See the "Select an action" title. -->
<string name="noApplications">No applications can perform this action.</string>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 7756135..e138200 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -21,30 +21,34 @@ import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IPowerManager;
+import android.os.Message;
import android.os.PowerManager;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
+import android.widget.LinearLayout;
+
+import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
-import android.widget.LinearLayout;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.State;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
/**
* An activity registered with connectivity manager broadcast
@@ -180,6 +184,24 @@ public class ConnectivityManagerTestActivity extends Activity {
}
}
+ private class WifiServiceHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ //AsyncChannel in msg.obj
+ } else {
+ log("Failed to establish AsyncChannel connection");
+ }
+ break;
+ default:
+ //Ignore
+ break;
+ }
+ }
+ }
+
public ConnectivityManagerTestActivity() {
mState = State.UNKNOWN;
scanResultAvailable = false;
@@ -216,6 +238,8 @@ public class ConnectivityManagerTestActivity extends Activity {
mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
// Get an instance of WifiManager
mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
+ mWifiManager.asyncConnect(this, new WifiServiceHandler());
+
initializeNetworkStates();
if (mWifiManager.isWifiEnabled()) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 9c72102..fe79e6c 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -34,12 +34,15 @@ import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
+import android.os.Handler;
+import android.os.Message;
import android.provider.Settings;
-
import android.test.suitebuilder.annotation.LargeTest;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
+import com.android.internal.util.AsyncChannel;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -75,6 +78,7 @@ public class WifiConnectionTest
enabledNetworks = getEnabledNetworks(mWifiManager.getConfiguredNetworks());
mAct = getActivity();
+ mWifiManager.asyncConnect(mAct, new WifiServiceHandler());
networks = mAct.loadNetworkConfigurations();
if (DEBUG) {
printNetworkConfigurations();
@@ -89,6 +93,24 @@ public class WifiConnectionTest
assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
}
+ private class WifiServiceHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ //AsyncChannel in msg.obj
+ } else {
+ log("Failed to establish AsyncChannel connection");
+ }
+ break;
+ default:
+ //Ignore
+ break;
+ }
+ }
+ }
+
private void printNetworkConfigurations() {
log("==== print network configurations parsed from XML file ====");
log("number of access points: " + networks.size());
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 01734f2..4be6995 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -44,6 +44,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
diff --git a/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
index 887b032..6efc61a 100644
--- a/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
+++ b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
@@ -96,7 +96,7 @@ public class AccountManagerServiceTest extends AndroidTestCase {
assertEquals(a21, accounts[1]);
assertEquals(a31, accounts[2]);
- mAms.removeAccount(a21);
+ mAms.removeAccountInternal(a21);
accounts = mAms.getAccounts("type1" );
Arrays.sort(accounts, new AccountSorter());
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index 672f252..5dedd4a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -316,4 +316,34 @@ public class BluetoothStressTest extends InstrumentationTestCase {
mTestUtils.disablePan(adapter);
mTestUtils.disable(adapter);
}
+
+ /**
+ * Stress test for verifying that AudioManager can open and close SCO connections.
+ * <p>
+ * In this test, a HSP connection is opened with an external headset and the SCO connection is
+ * repeatibly opened and closed.
+ */
+ public void testStartStopSco() {
+ int iterations = BluetoothTestRunner.sStartStopScoIterations;
+ if (iterations == 0) {
+ return;
+ }
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sHeadsetAddress);
+ mTestUtils.enable(adapter);
+ mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+ BluetoothTestRunner.sPairPin);
+ mTestUtils.connectProfile(adapter, device, BluetoothProfile.HEADSET);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("startStopSco iteration " + (i + 1) + " of " + iterations);
+ mTestUtils.startSco(adapter, device);
+ mTestUtils.stopSco(adapter, device);
+ }
+
+ mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.HEADSET);
+ mTestUtils.unpair(adapter, device);
+ mTestUtils.disable(adapter);
+ }
}
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
index cede05a..1febc5c 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
@@ -39,6 +39,7 @@ import android.util.Log;
* [-e connect_headset_iterations <iterations>] \
* [-e connect_input_iterations <iterations>] \
* [-e connect_pan_iterations <iterations>] \
+ * [-e start_stop_sco_iterations <iterations>] \
* [-e pair_address <address>] \
* [-e headset_address <address>] \
* [-e a2dp_address <address>] \
@@ -62,6 +63,7 @@ public class BluetoothTestRunner extends InstrumentationTestRunner {
public static int sConnectA2dpIterations = 100;
public static int sConnectInputIterations = 100;
public static int sConnectPanIterations = 100;
+ public static int sStartStopScoIterations = 100;
public static String sPairAddress = "";
public static String sHeadsetAddress = "";
@@ -167,6 +169,14 @@ public class BluetoothTestRunner extends InstrumentationTestRunner {
}
}
+ val = arguments.getString("start_stop_sco_iterations");
+ if (val != null) {
+ try {
+ sStartStopScoIterations = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ // Invalid argument, fall back to default value
+ }
+ }
val = arguments.getString("pair_address");
if (val != null) {
sPairAddress = val;
@@ -214,6 +224,7 @@ public class BluetoothTestRunner extends InstrumentationTestRunner {
Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
Log.i(TAG, String.format("connect_input_iterations=%d", sConnectInputIterations));
Log.i(TAG, String.format("connect_pan_iterations=%d", sConnectPanIterations));
+ Log.i(TAG, String.format("start_stop_sco_iterations=%d", sStartStopScoIterations));
Log.i(TAG, String.format("pair_address=%s", sPairAddress));
Log.i(TAG, String.format("a2dp_address=%s", sA2dpAddress));
Log.i(TAG, String.format("headset_address=%s", sHeadsetAddress));
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 85c5eaa..1741119 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.media.AudioManager;
import android.os.Environment;
import android.util.Log;
@@ -67,6 +68,11 @@ public class BluetoothTestUtils extends Assert {
private static final int CONNECT_PROXY_TIMEOUT = 5000;
/**
+ * Timeout to start or stop a SCO channel in ms.
+ */
+ private static final int START_STOP_SCO_TIMEOUT = 10000;
+
+ /**
* Time between polls in ms.
*/
private static final int POLL_TIME = 100;
@@ -319,6 +325,32 @@ public class BluetoothTestUtils extends Assert {
}
}
+ private class StartStopScoReceiver extends FlagReceiver {
+ private static final int STATE_CONNECTED_FLAG = 1;
+ private static final int STATE_DISCONNECTED_FLAG = 1 << 1;
+
+ public StartStopScoReceiver(int expectedFlags) {
+ super(expectedFlags);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED.equals(intent.getAction())) {
+ int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
+ AudioManager.SCO_AUDIO_STATE_ERROR);
+ assertNotSame(AudioManager.SCO_AUDIO_STATE_ERROR, state);
+ switch(state) {
+ case AudioManager.SCO_AUDIO_STATE_CONNECTED:
+ setFiredFlag(STATE_CONNECTED_FLAG);
+ break;
+ case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
+ setFiredFlag(STATE_DISCONNECTED_FLAG);
+ break;
+ }
+ }
+ }
+ }
+
private BluetoothProfile.ServiceListener mServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -1269,6 +1301,103 @@ public class BluetoothTestUtils extends Assert {
}
/**
+ * Opens a SCO channel using {@link android.media.AudioManager#startBluetoothSco()} and checks
+ * to make sure that the channel is opened and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void startSco(BluetoothAdapter adapter, BluetoothDevice device) {
+ startStopSco(adapter, device, true);
+ }
+
+ /**
+ * Closes a SCO channel using {@link android.media.AudioManager#stopBluetoothSco()} and checks
+ * to make sure that the channel is closed and that the correct actions were broadcast.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ */
+ public void stopSco(BluetoothAdapter adapter, BluetoothDevice device) {
+ startStopSco(adapter, device, false);
+ }
+ /**
+ * Helper method for {@link #startSco(BluetoothAdapter, BluetoothDevice)} and
+ * {@link #stopSco(BluetoothAdapter, BluetoothDevice)}.
+ *
+ * @param adapter The BT adapter.
+ * @param device The remote device.
+ * @param isStart Whether the SCO channel should be opened.
+ */
+ private void startStopSco(BluetoothAdapter adapter, BluetoothDevice device, boolean isStart) {
+ long start = -1;
+ int mask;
+ String methodName;
+
+ if (isStart) {
+ methodName = "startSco()";
+ mask = StartStopScoReceiver.STATE_CONNECTED_FLAG;
+ } else {
+ methodName = "stopSco()";
+ mask = StartStopScoReceiver.STATE_DISCONNECTED_FLAG;
+ }
+
+ if (!adapter.isEnabled()) {
+ fail(String.format("%s bluetooth not enabled: device=%s, start=%b", methodName, device,
+ isStart));
+ }
+
+ if (!adapter.getBondedDevices().contains(device)) {
+ fail(String.format("%s device not paired: device=%s, start=%b", methodName, device,
+ isStart));
+ }
+
+ AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ assertNotNull(manager);
+
+ if (!manager.isBluetoothScoAvailableOffCall()) {
+ fail(String.format("%s device does not support SCO: device=%s, start=%b", methodName,
+ device, isStart));
+ }
+
+ boolean isScoOn = manager.isBluetoothScoOn();
+ if (isStart == isScoOn) {
+ return;
+ }
+
+ StartStopScoReceiver receiver = getStartStopScoReceiver(mask);
+ start = System.currentTimeMillis();
+ if (isStart) {
+ manager.startBluetoothSco();
+ } else {
+ manager.stopBluetoothSco();
+ }
+
+ long s = System.currentTimeMillis();
+ while (System.currentTimeMillis() - s < START_STOP_SCO_TIMEOUT) {
+ isScoOn = manager.isBluetoothScoOn();
+ if ((isStart == isScoOn) &&
+ (receiver.getFiredFlags() & mask) == mask) {
+ long finish = receiver.getCompletedTime();
+ if (start != -1 && finish != -1) {
+ writeOutput(String.format("%s completed in %d ms", methodName,
+ (finish - start)));
+ } else {
+ writeOutput(String.format("%s completed", methodName));
+ }
+ removeReceiver(receiver);
+ return;
+ }
+ sleep(POLL_TIME);
+ }
+
+ int firedFlags = receiver.getFiredFlags();
+ removeReceiver(receiver);
+ fail(String.format("%s timeout: start=%b (expected %b), flags=0x%x (expected 0x%x)",
+ methodName, isScoOn, isStart, firedFlags, mask));
+ }
+
+ /**
* Writes a string to the logcat and a file if a file has been specified in the constructor.
*
* @param s The string to be written.
@@ -1336,6 +1465,13 @@ public class BluetoothTestUtils extends Assert {
return receiver;
}
+ private StartStopScoReceiver getStartStopScoReceiver(int expectedFlags) {
+ String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED};
+ StartStopScoReceiver receiver = new StartStopScoReceiver(expectedFlags);
+ addReceiver(receiver, actions);
+ return receiver;
+ }
+
private void removeReceiver(BroadcastReceiver receiver) {
mContext.unregisterReceiver(receiver);
mReceivers.remove(receiver);