Loading services/core/java/com/android/server/accounts/AccountManagerService.java +55 −42 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; Loading Loading @@ -267,10 +268,10 @@ public class AccountManagerService private int debugDbInsertionPoint = -1; private SQLiteStatement statementForLogging; UserAccounts(Context context, int userId) { UserAccounts(Context context, int userId, File preNDbFile, File deDbFile) { this.userId = userId; synchronized (cacheLock) { openHelper = DeDatabaseHelper.create(context, userId); openHelper = DeDatabaseHelper.create(context, userId, preNDbFile, deDbFile); } } } Loading Loading @@ -540,7 +541,9 @@ public class AccountManagerService UserAccounts accounts = mUsers.get(userId); boolean validateAccounts = false; if (accounts == null) { accounts = new UserAccounts(mContext, userId); File preNDbFile = new File(getPreNDatabaseName(userId)); File deDbFile = new File(getDeDatabaseName(userId)); accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile); initializeDebugDbSizeAndCompileSqlStatementForLogging( accounts.openHelper.getWritableDatabase(), accounts); mUsers.append(userId, accounts); Loading @@ -551,8 +554,10 @@ public class AccountManagerService if (!accounts.openHelper.isCeDatabaseAttached() && mUnlockedUsers.get(userId)) { Log.i(TAG, "User " + userId + " is unlocked - opening CE database"); synchronized (accounts.cacheLock) { CeDatabaseHelper.create(mContext, userId); accounts.openHelper.attachCeDatabase(); File preNDatabaseFile = new File(getPreNDatabaseName(userId)); File ceDatabaseFile = new File(getCeDatabaseName(userId)); CeDatabaseHelper.create(mContext, userId, preNDatabaseFile, ceDatabaseFile); accounts.openHelper.attachCeDatabase(ceDatabaseFile); } syncDeCeAccountsLocked(accounts); } Loading Loading @@ -647,7 +652,8 @@ public class AccountManagerService } } private void onUserUnlocked(Intent intent) { @VisibleForTesting void onUserUnlocked(Intent intent) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "onUserUnlocked " + userId); Loading Loading @@ -1553,7 +1559,7 @@ public class AccountManagerService } } /* For testing */ @VisibleForTesting protected void removeAccountInternal(Account account) { removeAccountInternal(getUserAccountsForCaller(), account, getCallingUid()); } Loading Loading @@ -4044,7 +4050,8 @@ public class AccountManagerService } } static String getPreNDatabaseName(int userId) { @VisibleForTesting String getPreNDatabaseName(int userId) { File systemDir = Environment.getDataSystemDirectory(); File databaseFile = new File(Environment.getUserSystemDirectory(userId), PRE_N_DATABASE_NAME); Loading @@ -4070,13 +4077,15 @@ public class AccountManagerService return databaseFile.getPath(); } static String getDeDatabaseName(int userId) { @VisibleForTesting String getDeDatabaseName(int userId) { File databaseFile = new File(Environment.getDataSystemDeDirectory(userId), DE_DATABASE_NAME); return databaseFile.getPath(); } static String getCeDatabaseName(int userId) { @VisibleForTesting String getCeDatabaseName(int userId) { File databaseFile = new File(Environment.getDataSystemCeDirectory(userId), CE_DATABASE_NAME); return databaseFile.getPath(); Loading Loading @@ -4217,13 +4226,11 @@ public class AccountManagerService } static class PreNDatabaseHelper extends SQLiteOpenHelper { private final Context mContext; private final int mUserId; public PreNDatabaseHelper(Context context, int userId) { super(context, AccountManagerService.getPreNDatabaseName(userId), null, PRE_N_DATABASE_VERSION); public PreNDatabaseHelper(Context context, int userId, String preNDatabaseName) { super(context, preNDatabaseName, null, PRE_N_DATABASE_VERSION); mContext = context; mUserId = userId; } Loading Loading @@ -4360,8 +4367,8 @@ public class AccountManagerService private final int mUserId; private volatile boolean mCeAttached; private DeDatabaseHelper(Context context, int userId) { super(context, getDeDatabaseName(userId), null, DE_DATABASE_VERSION); private DeDatabaseHelper(Context context, int userId, String deDatabaseName) { super(context, deDatabaseName, null, DE_DATABASE_VERSION); mUserId = userId; } Loading Loading @@ -4426,8 +4433,7 @@ public class AccountManagerService } } public void attachCeDatabase() { File ceDbFile = new File(getCeDatabaseName(mUserId)); public void attachCeDatabase(File ceDbFile) { SQLiteDatabase db = getWritableDatabase(); db.execSQL("ATTACH DATABASE '" + ceDbFile.getPath()+ "' AS ceDb"); mCeAttached = true; Loading @@ -4440,8 +4446,8 @@ public class AccountManagerService public SQLiteDatabase getReadableDatabaseUserIsUnlocked() { if(!mCeAttached) { Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked ", new Throwable()); Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked. CE database is not yet available.", new Throwable()); } return super.getReadableDatabase(); } Loading @@ -4449,7 +4455,7 @@ public class AccountManagerService public SQLiteDatabase getWritableDatabaseUserIsUnlocked() { if(!mCeAttached) { Log.wtf(TAG, "getWritableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked ", new Throwable()); + " is still locked. CE database is not yet available.", new Throwable()); } return super.getWritableDatabase(); } Loading Loading @@ -4502,20 +4508,24 @@ public class AccountManagerService db.execSQL("DETACH DATABASE preNDb"); } static DeDatabaseHelper create(Context context, int userId) { File oldDb = new File(getPreNDatabaseName(userId)); File newDb = new File(getDeDatabaseName(userId)); boolean newDbExists = newDb.exists(); DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId); 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 && oldDb.exists()) { if (!newDbExists && preNDatabaseFile.exists()) { // Migrate legacy db to the latest version - PRE_N_DATABASE_VERSION PreNDatabaseHelper preNDatabaseHelper = new PreNDatabaseHelper(context, userId); 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(oldDb); deDatabaseHelper.migratePreNDbToDe(preNDatabaseFile); } return deDatabaseHelper; } Loading @@ -4523,8 +4533,8 @@ public class AccountManagerService static class CeDatabaseHelper extends SQLiteOpenHelper { public CeDatabaseHelper(Context context, int userId) { super(context, getCeDatabaseName(userId), null, CE_DATABASE_VERSION); public CeDatabaseHelper(Context context, String ceDatabaseName) { super(context, ceDatabaseName, null, CE_DATABASE_VERSION); } /** Loading Loading @@ -4640,27 +4650,28 @@ public class AccountManagerService * @param context * @param userId id of the user where the database is located */ static CeDatabaseHelper create(Context context, int userId) { File oldDatabaseFile = new File(getPreNDatabaseName(userId)); File ceDatabaseFile = new File(getCeDatabaseName(userId)); 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=" + oldDatabaseFile.exists() + " newDbExists=" + newDbExists); + preNDatabaseFile.exists() + " newDbExists=" + newDbExists); } boolean removeOldDb = false; if (!newDbExists && oldDatabaseFile.exists()) { removeOldDb = migratePreNDbToCe(oldDatabaseFile, ceDatabaseFile); if (!newDbExists && preNDatabaseFile.exists()) { removeOldDb = migratePreNDbToCe(preNDatabaseFile, ceDatabaseFile); } // Try to open and upgrade if necessary CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, userId); CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, ceDatabaseFile.getPath()); ceHelper.getWritableDatabase(); ceHelper.close(); if (removeOldDb) { // TODO STOPSHIP - backup file during testing. Remove file before the release Log.i(TAG, "Migration complete - creating backup of old db " + oldDatabaseFile); renameToBakFile(oldDatabaseFile); Log.i(TAG, "Migration complete - creating backup of old db " + preNDatabaseFile); renameToBakFile(preNDatabaseFile); } return ceHelper; } Loading Loading @@ -4825,12 +4836,14 @@ public class AccountManagerService } } @VisibleForTesting protected void installNotification(final int notificationId, final Notification n, UserHandle user) { ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) .notifyAsUser(null, notificationId, n, user); } @VisibleForTesting protected void cancelNotification(int id, UserHandle user) { long identityToken = clearCallingIdentity(); try { Loading Loading @@ -5368,7 +5381,7 @@ public class AccountManagerService HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account); if (userDataForAccount == null) { // need to populate the cache for this account final SQLiteDatabase db = accounts.openHelper.getReadableDatabase(); final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked(); userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account); accounts.userDataCache.put(account, userDataForAccount); } Loading services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +120 −16 Original line number Diff line number Diff line Loading @@ -16,23 +16,34 @@ package com.android.server.accounts; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.accounts.Account; import android.accounts.AuthenticatorDescription; import android.app.AppOpsManager; import android.app.Notification; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.RegisteredServicesCache.ServiceInfo; import android.content.pm.RegisteredServicesCacheListener; import android.content.pm.UserInfo; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.test.AndroidTestCase; import android.test.IsolatedContext; import android.test.RenamingDelegatingContext; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.mock.MockPackageManager; import android.util.Log; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -41,20 +52,28 @@ import java.util.Collection; import java.util.Comparator; public class AccountManagerServiceTest extends AndroidTestCase { private static final String TAG = AccountManagerServiceTest.class.getSimpleName(); static final String PREN_DB = "pren.db"; static final String DE_DB = "de.db"; static final String CE_DB = "ce.db"; private AccountManagerService mAms; @Override protected void setUp() throws Exception { final String filenamePrefix = "test."; MockContentResolver resolver = new MockContentResolver(); RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext( new MyMockContext(), // The context that most methods are delegated to getContext(), // The context that file methods are delegated to filenamePrefix); Context context = new IsolatedContext(resolver, targetContextWrapper); setContext(context); Context realTestContext = getContext(); Context mockContext = new MyMockContext(realTestContext); setContext(mockContext); mAms = new MyAccountManagerService(getContext(), new MyMockPackageManager(), new MockAccountAuthenticatorCache()); new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realTestContext); } @Override protected void tearDown() throws Exception { new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)).delete(); new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)).delete(); new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)).delete(); super.tearDown(); } public class AccountSorter implements Comparator<Account> { Loading @@ -69,6 +88,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testCheckAddAccount() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a21 = new Account("account2", "type1"); Account a31 = new Account("account3", "type1"); Loading Loading @@ -109,6 +129,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testPasswords() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); mAms.addAccountExplicitly(a11, "p11", null); Loading @@ -124,6 +145,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testUserdata() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Bundle u11 = new Bundle(); u11.putString("a", "a_a11"); Loading Loading @@ -156,6 +178,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testAuthtokens() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); mAms.addAccountExplicitly(a11, "p11", null); Loading Loading @@ -188,15 +211,21 @@ public class AccountManagerServiceTest extends AndroidTestCase { assertNull(mAms.peekAuthToken(a12, "att2")); } private void unlockUser(int userId) { Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mAms.onUserUnlocked(intent); } static public class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache { private ArrayList<ServiceInfo<AuthenticatorDescription>> mServices; public MockAccountAuthenticatorCache() { mServices = new ArrayList<ServiceInfo<AuthenticatorDescription>>(); mServices = new ArrayList<>(); AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0); AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0); mServices.add(new ServiceInfo<AuthenticatorDescription>(d1, null, null)); mServices.add(new ServiceInfo<AuthenticatorDescription>(d2, null, null)); mServices.add(new ServiceInfo<>(d1, null, null)); mServices.add(new ServiceInfo<>(d2, null, null)); } @Override Loading Loading @@ -232,10 +261,68 @@ public class AccountManagerServiceTest extends AndroidTestCase { } static public class MyMockContext extends MockContext { private Context mTestContext; private AppOpsManager mAppOpsManager; private UserManager mUserManager; public MyMockContext(Context testContext) { this.mTestContext = testContext; this.mAppOpsManager = mock(AppOpsManager.class); this.mUserManager = mock(UserManager.class); final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0); when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui); } @Override public int checkCallingOrSelfPermission(final String permission) { return PackageManager.PERMISSION_GRANTED; } @Override public Object getSystemService(String name) { if (Context.APP_OPS_SERVICE.equals(name)) { return mAppOpsManager; } else if( Context.USER_SERVICE.equals(name)) { return mUserManager; } return null; } @Override public String getSystemServiceName(Class<?> serviceClass) { if (AppOpsManager.class.equals(serviceClass)) { return Context.APP_OPS_SERVICE; } return null; } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return null; } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return null; } @Override public SQLiteDatabase openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode); return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler); } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user); } @Override public String getOpPackageName() { return null; } } static public class MyMockPackageManager extends MockPackageManager { Loading @@ -246,9 +333,11 @@ public class AccountManagerServiceTest extends AndroidTestCase { } static public class MyAccountManagerService extends AccountManagerService { private Context mRealTestContext; public MyAccountManagerService(Context context, PackageManager packageManager, IAccountAuthenticatorCache authenticatorCache) { IAccountAuthenticatorCache authenticatorCache, Context realTestContext) { super(context, packageManager, authenticatorCache); this.mRealTestContext = realTestContext; } @Override Loading @@ -258,5 +347,20 @@ public class AccountManagerServiceTest extends AndroidTestCase { @Override protected void cancelNotification(final int id, UserHandle user) { } @Override protected String getCeDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), CE_DB).getPath(); } @Override protected String getDeDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), DE_DB).getPath(); } @Override String getPreNDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath(); } } } Loading
services/core/java/com/android/server/accounts/AccountManagerService.java +55 −42 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; Loading Loading @@ -267,10 +268,10 @@ public class AccountManagerService private int debugDbInsertionPoint = -1; private SQLiteStatement statementForLogging; UserAccounts(Context context, int userId) { UserAccounts(Context context, int userId, File preNDbFile, File deDbFile) { this.userId = userId; synchronized (cacheLock) { openHelper = DeDatabaseHelper.create(context, userId); openHelper = DeDatabaseHelper.create(context, userId, preNDbFile, deDbFile); } } } Loading Loading @@ -540,7 +541,9 @@ public class AccountManagerService UserAccounts accounts = mUsers.get(userId); boolean validateAccounts = false; if (accounts == null) { accounts = new UserAccounts(mContext, userId); File preNDbFile = new File(getPreNDatabaseName(userId)); File deDbFile = new File(getDeDatabaseName(userId)); accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile); initializeDebugDbSizeAndCompileSqlStatementForLogging( accounts.openHelper.getWritableDatabase(), accounts); mUsers.append(userId, accounts); Loading @@ -551,8 +554,10 @@ public class AccountManagerService if (!accounts.openHelper.isCeDatabaseAttached() && mUnlockedUsers.get(userId)) { Log.i(TAG, "User " + userId + " is unlocked - opening CE database"); synchronized (accounts.cacheLock) { CeDatabaseHelper.create(mContext, userId); accounts.openHelper.attachCeDatabase(); File preNDatabaseFile = new File(getPreNDatabaseName(userId)); File ceDatabaseFile = new File(getCeDatabaseName(userId)); CeDatabaseHelper.create(mContext, userId, preNDatabaseFile, ceDatabaseFile); accounts.openHelper.attachCeDatabase(ceDatabaseFile); } syncDeCeAccountsLocked(accounts); } Loading Loading @@ -647,7 +652,8 @@ public class AccountManagerService } } private void onUserUnlocked(Intent intent) { @VisibleForTesting void onUserUnlocked(Intent intent) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "onUserUnlocked " + userId); Loading Loading @@ -1553,7 +1559,7 @@ public class AccountManagerService } } /* For testing */ @VisibleForTesting protected void removeAccountInternal(Account account) { removeAccountInternal(getUserAccountsForCaller(), account, getCallingUid()); } Loading Loading @@ -4044,7 +4050,8 @@ public class AccountManagerService } } static String getPreNDatabaseName(int userId) { @VisibleForTesting String getPreNDatabaseName(int userId) { File systemDir = Environment.getDataSystemDirectory(); File databaseFile = new File(Environment.getUserSystemDirectory(userId), PRE_N_DATABASE_NAME); Loading @@ -4070,13 +4077,15 @@ public class AccountManagerService return databaseFile.getPath(); } static String getDeDatabaseName(int userId) { @VisibleForTesting String getDeDatabaseName(int userId) { File databaseFile = new File(Environment.getDataSystemDeDirectory(userId), DE_DATABASE_NAME); return databaseFile.getPath(); } static String getCeDatabaseName(int userId) { @VisibleForTesting String getCeDatabaseName(int userId) { File databaseFile = new File(Environment.getDataSystemCeDirectory(userId), CE_DATABASE_NAME); return databaseFile.getPath(); Loading Loading @@ -4217,13 +4226,11 @@ public class AccountManagerService } static class PreNDatabaseHelper extends SQLiteOpenHelper { private final Context mContext; private final int mUserId; public PreNDatabaseHelper(Context context, int userId) { super(context, AccountManagerService.getPreNDatabaseName(userId), null, PRE_N_DATABASE_VERSION); public PreNDatabaseHelper(Context context, int userId, String preNDatabaseName) { super(context, preNDatabaseName, null, PRE_N_DATABASE_VERSION); mContext = context; mUserId = userId; } Loading Loading @@ -4360,8 +4367,8 @@ public class AccountManagerService private final int mUserId; private volatile boolean mCeAttached; private DeDatabaseHelper(Context context, int userId) { super(context, getDeDatabaseName(userId), null, DE_DATABASE_VERSION); private DeDatabaseHelper(Context context, int userId, String deDatabaseName) { super(context, deDatabaseName, null, DE_DATABASE_VERSION); mUserId = userId; } Loading Loading @@ -4426,8 +4433,7 @@ public class AccountManagerService } } public void attachCeDatabase() { File ceDbFile = new File(getCeDatabaseName(mUserId)); public void attachCeDatabase(File ceDbFile) { SQLiteDatabase db = getWritableDatabase(); db.execSQL("ATTACH DATABASE '" + ceDbFile.getPath()+ "' AS ceDb"); mCeAttached = true; Loading @@ -4440,8 +4446,8 @@ public class AccountManagerService public SQLiteDatabase getReadableDatabaseUserIsUnlocked() { if(!mCeAttached) { Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked ", new Throwable()); Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked. CE database is not yet available.", new Throwable()); } return super.getReadableDatabase(); } Loading @@ -4449,7 +4455,7 @@ public class AccountManagerService public SQLiteDatabase getWritableDatabaseUserIsUnlocked() { if(!mCeAttached) { Log.wtf(TAG, "getWritableDatabaseUserIsUnlocked called while user " + mUserId + " is still locked ", new Throwable()); + " is still locked. CE database is not yet available.", new Throwable()); } return super.getWritableDatabase(); } Loading Loading @@ -4502,20 +4508,24 @@ public class AccountManagerService db.execSQL("DETACH DATABASE preNDb"); } static DeDatabaseHelper create(Context context, int userId) { File oldDb = new File(getPreNDatabaseName(userId)); File newDb = new File(getDeDatabaseName(userId)); boolean newDbExists = newDb.exists(); DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId); 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 && oldDb.exists()) { if (!newDbExists && preNDatabaseFile.exists()) { // Migrate legacy db to the latest version - PRE_N_DATABASE_VERSION PreNDatabaseHelper preNDatabaseHelper = new PreNDatabaseHelper(context, userId); 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(oldDb); deDatabaseHelper.migratePreNDbToDe(preNDatabaseFile); } return deDatabaseHelper; } Loading @@ -4523,8 +4533,8 @@ public class AccountManagerService static class CeDatabaseHelper extends SQLiteOpenHelper { public CeDatabaseHelper(Context context, int userId) { super(context, getCeDatabaseName(userId), null, CE_DATABASE_VERSION); public CeDatabaseHelper(Context context, String ceDatabaseName) { super(context, ceDatabaseName, null, CE_DATABASE_VERSION); } /** Loading Loading @@ -4640,27 +4650,28 @@ public class AccountManagerService * @param context * @param userId id of the user where the database is located */ static CeDatabaseHelper create(Context context, int userId) { File oldDatabaseFile = new File(getPreNDatabaseName(userId)); File ceDatabaseFile = new File(getCeDatabaseName(userId)); 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=" + oldDatabaseFile.exists() + " newDbExists=" + newDbExists); + preNDatabaseFile.exists() + " newDbExists=" + newDbExists); } boolean removeOldDb = false; if (!newDbExists && oldDatabaseFile.exists()) { removeOldDb = migratePreNDbToCe(oldDatabaseFile, ceDatabaseFile); if (!newDbExists && preNDatabaseFile.exists()) { removeOldDb = migratePreNDbToCe(preNDatabaseFile, ceDatabaseFile); } // Try to open and upgrade if necessary CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, userId); CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, ceDatabaseFile.getPath()); ceHelper.getWritableDatabase(); ceHelper.close(); if (removeOldDb) { // TODO STOPSHIP - backup file during testing. Remove file before the release Log.i(TAG, "Migration complete - creating backup of old db " + oldDatabaseFile); renameToBakFile(oldDatabaseFile); Log.i(TAG, "Migration complete - creating backup of old db " + preNDatabaseFile); renameToBakFile(preNDatabaseFile); } return ceHelper; } Loading Loading @@ -4825,12 +4836,14 @@ public class AccountManagerService } } @VisibleForTesting protected void installNotification(final int notificationId, final Notification n, UserHandle user) { ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) .notifyAsUser(null, notificationId, n, user); } @VisibleForTesting protected void cancelNotification(int id, UserHandle user) { long identityToken = clearCallingIdentity(); try { Loading Loading @@ -5368,7 +5381,7 @@ public class AccountManagerService HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account); if (userDataForAccount == null) { // need to populate the cache for this account final SQLiteDatabase db = accounts.openHelper.getReadableDatabase(); final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked(); userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account); accounts.userDataCache.put(account, userDataForAccount); } Loading
services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +120 −16 Original line number Diff line number Diff line Loading @@ -16,23 +16,34 @@ package com.android.server.accounts; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.accounts.Account; import android.accounts.AuthenticatorDescription; import android.app.AppOpsManager; import android.app.Notification; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.RegisteredServicesCache.ServiceInfo; import android.content.pm.RegisteredServicesCacheListener; import android.content.pm.UserInfo; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.test.AndroidTestCase; import android.test.IsolatedContext; import android.test.RenamingDelegatingContext; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.mock.MockPackageManager; import android.util.Log; import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; Loading @@ -41,20 +52,28 @@ import java.util.Collection; import java.util.Comparator; public class AccountManagerServiceTest extends AndroidTestCase { private static final String TAG = AccountManagerServiceTest.class.getSimpleName(); static final String PREN_DB = "pren.db"; static final String DE_DB = "de.db"; static final String CE_DB = "ce.db"; private AccountManagerService mAms; @Override protected void setUp() throws Exception { final String filenamePrefix = "test."; MockContentResolver resolver = new MockContentResolver(); RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext( new MyMockContext(), // The context that most methods are delegated to getContext(), // The context that file methods are delegated to filenamePrefix); Context context = new IsolatedContext(resolver, targetContextWrapper); setContext(context); Context realTestContext = getContext(); Context mockContext = new MyMockContext(realTestContext); setContext(mockContext); mAms = new MyAccountManagerService(getContext(), new MyMockPackageManager(), new MockAccountAuthenticatorCache()); new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realTestContext); } @Override protected void tearDown() throws Exception { new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)).delete(); new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)).delete(); new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)).delete(); super.tearDown(); } public class AccountSorter implements Comparator<Account> { Loading @@ -69,6 +88,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testCheckAddAccount() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a21 = new Account("account2", "type1"); Account a31 = new Account("account3", "type1"); Loading Loading @@ -109,6 +129,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testPasswords() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); mAms.addAccountExplicitly(a11, "p11", null); Loading @@ -124,6 +145,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testUserdata() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Bundle u11 = new Bundle(); u11.putString("a", "a_a11"); Loading Loading @@ -156,6 +178,7 @@ public class AccountManagerServiceTest extends AndroidTestCase { } public void testAuthtokens() throws Exception { unlockUser(UserHandle.USER_SYSTEM); Account a11 = new Account("account1", "type1"); Account a12 = new Account("account1", "type2"); mAms.addAccountExplicitly(a11, "p11", null); Loading Loading @@ -188,15 +211,21 @@ public class AccountManagerServiceTest extends AndroidTestCase { assertNull(mAms.peekAuthToken(a12, "att2")); } private void unlockUser(int userId) { Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mAms.onUserUnlocked(intent); } static public class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache { private ArrayList<ServiceInfo<AuthenticatorDescription>> mServices; public MockAccountAuthenticatorCache() { mServices = new ArrayList<ServiceInfo<AuthenticatorDescription>>(); mServices = new ArrayList<>(); AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0); AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0); mServices.add(new ServiceInfo<AuthenticatorDescription>(d1, null, null)); mServices.add(new ServiceInfo<AuthenticatorDescription>(d2, null, null)); mServices.add(new ServiceInfo<>(d1, null, null)); mServices.add(new ServiceInfo<>(d2, null, null)); } @Override Loading Loading @@ -232,10 +261,68 @@ public class AccountManagerServiceTest extends AndroidTestCase { } static public class MyMockContext extends MockContext { private Context mTestContext; private AppOpsManager mAppOpsManager; private UserManager mUserManager; public MyMockContext(Context testContext) { this.mTestContext = testContext; this.mAppOpsManager = mock(AppOpsManager.class); this.mUserManager = mock(UserManager.class); final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0); when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui); } @Override public int checkCallingOrSelfPermission(final String permission) { return PackageManager.PERMISSION_GRANTED; } @Override public Object getSystemService(String name) { if (Context.APP_OPS_SERVICE.equals(name)) { return mAppOpsManager; } else if( Context.USER_SERVICE.equals(name)) { return mUserManager; } return null; } @Override public String getSystemServiceName(Class<?> serviceClass) { if (AppOpsManager.class.equals(serviceClass)) { return Context.APP_OPS_SERVICE; } return null; } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return null; } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return null; } @Override public SQLiteDatabase openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode); return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler); } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user); } @Override public String getOpPackageName() { return null; } } static public class MyMockPackageManager extends MockPackageManager { Loading @@ -246,9 +333,11 @@ public class AccountManagerServiceTest extends AndroidTestCase { } static public class MyAccountManagerService extends AccountManagerService { private Context mRealTestContext; public MyAccountManagerService(Context context, PackageManager packageManager, IAccountAuthenticatorCache authenticatorCache) { IAccountAuthenticatorCache authenticatorCache, Context realTestContext) { super(context, packageManager, authenticatorCache); this.mRealTestContext = realTestContext; } @Override Loading @@ -258,5 +347,20 @@ public class AccountManagerServiceTest extends AndroidTestCase { @Override protected void cancelNotification(final int id, UserHandle user) { } @Override protected String getCeDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), CE_DB).getPath(); } @Override protected String getDeDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), DE_DB).getPath(); } @Override String getPreNDatabaseName(int userId) { return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath(); } } }