blob: ab4e91cf5c9306d3023e3bb367db261f44614422 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.accounts.Account;
import java.util.Map;
/**
* A specialization of the ContentProvider that centralizes functionality
* used by ContentProviders that are syncable. It also wraps calls to the ContentProvider
* inside of database transactions.
*
* @hide
*/
public abstract class SyncableContentProvider extends ContentProvider {
protected abstract boolean isTemporary();
private volatile TempProviderSyncAdapter mTempProviderSyncAdapter;
public void setTempProviderSyncAdapter(TempProviderSyncAdapter syncAdapter) {
mTempProviderSyncAdapter = syncAdapter;
}
public TempProviderSyncAdapter getTempProviderSyncAdapter() {
return mTempProviderSyncAdapter;
}
/**
* Close resources that must be closed. You must call this to properly release
* the resources used by the SyncableContentProvider.
*/
public abstract void close();
/**
* Override to create your schema and do anything else you need to do with a new database.
* This is run inside a transaction (so you don't need to use one).
* This method may not use getDatabase(), or call content provider methods, it must only
* use the database handle passed to it.
*/
protected abstract void bootstrapDatabase(SQLiteDatabase db);
/**
* Override to upgrade your database from an old version to the version you specified.
* Don't set the DB version, this will automatically be done after the method returns.
* This method may not use getDatabase(), or call content provider methods, it must only
* use the database handle passed to it.
*
* @param oldVersion version of the existing database
* @param newVersion current version to upgrade to
* @return true if the upgrade was lossless, false if it was lossy
*/
protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);
/**
* Override to do anything (like cleanups or checks) you need to do after opening a database.
* Does nothing by default. This is run inside a transaction (so you don't need to use one).
* This method may not use getDatabase(), or call content provider methods, it must only
* use the database handle passed to it.
*/
protected abstract void onDatabaseOpened(SQLiteDatabase db);
/**
* Get a non-persistent instance of this content provider.
* You must call {@link #close} on the returned
* SyncableContentProvider when you are done with it.
*
* @return a non-persistent content provider with the same layout as this
* provider.
*/
public abstract SyncableContentProvider getTemporaryInstance();
public abstract SQLiteDatabase getDatabase();
public abstract boolean getContainsDiffs();
public abstract void setContainsDiffs(boolean containsDiffs);
/**
* Each subclass of this class should define a subclass of {@link
* AbstractTableMerger} for each table they wish to merge. It
* should then override this method and return one instance of
* each merger, in sequence. Their {@link
* AbstractTableMerger#merge merge} methods will be called, one at a
* time, in the order supplied.
*
* <p>The default implementation returns an empty list, so that no
* merging will occur.
* @return A sequence of subclasses of {@link
* AbstractTableMerger}, one for each table that should be merged.
*/
protected abstract Iterable<? extends AbstractTableMerger> getMergers();
/**
* Check if changes to this URI can be syncable changes.
* @param uri the URI of the resource that was changed
* @return true if changes to this URI can be syncable changes, false otherwise
*/
public abstract boolean changeRequiresLocalSync(Uri uri);
/**
* Called right before a sync is started.
*
* @param context the sync context for the operation
* @param account
*/
public abstract void onSyncStart(SyncContext context, Account account);
/**
* Called right after a sync is completed
*
* @param context the sync context for the operation
* @param success true if the sync succeeded, false if an error occurred
*/
public abstract void onSyncStop(SyncContext context, boolean success);
/**
* The account of the most recent call to onSyncStart()
* @return the account
*/
public abstract Account getSyncingAccount();
/**
* Merge diffs from a sync source with this content provider.
*
* @param context the SyncContext within which this merge is taking place
* @param diffs A temporary content provider containing diffs from a sync
* source.
* @param result a MergeResult that contains information about the merge, including
* a temporary content provider with the same layout as this provider containing
* @param syncResult
*/
public abstract void merge(SyncContext context, SyncableContentProvider diffs,
TempProviderSyncResult result, SyncResult syncResult);
/**
* Invoked when the active sync has been canceled. The default
* implementation doesn't do anything (except ensure that this
* provider is syncable). Subclasses of ContentProvider
* that support canceling of sync should override this.
*/
public abstract void onSyncCanceled();
public abstract boolean isMergeCancelled();
/**
* Subclasses should override this instead of update(). See update()
* for details.
*
* <p> This method is called within a acquireDbLock()/releaseDbLock() block,
* which means a database transaction will be active during the call;
*/
protected abstract int updateInternal(Uri url, ContentValues values,
String selection, String[] selectionArgs);
/**
* Subclasses should override this instead of delete(). See delete()
* for details.
*
* <p> This method is called within a acquireDbLock()/releaseDbLock() block,
* which means a database transaction will be active during the call;
*/
protected abstract int deleteInternal(Uri url, String selection, String[] selectionArgs);
/**
* Subclasses should override this instead of insert(). See insert()
* for details.
*
* <p> This method is called within a acquireDbLock()/releaseDbLock() block,
* which means a database transaction will be active during the call;
*/
protected abstract Uri insertInternal(Uri url, ContentValues values);
/**
* Subclasses should override this instead of query(). See query()
* for details.
*
* <p> This method is *not* called within a acquireDbLock()/releaseDbLock()
* block for performance reasons. If an implementation needs atomic access
* to the database the lock can be acquired then.
*/
protected abstract Cursor queryInternal(Uri url, String[] projection,
String selection, String[] selectionArgs, String sortOrder);
/**
* Make sure that there are no entries for accounts that no longer exist
* @param accountsArray the array of currently-existing accounts
*/
protected abstract void onAccountsChanged(Account[] accountsArray);
/**
* A helper method to delete all rows whose account is not in the accounts
* map. The accountColumnName is the name of the column that is expected
* to hold the account. If a row has an empty account it is never deleted.
*
* @param accounts a map of existing accounts
* @param table the table to delete from
*/
protected abstract void deleteRowsForRemovedAccounts(Map<Account, Boolean> accounts,
String table);
/**
* Called when the sync system determines that this provider should no longer
* contain records for the specified account.
*/
public abstract void wipeAccount(Account account);
/**
* Retrieves the SyncData bytes for the given account. The byte array returned may be null.
*/
public abstract byte[] readSyncDataBytes(Account account);
/**
* Sets the SyncData bytes for the given account. The bytes array may be null.
*/
public abstract void writeSyncDataBytes(Account account, byte[] data);
}