• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.accounts;
18 
19 import static org.mockito.Matchers.eq;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.when;
22 
23 import android.accounts.Account;
24 import android.accounts.AuthenticatorDescription;
25 import android.app.AppOpsManager;
26 import android.app.Notification;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.pm.PackageManager;
32 import android.content.pm.RegisteredServicesCache.ServiceInfo;
33 import android.content.pm.RegisteredServicesCacheListener;
34 import android.content.pm.UserInfo;
35 import android.database.Cursor;
36 import android.database.DatabaseErrorHandler;
37 import android.database.sqlite.SQLiteDatabase;
38 import android.os.Bundle;
39 import android.os.Handler;
40 import android.os.UserHandle;
41 import android.os.UserManager;
42 import android.test.AndroidTestCase;
43 import android.test.mock.MockContext;
44 import android.test.mock.MockPackageManager;
45 import android.util.Log;
46 
47 import java.io.File;
48 import java.io.FileDescriptor;
49 import java.io.PrintWriter;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collection;
53 import java.util.Comparator;
54 
55 public class AccountManagerServiceTest extends AndroidTestCase {
56     private static final String TAG = AccountManagerServiceTest.class.getSimpleName();
57 
58     static final String PREN_DB = "pren.db";
59     static final String DE_DB = "de.db";
60     static final String CE_DB = "ce.db";
61     private AccountManagerService mAms;
62 
63     @Override
setUp()64     protected void setUp() throws Exception {
65         Context realTestContext = getContext();
66         Context mockContext = new MyMockContext(realTestContext);
67         setContext(mockContext);
68         mAms = createAccountManagerService(mockContext, realTestContext);
69     }
70 
71     @Override
tearDown()72     protected void tearDown() throws Exception {
73         SQLiteDatabase.deleteDatabase(new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)));
74         SQLiteDatabase.deleteDatabase(new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)));
75         SQLiteDatabase.deleteDatabase(new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)));
76         super.tearDown();
77     }
78 
79     public class AccountSorter implements Comparator<Account> {
compare(Account object1, Account object2)80         public int compare(Account object1, Account object2) {
81             if (object1 == object2) return 0;
82             if (object1 == null) return 1;
83             if (object2 == null) return -1;
84             int result = object1.type.compareTo(object2.type);
85             if (result != 0) return result;
86             return object1.name.compareTo(object2.name);
87         }
88     }
89 
testCheckAddAccount()90     public void testCheckAddAccount() throws Exception {
91         unlockSystemUser();
92         Account a11 = new Account("account1", "type1");
93         Account a21 = new Account("account2", "type1");
94         Account a31 = new Account("account3", "type1");
95         Account a12 = new Account("account1", "type2");
96         Account a22 = new Account("account2", "type2");
97         Account a32 = new Account("account3", "type2");
98         mAms.addAccountExplicitly(a11, "p11", null);
99         mAms.addAccountExplicitly(a12, "p12", null);
100         mAms.addAccountExplicitly(a21, "p21", null);
101         mAms.addAccountExplicitly(a22, "p22", null);
102         mAms.addAccountExplicitly(a31, "p31", null);
103         mAms.addAccountExplicitly(a32, "p32", null);
104 
105         Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
106         Arrays.sort(accounts, new AccountSorter());
107         assertEquals(6, accounts.length);
108         assertEquals(a11, accounts[0]);
109         assertEquals(a21, accounts[1]);
110         assertEquals(a31, accounts[2]);
111         assertEquals(a12, accounts[3]);
112         assertEquals(a22, accounts[4]);
113         assertEquals(a32, accounts[5]);
114 
115         accounts = mAms.getAccounts("type1", mContext.getOpPackageName());
116         Arrays.sort(accounts, new AccountSorter());
117         assertEquals(3, accounts.length);
118         assertEquals(a11, accounts[0]);
119         assertEquals(a21, accounts[1]);
120         assertEquals(a31, accounts[2]);
121 
122         mAms.removeAccountInternal(a21);
123 
124         accounts = mAms.getAccounts("type1", mContext.getOpPackageName());
125         Arrays.sort(accounts, new AccountSorter());
126         assertEquals(2, accounts.length);
127         assertEquals(a11, accounts[0]);
128         assertEquals(a31, accounts[1]);
129     }
130 
testPasswords()131     public void testPasswords() throws Exception {
132         unlockSystemUser();
133         Account a11 = new Account("account1", "type1");
134         Account a12 = new Account("account1", "type2");
135         mAms.addAccountExplicitly(a11, "p11", null);
136         mAms.addAccountExplicitly(a12, "p12", null);
137 
138         assertEquals("p11", mAms.getPassword(a11));
139         assertEquals("p12", mAms.getPassword(a12));
140 
141         mAms.setPassword(a11, "p11b");
142 
143         assertEquals("p11b", mAms.getPassword(a11));
144         assertEquals("p12", mAms.getPassword(a12));
145     }
146 
testUserdata()147     public void testUserdata() throws Exception {
148         unlockSystemUser();
149         Account a11 = new Account("account1", "type1");
150         Bundle u11 = new Bundle();
151         u11.putString("a", "a_a11");
152         u11.putString("b", "b_a11");
153         u11.putString("c", "c_a11");
154         Account a12 = new Account("account1", "type2");
155         Bundle u12 = new Bundle();
156         u12.putString("a", "a_a12");
157         u12.putString("b", "b_a12");
158         u12.putString("c", "c_a12");
159         mAms.addAccountExplicitly(a11, "p11", u11);
160         mAms.addAccountExplicitly(a12, "p12", u12);
161 
162         assertEquals("a_a11", mAms.getUserData(a11, "a"));
163         assertEquals("b_a11", mAms.getUserData(a11, "b"));
164         assertEquals("c_a11", mAms.getUserData(a11, "c"));
165         assertEquals("a_a12", mAms.getUserData(a12, "a"));
166         assertEquals("b_a12", mAms.getUserData(a12, "b"));
167         assertEquals("c_a12", mAms.getUserData(a12, "c"));
168 
169         mAms.setUserData(a11, "b", "b_a11b");
170         mAms.setUserData(a12, "c", null);
171 
172         assertEquals("a_a11", mAms.getUserData(a11, "a"));
173         assertEquals("b_a11b", mAms.getUserData(a11, "b"));
174         assertEquals("c_a11", mAms.getUserData(a11, "c"));
175         assertEquals("a_a12", mAms.getUserData(a12, "a"));
176         assertEquals("b_a12", mAms.getUserData(a12, "b"));
177         assertNull(mAms.getUserData(a12, "c"));
178     }
179 
testAuthtokens()180     public void testAuthtokens() throws Exception {
181         unlockSystemUser();
182         Account a11 = new Account("account1", "type1");
183         Account a12 = new Account("account1", "type2");
184         mAms.addAccountExplicitly(a11, "p11", null);
185         mAms.addAccountExplicitly(a12, "p12", null);
186 
187         mAms.setAuthToken(a11, "att1", "a11_att1");
188         mAms.setAuthToken(a11, "att2", "a11_att2");
189         mAms.setAuthToken(a11, "att3", "a11_att3");
190         mAms.setAuthToken(a12, "att1", "a12_att1");
191         mAms.setAuthToken(a12, "att2", "a12_att2");
192         mAms.setAuthToken(a12, "att3", "a12_att3");
193 
194         assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1"));
195         assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2"));
196         assertEquals("a11_att3", mAms.peekAuthToken(a11, "att3"));
197         assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1"));
198         assertEquals("a12_att2", mAms.peekAuthToken(a12, "att2"));
199         assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3"));
200 
201         mAms.setAuthToken(a11, "att3", "a11_att3b");
202         mAms.invalidateAuthToken(a12.type, "a12_att2");
203 
204         assertEquals("a11_att1", mAms.peekAuthToken(a11, "att1"));
205         assertEquals("a11_att2", mAms.peekAuthToken(a11, "att2"));
206         assertEquals("a11_att3b", mAms.peekAuthToken(a11, "att3"));
207         assertEquals("a12_att1", mAms.peekAuthToken(a12, "att1"));
208         assertNull(mAms.peekAuthToken(a12, "att2"));
209         assertEquals("a12_att3", mAms.peekAuthToken(a12, "att3"));
210 
211         assertNull(mAms.peekAuthToken(a12, "att2"));
212     }
213 
testRemovedAccountSync()214     public void testRemovedAccountSync() throws Exception {
215         unlockSystemUser();
216         Account a1 = new Account("account1", "type1");
217         Account a2 = new Account("account2", "type2");
218         mAms.addAccountExplicitly(a1, "p1", null);
219         mAms.addAccountExplicitly(a2, "p2", null);
220 
221         Context originalContext = ((MyMockContext)getContext()).mTestContext;
222         // create a separate instance of AMS. It initially assumes that user0 is locked
223         AccountManagerService ams2 = createAccountManagerService(getContext(), originalContext);
224 
225         // Verify that account can be removed when user is locked
226         ams2.removeAccountInternal(a1);
227         Account[] accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName());
228         assertEquals(1, accounts.length);
229         assertEquals("Only a2 should be returned", a2, accounts[0]);
230 
231         // Verify that CE db file is unchanged and still has 2 accounts
232         String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
233         int accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
234         assertEquals("CE database should still have 2 accounts", 2, accountsNumber);
235 
236         // Unlock the user and verify that db has been updated
237         ams2.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
238         accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
239         assertEquals("CE database should now have 1 account", 2, accountsNumber);
240         accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName());
241         assertEquals(1, accounts.length);
242         assertEquals("Only a2 should be returned", a2, accounts[0]);
243     }
244 
testPreNDatabaseMigration()245     public void testPreNDatabaseMigration() throws Exception {
246         String preNDatabaseName = mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM);
247         Context originalContext = ((MyMockContext) getContext()).mTestContext;
248         PreNTestDatabaseHelper.createV4Database(originalContext, preNDatabaseName);
249         // Assert that database was created with 1 account
250         int n = readNumberOfAccountsFromDbFile(originalContext, preNDatabaseName);
251         assertEquals("pre-N database should have 1 account", 1, n);
252 
253         // Start testing
254         unlockSystemUser();
255         Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
256         assertEquals("1 account should be migrated", 1, accounts.length);
257         assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
258         assertEquals(PreNTestDatabaseHelper.ACCOUNT_PASSWORD, mAms.getPassword(accounts[0]));
259         assertEquals("Authtoken should be migrated",
260                 PreNTestDatabaseHelper.TOKEN_STRING,
261                 mAms.peekAuthToken(accounts[0], PreNTestDatabaseHelper.TOKEN_TYPE));
262 
263         assertFalse("pre-N database file should be removed but was found at " + preNDatabaseName,
264                 new File(preNDatabaseName).exists());
265 
266         // Verify that ce/de files are present
267         String deDatabaseName = mAms.getDeDatabaseName(UserHandle.USER_SYSTEM);
268         String ceDatabaseName = mAms.getCeDatabaseName(UserHandle.USER_SYSTEM);
269         assertTrue("DE database file should be created at " + deDatabaseName,
270                 new File(deDatabaseName).exists());
271         assertTrue("CE database file should be created at " + ceDatabaseName,
272                 new File(ceDatabaseName).exists());
273     }
274 
readNumberOfAccountsFromDbFile(Context context, String dbName)275     private int readNumberOfAccountsFromDbFile(Context context, String dbName) {
276         SQLiteDatabase ceDb = context.openOrCreateDatabase(dbName, 0, null);
277         try (Cursor cursor = ceDb.rawQuery("SELECT count(*) FROM accounts", null)) {
278             assertTrue(cursor.moveToNext());
279             return cursor.getInt(0);
280         }
281     }
282 
createAccountManagerService(Context mockContext, Context realContext)283     private AccountManagerService createAccountManagerService(Context mockContext,
284             Context realContext) {
285         return new MyAccountManagerService(mockContext,
286                 new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realContext);
287     }
288 
unlockSystemUser()289     private void unlockSystemUser() {
290         mAms.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
291     }
292 
newIntentForUser(int userId)293     private static Intent newIntentForUser(int userId) {
294         Intent intent = new Intent();
295         intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
296         return intent;
297     }
298 
299     static public class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache {
300         private ArrayList<ServiceInfo<AuthenticatorDescription>> mServices;
301 
MockAccountAuthenticatorCache()302         public MockAccountAuthenticatorCache() {
303             mServices = new ArrayList<>();
304             AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0);
305             AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0);
306             mServices.add(new ServiceInfo<>(d1, null, null));
307             mServices.add(new ServiceInfo<>(d2, null, null));
308         }
309 
310         @Override
getServiceInfo( AuthenticatorDescription type, int userId)311         public ServiceInfo<AuthenticatorDescription> getServiceInfo(
312                 AuthenticatorDescription type, int userId) {
313             for (ServiceInfo<AuthenticatorDescription> service : mServices) {
314                 if (service.type.equals(type)) {
315                     return service;
316                 }
317             }
318             return null;
319         }
320 
321         @Override
getAllServices(int userId)322         public Collection<ServiceInfo<AuthenticatorDescription>> getAllServices(int userId) {
323             return mServices;
324         }
325 
326         @Override
dump( final FileDescriptor fd, final PrintWriter fout, final String[] args, int userId)327         public void dump(
328                 final FileDescriptor fd, final PrintWriter fout, final String[] args, int userId) {
329         }
330 
331         @Override
setListener( final RegisteredServicesCacheListener<AuthenticatorDescription> listener, final Handler handler)332         public void setListener(
333                 final RegisteredServicesCacheListener<AuthenticatorDescription> listener,
334                 final Handler handler) {
335         }
336 
337         @Override
invalidateCache(int userId)338         public void invalidateCache(int userId) {
339         }
340 
341         @Override
updateServices(int userId)342         public void updateServices(int userId) {
343         }
344     }
345 
346     static public class MyMockContext extends MockContext {
347         private Context mTestContext;
348         private AppOpsManager mAppOpsManager;
349         private UserManager mUserManager;
350         private PackageManager mPackageManager;
351 
MyMockContext(Context testContext)352         public MyMockContext(Context testContext) {
353             this.mTestContext = testContext;
354             this.mAppOpsManager = mock(AppOpsManager.class);
355             this.mUserManager = mock(UserManager.class);
356             this.mPackageManager = mock(PackageManager.class);
357             final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
358             when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui);
359         }
360 
361         @Override
checkCallingOrSelfPermission(final String permission)362         public int checkCallingOrSelfPermission(final String permission) {
363             return PackageManager.PERMISSION_GRANTED;
364         }
365 
366         @Override
getPackageManager()367         public PackageManager getPackageManager() {
368             return mPackageManager;
369         }
370 
371         @Override
getSystemService(String name)372         public Object getSystemService(String name) {
373             if (Context.APP_OPS_SERVICE.equals(name)) {
374                 return mAppOpsManager;
375             } else if( Context.USER_SERVICE.equals(name)) {
376                 return mUserManager;
377             }
378             return null;
379         }
380 
381         @Override
getSystemServiceName(Class<?> serviceClass)382         public String getSystemServiceName(Class<?> serviceClass) {
383             if (AppOpsManager.class.equals(serviceClass)) {
384                 return Context.APP_OPS_SERVICE;
385             }
386             return null;
387         }
388 
389         @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)390         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
391             return null;
392         }
393 
394         @Override
registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler)395         public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
396                 IntentFilter filter, String broadcastPermission, Handler scheduler) {
397             return null;
398         }
399 
400         @Override
openOrCreateDatabase(String file, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler)401         public SQLiteDatabase openOrCreateDatabase(String file, int mode,
402                 SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
403             Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode);
404             return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler);
405         }
406 
407         @Override
sendBroadcastAsUser(Intent intent, UserHandle user)408         public void sendBroadcastAsUser(Intent intent, UserHandle user) {
409             Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user);
410         }
411 
412         @Override
getOpPackageName()413         public String getOpPackageName() {
414             return null;
415         }
416     }
417 
418     static public class MyMockPackageManager extends MockPackageManager {
419         @Override
checkSignatures(final int uid1, final int uid2)420         public int checkSignatures(final int uid1, final int uid2) {
421             return PackageManager.SIGNATURE_MATCH;
422         }
423     }
424 
425     static public class MyAccountManagerService extends AccountManagerService {
426         private Context mRealTestContext;
MyAccountManagerService(Context context, PackageManager packageManager, IAccountAuthenticatorCache authenticatorCache, Context realTestContext)427         public MyAccountManagerService(Context context, PackageManager packageManager,
428                 IAccountAuthenticatorCache authenticatorCache, Context realTestContext) {
429             super(context, packageManager, authenticatorCache);
430             this.mRealTestContext = realTestContext;
431         }
432 
433         @Override
installNotification(final int notificationId, final Notification n, UserHandle user)434         protected void installNotification(final int notificationId, final Notification n, UserHandle user) {
435         }
436 
437         @Override
cancelNotification(final int id, UserHandle user)438         protected void cancelNotification(final int id, UserHandle user) {
439         }
440 
441         @Override
getCeDatabaseName(int userId)442         protected String getCeDatabaseName(int userId) {
443             return new File(mRealTestContext.getCacheDir(), CE_DB).getPath();
444         }
445 
446         @Override
getDeDatabaseName(int userId)447         protected String getDeDatabaseName(int userId) {
448             return new File(mRealTestContext.getCacheDir(), DE_DB).getPath();
449         }
450 
451         @Override
getPreNDatabaseName(int userId)452         String getPreNDatabaseName(int userId) {
453             return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath();
454         }
455     }
456 }
457