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