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