1 /* 2 * Copyright (C) 2007 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 android.content; 18 19 import android.database.Cursor; 20 import android.database.sqlite.SQLiteDatabase; 21 import android.net.Uri; 22 import android.accounts.Account; 23 24 import java.util.Map; 25 26 /** 27 * A specialization of the ContentProvider that centralizes functionality 28 * used by ContentProviders that are syncable. It also wraps calls to the ContentProvider 29 * inside of database transactions. 30 * 31 * @hide 32 */ 33 public abstract class SyncableContentProvider extends ContentProvider { isTemporary()34 protected abstract boolean isTemporary(); 35 36 private volatile TempProviderSyncAdapter mTempProviderSyncAdapter; 37 setTempProviderSyncAdapter(TempProviderSyncAdapter syncAdapter)38 public void setTempProviderSyncAdapter(TempProviderSyncAdapter syncAdapter) { 39 mTempProviderSyncAdapter = syncAdapter; 40 } 41 getTempProviderSyncAdapter()42 public TempProviderSyncAdapter getTempProviderSyncAdapter() { 43 return mTempProviderSyncAdapter; 44 } 45 46 /** 47 * Close resources that must be closed. You must call this to properly release 48 * the resources used by the SyncableContentProvider. 49 */ close()50 public abstract void close(); 51 52 /** 53 * Override to create your schema and do anything else you need to do with a new database. 54 * This is run inside a transaction (so you don't need to use one). 55 * This method may not use getDatabase(), or call content provider methods, it must only 56 * use the database handle passed to it. 57 */ bootstrapDatabase(SQLiteDatabase db)58 protected abstract void bootstrapDatabase(SQLiteDatabase db); 59 60 /** 61 * Override to upgrade your database from an old version to the version you specified. 62 * Don't set the DB version, this will automatically be done after the method returns. 63 * This method may not use getDatabase(), or call content provider methods, it must only 64 * use the database handle passed to it. 65 * 66 * @param oldVersion version of the existing database 67 * @param newVersion current version to upgrade to 68 * @return true if the upgrade was lossless, false if it was lossy 69 */ upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion)70 protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion); 71 72 /** 73 * Override to do anything (like cleanups or checks) you need to do after opening a database. 74 * Does nothing by default. This is run inside a transaction (so you don't need to use one). 75 * This method may not use getDatabase(), or call content provider methods, it must only 76 * use the database handle passed to it. 77 */ onDatabaseOpened(SQLiteDatabase db)78 protected abstract void onDatabaseOpened(SQLiteDatabase db); 79 80 /** 81 * Get a non-persistent instance of this content provider. 82 * You must call {@link #close} on the returned 83 * SyncableContentProvider when you are done with it. 84 * 85 * @return a non-persistent content provider with the same layout as this 86 * provider. 87 */ getTemporaryInstance()88 public abstract SyncableContentProvider getTemporaryInstance(); 89 getDatabase()90 public abstract SQLiteDatabase getDatabase(); 91 getContainsDiffs()92 public abstract boolean getContainsDiffs(); 93 setContainsDiffs(boolean containsDiffs)94 public abstract void setContainsDiffs(boolean containsDiffs); 95 96 /** 97 * Each subclass of this class should define a subclass of {@link 98 * AbstractTableMerger} for each table they wish to merge. It 99 * should then override this method and return one instance of 100 * each merger, in sequence. Their {@link 101 * AbstractTableMerger#merge merge} methods will be called, one at a 102 * time, in the order supplied. 103 * 104 * <p>The default implementation returns an empty list, so that no 105 * merging will occur. 106 * @return A sequence of subclasses of {@link 107 * AbstractTableMerger}, one for each table that should be merged. 108 */ getMergers()109 protected abstract Iterable<? extends AbstractTableMerger> getMergers(); 110 111 /** 112 * Check if changes to this URI can be syncable changes. 113 * @param uri the URI of the resource that was changed 114 * @return true if changes to this URI can be syncable changes, false otherwise 115 */ changeRequiresLocalSync(Uri uri)116 public abstract boolean changeRequiresLocalSync(Uri uri); 117 118 /** 119 * Called right before a sync is started. 120 * 121 * @param context the sync context for the operation 122 * @param account 123 */ onSyncStart(SyncContext context, Account account)124 public abstract void onSyncStart(SyncContext context, Account account); 125 126 /** 127 * Called right after a sync is completed 128 * 129 * @param context the sync context for the operation 130 * @param success true if the sync succeeded, false if an error occurred 131 */ onSyncStop(SyncContext context, boolean success)132 public abstract void onSyncStop(SyncContext context, boolean success); 133 134 /** 135 * The account of the most recent call to onSyncStart() 136 * @return the account 137 */ getSyncingAccount()138 public abstract Account getSyncingAccount(); 139 140 /** 141 * Merge diffs from a sync source with this content provider. 142 * 143 * @param context the SyncContext within which this merge is taking place 144 * @param diffs A temporary content provider containing diffs from a sync 145 * source. 146 * @param result a MergeResult that contains information about the merge, including 147 * a temporary content provider with the same layout as this provider containing 148 * @param syncResult 149 */ merge(SyncContext context, SyncableContentProvider diffs, TempProviderSyncResult result, SyncResult syncResult)150 public abstract void merge(SyncContext context, SyncableContentProvider diffs, 151 TempProviderSyncResult result, SyncResult syncResult); 152 153 154 /** 155 * Invoked when the active sync has been canceled. The default 156 * implementation doesn't do anything (except ensure that this 157 * provider is syncable). Subclasses of ContentProvider 158 * that support canceling of sync should override this. 159 */ onSyncCanceled()160 public abstract void onSyncCanceled(); 161 162 isMergeCancelled()163 public abstract boolean isMergeCancelled(); 164 165 /** 166 * Subclasses should override this instead of update(). See update() 167 * for details. 168 * 169 * <p> This method is called within a acquireDbLock()/releaseDbLock() block, 170 * which means a database transaction will be active during the call; 171 */ updateInternal(Uri url, ContentValues values, String selection, String[] selectionArgs)172 protected abstract int updateInternal(Uri url, ContentValues values, 173 String selection, String[] selectionArgs); 174 175 /** 176 * Subclasses should override this instead of delete(). See delete() 177 * for details. 178 * 179 * <p> This method is called within a acquireDbLock()/releaseDbLock() block, 180 * which means a database transaction will be active during the call; 181 */ deleteInternal(Uri url, String selection, String[] selectionArgs)182 protected abstract int deleteInternal(Uri url, String selection, String[] selectionArgs); 183 184 /** 185 * Subclasses should override this instead of insert(). See insert() 186 * for details. 187 * 188 * <p> This method is called within a acquireDbLock()/releaseDbLock() block, 189 * which means a database transaction will be active during the call; 190 */ insertInternal(Uri url, ContentValues values)191 protected abstract Uri insertInternal(Uri url, ContentValues values); 192 193 /** 194 * Subclasses should override this instead of query(). See query() 195 * for details. 196 * 197 * <p> This method is *not* called within a acquireDbLock()/releaseDbLock() 198 * block for performance reasons. If an implementation needs atomic access 199 * to the database the lock can be acquired then. 200 */ queryInternal(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder)201 protected abstract Cursor queryInternal(Uri url, String[] projection, 202 String selection, String[] selectionArgs, String sortOrder); 203 204 /** 205 * Make sure that there are no entries for accounts that no longer exist 206 * @param accountsArray the array of currently-existing accounts 207 */ onAccountsChanged(Account[] accountsArray)208 protected abstract void onAccountsChanged(Account[] accountsArray); 209 210 /** 211 * A helper method to delete all rows whose account is not in the accounts 212 * map. The accountColumnName is the name of the column that is expected 213 * to hold the account. If a row has an empty account it is never deleted. 214 * 215 * @param accounts a map of existing accounts 216 * @param table the table to delete from 217 */ deleteRowsForRemovedAccounts(Map<Account, Boolean> accounts, String table)218 protected abstract void deleteRowsForRemovedAccounts(Map<Account, Boolean> accounts, 219 String table); 220 221 /** 222 * Called when the sync system determines that this provider should no longer 223 * contain records for the specified account. 224 */ wipeAccount(Account account)225 public abstract void wipeAccount(Account account); 226 227 /** 228 * Retrieves the SyncData bytes for the given account. The byte array returned may be null. 229 */ readSyncDataBytes(Account account)230 public abstract byte[] readSyncDataBytes(Account account); 231 232 /** 233 * Sets the SyncData bytes for the given account. The bytes array may be null. 234 */ writeSyncDataBytes(Account account, byte[] data)235 public abstract void writeSyncDataBytes(Account account, byte[] data); 236 } 237 238