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