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.providers.contacts; 18 19 import android.accounts.Account; 20 import android.content.Context; 21 import android.database.sqlite.SQLiteDatabase; 22 import android.util.Log; 23 24 import junit.framework.Assert; 25 26 import java.util.Locale; 27 28 /** 29 * A version of {@link ContactsProvider2} class that performs aggregation 30 * synchronously and wipes all data at construction time. 31 */ 32 public class SynchronousContactsProvider2 extends ContactsProvider2 { 33 public static final String READ_ONLY_ACCOUNT_TYPE = "ro"; 34 35 private static final Object sDataWipedLock = new Object(); 36 private static boolean sDataWiped = false; 37 private static ContactsDatabaseHelper sDbHelper; 38 private Account mAccount; 39 private boolean mNetworkNotified; 40 private boolean mIsPhone = true; 41 private boolean mIsVoiceCapable = true; 42 43 @Override newDatabaseHelper(final Context context)44 public ContactsDatabaseHelper newDatabaseHelper(final Context context) { 45 if (sDbHelper == null) { 46 sDbHelper = ContactsDatabaseHelper.getNewInstanceForTest(context, 47 TestUtils.getContactsDatabaseFilename(getContext())); 48 } 49 return sDbHelper; 50 } 51 52 @Override newProfileProvider()53 public ProfileProvider newProfileProvider() { 54 return new SynchronousProfileProvider(this); 55 } 56 getProfileDatabaseHelper()57 public ProfileDatabaseHelper getProfileDatabaseHelper() { 58 return getProfileProviderForTest().getDatabaseHelper(); 59 } 60 61 @Override onBegin()62 public void onBegin() { 63 super.onBegin(); 64 mNetworkNotified = false; 65 } 66 67 @Override notifyChange(boolean syncToNetwork)68 protected void notifyChange(boolean syncToNetwork) { 69 mNetworkNotified |= syncToNetwork; 70 } 71 isNetworkNotified()72 public boolean isNetworkNotified() { 73 return mNetworkNotified; 74 } 75 setIsPhone(boolean flag)76 public void setIsPhone(boolean flag) { 77 mIsPhone = flag; 78 } 79 80 @Override isPhone()81 public boolean isPhone() { 82 return mIsPhone; 83 } 84 setIsVoiceCapable(boolean flag)85 public void setIsVoiceCapable(boolean flag) { 86 mIsVoiceCapable = flag; 87 } 88 89 @Override isVoiceCapable()90 public boolean isVoiceCapable() { 91 return mIsVoiceCapable; 92 } 93 94 @Override onCreate()95 public boolean onCreate() { 96 boolean created = super.onCreate(); 97 synchronized (sDataWipedLock) { 98 if (!sDataWiped) { 99 sDataWiped = true; 100 wipeData(); 101 } 102 } 103 return created; 104 } 105 106 @Override shouldThrowExceptionForInitializationError()107 protected boolean shouldThrowExceptionForInitializationError() { 108 return true; 109 } 110 111 /** We'll use a static size for unit tests */ 112 @Override getMaxThumbnailDim()113 public int getMaxThumbnailDim() { 114 return 96; 115 } 116 117 /** We'll use a static size for unit tests */ 118 @Override getMaxDisplayPhotoDim()119 public int getMaxDisplayPhotoDim() { 120 return 256; 121 } 122 123 @Override scheduleBackgroundTask(int task)124 protected void scheduleBackgroundTask(int task) { 125 performBackgroundTask(task, null); 126 } 127 128 @Override scheduleBackgroundTask(int task, Object arg)129 protected void scheduleBackgroundTask(int task, Object arg) { 130 performBackgroundTask(task, arg); 131 } 132 133 @Override updateLocaleInBackground()134 protected void updateLocaleInBackground() { 135 } 136 137 @Override updateDirectoriesInBackground(boolean rescan)138 protected void updateDirectoriesInBackground(boolean rescan) { 139 } 140 141 @Override getDefaultAccount()142 protected Account getDefaultAccount() { 143 if (mAccount == null) { 144 mAccount = new Account("androidtest@gmail.com", "com.google"); 145 } 146 return mAccount; 147 } 148 149 @Override isContactsAccount(Account account)150 protected boolean isContactsAccount(Account account) { 151 return true; 152 } 153 154 /** 155 * Creates a mock PhotoPriorityResolver 156 */ 157 @Override createPhotoPriorityResolver(Context context)158 PhotoPriorityResolver createPhotoPriorityResolver(Context context) { 159 return new PhotoPriorityResolver(context) { 160 @Override 161 public synchronized int getPhotoPriority(String accountType) { 162 if ("cupcake".equals(accountType)) { 163 return 3; 164 } 165 if ("donut".equals(accountType)) { 166 return 2; 167 } 168 if ("froyo".equals(accountType)) { 169 return 1; 170 } 171 return 0; 172 } 173 }; 174 } 175 176 @Override 177 protected Locale getLocale() { 178 return Locale.US; 179 } 180 181 @Override 182 protected boolean isContactSharingEnabledForCloneProfile() { 183 return true; 184 } 185 186 @Override 187 public boolean isWritableAccountWithDataSet(String accountType) { 188 return !READ_ONLY_ACCOUNT_TYPE.equals(accountType); 189 } 190 191 public void prepareForFullAggregation(int maxContact) { 192 SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); 193 db.execSQL("UPDATE raw_contacts SET aggregation_mode=0,aggregation_needed=1;"); 194 long rowId = 195 db.compileStatement("SELECT _id FROM raw_contacts LIMIT 1 OFFSET " + maxContact) 196 .simpleQueryForLong(); 197 db.execSQL("DELETE FROM raw_contacts WHERE _id > " + rowId + ";"); 198 } 199 200 public long getRawContactCount() { 201 SQLiteDatabase db = getDatabaseHelper().getReadableDatabase(); 202 return db.compileStatement("SELECT COUNT(*) FROM raw_contacts").simpleQueryForLong(); 203 } 204 205 public long getContactCount() { 206 SQLiteDatabase db = getDatabaseHelper().getReadableDatabase(); 207 return db.compileStatement("SELECT COUNT(*) FROM contacts").simpleQueryForLong(); 208 } 209 210 @Override 211 public void wipeData() { 212 Log.i(TAG, "wipeData"); 213 super.wipeData(); 214 SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); 215 db.execSQL("replace into SQLITE_SEQUENCE (name,seq) values('raw_contacts', 42)"); 216 db.execSQL("replace into SQLITE_SEQUENCE (name,seq) values('contacts', 2009)"); 217 db.execSQL("replace into SQLITE_SEQUENCE (name,seq) values('data', 777)"); 218 219 getContactDirectoryManagerForTest().scanAllPackages(/* rescan= */ true); 220 } 221 222 // Flags to remember which transaction callback has been called for which mode. 223 private boolean mOnBeginTransactionInternalCalledInProfileMode; 224 private boolean mOnCommitTransactionInternalCalledInProfileMode; 225 private boolean mOnRollbackTransactionInternalCalledInProfileMode; 226 227 private boolean mOnBeginTransactionInternalCalledInContactMode; 228 private boolean mOnCommitTransactionInternalCalledInContactMode; 229 private boolean mOnRollbackTransactionInternalCalledInContactMode; 230 231 public void resetTrasactionCallbackCalledFlags() { 232 mOnBeginTransactionInternalCalledInProfileMode = false; 233 mOnCommitTransactionInternalCalledInProfileMode = false; 234 mOnRollbackTransactionInternalCalledInProfileMode = false; 235 236 mOnBeginTransactionInternalCalledInContactMode = false; 237 mOnCommitTransactionInternalCalledInContactMode = false; 238 mOnRollbackTransactionInternalCalledInContactMode = false; 239 } 240 241 @Override 242 protected void onBeginTransactionInternal(boolean forProfile) { 243 super.onBeginTransactionInternal(forProfile); 244 if (forProfile) { 245 mOnBeginTransactionInternalCalledInProfileMode = true; 246 } else { 247 mOnBeginTransactionInternalCalledInContactMode = true; 248 } 249 } 250 251 @Override 252 protected void onCommitTransactionInternal(boolean forProfile) { 253 super.onCommitTransactionInternal(forProfile); 254 if (forProfile) { 255 mOnCommitTransactionInternalCalledInProfileMode = true; 256 } else { 257 mOnCommitTransactionInternalCalledInContactMode = true; 258 } 259 } 260 261 @Override 262 protected void onRollbackTransactionInternal(boolean forProfile) { 263 super.onRollbackTransactionInternal(forProfile); 264 if (forProfile) { 265 mOnRollbackTransactionInternalCalledInProfileMode = true; 266 } else { 267 mOnRollbackTransactionInternalCalledInContactMode = true; 268 } 269 } 270 271 public void assertCommitTransactionCalledForProfileMode() { 272 Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode); 273 Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInProfileMode); 274 Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode); 275 } 276 277 public void assertRollbackTransactionCalledForProfileMode() { 278 Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode); 279 Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode); 280 Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInProfileMode); 281 } 282 283 public void assertNoTransactionsForProfileMode() { 284 Assert.assertFalse("begin", mOnBeginTransactionInternalCalledInProfileMode); 285 Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode); 286 Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode); 287 } 288 289 290 public void assertCommitTransactionCalledForContactMode() { 291 Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode); 292 Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInContactMode); 293 Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInContactMode); 294 } 295 296 public void assertRollbackTransactionCalledForContactMode() { 297 Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode); 298 Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInContactMode); 299 Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInContactMode); 300 } 301 } 302