Introduced AccountDb API replacing helpers
Refactored AccountsDb to provide unified interface for interacting with
CE/DE database.
Benefits of the new API:
- Better encapsulation - only relevant methods are exposed.
Implementation details are hidden in private helper classes.
- Clients can now treat CE tables as if they were in DE database, but
only available when the user is unlocked.
- Opening database is now implicit - no more getReadableDatabase
/getWritableDatabase calls. Clients only need to define transaction
boundaries, when necessary.
Test: Refactoring
Bug: 30639520
Change-Id: I08b1fc95b7a633b036e05e8ef7e8ebd239187aa1
diff --git a/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java b/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java
index 63afccc..c3b7e15 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java
@@ -142,9 +142,8 @@
final AccountManagerService.UserAccounts accounts = mAccountManagerService
.getUserAccounts(userId);
synchronized (accounts.cacheLock) {
- SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
- List<Pair<String, Integer>> allAccountGrants = DeDatabaseHelper.findAllAccountGrants(
- db);
+ List<Pair<String, Integer>> allAccountGrants = accounts.accountsDb
+ .findAllAccountGrants();
if (allAccountGrants.isEmpty()) {
return null;
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 575018d..7802576 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -98,9 +98,6 @@
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
-import com.android.server.accounts.AccountsDb.CeDatabaseHelper;
-import com.android.server.accounts.AccountsDb.DeDatabaseHelper;
-import com.android.server.accounts.AccountsDb.DebugDbHelper;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -161,8 +158,6 @@
}
}
- private static final int MAX_DEBUG_DB_SIZE = 64;
-
final Context mContext;
private final PackageManager mPackageManager;
@@ -193,7 +188,7 @@
static class UserAccounts {
private final int userId;
- final DeDatabaseHelper openHelper;
+ final AccountsDb accountsDb;
private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
credentialsPermissionNotificationIds =
new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
@@ -242,12 +237,12 @@
new HashMap<Account, AtomicReference<String>>();
private int debugDbInsertionPoint = -1;
- private SQLiteStatement statementForLogging;
+ private SQLiteStatement statementForLogging; // TODO Move to AccountsDb
UserAccounts(Context context, int userId, File preNDbFile, File deDbFile) {
this.userId = userId;
synchronized (cacheLock) {
- openHelper = DeDatabaseHelper.create(context, userId, preNDbFile, deDbFile);
+ accountsDb = AccountsDb.create(context, userId, preNDbFile, deDbFile);
}
}
}
@@ -993,7 +988,7 @@
UserAccounts accounts, boolean invalidateAuthenticatorCache) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "validateAccountsInternal " + accounts.userId
- + " isCeDatabaseAttached=" + accounts.openHelper.isCeDatabaseAttached()
+ + " isCeDatabaseAttached=" + accounts.accountsDb.isCeDatabaseAttached()
+ " userLocked=" + mLocalUnlockedUsers.get(accounts.userId));
}
@@ -1006,11 +1001,11 @@
boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
boolean accountDeleted = false;
// Get a map of stored authenticator types to UID
- Map<String, Integer> metaAuthUid = DeDatabaseHelper.findMetaAuthUid(db);
+ final AccountsDb accountsDb = accounts.accountsDb;
+ Map<String, Integer> metaAuthUid = accountsDb.findMetaAuthUid();
// Create a list of authenticator type whose previous uid no longer exists
HashSet<String> obsoleteAuthType = Sets.newHashSet();
SparseBooleanArray knownUids = null;
@@ -1047,7 +1042,7 @@
// So purge its data from the account databases.
obsoleteAuthType.add(type);
// And delete it from the TABLE_META
- DeDatabaseHelper.deleteMetaByAuthTypeAndUid(db, type, uid);
+ accountsDb.deleteMetaByAuthTypeAndUid(type, uid);
}
}
}
@@ -1056,11 +1051,10 @@
// been re-enabled (after being updated for example), then we just overwrite the old
// values.
for (Entry<String, Integer> entry : knownAuth.entrySet()) {
- DeDatabaseHelper.insertOrReplaceMetaAuthTypeAndUid(db, entry.getKey(),
- entry.getValue());
+ accountsDb.insertOrReplaceMetaAuthTypeAndUid(entry.getKey(), entry.getValue());
}
- final Map<Long, Account> accountsMap = DeDatabaseHelper.findAllAccounts(db);
+ final Map<Long, Account> accountsMap = accountsDb.findAllDeAccounts();
try {
accounts.accountCache.clear();
final HashMap<String, ArrayList<String>> accountNamesByType = new LinkedHashMap<>();
@@ -1070,17 +1064,17 @@
if (obsoleteAuthType.contains(account.type)) {
Slog.w(TAG, "deleting account " + account.name + " because type "
+ account.type + "'s registered authenticator no longer exist.");
- db.beginTransaction();
+ accountsDb.beginTransaction();
try {
- DeDatabaseHelper.deleteAccount(db, accountId);
+ accountsDb.deleteDeAccount(accountId);
// Also delete from CE table if user is unlocked; if user is currently
// locked the account will be removed later by syncDeCeAccountsLocked
if (userUnlocked) {
- AccountsDb.deleteCeAccount(db, accountId);
+ accountsDb.deleteCeAccount(accountId);
}
- db.setTransactionSuccessful();
+ accountsDb.setTransactionSuccessful();
} finally {
- db.endTransaction();
+ accountsDb.endTransaction();
}
accountDeleted = true;
@@ -1163,20 +1157,17 @@
File preNDbFile = new File(mInjector.getPreNDatabaseName(userId));
File deDbFile = new File(mInjector.getDeDatabaseName(userId));
accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile);
- initializeDebugDbSizeAndCompileSqlStatementForLogging(
- accounts.openHelper.getWritableDatabase(), accounts);
+ initializeDebugDbSizeAndCompileSqlStatementForLogging(accounts);
mUsers.append(userId, accounts);
purgeOldGrants(accounts);
validateAccounts = true;
}
// open CE database if necessary
- if (!accounts.openHelper.isCeDatabaseAttached() && mLocalUnlockedUsers.get(userId)) {
+ if (!accounts.accountsDb.isCeDatabaseAttached() && mLocalUnlockedUsers.get(userId)) {
Log.i(TAG, "User " + userId + " is unlocked - opening CE database");
synchronized (accounts.cacheLock) {
- File preNDatabaseFile = new File(mInjector.getPreNDatabaseName(userId));
File ceDatabaseFile = new File(mInjector.getCeDatabaseName(userId));
- CeDatabaseHelper.create(mContext, userId, preNDatabaseFile, ceDatabaseFile);
- accounts.openHelper.attachCeDatabase(ceDatabaseFile);
+ accounts.accountsDb.attachCeDatabase(ceDatabaseFile);
}
syncDeCeAccountsLocked(accounts);
}
@@ -1189,8 +1180,7 @@
private void syncDeCeAccountsLocked(UserAccounts accounts) {
Preconditions.checkState(Thread.holdsLock(mUsers), "mUsers lock must be held");
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
- List<Account> accountsToRemove = AccountsDb.findCeAccountsNotInDe(db);
+ List<Account> accountsToRemove = accounts.accountsDb.findCeAccountsNotInDe();
if (!accountsToRemove.isEmpty()) {
Slog.i(TAG, "Accounts " + accountsToRemove + " were previously deleted while user "
+ accounts.userId + " was locked. Removing accounts from CE tables");
@@ -1213,8 +1203,7 @@
private void purgeOldGrants(UserAccounts accounts) {
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- List<Integer> uids = DeDatabaseHelper.findAllUidGrants(db);
+ List<Integer> uids = accounts.accountsDb.findAllUidGrants();
for (int uid : uids) {
final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
if (packageExists) {
@@ -1222,7 +1211,7 @@
}
Log.d(TAG, "deleting grants for UID " + uid
+ " because its package is no longer installed");
- DeDatabaseHelper.deleteGrantsByUid(db, uid);
+ accounts.accountsDb.deleteGrantsByUid(uid);
}
}
}
@@ -1241,7 +1230,7 @@
}
if (accounts != null) {
synchronized (accounts.cacheLock) {
- accounts.openHelper.close();
+ accounts.accountsDb.close();
}
}
Log.i(TAG, "Removing database files for user " + userId);
@@ -1334,9 +1323,7 @@
}
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
- return CeDatabaseHelper.findAccountPasswordByNameAndType(db, account.name,
- account.type);
+ return accounts.accountsDb.findAccountPasswordByNameAndType(account.name, account.type);
}
}
@@ -1365,8 +1352,7 @@
synchronized (accounts.cacheLock) {
AtomicReference<String> previousNameRef = accounts.previousNameCache.get(account);
if (previousNameRef == null) {
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
- String previousName = DeDatabaseHelper.findAccountPreviousName(db, account);
+ String previousName = accounts.accountsDb.findDeAccountPreviousName(account);
previousNameRef = new AtomicReference<>(previousName);
accounts.previousNameCache.put(account, previousNameRef);
return previousName;
@@ -1602,8 +1588,7 @@
private boolean updateLastAuthenticatedTime(Account account) {
final UserAccounts accounts = getUserAccountsForCaller();
synchronized (accounts.cacheLock) {
- return DeDatabaseHelper.updateAccountLastAuthenticatedTime(
- accounts.openHelper.getWritableDatabase(), account);
+ return accounts.accountsDb.updateAccountLastAuthenticatedTime(account);
}
}
@@ -1672,22 +1657,21 @@
return false;
}
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- if (CeDatabaseHelper.findAccountId(db, account) >= 0) {
+ if (accounts.accountsDb.findCeAccountId(account) >= 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account
+ ", skipping since the account already exists");
return false;
}
- long accountId = CeDatabaseHelper.insertAccount(db, account, password);
+ long accountId = accounts.accountsDb.insertCeAccount(account, password);
if (accountId < 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account
+ ", skipping the DB insert failed");
return false;
}
// Insert into DE table
- if (DeDatabaseHelper.insertAccount(db, account, accountId) < 0) {
+ if (accounts.accountsDb.insertDeAccount(account, accountId) < 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account
+ ", skipping the DB insert failed");
return false;
@@ -1695,21 +1679,21 @@
if (extras != null) {
for (String key : extras.keySet()) {
final String value = extras.getString(key);
- if (CeDatabaseHelper.insertExtra(db, accountId, key, value) < 0) {
+ if (accounts.accountsDb.insertExtra(accountId, key, value) < 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account
+ ", skipping since insertExtra failed for key " + key);
return false;
}
}
}
- db.setTransactionSuccessful();
+ accounts.accountsDb.setTransactionSuccessful();
logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS,
accountId, accounts, callingUid);
insertAccountIntoCacheLocked(accounts, account);
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
}
if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) {
@@ -1892,17 +1876,16 @@
}
}
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
Account renamedAccount = new Account(newName, accountToRename.type);
try {
- final long accountId = DeDatabaseHelper.findAccountId(db, accountToRename);
+ final long accountId = accounts.accountsDb.findDeAccountId(accountToRename);
if (accountId >= 0) {
- CeDatabaseHelper.renameAccount(db, accountId, newName);
- DeDatabaseHelper.renameAccount(db, accountId, newName, accountToRename.name);
+ accounts.accountsDb.renameCeAccount(accountId, newName);
+ accounts.accountsDb.renameDeAccount(accountId, newName, accountToRename.name);
}
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
/*
* Database transaction was successful. Clean up cached
@@ -2025,8 +2008,7 @@
}
}
}
- SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
- final long accountId = DeDatabaseHelper.findAccountId(db, account);
+ final long accountId = accounts.accountsDb.findDeAccountId(account);
logRecord(
AccountsDb.DEBUG_ACTION_CALLED_ACCOUNT_REMOVE,
AccountsDb.TABLE_ACCOUNTS,
@@ -2065,8 +2047,7 @@
}
removeVisibleListFunctionality(account, getUserAccounts(UserHandle.getUserId(callingUid)));
UserAccounts accounts = getUserAccountsForCaller();
- SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
- final long accountId = DeDatabaseHelper.findAccountId(db, account);
+ final long accountId = accounts.accountsDb.findDeAccountId(account);
logRecord(
AccountsDb.DEBUG_ACTION_CALLED_ACCOUNT_REMOVE,
AccountsDb.TABLE_ACCOUNTS,
@@ -2143,26 +2124,23 @@
+ " is still locked. CE data will be removed later");
}
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = userUnlocked
- ? accounts.openHelper.getWritableDatabaseUserIsUnlocked()
- : accounts.openHelper.getWritableDatabase();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
// Set to a dummy value, this will only be used if the database
// transaction succeeds.
long accountId = -1;
try {
- accountId = DeDatabaseHelper.findAccountId(db, account);
+ accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId >= 0) {
- DeDatabaseHelper.deleteAccount(db, accountId);
+ accounts.accountsDb.deleteDeAccount(accountId);
if (userUnlocked) {
// Delete from CE table
- AccountsDb.deleteCeAccount(db, accountId);
+ accounts.accountsDb.deleteCeAccount(accountId);
}
- db.setTransactionSuccessful();
+ accounts.accountsDb.setTransactionSuccessful();
isChanged = true;
}
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
if (isChanged) {
removeAccountFromCacheLocked(accounts, account);
@@ -2221,14 +2199,13 @@
try {
UserAccounts accounts = getUserAccounts(userId);
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- invalidateAuthTokenLocked(accounts, db, accountType, authToken);
+ invalidateAuthTokenLocked(accounts, accountType, authToken);
invalidateCustomTokenLocked(accounts, accountType, authToken);
- db.setTransactionSuccessful();
+ accounts.accountsDb.setTransactionSuccessful();
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
}
} finally {
@@ -2247,21 +2224,20 @@
accounts.accountTokenCaches.remove(accountType, authToken);
}
- private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
- String accountType, String authToken) {
+ private void invalidateAuthTokenLocked(UserAccounts accounts, String accountType,
+ String authToken) {
if (authToken == null || accountType == null) {
return;
}
- Cursor cursor = CeDatabaseHelper.findAuthtokenForAllAccounts(db, accountType, authToken);
+ Cursor cursor = accounts.accountsDb.findAuthtokenForAllAccounts(accountType, authToken);
try {
while (cursor.moveToNext()) {
String authTokenId = cursor.getString(0);
String accountName = cursor.getString(1);
String authTokenType = cursor.getString(2);
- CeDatabaseHelper.deleteAuthToken(db, authTokenId);
+ accounts.accountsDb.deleteAuthToken(authTokenId);
writeAuthTokenIntoCacheLocked(
accounts,
- db,
new Account(accountName, accountType),
authTokenType,
null);
@@ -2299,22 +2275,21 @@
cancelNotification(getSigninRequiredNotificationId(accounts, account),
UserHandle.of(accounts.userId));
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- long accountId = DeDatabaseHelper.findAccountId(db, account);
+ long accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId < 0) {
return false;
}
- CeDatabaseHelper.deleteAuthtokensByAccountIdAndType(db, accountId, type);
- if (CeDatabaseHelper.insertAuthToken(db, accountId, type, authToken) >= 0) {
- db.setTransactionSuccessful();
- writeAuthTokenIntoCacheLocked(accounts, db, account, type, authToken);
+ accounts.accountsDb.deleteAuthtokensByAccountIdAndType(accountId, type);
+ if (accounts.accountsDb.insertAuthToken(accountId, type, authToken) >= 0) {
+ accounts.accountsDb.setTransactionSuccessful();
+ writeAuthTokenIntoCacheLocked(accounts, account, type, authToken);
return true;
}
return false;
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
}
}
@@ -2413,16 +2388,15 @@
}
boolean isChanged = false;
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- final long accountId = DeDatabaseHelper.findAccountId(db, account);
+ final long accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId >= 0) {
- CeDatabaseHelper.updateAccountPassword(db, accountId, password);
- CeDatabaseHelper.deleteAuthTokensByAccountId(db, accountId);
+ accounts.accountsDb.updateCeAccountPassword(accountId, password);
+ accounts.accountsDb.deleteAuthTokensByAccountId(accountId);
accounts.authTokenCache.remove(account);
accounts.accountTokenCaches.remove(account);
- db.setTransactionSuccessful();
+ accounts.accountsDb.setTransactionSuccessful();
// If there is an account whose password will be updated and the database
// transactions succeed, then we say that a change has occured. Even if the
// new password is the same as the old and there were no authtokens to delete.
@@ -2433,7 +2407,7 @@
logRecord(action, AccountsDb.TABLE_ACCOUNTS, accountId, accounts, callingUid);
}
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
if (isChanged) {
// Send LOGIN_ACCOUNTS_CHANGED only if the something changed.
sendAccountsChangedBroadcast(accounts.userId);
@@ -2523,26 +2497,25 @@
if (account == null || key == null) {
return;
}
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- long accountId = DeDatabaseHelper.findAccountId(db, account);
+ long accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId < 0) {
return;
}
- long extrasId = CeDatabaseHelper.findExtrasIdByAccountId(db, accountId, key);
+ long extrasId = accounts.accountsDb.findExtrasIdByAccountId(accountId, key);
if (extrasId < 0) {
- extrasId = CeDatabaseHelper.insertExtra(db, accountId, key, value);
+ extrasId = accounts.accountsDb.insertExtra(accountId, key, value);
if (extrasId < 0) {
return;
}
- } else if (!CeDatabaseHelper.updateExtra(db, extrasId, value)) {
+ } else if (!accounts.accountsDb.updateExtra(extrasId, value)) {
return;
}
- writeUserDataIntoCacheLocked(accounts, db, account, key, value);
- db.setTransactionSuccessful();
+ writeUserDataIntoCacheLocked(accounts, account, key, value);
+ accounts.accountsDb.setTransactionSuccessful();
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
}
@@ -4171,9 +4144,8 @@
private boolean addSharedAccountAsUser(Account account, int userId) {
userId = handleIncomingUser(userId);
UserAccounts accounts = getUserAccounts(userId);
- SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- DeDatabaseHelper.deleteSharedAccount(db, account);
- long accountId = DeDatabaseHelper.insertSharedAccount(db, account);
+ accounts.accountsDb.deleteSharedAccount(account);
+ long accountId = accounts.accountsDb.insertSharedAccount(account);
if (accountId < 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account
+ ", skipping the DB insert failed");
@@ -4188,9 +4160,8 @@
public boolean renameSharedAccountAsUser(Account account, String newName, int userId) {
userId = handleIncomingUser(userId);
UserAccounts accounts = getUserAccounts(userId);
- SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- long sharedTableAccountId = DeDatabaseHelper.findSharedAccountId(db, account);
- int r = DeDatabaseHelper.renameSharedAccount(db, account, newName);
+ long sharedTableAccountId = accounts.accountsDb.findSharedAccountId(account);
+ int r = accounts.accountsDb.renameSharedAccount(account, newName);
if (r > 0) {
int callingUid = getCallingUid();
logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_RENAME, AccountsDb.TABLE_SHARED_ACCOUNTS,
@@ -4209,9 +4180,8 @@
private boolean removeSharedAccountAsUser(Account account, int userId, int callingUid) {
userId = handleIncomingUser(userId);
UserAccounts accounts = getUserAccounts(userId);
- SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- long sharedTableAccountId = DeDatabaseHelper.findSharedAccountId(db, account);
- boolean deleted = DeDatabaseHelper.deleteSharedAccount(db, account);
+ long sharedTableAccountId = accounts.accountsDb.findSharedAccountId(account);
+ boolean deleted = accounts.accountsDb.deleteSharedAccount(account);
if (deleted) {
logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE, AccountsDb.TABLE_SHARED_ACCOUNTS,
sharedTableAccountId, accounts, callingUid);
@@ -4223,8 +4193,8 @@
@Override
public Account[] getSharedAccountsAsUser(int userId) {
userId = handleIncomingUser(userId);
- SQLiteDatabase db = getUserAccounts(userId).openHelper.getReadableDatabase();
- List<Account> accountList = DeDatabaseHelper.getSharedAccounts(db);
+ UserAccounts accounts = getUserAccounts(userId);
+ List<Account> accountList = accounts.accountsDb.getSharedAccounts();
Account[] accountArray = new Account[accountList.size()];
accountList.toArray(accountArray);
return accountArray;
@@ -4575,9 +4545,8 @@
if (mAuthDetailsRequired) {
long lastAuthenticatedTime = -1;
if (accountPresent) {
- lastAuthenticatedTime = DeDatabaseHelper
+ lastAuthenticatedTime = mAccounts.accountsDb
.findAccountLastAuthenticatedTime(
- mAccounts.openHelper.getReadableDatabase(),
new Account(mAccountName, mAccountType));
}
result.putLong(AccountManager.KEY_LAST_AUTHENTICATED_TIME,
@@ -4795,7 +4764,7 @@
LogRecordTask logTask = new LogRecordTask(action, tableName, accountId, userAccount,
callingUid, userAccount.debugDbInsertionPoint);
userAccount.debugDbInsertionPoint = (userAccount.debugDbInsertionPoint + 1)
- % MAX_DEBUG_DB_SIZE;
+ % AccountsDb.MAX_DEBUG_DB_SIZE;
mHandler.post(logTask);
}
@@ -4803,17 +4772,10 @@
* This should only be called once to compile the sql statement for logging
* and to find the insertion point.
*/
- private void initializeDebugDbSizeAndCompileSqlStatementForLogging(SQLiteDatabase db,
- UserAccounts userAccount) {
- // Initialize the count if not done earlier.
- int size = DebugDbHelper.getDebugTableRowCount(db);
- if (size >= MAX_DEBUG_DB_SIZE) {
- // Table is full, and we need to find the point where to insert.
- userAccount.debugDbInsertionPoint = DebugDbHelper.getDebugTableInsertionPoint(db);
- } else {
- userAccount.debugDbInsertionPoint = size;
- }
- userAccount.statementForLogging = DebugDbHelper.compileSqlStatementForLogging(db);
+ private void initializeDebugDbSizeAndCompileSqlStatementForLogging(UserAccounts userAccount) {
+ userAccount.debugDbInsertionPoint = userAccount.accountsDb
+ .calculateDebugTableInsertionPoint();
+ userAccount.statementForLogging = userAccount.accountsDb.compileSqlStatementForLogging();
}
public IBinder onBind(@SuppressWarnings("unused") Intent intent) {
@@ -4862,11 +4824,9 @@
private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter fout,
String[] args, boolean isCheckinRequest) {
synchronized (userAccounts.cacheLock) {
- final SQLiteDatabase db = userAccounts.openHelper.getReadableDatabase();
-
if (isCheckinRequest) {
// This is a checkin request. *Only* upload the account types and the count of each.
- DeDatabaseHelper.dumpAccountsTable(db, fout);
+ userAccounts.accountsDb.dumpDeAccountsTable(fout);
} else {
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
Process.myUid(), null);
@@ -4877,7 +4837,7 @@
// Add debug information.
fout.println();
- DebugDbHelper.dumpDebugTable(db, fout);
+ userAccounts.accountsDb.dumpDebugTable(fout);
fout.println();
synchronized (mSessions) {
final long now = SystemClock.elapsedRealtime();
@@ -5139,13 +5099,12 @@
}
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callerUid));
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
long grantsCount;
if (authTokenType != null) {
- grantsCount = DeDatabaseHelper.findMatchingGrantsCount(db, callerUid, authTokenType,
+ grantsCount = accounts.accountsDb.findMatchingGrantsCount(callerUid, authTokenType,
account);
} else {
- grantsCount = DeDatabaseHelper.findMatchingGrantsCountAnyToken(db, callerUid,
+ grantsCount = accounts.accountsDb.findMatchingGrantsCountAnyToken(callerUid,
account);
}
final boolean permissionGranted = grantsCount > 0;
@@ -5273,10 +5232,9 @@
}
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- long accountId = DeDatabaseHelper.findAccountId(db, account);
+ long accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId >= 0) {
- DeDatabaseHelper.insertGrant(db, accountId, authTokenType, uid);
+ accounts.accountsDb.insertGrant(accountId, authTokenType, uid);
}
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
UserHandle.of(accounts.userId));
@@ -5306,17 +5264,16 @@
}
UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- db.beginTransaction();
+ accounts.accountsDb.beginTransaction();
try {
- long accountId = DeDatabaseHelper.findAccountId(db, account);
+ long accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId >= 0) {
- DeDatabaseHelper.deleteGrantsByAccountIdAuthTokenTypeAndUid(
- db, accountId, authTokenType, uid);
- db.setTransactionSuccessful();
+ accounts.accountsDb.deleteGrantsByAccountIdAuthTokenTypeAndUid(
+ accountId, authTokenType, uid);
+ accounts.accountsDb.setTransactionSuccessful();
}
} finally {
- db.endTransaction();
+ accounts.accountsDb.endTransaction();
}
cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
@@ -5472,11 +5429,11 @@
}
}
- protected void writeUserDataIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
+ protected void writeUserDataIntoCacheLocked(UserAccounts accounts,
Account account, String key, String value) {
Map<String, String> userDataForAccount = accounts.userDataCache.get(account);
if (userDataForAccount == null) {
- userDataForAccount = CeDatabaseHelper.findUserExtrasForAccount(db, account);
+ userDataForAccount = accounts.accountsDb.findUserExtrasForAccount(account);
accounts.userDataCache.put(account, userDataForAccount);
}
if (value == null) {
@@ -5498,11 +5455,11 @@
}
}
- protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
+ protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts,
Account account, String key, String value) {
Map<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
if (authTokensForAccount == null) {
- authTokensForAccount = CeDatabaseHelper.findAuthTokensByAccount(db, account);
+ authTokensForAccount = accounts.accountsDb.findAuthTokensByAccount(account);
accounts.authTokenCache.put(account, authTokensForAccount);
}
if (value == null) {
@@ -5518,8 +5475,7 @@
Map<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
if (authTokensForAccount == null) {
// need to populate the cache for this account
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
- authTokensForAccount = CeDatabaseHelper.findAuthTokensByAccount(db, account);
+ authTokensForAccount = accounts.accountsDb.findAuthTokensByAccount(account);
accounts.authTokenCache.put(account, authTokensForAccount);
}
return authTokensForAccount.get(authTokenType);
@@ -5531,8 +5487,7 @@
Map<String, String> userDataForAccount = accounts.userDataCache.get(account);
if (userDataForAccount == null) {
// need to populate the cache for this account
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
- userDataForAccount = CeDatabaseHelper.findUserExtrasForAccount(db, account);
+ userDataForAccount = accounts.accountsDb.findUserExtrasForAccount(account);
accounts.userDataCache.put(account, userDataForAccount);
}
return userDataForAccount.get(key);
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 6ef521e..1adcf34 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -42,8 +42,13 @@
/**
* Persistence layer abstraction for accessing accounts_ce/accounts_de databases.
+ *
+ * <p>At first, CE database needs to be {@link #attachCeDatabase(File) attached to DE},
+ * in order for the tables to be available. All operations with CE database are done through the
+ * connection to the DE database, to which it is attached. This approach allows atomic
+ * transactions across two databases</p>
*/
-class AccountsDb {
+class AccountsDb implements AutoCloseable {
private static final String TAG = "AccountsDb";
private static final String DATABASE_NAME = "accounts.db";
@@ -128,6 +133,8 @@
private static final String CE_TABLE_AUTHTOKENS = CE_DB_PREFIX + TABLE_AUTHTOKENS;
private static final String CE_TABLE_EXTRAS = CE_DB_PREFIX + TABLE_EXTRAS;
+ static final int MAX_DEBUG_DB_SIZE = 64;
+
private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
@@ -169,7 +176,17 @@
private static final String META_KEY_DELIMITER = ":";
private static final String SELECTION_META_BY_AUTHENTICATOR_TYPE = META_KEY + " LIKE ?";
- static class CeDatabaseHelper extends SQLiteOpenHelper {
+ private final DeDatabaseHelper mDeDatabase;
+ private final Context mContext;
+ private final File mPreNDatabaseFile;
+
+ AccountsDb(DeDatabaseHelper deDatabase, Context context, File preNDatabaseFile) {
+ mDeDatabase = deDatabase;
+ mContext = context;
+ mPreNDatabaseFile = preNDatabaseFile;
+ }
+
+ private static class CeDatabaseHelper extends SQLiteOpenHelper {
CeDatabaseHelper(Context context, String ceDatabaseName) {
super(context, ceDatabaseName, null, CE_DATABASE_VERSION);
@@ -249,17 +266,16 @@
/**
* Creates a new {@code CeDatabaseHelper}. If pre-N db file is present at the old location,
* it also performs migration to the new CE database.
- * @param userId id of the user where the database is located
*/
static CeDatabaseHelper create(
Context context,
- int userId,
File preNDatabaseFile,
File ceDatabaseFile) {
boolean newDbExists = ceDatabaseFile.exists();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "CeDatabaseHelper.create userId=" + userId + " oldDbExists="
- + preNDatabaseFile.exists() + " newDbExists=" + newDbExists);
+ Log.v(TAG, "CeDatabaseHelper.create ceDatabaseFile=" + ceDatabaseFile
+ + " oldDbExists=" + preNDatabaseFile.exists()
+ + " newDbExists=" + newDbExists);
}
boolean removeOldDb = false;
if (!newDbExists && preNDatabaseFile.exists()) {
@@ -290,187 +306,189 @@
}
return true;
}
-
- /**
- * Returns information about auth tokens and their account for the specified query
- * parameters.
- * Output is in the format:
- * <pre><code> | AUTHTOKEN_ID | ACCOUNT_NAME | AUTH_TOKEN_TYPE |</code></pre>
- */
- static Cursor findAuthtokenForAllAccounts(SQLiteDatabase db, String accountType,
- String authToken) {
- return db.rawQuery(
- "SELECT " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
- + ", " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
- + ", " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE
- + " FROM " + CE_TABLE_ACCOUNTS
- + " JOIN " + CE_TABLE_AUTHTOKENS
- + " ON " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_ID
- + " = " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_ACCOUNTS_ID
- + " WHERE " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_AUTHTOKEN
- + " = ? AND " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?",
- new String[]{authToken, accountType});
- }
-
- static boolean deleteAuthtokensByAccountIdAndType(SQLiteDatabase db, long accountId,
- String authtokenType) {
- return db.delete(CE_TABLE_AUTHTOKENS,
- AUTHTOKENS_ACCOUNTS_ID + "=?" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
- new String[]{String.valueOf(accountId), authtokenType}) > 0;
- }
-
- static boolean deleteAuthToken(SQLiteDatabase db, String authTokenId) {
- return db.delete(
- CE_TABLE_AUTHTOKENS, AUTHTOKENS_ID + "= ?",
- new String[]{authTokenId}) > 0;
- }
-
- static long insertAuthToken(SQLiteDatabase db, long accountId, String authTokenType,
- String authToken) {
- ContentValues values = new ContentValues();
- values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
- values.put(AUTHTOKENS_TYPE, authTokenType);
- values.put(AUTHTOKENS_AUTHTOKEN, authToken);
- return db.insert(
- CE_TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values);
- }
-
- static Map<String, String> findAuthTokensByAccount(final SQLiteDatabase db,
- Account account) {
- HashMap<String, String> authTokensForAccount = new HashMap<>();
- Cursor cursor = db.query(CE_TABLE_AUTHTOKENS,
- COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
- SELECTION_AUTHTOKENS_BY_ACCOUNT,
- new String[]{account.name, account.type},
- null, null, null);
- try {
- while (cursor.moveToNext()) {
- final String type = cursor.getString(0);
- final String authToken = cursor.getString(1);
- authTokensForAccount.put(type, authToken);
- }
- } finally {
- cursor.close();
- }
- return authTokensForAccount;
- }
-
- static int updateAccountPassword(SQLiteDatabase db, long accountId, String password) {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_PASSWORD, password);
- return db.update(
- CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?",
- new String[]{String.valueOf(accountId)});
- }
-
- static boolean renameAccount(SQLiteDatabase db, long accountId, String newName) {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, newName);
- final String[] argsAccountId = {String.valueOf(accountId)};
- return db.update(
- CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId) > 0;
- }
-
- static boolean deleteAuthTokensByAccountId(SQLiteDatabase db, long accountId) {
- return db.delete(
- CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?",
- new String[]{String.valueOf(accountId)}) > 0;
- }
-
- static long findExtrasIdByAccountId(SQLiteDatabase db, long accountId, String key) {
- Cursor cursor = db.query(
- CE_TABLE_EXTRAS, new String[]{EXTRAS_ID},
- EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
- new String[]{key}, null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getLong(0);
- }
- return -1;
- } finally {
- cursor.close();
- }
- }
-
- static boolean updateExtra(SQLiteDatabase db, long extrasId, String value) {
- ContentValues values = new ContentValues();
- values.put(EXTRAS_VALUE, value);
- int rows = db.update(
- TABLE_EXTRAS, values, EXTRAS_ID + "=?",
- new String[]{String.valueOf(extrasId)});
- return rows == 1;
- }
-
- static long insertExtra(SQLiteDatabase db, long accountId, String key, String value) {
- ContentValues values = new ContentValues();
- values.put(EXTRAS_KEY, key);
- values.put(EXTRAS_ACCOUNTS_ID, accountId);
- values.put(EXTRAS_VALUE, value);
- return db.insert(CE_TABLE_EXTRAS, EXTRAS_KEY, values);
- }
-
- static Map<String, String> findUserExtrasForAccount(SQLiteDatabase db, Account account) {
- Map<String, String> userExtrasForAccount = new HashMap<>();
- Cursor cursor = db.query(CE_TABLE_EXTRAS,
- COLUMNS_EXTRAS_KEY_AND_VALUE,
- SELECTION_USERDATA_BY_ACCOUNT,
- new String[]{account.name, account.type},
- null, null, null);
- try {
- while (cursor.moveToNext()) {
- final String tmpkey = cursor.getString(0);
- final String value = cursor.getString(1);
- userExtrasForAccount.put(tmpkey, value);
- }
- } finally {
- cursor.close();
- }
- return userExtrasForAccount;
- }
-
- static long findAccountId(SQLiteDatabase db, Account account) {
- Cursor cursor = db.query(
- CE_TABLE_ACCOUNTS, new String[]{
- ACCOUNTS_ID},
- "name=? AND type=?", new String[]{account.name, account.type}, null, null,
- null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getLong(0);
- }
- return -1;
- } finally {
- cursor.close();
- }
- }
-
- static String findAccountPasswordByNameAndType(SQLiteDatabase db, String name,
- String type) {
- Cursor cursor = db.query(CE_TABLE_ACCOUNTS, new String[]{
- ACCOUNTS_PASSWORD},
- ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
- new String[]{name, type}, null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- }
- return null;
- } finally {
- cursor.close();
- }
- }
-
- static long insertAccount(SQLiteDatabase db, Account account, String password) {
- ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, account.name);
- values.put(ACCOUNTS_TYPE, account.type);
- values.put(ACCOUNTS_PASSWORD, password);
- return db.insert(
- CE_TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
- }
-
}
+ /**
+ * Returns information about auth tokens and their account for the specified query
+ * parameters.
+ * Output is in the format:
+ * <pre><code> | AUTHTOKEN_ID | ACCOUNT_NAME | AUTH_TOKEN_TYPE |</code></pre>
+ */
+ Cursor findAuthtokenForAllAccounts(String accountType, String authToken) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ return db.rawQuery(
+ "SELECT " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
+ + ", " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
+ + ", " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE
+ + " FROM " + CE_TABLE_ACCOUNTS
+ + " JOIN " + CE_TABLE_AUTHTOKENS
+ + " ON " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_ID
+ + " = " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_ACCOUNTS_ID
+ + " WHERE " + CE_TABLE_AUTHTOKENS + "." + AUTHTOKENS_AUTHTOKEN
+ + " = ? AND " + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?",
+ new String[]{authToken, accountType});
+ }
+
+ Map<String, String> findAuthTokensByAccount(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ HashMap<String, String> authTokensForAccount = new HashMap<>();
+ Cursor cursor = db.query(CE_TABLE_AUTHTOKENS,
+ COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
+ SELECTION_AUTHTOKENS_BY_ACCOUNT,
+ new String[] {account.name, account.type},
+ null, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ final String type = cursor.getString(0);
+ final String authToken = cursor.getString(1);
+ authTokensForAccount.put(type, authToken);
+ }
+ } finally {
+ cursor.close();
+ }
+ return authTokensForAccount;
+ }
+
+ boolean deleteAuthtokensByAccountIdAndType(long accountId, String authtokenType) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ return db.delete(CE_TABLE_AUTHTOKENS,
+ AUTHTOKENS_ACCOUNTS_ID + "=?" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
+ new String[]{String.valueOf(accountId), authtokenType}) > 0;
+ }
+
+ boolean deleteAuthToken(String authTokenId) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ return db.delete(
+ CE_TABLE_AUTHTOKENS, AUTHTOKENS_ID + "= ?",
+ new String[]{authTokenId}) > 0;
+ }
+
+ long insertAuthToken(long accountId, String authTokenType, String authToken) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ ContentValues values = new ContentValues();
+ values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
+ values.put(AUTHTOKENS_TYPE, authTokenType);
+ values.put(AUTHTOKENS_AUTHTOKEN, authToken);
+ return db.insert(
+ CE_TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values);
+ }
+
+ int updateCeAccountPassword(long accountId, String password) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_PASSWORD, password);
+ return db.update(
+ CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?",
+ new String[] {String.valueOf(accountId)});
+ }
+
+ boolean renameCeAccount(long accountId, String newName) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, newName);
+ final String[] argsAccountId = {String.valueOf(accountId)};
+ return db.update(
+ CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId) > 0;
+ }
+
+ boolean deleteAuthTokensByAccountId(long accountId) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ return db.delete(CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?",
+ new String[] {String.valueOf(accountId)}) > 0;
+ }
+
+ long findExtrasIdByAccountId(long accountId, String key) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ Cursor cursor = db.query(
+ CE_TABLE_EXTRAS, new String[]{EXTRAS_ID},
+ EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
+ new String[]{key}, null, null, null);
+ try {
+ if (cursor.moveToNext()) {
+ return cursor.getLong(0);
+ }
+ return -1;
+ } finally {
+ cursor.close();
+ }
+ }
+
+ boolean updateExtra(long extrasId, String value) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ ContentValues values = new ContentValues();
+ values.put(EXTRAS_VALUE, value);
+ int rows = db.update(
+ TABLE_EXTRAS, values, EXTRAS_ID + "=?",
+ new String[]{String.valueOf(extrasId)});
+ return rows == 1;
+ }
+
+ long insertExtra(long accountId, String key, String value) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ ContentValues values = new ContentValues();
+ values.put(EXTRAS_KEY, key);
+ values.put(EXTRAS_ACCOUNTS_ID, accountId);
+ values.put(EXTRAS_VALUE, value);
+ return db.insert(CE_TABLE_EXTRAS, EXTRAS_KEY, values);
+ }
+
+ Map<String, String> findUserExtrasForAccount(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ Map<String, String> userExtrasForAccount = new HashMap<>();
+ String[] selectionArgs = {account.name, account.type};
+ try (Cursor cursor = db.query(CE_TABLE_EXTRAS,
+ COLUMNS_EXTRAS_KEY_AND_VALUE,
+ SELECTION_USERDATA_BY_ACCOUNT,
+ selectionArgs,
+ null, null, null)) {
+ while (cursor.moveToNext()) {
+ final String tmpkey = cursor.getString(0);
+ final String value = cursor.getString(1);
+ userExtrasForAccount.put(tmpkey, value);
+ }
+ }
+ return userExtrasForAccount;
+ }
+
+ long findCeAccountId(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ String[] columns = { ACCOUNTS_ID };
+ String selection = "name=? AND type=?";
+ String[] selectionArgs = {account.name, account.type};
+ try (Cursor cursor = db.query(CE_TABLE_ACCOUNTS, columns, selection, selectionArgs,
+ null, null, null)) {
+ if (cursor.moveToNext()) {
+ return cursor.getLong(0);
+ }
+ return -1;
+ }
+ }
+
+ String findAccountPasswordByNameAndType(String name, String type) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ String selection = ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?";
+ String[] selectionArgs = {name, type};
+ String[] columns = {ACCOUNTS_PASSWORD};
+ try (Cursor cursor = db.query(CE_TABLE_ACCOUNTS, columns, selection, selectionArgs,
+ null, null, null)) {
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
+ }
+ return null;
+ }
+ }
+
+ long insertCeAccount(Account account, String password) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
+ ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, account.name);
+ values.put(ACCOUNTS_TYPE, account.type);
+ values.put(ACCOUNTS_PASSWORD, password);
+ return db.insert(
+ CE_TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
+ }
+
+
static class DeDatabaseHelper extends SQLiteOpenHelper {
private final int mUserId;
@@ -504,7 +522,7 @@
createGrantsTable(db);
createSharedAccountsTable(db);
createAccountsDeletionTrigger(db);
- DebugDbHelper.createDebugTable(db);
+ createDebugTable(db);
}
private void createSharedAccountsTable(SQLiteDatabase db) {
@@ -533,6 +551,18 @@
+ "," + GRANTS_GRANTEE_UID + "))");
}
+ static void createDebugTable(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( "
+ + ACCOUNTS_ID + " INTEGER,"
+ + DEBUG_TABLE_ACTION_TYPE + " TEXT NOT NULL, "
+ + DEBUG_TABLE_TIMESTAMP + " DATETIME,"
+ + DEBUG_TABLE_CALLER_UID + " INTEGER NOT NULL,"
+ + DEBUG_TABLE_TABLE_NAME + " TEXT NOT NULL,"
+ + DEBUG_TABLE_KEY + " INTEGER PRIMARY KEY)");
+ db.execSQL("CREATE INDEX timestamp_index ON " + TABLE_DEBUG + " ("
+ + DEBUG_TABLE_TIMESTAMP + ")");
+ }
+
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
@@ -542,17 +572,6 @@
}
}
- public void attachCeDatabase(File ceDbFile) {
- SQLiteDatabase db = getWritableDatabase();
- db.execSQL("ATTACH DATABASE '" + ceDbFile.getPath()+ "' AS ceDb");
- mCeAttached = true;
- }
-
- public boolean isCeDatabaseAttached() {
- return mCeAttached;
- }
-
-
public SQLiteDatabase getReadableDatabaseUserIsUnlocked() {
if(!mCeAttached) {
Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId
@@ -616,343 +635,305 @@
db.execSQL("DETACH DATABASE preNDb");
}
+ }
- static boolean deleteAccount(SQLiteDatabase db, long accountId) {
- return db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null) > 0;
- }
+ boolean deleteDeAccount(long accountId) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ return db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null) > 0;
+ }
- static long insertSharedAccount(SQLiteDatabase db, Account account) {
- ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, account.name);
- values.put(ACCOUNTS_TYPE, account.type);
- return db.insert(
- TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME, values);
- }
+ long insertSharedAccount(Account account) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, account.name);
+ values.put(ACCOUNTS_TYPE, account.type);
+ return db.insert(
+ TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME, values);
+ }
- static boolean deleteSharedAccount(SQLiteDatabase db, Account account) {
- return db
- .delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
- new String[]{account.name, account.type}) > 0;
- }
+ boolean deleteSharedAccount(Account account) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ return db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+ new String[]{account.name, account.type}) > 0;
+ }
- static int renameSharedAccount(SQLiteDatabase db, Account account, String newName) {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, newName);
- return db.update(TABLE_SHARED_ACCOUNTS,
- values,
- ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
- + "=?",
- new String[]{account.name, account.type});
- }
+ int renameSharedAccount(Account account, String newName) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, newName);
+ return db.update(TABLE_SHARED_ACCOUNTS,
+ values,
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+ new String[] {account.name, account.type});
+ }
- static List<Account> getSharedAccounts(SQLiteDatabase db) {
- ArrayList<Account> accountList = new ArrayList<>();
- Cursor cursor = null;
- try {
- cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[]{
- ACCOUNTS_NAME, ACCOUNTS_TYPE},
- null, null, null, null, null);
- if (cursor != null && cursor.moveToFirst()) {
- int nameIndex = cursor.getColumnIndex(ACCOUNTS_NAME);
- int typeIndex = cursor.getColumnIndex(ACCOUNTS_TYPE);
- do {
- accountList.add(new Account(cursor.getString(nameIndex),
- cursor.getString(typeIndex)));
- } while (cursor.moveToNext());
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return accountList;
- }
-
- static long findSharedAccountId(SQLiteDatabase db, Account account) {
- Cursor cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[]{
- ACCOUNTS_ID},
- "name=? AND type=?", new String[]{account.name, account.type}, null, null,
- null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getLong(0);
- }
- return -1;
- } finally {
- cursor.close();
- }
- }
-
- static long findAccountLastAuthenticatedTime(SQLiteDatabase db, Account account) {
- return DatabaseUtils.longForQuery(
- db,
- "SELECT " + AccountsDb.ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS
- + " FROM " +
- TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND "
- + ACCOUNTS_TYPE + "=?",
- new String[] {account.name, account.type});
- }
-
- static boolean updateAccountLastAuthenticatedTime(SQLiteDatabase db, Account account) {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
- int rowCount = db.update(
- TABLE_ACCOUNTS,
- values,
- ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
- new String[] {
- account.name, account.type
- });
- return rowCount > 0;
- }
-
-
- static void dumpAccountsTable(SQLiteDatabase db, PrintWriter pw) {
- Cursor cursor = db.query(
- TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
- null, null, ACCOUNTS_TYPE, null, null);
- try {
- while (cursor.moveToNext()) {
- // print type,count
- pw.println(cursor.getString(0) + "," + cursor.getString(1));
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- static long findAccountId(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 {
- if (cursor.moveToNext()) {
- return cursor.getLong(0);
- }
- return -1;
- } finally {
- cursor.close();
- }
- }
-
- static Map<Long, Account> findAllAccounts(SQLiteDatabase db) {
- LinkedHashMap<Long, Account> map = new LinkedHashMap<>();
- Cursor cursor = db.query(TABLE_ACCOUNTS,
- new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
- null, null, null, null, ACCOUNTS_ID);
- try {
- while (cursor.moveToNext()) {
- final long accountId = cursor.getLong(0);
- final String accountType = cursor.getString(1);
- final String accountName = cursor.getString(2);
-
- final Account account = new Account(accountName, accountType);
- map.put(accountId, account);
- }
- } finally {
- cursor.close();
- }
- return map;
- }
-
- static String findAccountPreviousName(SQLiteDatabase db, Account account) {
- Cursor cursor = db.query(
- TABLE_ACCOUNTS,
- new String[]{ACCOUNTS_PREVIOUS_NAME},
- ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
- + "=?",
- new String[]{account.name, account.type},
- null,
- null,
- null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- }
- } finally {
- cursor.close();
- }
- return null;
- }
-
- static long insertAccount(SQLiteDatabase db, Account account, long accountId) {
- ContentValues values = new ContentValues();
- values.put(ACCOUNTS_ID, accountId);
- values.put(ACCOUNTS_NAME, account.name);
- values.put(ACCOUNTS_TYPE, account.type);
- values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
- return db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
- }
-
- static boolean renameAccount(SQLiteDatabase db, long accountId, String newName,
- String previousName) {
- final ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, newName);
- values.put(ACCOUNTS_PREVIOUS_NAME, previousName);
- final String[] argsAccountId = {String.valueOf(accountId)};
- return db.update(
- TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId) > 0;
- }
-
- static boolean deleteGrantsByAccountIdAuthTokenTypeAndUid(SQLiteDatabase db, long accountId,
- String authTokenType, long uid) {
- return 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)})
- > 0;
- }
-
- static List<Integer> findAllUidGrants(SQLiteDatabase db) {
- List<Integer> result = new ArrayList<>();
- 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);
- result.add(uid);
- }
- } finally {
- cursor.close();
- }
- return result;
- }
-
- static long findMatchingGrantsCount(SQLiteDatabase db,
- int uid, String authTokenType, Account account) {
- String[] args = {String.valueOf(uid), authTokenType,
- account.name, account.type};
- return DatabaseUtils
- .longForQuery(db, COUNT_OF_MATCHING_GRANTS, args);
- }
-
- static long findMatchingGrantsCountAnyToken(SQLiteDatabase db,
- int uid, Account account) {
- String[] args = {String.valueOf(uid), account.name, account.type};
- return DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS_ANY_TOKEN, args);
- }
-
- static long insertGrant(SQLiteDatabase db, long accountId, String authTokenType, int uid) {
- ContentValues values = new ContentValues();
- values.put(GRANTS_ACCOUNTS_ID, accountId);
- values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
- values.put(GRANTS_GRANTEE_UID, uid);
- return db.insert(
- TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
- }
-
- static boolean deleteGrantsByUid(SQLiteDatabase db, int uid) {
- return db.delete(
- TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
- new String[]{Integer.toString(uid)}) > 0;
- }
-
- static long insertMetaAuthTypeAndUid(SQLiteDatabase db, String authenticatorType, int uid) {
- ContentValues values = new ContentValues();
- values.put(META_KEY,
- META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + authenticatorType);
- values.put(META_VALUE, uid);
- return db.insert(TABLE_META, null, values);
- }
-
- static long insertOrReplaceMetaAuthTypeAndUid(SQLiteDatabase db, String authenticatorType,
- int uid) {
- ContentValues values = new ContentValues();
- values.put(META_KEY,
- META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + authenticatorType);
- values.put(META_VALUE, uid);
- return db.insertWithOnConflict(TABLE_META, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
- }
-
- static Map<String, Integer> findMetaAuthUid(SQLiteDatabase db) {
- Cursor metaCursor = db.query(
- TABLE_META,
- new String[]{META_KEY, META_VALUE},
- SELECTION_META_BY_AUTHENTICATOR_TYPE,
- new String[]{META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + "%"},
- null /* groupBy */,
- null /* having */,
- META_KEY);
- Map<String, Integer> map = new LinkedHashMap<>();
- try {
- while (metaCursor.moveToNext()) {
- String type = TextUtils
- .split(metaCursor.getString(0), META_KEY_DELIMITER)[1];
- String uidStr = metaCursor.getString(1);
- if (TextUtils.isEmpty(type) || TextUtils.isEmpty(uidStr)) {
- // Should never happen.
- Slog.e(TAG, "Auth type empty: " + TextUtils.isEmpty(type)
- + ", uid empty: " + TextUtils.isEmpty(uidStr));
- continue;
- }
- int uid = Integer.parseInt(metaCursor.getString(1));
- map.put(type, uid);
- }
- } finally {
- metaCursor.close();
- }
- return map;
- }
-
- static boolean deleteMetaByAuthTypeAndUid(SQLiteDatabase db, String type, int uid) {
- return db.delete(
- TABLE_META,
- META_KEY + "=? AND " + META_VALUE + "=?",
- new String[]{
- META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
- String.valueOf(uid)}
- ) > 0;
- }
-
- static List<Pair<String, Integer>> findAllAccountGrants(SQLiteDatabase db) {
- try (Cursor cursor = db.rawQuery(ACCOUNT_ACCESS_GRANTS, null)) {
- if (cursor == null || !cursor.moveToFirst()) {
- return Collections.emptyList();
- }
- List<Pair<String, Integer>> results = new ArrayList<>();
+ List<Account> getSharedAccounts() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ ArrayList<Account> accountList = new ArrayList<>();
+ Cursor cursor = null;
+ try {
+ cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[] {ACCOUNTS_NAME, ACCOUNTS_TYPE},
+ null, null, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ int nameIndex = cursor.getColumnIndex(ACCOUNTS_NAME);
+ int typeIndex = cursor.getColumnIndex(ACCOUNTS_TYPE);
do {
- final String accountName = cursor.getString(0);
- final int uid = cursor.getInt(1);
- results.add(Pair.create(accountName, uid));
+ accountList.add(new Account(cursor.getString(nameIndex),
+ cursor.getString(typeIndex)));
} while (cursor.moveToNext());
- return results;
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
}
}
+ return accountList;
+ }
- static DeDatabaseHelper create(
- Context context,
- int userId,
- File preNDatabaseFile,
- File deDatabaseFile) {
- boolean newDbExists = deDatabaseFile.exists();
- DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId,
- deDatabaseFile.getPath());
- // If the db just created, and there is a legacy db, migrate it
- if (!newDbExists && preNDatabaseFile.exists()) {
- // Migrate legacy db to the latest version - PRE_N_DATABASE_VERSION
- PreNDatabaseHelper
- preNDatabaseHelper = new PreNDatabaseHelper(context, userId,
- preNDatabaseFile.getPath());
- // Open the database to force upgrade if required
- preNDatabaseHelper.getWritableDatabase();
- preNDatabaseHelper.close();
- // Move data without SPII to DE
- deDatabaseHelper.migratePreNDbToDe(preNDatabaseFile);
+ long findSharedAccountId(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ Cursor cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[]{
+ ACCOUNTS_ID},
+ "name=? AND type=?", new String[]{account.name, account.type}, null, null,
+ null);
+ try {
+ if (cursor.moveToNext()) {
+ return cursor.getLong(0);
}
- return deDatabaseHelper;
+ return -1;
+ } finally {
+ cursor.close();
}
}
- static class PreNDatabaseHelper extends SQLiteOpenHelper {
+ long findAccountLastAuthenticatedTime(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ return DatabaseUtils.longForQuery(db,
+ "SELECT " + AccountsDb.ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS
+ + " FROM " + TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND "
+ + ACCOUNTS_TYPE + "=?",
+ new String[] {account.name, account.type});
+ }
+
+ boolean updateAccountLastAuthenticatedTime(Account account) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
+ int rowCount = db.update(TABLE_ACCOUNTS,
+ values,
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+ new String[] { account.name, account.type });
+ return rowCount > 0;
+ }
+
+ void dumpDeAccountsTable(PrintWriter pw) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ Cursor cursor = db.query(
+ TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
+ null, null, ACCOUNTS_TYPE, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ // print type,count
+ pw.println(cursor.getString(0) + "," + cursor.getString(1));
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ long findDeAccountId(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ String[] columns = {ACCOUNTS_ID};
+ String selection = "name=? AND type=?";
+ String[] selectionArgs = {account.name, account.type};
+ try (Cursor cursor = db.query(TABLE_ACCOUNTS, columns, selection, selectionArgs,
+ null, null, null)) {
+ if (cursor.moveToNext()) {
+ return cursor.getLong(0);
+ }
+ return -1;
+ }
+ }
+
+ Map<Long, Account> findAllDeAccounts() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ LinkedHashMap<Long, Account> map = new LinkedHashMap<>();
+ String[] columns = {ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME};
+ try (Cursor cursor = db.query(TABLE_ACCOUNTS, columns,
+ null, null, null, null, ACCOUNTS_ID)) {
+ while (cursor.moveToNext()) {
+ final long accountId = cursor.getLong(0);
+ final String accountType = cursor.getString(1);
+ final String accountName = cursor.getString(2);
+
+ final Account account = new Account(accountName, accountType);
+ map.put(accountId, account);
+ }
+ }
+ return map;
+ }
+
+ String findDeAccountPreviousName(Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ String[] columns = {ACCOUNTS_PREVIOUS_NAME};
+ String selection = ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?";
+ String[] selectionArgs = {account.name, account.type};
+ try (Cursor cursor = db.query(TABLE_ACCOUNTS, columns, selection, selectionArgs,
+ null, null, null)) {
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
+ }
+ }
+ return null;
+ }
+
+ long insertDeAccount(Account account, long accountId) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_ID, accountId);
+ values.put(ACCOUNTS_NAME, account.name);
+ values.put(ACCOUNTS_TYPE, account.type);
+ values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
+ return db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
+ }
+
+ boolean renameDeAccount(long accountId, String newName, String previousName) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ final ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, newName);
+ values.put(ACCOUNTS_PREVIOUS_NAME, previousName);
+ final String[] argsAccountId = {String.valueOf(accountId)};
+ return db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId) > 0;
+ }
+
+ boolean deleteGrantsByAccountIdAuthTokenTypeAndUid(long accountId,
+ String authTokenType, long uid) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ return 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)}) > 0;
+ }
+
+ List<Integer> findAllUidGrants() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ List<Integer> result = new ArrayList<>();
+ 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);
+ result.add(uid);
+ }
+ } finally {
+ cursor.close();
+ }
+ return result;
+ }
+
+ long findMatchingGrantsCount(int uid, String authTokenType, Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ String[] args = {String.valueOf(uid), authTokenType, account.name, account.type};
+ return DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args);
+ }
+
+ long findMatchingGrantsCountAnyToken(int uid, Account account) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ String[] args = {String.valueOf(uid), account.name, account.type};
+ return DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS_ANY_TOKEN, args);
+ }
+
+ long insertGrant(long accountId, String authTokenType, int uid) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(GRANTS_ACCOUNTS_ID, accountId);
+ values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
+ values.put(GRANTS_GRANTEE_UID, uid);
+ return db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
+ }
+
+ boolean deleteGrantsByUid(int uid) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ return db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
+ new String[] {Integer.toString(uid)}) > 0;
+ }
+
+ long insertOrReplaceMetaAuthTypeAndUid(String authenticatorType, int uid) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(META_KEY,
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + authenticatorType);
+ values.put(META_VALUE, uid);
+ return db.insertWithOnConflict(TABLE_META, null, values,
+ SQLiteDatabase.CONFLICT_REPLACE);
+ }
+
+ Map<String, Integer> findMetaAuthUid() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ Cursor metaCursor = db.query(
+ TABLE_META,
+ new String[]{META_KEY, META_VALUE},
+ SELECTION_META_BY_AUTHENTICATOR_TYPE,
+ new String[]{META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + "%"},
+ null /* groupBy */,
+ null /* having */,
+ META_KEY);
+ Map<String, Integer> map = new LinkedHashMap<>();
+ try {
+ while (metaCursor.moveToNext()) {
+ String type = TextUtils
+ .split(metaCursor.getString(0), META_KEY_DELIMITER)[1];
+ String uidStr = metaCursor.getString(1);
+ if (TextUtils.isEmpty(type) || TextUtils.isEmpty(uidStr)) {
+ // Should never happen.
+ Slog.e(TAG, "Auth type empty: " + TextUtils.isEmpty(type)
+ + ", uid empty: " + TextUtils.isEmpty(uidStr));
+ continue;
+ }
+ int uid = Integer.parseInt(metaCursor.getString(1));
+ map.put(type, uid);
+ }
+ } finally {
+ metaCursor.close();
+ }
+ return map;
+ }
+
+ boolean deleteMetaByAuthTypeAndUid(String type, int uid) {
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ return db.delete(
+ TABLE_META,
+ META_KEY + "=? AND " + META_VALUE + "=?",
+ new String[]{
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
+ String.valueOf(uid)}
+ ) > 0;
+ }
+
+ List<Pair<String, Integer>> findAllAccountGrants() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ try (Cursor cursor = db.rawQuery(ACCOUNT_ACCESS_GRANTS, null)) {
+ if (cursor == null || !cursor.moveToFirst()) {
+ return Collections.emptyList();
+ }
+ List<Pair<String, Integer>> results = new ArrayList<>();
+ do {
+ final String accountName = cursor.getString(0);
+ final int uid = cursor.getInt(1);
+ results.add(Pair.create(accountName, uid));
+ } while (cursor.moveToNext());
+ return results;
+ }
+ }
+
+ private static class PreNDatabaseHelper extends SQLiteOpenHelper {
private final Context mContext;
private final int mUserId;
- public PreNDatabaseHelper(Context context, int userId, String preNDatabaseName) {
+ PreNDatabaseHelper(Context context, int userId, String preNDatabaseName) {
super(context, preNDatabaseName, null, PRE_N_DATABASE_VERSION);
mContext = context;
mUserId = userId;
@@ -982,7 +963,7 @@
}
private void addDebugTable(SQLiteDatabase db) {
- DebugDbHelper.createDebugTable(db);
+ DeDatabaseHelper.createDebugTable(db);
}
private void createAccountsDeletionTrigger(SQLiteDatabase db) {
@@ -1007,10 +988,18 @@
+ "," + GRANTS_GRANTEE_UID + "))");
}
+ static long insertMetaAuthTypeAndUid(SQLiteDatabase db, String authenticatorType, int uid) {
+ ContentValues values = new ContentValues();
+ values.put(META_KEY,
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + authenticatorType);
+ values.put(META_VALUE, uid);
+ return db.insert(TABLE_META, null, values);
+ }
+
private void populateMetaTableWithAuthTypeAndUID(SQLiteDatabase db,
Map<String, Integer> authTypeAndUIDMap) {
for (Map.Entry<String, Integer> entry : authTypeAndUIDMap.entrySet()) {
- DeDatabaseHelper.insertMetaAuthTypeAndUid(db, entry.getKey(), entry.getValue());
+ insertMetaAuthTypeAndUid(db, entry.getKey(), entry.getValue());
}
}
@@ -1078,68 +1067,8 @@
}
}
- static class DebugDbHelper{
- private DebugDbHelper() {
- }
-
-
- private static void createDebugTable(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( "
- + ACCOUNTS_ID + " INTEGER,"
- + DEBUG_TABLE_ACTION_TYPE + " TEXT NOT NULL, "
- + DEBUG_TABLE_TIMESTAMP + " DATETIME,"
- + DEBUG_TABLE_CALLER_UID + " INTEGER NOT NULL,"
- + DEBUG_TABLE_TABLE_NAME + " TEXT NOT NULL,"
- + DEBUG_TABLE_KEY + " INTEGER PRIMARY KEY)");
- db.execSQL("CREATE INDEX timestamp_index ON " + TABLE_DEBUG + " ("
- + DEBUG_TABLE_TIMESTAMP + ")");
- }
-
- static SQLiteStatement compileSqlStatementForLogging(SQLiteDatabase db) {
- String sql = "INSERT OR REPLACE INTO " + AccountsDb.TABLE_DEBUG
- + " VALUES (?,?,?,?,?,?)";
- return db.compileStatement(sql);
- }
-
- static int getDebugTableRowCount(SQLiteDatabase db) {
- String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + TABLE_DEBUG;
- return (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
- }
-
- /*
- * Finds the row key where the next insertion should take place. This should
- * be invoked only if the table has reached its full capacity.
- */
- static int getDebugTableInsertionPoint(SQLiteDatabase db) {
- // This query finds the smallest timestamp value (and if 2 records have
- // same timestamp, the choose the lower id).
- String queryCountDebugDbRows = "SELECT " + DEBUG_TABLE_KEY +
- " FROM " + TABLE_DEBUG +
- " ORDER BY " + DEBUG_TABLE_TIMESTAMP + "," + DEBUG_TABLE_KEY +
- " LIMIT 1";
- return (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
- }
-
- static void dumpDebugTable(SQLiteDatabase db, PrintWriter pw) {
- Cursor cursor = db.query(TABLE_DEBUG, null,
- null, null, null, null, DEBUG_TABLE_TIMESTAMP);
- pw.println("AccountId, Action_Type, timestamp, UID, TableName, Key");
- pw.println("Accounts History");
- try {
- while (cursor.moveToNext()) {
- // print type,count
- pw.println(cursor.getString(0) + "," + cursor.getString(1) + "," +
- cursor.getString(2) + "," + cursor.getString(3) + ","
- + cursor.getString(4) + "," + cursor.getString(5));
- }
- } finally {
- cursor.close();
- }
- }
-
- }
-
- static List<Account> findCeAccountsNotInDe(SQLiteDatabase db) {
+ List<Account> findCeAccountsNotInDe() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
// Select accounts from CE that do not exist in DE
Cursor cursor = db.rawQuery(
"SELECT " + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE
@@ -1161,14 +1090,110 @@
}
}
- static boolean deleteCeAccount(SQLiteDatabase db, long accountId) {
+ boolean deleteCeAccount(long accountId) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
return db.delete(
CE_TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null) > 0;
}
+ boolean isCeDatabaseAttached() {
+ return mDeDatabase.mCeAttached;
+ }
+
+ void beginTransaction() {
+ mDeDatabase.getWritableDatabase().beginTransaction();
+ }
+
+ void setTransactionSuccessful() {
+ mDeDatabase.getWritableDatabase().setTransactionSuccessful();
+ }
+
+ void endTransaction() {
+ mDeDatabase.getWritableDatabase().endTransaction();
+ }
+
+ void attachCeDatabase(File ceDbFile) {
+ CeDatabaseHelper.create(mContext, mPreNDatabaseFile, ceDbFile);
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ db.execSQL("ATTACH DATABASE '" + ceDbFile.getPath()+ "' AS ceDb");
+ mDeDatabase.mCeAttached = true;
+ }
+
+ /*
+ * Finds the row key where the next insertion should take place. Returns number of rows
+ * if it is less {@link #MAX_DEBUG_DB_SIZE}, otherwise finds the lowest number available.
+ */
+ int calculateDebugTableInsertionPoint() {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + TABLE_DEBUG;
+ int size = (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+ if (size < MAX_DEBUG_DB_SIZE) {
+ return size;
+ }
+
+ // This query finds the smallest timestamp value (and if 2 records have
+ // same timestamp, the choose the lower id).
+ queryCountDebugDbRows = "SELECT " + DEBUG_TABLE_KEY +
+ " FROM " + TABLE_DEBUG +
+ " ORDER BY " + DEBUG_TABLE_TIMESTAMP + "," + DEBUG_TABLE_KEY +
+ " LIMIT 1";
+ return (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+ }
+
+ SQLiteStatement compileSqlStatementForLogging() {
+ // TODO b/31708085 Fix debug logging - it eagerly opens database for write without a need
+ SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+ String sql = "INSERT OR REPLACE INTO " + AccountsDb.TABLE_DEBUG
+ + " VALUES (?,?,?,?,?,?)";
+ return db.compileStatement(sql);
+ }
+
+ void dumpDebugTable(PrintWriter pw) {
+ SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+ Cursor cursor = db.query(TABLE_DEBUG, null,
+ null, null, null, null, DEBUG_TABLE_TIMESTAMP);
+ pw.println("AccountId, Action_Type, timestamp, UID, TableName, Key");
+ pw.println("Accounts History");
+ try {
+ while (cursor.moveToNext()) {
+ // print type,count
+ pw.println(cursor.getString(0) + "," + cursor.getString(1) + "," +
+ cursor.getString(2) + "," + cursor.getString(3) + ","
+ + cursor.getString(4) + "," + cursor.getString(5));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ public void close() {
+ mDeDatabase.close();
+ }
+
static void deleteDbFileWarnIfFailed(File dbFile) {
if (!SQLiteDatabase.deleteDatabase(dbFile)) {
Log.w(TAG, "Database at " + dbFile + " was not deleted successfully");
}
}
+
+ public static AccountsDb create(Context context, int userId, File preNDatabaseFile,
+ File deDatabaseFile) {
+ boolean newDbExists = deDatabaseFile.exists();
+ DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId,
+ deDatabaseFile.getPath());
+ // If the db just created, and there is a legacy db, migrate it
+ if (!newDbExists && preNDatabaseFile.exists()) {
+ // Migrate legacy db to the latest version - PRE_N_DATABASE_VERSION
+ PreNDatabaseHelper
+ preNDatabaseHelper = new PreNDatabaseHelper(context, userId,
+ preNDatabaseFile.getPath());
+ // Open the database to force upgrade if required
+ preNDatabaseHelper.getWritableDatabase();
+ preNDatabaseHelper.close();
+ // Move data without SPII to DE
+ deDatabaseHelper.migratePreNDbToDe(preNDatabaseFile);
+ }
+ return new AccountsDb(deDatabaseHelper, context, preNDatabaseFile);
+ }
+
}